osrg / gobgp

BGP implemented in the Go Programming Language
https://osrg.github.io/gobgp/
Apache License 2.0
3.62k stars 688 forks source link

C/C++ integration code #285

Closed pavel-odintsov closed 9 years ago

pavel-odintsov commented 9 years ago

Hello, folks!

I'm developer of https://github.com/FastVPSEestiOu/fastnetmon and I widely use BGP and Flow Spec.

My Customers asked me about GoBGP integration https://github.com/FastVPSEestiOu/fastnetmon/issues/389 And I really like your project!

So I have found this nice page https://github.com/osrg/gobgp/blob/master/docs/sources/grpc-client.md and looking for some way for C++/C integration.

Thus I could add GoBGP syntax to my BGP Flow Spec library (it's generates flow spec from C structures): https://github.com/FastVPSEestiOu/fastnetmon/blob/master/src/bgp_flow_spec.h and feed it with CLI.

But I looking for some way for more deeper integration :) Could you help me?

pavel-odintsov commented 9 years ago

I need following options from BGPd side:

So could I do this with GoBGP now?

ishidawataru commented 9 years ago

Hello @pavel-odintsov,

Yes, all the above things can be done through GoBGP's gRPC API ! See https://github.com/osrg/gobgp/blob/master/api/gobgp.proto for API details. You can use ModPath to announce/withdraw routes and GetRib to get full list of announced rules.

Note that the arguments of both APIs contains raw BGP messages. so you need BGP message decoder and serializer to play with.

pavel-odintsov commented 9 years ago

Hello!

Looks like gRPC has binding for C++ too https://github.com/grpc/grpc/tree/master/src/cpp out of the box! Nice! :)

But parsing BGP messages is a real pain. Do you have any plans to accept/export this data in some format which simpler to parse?

ishidawataru commented 9 years ago

Currently there is no such ongoing work. One possible way is to make a c-shared library which has handy functions to interact with GoBGP from GoBGP's source code (latest go compiler supports that) and use it from your program. Another easy way is call gobgp's cli command via exec().

pavel-odintsov commented 9 years ago

Thanks for answer! So I could build your gobgp library this way and link it with my C++ project.

And I could use it with gRPC for conversation with gobgpd. I will try shortly!

ishidawataru commented 9 years ago

Hi @pavel-odintsov !

I've tried a bit to make a gobgp c-shared library. (https://github.com/ishidawataru/gobgp/commit/8318c5cd9e47e72f074b9780a3c34d9b759d8450) To push to the master, I should do more refactoring, however this can be a first step to meet your need.

If you have time to try, refer this document

pavel-odintsov commented 9 years ago

Awesome! I have so much time for it and could test shortly! :)

pavel-odintsov commented 9 years ago

I have tried to compile this code and haven't any success here:

[root@myprivatevps src]# git clone https://github.com/ishidawataru/gobgp.git
Cloning into 'gobgp'...
remote: Counting objects: 4987, done.
remote: Total 4987 (delta 0), reused 0 (delta 0), pack-reused 4987
Receiving objects: 100% (4987/4987), 2.31 MiB | 575.00 KiB/s, done.
Resolving deltas: 100% (3219/3219), done.
[root@myprivatevps src]# cd gobgp/gobgp
[root@myprivatevps gobgp]# ls
common.go  global.go  main.go  monitor.go  neighbor.go  policy.go
[root@myprivatevps gobgp]# go version
go version go1.5 linux/amd64
[root@myprivatevps gobgp]# go build -buildmode=c-shared -o libgobgp.so *.go
# command-line-arguments
./common.go:124: p[i].Nlri.Prefix undefined (type []byte has no field or method Prefix)
./common.go:124: p[j].Nlri.Prefix undefined (type []byte has no field or method Prefix)
./common.go:129: p[i].Nlri.Prefix undefined (type []byte has no field or method Prefix)
./common.go:130: p[j].Nlri.Prefix undefined (type []byte has no field or method Prefix)
./common.go:266: undefined: api.AddressFamily
./common.go:267: undefined: api.AddressFamily
./common.go:271: undefined: api.AF_IPV4_UC
./common.go:273: undefined: api.AF_IPV6_UC
./common.go:275: undefined: api.AF_EVPN
./common.go:277: undefined: api.AF_ENCAP
./common.go:277: too many errors

Could you help with fixing of this issue?

ishidawataru commented 9 years ago

try c-shared-lib branch!

pavel-odintsov commented 9 years ago

Works perfectly!

go build -buildmode=c-shared -o libgobgp.so *.go
gcc gobgp.c -o test -L . -lgobgp

Output:

LD_LIBRARY_PATH=. ./test 
input: match protocol tcp source 10.0.0.0/24 destination 20.0.0.0/24 then redirect 10:10
output: {"nlri":{"value":[{"Items":[{"Op":129,"Value":6}]},{"Prefix":{"prefix":"10.0.0.0/24"}},{"Prefix":{"prefix":"20.0.0.0/24"}}]},"attrs":[{"type":14,"nexthop":"\u003cnil\u003e","afi":1,"safi":133,"value":[{"value":[{"Items":[{"Op":129,"Value":6}]},{"Prefix":{"prefix":"10.0.0.0/24"}},{"Prefix":{"prefix":"20.0.0.0/24"}}]}]},{"type":1,"value":0},{"type":16,"value":[{"type":128,"subtype":8,"value":"10:10"}]}],"age":0,"best":false,"is_withdraw":false,"validateion":0}

Could you merge this code to main project?

Thanks you so much!

pavel-odintsov commented 9 years ago

Hello :)

I have created stub application with gRPC and protocol buffers implementation for C++: https://github.com/pavel-odintsov/gobgp_api_cpp_client

If you want we could incorporate my examples into you project.

ishidawataru commented 9 years ago

Great! Yes please send a pull request. I'll push the code for c-shared-lib soon.

pavel-odintsov commented 9 years ago

Hi!

Here you go: https://github.com/osrg/gobgp/pull/312

pavel-odintsov commented 9 years ago

I saw your upgraded code in repo! Nice work!

I want to share my example file for flow spec and unicast:

#include <stdio.h>
#include "libgobgp.h"

void flow_spec() {
    path* p;
    char* input = "match protocol tcp source 10.0.0.0/24 destination 20.0.0.0/24 then redirect 10:10";
    printf("input: %s\n", input);

    unsigned int AFI_IP = 1;
    unsigned int SAFI_FLOW_SPEC_UNICAST = 133;
    unsigned int route_family = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST;

    p = serialize_path(route_family, input);
    printf("output: %s\n", decode_path(p));
}

void ipv4_unicast() {
    path* p;
    char* input = "77.88.11.0/24";
    printf("input: %s\n", input);

    unsigned int AFI_IP = 1;
    unsigned int SAFI_UNICAST = 1;

    unsigned int route_family = AFI_IP<<16 | SAFI_UNICAST;

    p = serialize_path(route_family, input);
    printf("output: %s\n", decode_path(p));
}

int main() {
    flow_spec();

    ipv4_unicast();

   return 0;
}

Works really well:

LD_LIBRARY_PATH=. ./test
input: match protocol tcp source 10.0.0.0/24 destination 20.0.0.0/24 then redirect 10:10
output: {"nlri":{"value":[{"type":3,"value":[{"op":129,"value":6}]},{"type":2,"value":{"prefix":"10.0.0.0/24"}},{"type":1,"value":{"prefix":"20.0.0.0/24"}}]},"attrs":[{"type":14,"nexthop":"0.0.0.0","afi":1,"safi":133,"value":[{"value":[{"type":3,"value":[{"op":129,"value":6}]},{"type":2,"value":{"prefix":"10.0.0.0/24"}},{"type":1,"value":{"prefix":"20.0.0.0/24"}}]}]},{"type":1,"value":0},{"type":16,"value":[{"type":128,"subtype":8,"value":"10:10"}]}]}
input: 77.88.11.0/24
4
output: {"nlri":{"prefix":"77.88.11.0/24"},"attrs":[{"type":3,"nexthop":"0.0.0.0"},{"type":1,"value":0}]}
pavel-odintsov commented 9 years ago

Hello :)

I have implemented code which bring together gRPC, protobuffers and gobgp C-library in single application.

So I could list all routes from gobgpd:

LD_LIBRARY_PATH=. ./gobgp_api_client 
List of announced prefixes

Prefix: [destination:10.33.0.0/24][source:20.0.0.0/24]
NLRI: {"nlri":{"value":[{"type":1,"value":{"prefix":"10.33.0.0/24"}},{"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.33.0.0/24"}},{"type":2,"value":{"prefix":"20.0.0.0/24"}}]}]},{"type":16,"value":[{"type":128,"subtype":8,"value":"10:10"}]}]}

I have used this code for example flow spec:

gobgp global rib -a ipv4-flowspec add match destination 10.33.0.0/24 proto tcp source 20.0.0.0/24 then redirect 10:10 

All code here: https://github.com/pavel-odintsov/gobgp_api_cpp_client

pavel-odintsov commented 9 years ago

Hello, folks!

I have finished! So I have all options mentioned before:

My code here: https://github.com/pavel-odintsov/gobgp_api_cpp_client

pavel-odintsov commented 9 years ago

This code implemented in C++ examples and sent with pull request. So we could close this issue.