diff options
Diffstat (limited to 'tools/grpc')
-rw-r--r-- | tools/grpc/cpp/Makefile | 2 | ||||
-rw-r--r-- | tools/grpc/cpp/gobgp_api_client.cc | 257 |
2 files changed, 233 insertions, 26 deletions
diff --git a/tools/grpc/cpp/Makefile b/tools/grpc/cpp/Makefile index e277acfb..2fcb5c8c 100644 --- a/tools/grpc/cpp/Makefile +++ b/tools/grpc/cpp/Makefile @@ -13,7 +13,7 @@ vpath %.proto $(PROTOS_PATH) all: system-check gobgp_api_client gobgp_api_client: gobgp_api_client.pb.o gobgp_api_client.grpc.pb.o gobgp_api_client.o - $(CXX) $^ $(LDFLAGS) -o $@ + $(CXX) $^ $(LDFLAGS) -L. -lgobgp -o $@ %.grpc.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $< diff --git a/tools/grpc/cpp/gobgp_api_client.cc b/tools/grpc/cpp/gobgp_api_client.cc index 938b9f0e..5ff21872 100644 --- a/tools/grpc/cpp/gobgp_api_client.cc +++ b/tools/grpc/cpp/gobgp_api_client.cc @@ -2,6 +2,7 @@ #include <memory> #include <sstream> #include <string> +#include <string.h> #include <grpc/grpc.h> #include <grpc++/channel.h> @@ -10,54 +11,260 @@ #include <grpc++/security/credentials.h> #include "gobgp_api_client.grpc.pb.h" +extern "C" { + // Gobgp library + #include "libgobgp.h" +} + using grpc::Channel; using grpc::ClientContext; using grpc::Status; -using api::Grpc; +using gobgpapi::GobgpApi; class GrpcClient { public: - GrpcClient(std::shared_ptr<Channel> channel) : stub_(Grpc::NewStub(channel)) {} + GrpcClient(std::shared_ptr<Channel> channel) : stub_(GobgpApi::NewStub(channel)) {} + void GetAllActiveAnnounces(unsigned int route_family) { + ClientContext context; + gobgpapi::Arguments arguments; + + arguments.set_rf(route_family); + // We could specify certain neighbor here + arguments.set_name(""); + arguments.set_resource(gobgpapi::Resource::GLOBAL); + + auto destinations_list = stub_->GetRib(&context, arguments); + + gobgpapi::Destination current_destination; + + std::cout << "List of announced prefixes for route family: " << route_family << std::endl << std::endl; + while (destinations_list->Read(¤t_destination)) { + 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; + } + + Status status = destinations_list->Finish(); + if (!status.ok()) { + // error_message + std::cout << "Problem with RPC: " << status.error_code() << " message " << status.error_message() << std::endl; + } else { + // std::cout << "RPC working well" << std::endl; + } + } + + void AnnounceFlowSpecPrefix() { + 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; + // If you want withdraw, please use it + // current_path->set_is_withdraw(true); + + /* + 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<grpc::ClientWriter<gobgpapi::ModPathArguments> > + 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() { + 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; + // If you want withdraw, please use it + // current_path->set_is_withdraw(true); + + /* + 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<grpc::ClientWriter<api::ModPathArguments> > + 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 GetAllNeighbor(std::string neighbor_ip) { - api::Arguments request; - request.set_rf(4); - request.set_name(neighbor_ip); + gobgpapi::Arguments request; + request.set_rf(4); + request.set_name(neighbor_ip); - ClientContext context; + ClientContext context; - api::Peer peer; - grpc::Status status = stub_->GetNeighbor(&context, request, &peer); + gobgpapi::Peer peer; + grpc::Status status = stub_->GetNeighbor(&context, request, &peer); - if (status.ok()) { - api::PeerConf peer_conf = peer.conf(); - api::PeerInfo peer_info = peer.info(); + if (status.ok()) { + gobgpapi::PeerConf peer_conf = peer.conf(); + gobgpapi::PeerInfo peer_info = peer.info(); - std::stringstream buffer; + std::stringstream buffer; - buffer - << "Peer AS: " << peer_conf.remote_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"; - } + buffer + << "Peer AS: " << peer_conf.remote_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<Grpc::Stub> stub_; + std::unique_ptr<GobgpApi::Stub> stub_; }; int main(int argc, char** argv) { GrpcClient gobgp_client(grpc::CreateChannel("localhost:8080", grpc::InsecureCredentials())); - std::string reply = gobgp_client.GetAllNeighbor("213.133.111.200"); - std::cout << "We received: " << reply << std::endl; + //std::string reply = gobgp_client.GetAllNeighbor("213.133.111.200"); + //std::cout << "We received: " << reply << std::endl; + + gobgp_client.AnnounceUnicastPrefix(); + + gobgp_client.AnnounceFlowSpecPrefix(); + + 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; } |