#include #include #include #include #include #include #include #include #include #include #include "gobgp_api_client.grpc.pb.h" extern "C" { // Gobgp library #include "libgobgp.h" } using grpc::Channel; using grpc::ClientContext; using grpc::Status; using gobgpapi::GobgpApi; class GrpcClient { public: GrpcClient(std::shared_ptr channel) : stub_(GobgpApi::NewStub(channel)) {} void GetAllActiveAnnounces(unsigned int route_family) { ClientContext context; gobgpapi::Table table; table.set_family(route_family); // We could specify certain neighbor here table.set_name(""); table.set_type(gobgpapi::Resource::GLOBAL); gobgpapi::Table response_table; auto status = stub_->GetRib(&context, table, &response_table); if (!status.ok()) { // error_message std::cout << "Problem with RPC: " << status.error_code() << " message " << status.error_message() << std::endl; return; } else { // std::cout << "RPC working well" << std::endl; } std::cout << "List of announced prefixes for route family: " << route_family << std::endl << std::endl; for (auto current_destination : response_table.destinations()) { std::cout << "Prefix: " << current_destination.prefix() << std::endl; //std::cout << "Paths size: " << current_destination.paths_size() << std::endl; gobgpapi::Path my_path = current_destination.paths(0); // std::cout << "Pattrs size: " << my_path.pattrs_size() << std::endl; buf my_nlri; my_nlri.value = (char*)my_path.nlri().c_str(); my_nlri.len = my_path.nlri().size(); path_t gobgp_lib_path; gobgp_lib_path.nlri = my_nlri; // Not used in library code! gobgp_lib_path.path_attributes_cap = 0; gobgp_lib_path.path_attributes_len = my_path.pattrs_size(); buf* my_path_attributes[ my_path.pattrs_size() ]; for (int i = 0; i < my_path.pattrs_size(); i++) { my_path_attributes[i] = (buf*)malloc(sizeof(buf)); my_path_attributes[i]->len = my_path.pattrs(i).size(); my_path_attributes[i]->value = (char*)my_path.pattrs(i).c_str(); } gobgp_lib_path.path_attributes = my_path_attributes; std::cout << "NLRI: " << decode_path(&gobgp_lib_path) << std::endl; } } void AnnounceFlowSpecPrefix(bool withdraw) { const gobgpapi::ModPathArguments current_mod_path_arguments; unsigned int AFI_IP = 1; unsigned int SAFI_FLOW_SPEC_UNICAST = 133; unsigned int ipv4_flow_spec_route_family = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST; gobgpapi::Path* current_path = new gobgpapi::Path; current_path->set_is_withdraw(withdraw); /* buf: char *value; int len; path: buf nlri; buf** path_attributes; int path_attributes_len; int path_attributes_cap; */ path* path_c_struct = serialize_path(ipv4_flow_spec_route_family, (char*)"match destination 10.0.0.0/24 protocol tcp source 20.0.0.0/24 then redirect 10:10"); // printf("Decoded NLRI output: %s, length %d raw string length: %d\n", decode_path(path_c_struct), path_c_struct->nlri.len, strlen(path_c_struct->nlri.value)); for (int path_attribute_number = 0; path_attribute_number < path_c_struct->path_attributes_len; path_attribute_number++) { current_path->add_pattrs(path_c_struct->path_attributes[path_attribute_number]->value, path_c_struct->path_attributes[path_attribute_number]->len); } current_path->set_nlri(path_c_struct->nlri.value, path_c_struct->nlri.len); gobgpapi::ModPathArguments request; request.set_resource(gobgpapi::Resource::GLOBAL); google::protobuf::RepeatedPtrField< ::gobgpapi::Path >* current_path_list = request.mutable_paths(); current_path_list->AddAllocated(current_path); request.set_name(""); ClientContext context; gobgpapi::Error return_error; // result is a std::unique_ptr > auto send_stream = stub_->ModPath(&context, &return_error); bool write_result = send_stream->Write(request); if (!write_result) { std::cout << "Write to API failed\n"; } // Finish all writes send_stream->WritesDone(); auto status = send_stream->Finish(); if (status.ok()) { //std::cout << "modpath executed correctly" << std::cout; } else { std::cout << "modpath failed with code: " << status.error_code() << " message " << status.error_message() << std::endl; } } void AnnounceUnicastPrefix(bool withdraw) { const gobgpapi::ModPathArguments current_mod_path_arguments; unsigned int AFI_IP = 1; unsigned int SAFI_UNICAST = 1; unsigned int ipv4_unicast_route_family = AFI_IP<<16 | SAFI_UNICAST; gobgpapi::Path* current_path = new gobgpapi::Path; current_path->set_is_withdraw(withdraw); /* buf: char *value; int len; path: buf nlri; buf** path_attributes; int path_attributes_len; int path_attributes_cap; */ // 10.10.20.33/22 nexthop 10.10.1.99/32 path* path_c_struct = serialize_path(ipv4_unicast_route_family, (char*)"10.10.20.33/22"); // printf("Decoded NLRI output: %s, length %d raw string length: %d\n", decode_path(path_c_struct), path_c_struct->nlri.len, strlen(path_c_struct->nlri.value)); for (int path_attribute_number = 0; path_attribute_number < path_c_struct->path_attributes_len; path_attribute_number++) { current_path->add_pattrs(path_c_struct->path_attributes[path_attribute_number]->value, path_c_struct->path_attributes[path_attribute_number]->len); } current_path->set_nlri(path_c_struct->nlri.value, path_c_struct->nlri.len); gobgpapi::ModPathArguments request; request.set_resource(gobgpapi::Resource::GLOBAL); google::protobuf::RepeatedPtrField< ::gobgpapi::Path >* current_path_list = request.mutable_paths(); current_path_list->AddAllocated(current_path); request.set_name(""); ClientContext context; gobgpapi::Error return_error; // result is a std::unique_ptr > auto send_stream = stub_->ModPath(&context, &return_error); bool write_result = send_stream->Write(request); if (!write_result) { std::cout << "Write to API failed\n"; } // Finish all writes send_stream->WritesDone(); auto status = send_stream->Finish(); if (status.ok()) { //std::cout << "modpath executed correctly" << std::cout; } else { std::cout << "modpath failed with code: " << status.error_code() << " message " << status.error_message() << std::endl; } } std::string GetNeighbor(std::string neighbor_ip) { gobgpapi::Arguments request; request.set_family(4); request.set_name(neighbor_ip); ClientContext context; gobgpapi::Peer peer; grpc::Status status = stub_->GetNeighbor(&context, request, &peer); if (status.ok()) { gobgpapi::PeerConf peer_conf = peer.conf(); gobgpapi::PeerState peer_info = peer.info(); std::stringstream buffer; buffer << "Peer AS: " << peer_conf.peer_as() << "\n" << "Peer router id: " << peer_conf.id() << "\n" << "Peer flops: " << peer_info.flops() << "\n" << "BGP state: " << peer_info.bgp_state(); return buffer.str(); } else { return "Something wrong"; } } private: std::unique_ptr stub_; }; int main(int argc, char** argv) { GrpcClient gobgp_client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials())); std::string reply = gobgp_client.GetNeighbor("213.133.111.200"); std::cout << "Neighbor information: " << reply << std::endl; gobgp_client.AnnounceUnicastPrefix(false); gobgp_client.AnnounceFlowSpecPrefix(false); unsigned int AFI_IP = 1; unsigned int SAFI_UNICAST = 1; unsigned int SAFI_FLOW_SPEC_UNICAST = 133; unsigned int ipv4_unicast_route_family = AFI_IP<<16 | SAFI_UNICAST; unsigned int ipv4_flow_spec_route_family = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST; gobgp_client.GetAllActiveAnnounces(ipv4_unicast_route_family); std::cout << std::endl << std::endl; gobgp_client.GetAllActiveAnnounces(ipv4_flow_spec_route_family); return 0; }