diff options
author | Pavel Odintsov <pavel.odintsov@gmail.com> | 2015-10-01 13:38:33 +0300 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-10-02 03:25:32 +0900 |
commit | 94b9f27c89d050c80183514986edebc9f6c8361f (patch) | |
tree | 5e5ae08d21bd48d020d068323df8181ec8bade13 | |
parent | 40742a4194f137a7add1e1fb612919e25fde6a28 (diff) |
Enhanced C++ client library
Now we could call any important functions for IPv4 unicast and IPv4
Flow Spec. I have updated code for new service / packages names.
-rw-r--r-- | docs/sources/grpc-client.md | 27 | ||||
-rw-r--r-- | tools/grpc/cpp/Makefile | 2 | ||||
-rw-r--r-- | tools/grpc/cpp/gobgp_api_client.cc | 257 |
3 files changed, 253 insertions, 33 deletions
diff --git a/docs/sources/grpc-client.md b/docs/sources/grpc-client.md index db4e6b8b..493b3cc8 100644 --- a/docs/sources/grpc-client.md +++ b/docs/sources/grpc-client.md @@ -205,22 +205,35 @@ echo "/opt/protobuf_3.0.0_alpha4/lib" > /etc/ld.so.conf.d/protobuf.conf ldconfig ``` +We use .so compilation with golang, please use only 1.5 or newer version of Go Lang. + Clone this repository and build API example: ```bash export PATH="$PATH:/opt//grpc/bin:/opt/protobuf_3.0.0_alpha4/bin/" cd /usr/src git clone https://github.com/osrg/gobgp.git -cp gobgp/api/gobgp.proto gobgp/tools/grpc/cpp/gobgp_api_client.proto -cd gobgp/tools/grpc/cpp +cd gobgp/gobgp/lib +go build -buildmode=c-shared -o libgobgp.so *.go +cp libgobgp.h /usr/src/gobgp/tools/grpc/cpp +cp libgobgp.so /usr/src/gobgp/tools/grpc/cpp +cp /usr/src/gobgp/api/gobgp.proto /usr/src/gobgp/tools/grpc/cpp/gobgp_api_client.proto +cd /usr/src/gobgp/tools/grpc/cpp make ``` ### Let's run it: ```bash -./gobgp_api_client -We received: Peer AS: 65001 -Peer router id: 213.133.111.200 -Peer flops: 0 -BGP state: BGP_FSM_ESTABLISHED +LD_LIBRARY_PATH=. ./gobgp_api_client + +List of announced prefixes for route family: 65537 + +Prefix: 10.10.20.0/22 +NLRI: {"nlri":{"prefix":"10.10.20.0/22"},"attrs":[{"type":1,"value":0},{"type":3,"nexthop":"0.0.0.0"}]} + + +List of announced prefixes for route family: 65669 + +Prefix: [destination:10.0.0.0/24][protocol: tcp][source:20.0.0.0/24] +NLRI: {"nlri":{"value":[{"type":1,"value":{"prefix":"10.0.0.0/24"}},{"type":3,"value":[{"op":129,"value":6}]},{"type":2,"value":{"prefix":"20.0.0.0/24"}}]},"attrs":[{"type":1,"value":0},{"type":14,"nexthop":"0.0.0.0","afi":1,"safi":133,"value":[{"value":[{"type":1,"value":{"prefix":"10.0.0.0/24"}},{"type":3,"value":[{"op":129,"value":6}]},{"type":2,"value":{"prefix":"20.0.0.0/24"}}]}]},{"type":16,"value":[{"type":128,"subtype":8,"value":"10:10"}]}]} ``` 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; } |