1
0
Fork 0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-05-04 06:46:15 +02:00

Extracted GoBGP client into separate module

This commit is contained in:
Pavel Odintsov 2023-08-05 14:06:42 +01:00
parent dfbde597ee
commit b89113b81b
4 changed files with 225 additions and 162 deletions

View File

@ -521,6 +521,10 @@ endif()
if (ENABLE_GOBGP_SUPPORT)
add_definitions(-DENABLE_GOBGP)
# GoBGP client library
add_library(gobgp_client STATIC gobgp_client/gobgp_client.cpp)
add_library(gobgp_action STATIC actions/gobgp_action.cpp)
# We use find_package for Windows as our approach for *nix platforms leads to bunch of linking errors
@ -542,7 +546,9 @@ if (ENABLE_GOBGP_SUPPORT)
message(FATAL_ERROR "NOT Found gRPC module")
endif()
target_link_libraries(gobgp_action gRPC::grpc gRPC::grpc++)
target_link_libraries(gobgp_client gRPC::grpc gRPC::grpc++)
target_link_libraries(gobgp_action gRPC::grpc gRPC::grpc++ gobgp_client)
else()
@ -556,7 +562,12 @@ if (ENABLE_GOBGP_SUPPORT)
target_link_libraries(gobgp_action ${GRPC_LIBRARY_GRPC_PATH})
target_link_libraries(gobgp_action ${GRPC_LIBRARY_GPR_PATH})
target_link_libraries(gobgp_action ${GRPC_LIBRARY_GRPC_CPP_PATH})
target_link_libraries(gobgp_action gobgp_client)
target_link_libraries(gobgp_client ${GRPC_LIBRARY_GRPC_PATH})
target_link_libraries(gobgp_client ${GRPC_LIBRARY_GPR_PATH})
target_link_libraries(gobgp_client ${GRPC_LIBRARY_GRPC_CPP_PATH})
message(STATUS "Found gRPC library: ${GRPC_LIBRARY_GRPC_PATH} ${GRPC_LIBRARY_GPR_PATH} ${GRPC_LIBRARY_GRPC_CPP_PATH}")
else()
message(FATAL_ERROR "Could not find gRPC library")

View File

@ -1,16 +1,10 @@
#include "gobgp_action.hpp"
#include "../fastnetmon_actions.hpp"
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include <grpc/grpc.h>
unsigned int gobgp_client_connection_timeout = 5;
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
#include "../bgp_protocol.hpp"
#include "../gobgp_client/gobgp_client.hpp"

View File

@ -0,0 +1,204 @@
#include "gobgp_client.hpp"
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif // __GNUC__
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
//
// MinGW has quite weird definitions which clash with field names in gRPC bindinds
// We need to apply some trickery to avoid complilation errors:
// https://github.com/pavel-odintsov/fastnetmon/issues/977
//
#ifdef _WIN32
// Save previous values of these defines
#pragma push_macro("interface")
#pragma push_macro("IN")
#pragma push_macro("OUT")
#undef interface
#undef IN
#undef OUT
#endif
#include "../gobgp_client/attribute.pb.h"
#ifdef _WIN32
// Restore original values of these defines
#pragma pop_macro("interface")
#pragma pop_macro("IN")
#pragma pop_macro("OUT")
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__
using apipb::GobgpApi;
#include "../all_logcpp_libraries.hpp"
#include "../fast_library.hpp"
unsigned int gobgp_client_connection_timeout = 5;
extern log4cpp::Category& logger;
GrpcClient::GrpcClient(std::shared_ptr<Channel> channel) : stub_(GobgpApi::NewStub(channel)) {
}
bool GrpcClient::AnnounceUnicastPrefixIPv4(std::string announced_address,
std::string announced_prefix_nexthop,
bool is_withdrawal,
unsigned int cidr_mask,
uint32_t community_as_32bit_int) {
grpc::ClientContext context;
// Set timeout for API
std::chrono::system_clock::time_point deadline =
std::chrono::system_clock::now() + std::chrono::seconds(gobgp_client_connection_timeout);
context.set_deadline(deadline);
auto gobgp_ipv4_unicast_route_family = new apipb::Family;
gobgp_ipv4_unicast_route_family->set_afi(apipb::Family::AFI_IP);
gobgp_ipv4_unicast_route_family->set_safi(apipb::Family::SAFI_UNICAST);
apipb::AddPathRequest request;
request.set_table_type(apipb::TableType::GLOBAL);
apipb::Path* current_path = new apipb::Path;
current_path->set_allocated_family(gobgp_ipv4_unicast_route_family);
if (is_withdrawal) {
current_path->set_is_withdraw(true);
}
// Configure required announce
google::protobuf::Any* current_nlri = new google::protobuf::Any;
apipb::IPAddressPrefix current_ipaddrprefix;
current_ipaddrprefix.set_prefix(announced_address);
current_ipaddrprefix.set_prefix_len(cidr_mask);
current_nlri->PackFrom(current_ipaddrprefix);
current_path->set_allocated_nlri(current_nlri);
// Updating OriginAttribute info for current_path
google::protobuf::Any* current_origin = current_path->add_pattrs();
apipb::OriginAttribute current_origin_t;
current_origin_t.set_origin(0);
current_origin->PackFrom(current_origin_t);
// Updating NextHopAttribute info for current_path
google::protobuf::Any* current_next_hop = current_path->add_pattrs();
apipb::NextHopAttribute current_next_hop_t;
current_next_hop_t.set_next_hop(announced_prefix_nexthop);
current_next_hop->PackFrom(current_next_hop_t);
// Updating CommunitiesAttribute for current_path
google::protobuf::Any* current_communities = current_path->add_pattrs();
apipb::CommunitiesAttribute current_communities_t;
current_communities_t.add_communities(community_as_32bit_int);
current_communities->PackFrom(current_communities_t);
request.set_allocated_path(current_path);
apipb::AddPathResponse response;
// Don't be confused by name, it also can withdraw announces
auto status = stub_->AddPath(&context, request, &response);
if (!status.ok()) {
logger << log4cpp::Priority::ERROR << "AddPath request to BGP daemon failed with code: " << status.error_code()
<< " message " << status.error_message();
return false;
}
return true;
}
bool GrpcClient::AnnounceUnicastPrefixIPv6(const subnet_ipv6_cidr_mask_t& client_ipv6,
const subnet_ipv6_cidr_mask_t& ipv6_next_hop,
bool is_withdrawal,
uint32_t community_as_32bit_int) {
grpc::ClientContext context;
// Set timeout for API
std::chrono::system_clock::time_point deadline =
std::chrono::system_clock::now() + std::chrono::seconds(gobgp_client_connection_timeout);
context.set_deadline(deadline);
auto gobgp_ipv6_unicast_route_family = new apipb::Family;
gobgp_ipv6_unicast_route_family->set_afi(apipb::Family::AFI_IP6);
gobgp_ipv6_unicast_route_family->set_safi(apipb::Family::SAFI_UNICAST);
apipb::AddPathRequest request;
request.set_table_type(apipb::TableType::GLOBAL);
apipb::Path* current_path = new apipb::Path;
current_path->set_allocated_family(gobgp_ipv6_unicast_route_family);
if (is_withdrawal) {
current_path->set_is_withdraw(true);
}
// Configure required announce
google::protobuf::Any* current_nlri = new google::protobuf::Any;
apipb::IPAddressPrefix current_ipaddrprefix;
current_ipaddrprefix.set_prefix(print_ipv6_address(client_ipv6.subnet_address));
current_ipaddrprefix.set_prefix_len(client_ipv6.cidr_prefix_length);
current_nlri->PackFrom(current_ipaddrprefix);
current_path->set_allocated_nlri(current_nlri);
// Updating OriginAttribute info for current_path
google::protobuf::Any* current_origin = current_path->add_pattrs();
apipb::OriginAttribute current_origin_t;
current_origin_t.set_origin(0);
current_origin->PackFrom(current_origin_t);
// Updating NextHopAttribute info for current_path
google::protobuf::Any* current_next_hop = current_path->add_pattrs();
apipb::NextHopAttribute current_next_hop_t;
current_next_hop_t.set_next_hop(print_ipv6_address(ipv6_next_hop.subnet_address));
current_next_hop->PackFrom(current_next_hop_t);
// Updating CommunitiesAttribute for current_path
google::protobuf::Any* current_communities = current_path->add_pattrs();
apipb::CommunitiesAttribute current_communities_t;
current_communities_t.add_communities(community_as_32bit_int);
current_communities->PackFrom(current_communities_t);
request.set_allocated_path(current_path);
apipb::AddPathResponse response;
// Don't be confused by name, it also can withdraw announces
auto status = stub_->AddPath(&context, request, &response);
if (!status.ok()) {
logger << log4cpp::Priority::ERROR << "AddPath request to BGP daemon failed with code: " << status.error_code()
<< " message " << status.error_message();
return false;
}
return true;
}

View File

@ -1,15 +1,9 @@
#pragma once
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif // __GNUC__
#include <grpc/grpc.h>
#include <grpc++/channel.h>
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
#include "../fastnetmon_networks.hpp"
//
// MinGW has quite weird definitions which clash with field names in gRPC bindinds
@ -31,7 +25,6 @@ using grpc::Status;
#endif
#include "../gobgp_client/attribute.pb.h"
#include "../gobgp_client/gobgp.grpc.pb.h"
#ifdef _WIN32
@ -43,166 +36,27 @@ using grpc::Status;
#endif
#include "../bgp_protocol.hpp"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__
using apipb::GobgpApi;
class GrpcClient {
public:
GrpcClient(std::shared_ptr<Channel> channel) : stub_(GobgpApi::NewStub(channel)) {
}
GrpcClient(std::shared_ptr<grpc::Channel> channel);
bool AnnounceUnicastPrefixIPv4(std::string announced_address,
std::string announced_prefix_nexthop,
bool is_withdrawal,
unsigned int cidr_mask,
uint32_t community_as_32bit_int) {
grpc::ClientContext context;
// Set timeout for API
std::chrono::system_clock::time_point deadline =
std::chrono::system_clock::now() + std::chrono::seconds(gobgp_client_connection_timeout);
context.set_deadline(deadline);
auto gobgp_ipv4_unicast_route_family = new apipb::Family;
gobgp_ipv4_unicast_route_family->set_afi(apipb::Family::AFI_IP);
gobgp_ipv4_unicast_route_family->set_safi(apipb::Family::SAFI_UNICAST);
apipb::AddPathRequest request;
request.set_table_type(apipb::TableType::GLOBAL);
apipb::Path* current_path = new apipb::Path;
current_path->set_allocated_family(gobgp_ipv4_unicast_route_family);
if (is_withdrawal) {
current_path->set_is_withdraw(true);
}
// Configure required announce
google::protobuf::Any* current_nlri = new google::protobuf::Any;
apipb::IPAddressPrefix current_ipaddrprefix;
current_ipaddrprefix.set_prefix(announced_address);
current_ipaddrprefix.set_prefix_len(cidr_mask);
current_nlri->PackFrom(current_ipaddrprefix);
current_path->set_allocated_nlri(current_nlri);
// Updating OriginAttribute info for current_path
google::protobuf::Any* current_origin = current_path->add_pattrs();
apipb::OriginAttribute current_origin_t;
current_origin_t.set_origin(0);
current_origin->PackFrom(current_origin_t);
// Updating NextHopAttribute info for current_path
google::protobuf::Any* current_next_hop = current_path->add_pattrs();
apipb::NextHopAttribute current_next_hop_t;
current_next_hop_t.set_next_hop(announced_prefix_nexthop);
current_next_hop->PackFrom(current_next_hop_t);
// Updating CommunitiesAttribute for current_path
google::protobuf::Any* current_communities = current_path->add_pattrs();
apipb::CommunitiesAttribute current_communities_t;
current_communities_t.add_communities(community_as_32bit_int);
current_communities->PackFrom(current_communities_t);
request.set_allocated_path(current_path);
apipb::AddPathResponse response;
// Don't be confused by name, it also can withdraw announces
auto status = stub_->AddPath(&context, request, &response);
if (!status.ok()) {
logger << log4cpp::Priority::ERROR << "AddPath request to BGP daemon failed with code: " << status.error_code()
<< " message " << status.error_message();
return false;
}
return true;
}
uint32_t community_as_32bit_int);
bool AnnounceUnicastPrefixIPv6(const subnet_ipv6_cidr_mask_t& client_ipv6,
const subnet_ipv6_cidr_mask_t& ipv6_next_hop,
bool is_withdrawal,
uint32_t community_as_32bit_int) {
grpc::ClientContext context;
// Set timeout for API
std::chrono::system_clock::time_point deadline =
std::chrono::system_clock::now() + std::chrono::seconds(gobgp_client_connection_timeout);
context.set_deadline(deadline);
auto gobgp_ipv6_unicast_route_family = new apipb::Family;
gobgp_ipv6_unicast_route_family->set_afi(apipb::Family::AFI_IP6);
gobgp_ipv6_unicast_route_family->set_safi(apipb::Family::SAFI_UNICAST);
apipb::AddPathRequest request;
request.set_table_type(apipb::TableType::GLOBAL);
apipb::Path* current_path = new apipb::Path;
current_path->set_allocated_family(gobgp_ipv6_unicast_route_family);
if (is_withdrawal) {
current_path->set_is_withdraw(true);
}
// Configure required announce
google::protobuf::Any* current_nlri = new google::protobuf::Any;
apipb::IPAddressPrefix current_ipaddrprefix;
current_ipaddrprefix.set_prefix(print_ipv6_address(client_ipv6.subnet_address));
current_ipaddrprefix.set_prefix_len(client_ipv6.cidr_prefix_length);
current_nlri->PackFrom(current_ipaddrprefix);
current_path->set_allocated_nlri(current_nlri);
// Updating OriginAttribute info for current_path
google::protobuf::Any* current_origin = current_path->add_pattrs();
apipb::OriginAttribute current_origin_t;
current_origin_t.set_origin(0);
current_origin->PackFrom(current_origin_t);
// Updating NextHopAttribute info for current_path
google::protobuf::Any* current_next_hop = current_path->add_pattrs();
apipb::NextHopAttribute current_next_hop_t;
current_next_hop_t.set_next_hop(print_ipv6_address(ipv6_next_hop.subnet_address));
current_next_hop->PackFrom(current_next_hop_t);
// Updating CommunitiesAttribute for current_path
google::protobuf::Any* current_communities = current_path->add_pattrs();
apipb::CommunitiesAttribute current_communities_t;
current_communities_t.add_communities(community_as_32bit_int);
current_communities->PackFrom(current_communities_t);
request.set_allocated_path(current_path);
apipb::AddPathResponse response;
// Don't be confused by name, it also can withdraw announces
auto status = stub_->AddPath(&context, request, &response);
if (!status.ok()) {
logger << log4cpp::Priority::ERROR << "AddPath request to BGP daemon failed with code: " << status.error_code()
<< " message " << status.error_message();
return false;
}
return true;
}
uint32_t community_as_32bit_int);
private:
std::unique_ptr<GobgpApi::Stub> stub_;
std::unique_ptr<apipb::GobgpApi::Stub> stub_;
};