diff --git a/.gitignore b/.gitignore index f135138c6ab840e024f1772f9c146b3159fd530e..0d49122196db33067d384bb07213f789dad44360 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ bio-rd examples/bgp examples/bmp examples/fib/fib +examples/device/device # bazel directories /bazel-* diff --git a/config/peer.go b/config/peer.go index 1736ac667e05eb81400b91d2e95d5f319ff3c9ed..a5e448bf76d7067313b8e8cc838a12153746c304 100644 --- a/config/peer.go +++ b/config/peer.go @@ -6,7 +6,7 @@ import ( bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/routingtable" "github.com/bio-routing/bio-rd/routingtable/filter" - "github.com/bio-routing/bio-rd/routingtable/locRIB" + "github.com/bio-routing/bio-rd/routingtable/vrf" ) // Peer defines the configuration for a BGP session @@ -27,11 +27,11 @@ type Peer struct { AdvertiseIPv4MultiProtocol bool IPv4 *AddressFamilyConfig IPv6 *AddressFamilyConfig + VRF *vrf.VRF } // AddressFamilyConfig represents all configuration parameters specific for an address family type AddressFamilyConfig struct { - RIB *locRIB.LocRIB ImportFilter *filter.Filter ExportFilter *filter.Filter AddPathSend routingtable.ClientOptions diff --git a/examples/bgp/main.go b/examples/bgp/main.go index 11c2a6895ade4237dbf48249437c2d202bb8aa58..e2e7d9d883c7ea1b34d88ddc80bb2a31020b8776 100644 --- a/examples/bgp/main.go +++ b/examples/bgp/main.go @@ -1,15 +1,12 @@ package main import ( - "fmt" - "time" - - "github.com/sirupsen/logrus" - - "github.com/bio-routing/bio-rd/protocols/bgp/server" - "github.com/bio-routing/bio-rd/routingtable/locRIB" + "log" bnet "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/protocols/bgp/server" + "github.com/bio-routing/bio-rd/routingtable/vrf" + "github.com/sirupsen/logrus" ) func strAddr(s string) uint32 { @@ -20,16 +17,13 @@ func strAddr(s string) uint32 { func main() { logrus.Printf("This is a BGP speaker\n") - rib := locRIB.New() b := server.NewBgpServer() - startServer(b, rib) + v, err := vrf.New("master") + if err != nil { + log.Fatal(err) + } - go func() { - for { - fmt.Printf("LocRIB count: %d\n", rib.Count()) - time.Sleep(time.Second * 10) - } - }() + startServer(b, v) select {} } diff --git a/examples/bgp/main_ipv4.go b/examples/bgp/main_ipv4.go index c280c0723e28449664dcf2692f0150e4a60c5fc2..bd9fb5e1524445cb8b48dfd5b136ab3e30d55ec5 100644 --- a/examples/bgp/main_ipv4.go +++ b/examples/bgp/main_ipv4.go @@ -6,18 +6,17 @@ import ( "net" "time" - "github.com/bio-routing/bio-rd/routingtable/locRIB" + "github.com/bio-routing/bio-rd/routingtable/vrf" "github.com/bio-routing/bio-rd/config" + bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/protocols/bgp/server" "github.com/bio-routing/bio-rd/routingtable" "github.com/bio-routing/bio-rd/routingtable/filter" "github.com/sirupsen/logrus" - - bnet "github.com/bio-routing/bio-rd/net" ) -func startServer(b server.BGPServer, rib *locRIB.LocRIB) { +func startServer(b server.BGPServer, v *vrf.VRF) { err := b.Start(&config.Global{ Listen: true, LocalAddressList: []net.IP{ @@ -41,7 +40,6 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { Passive: true, RouterID: b.RouterID(), IPv4: &config.AddressFamilyConfig{ - RIB: rib, ImportFilter: filter.NewAcceptAllFilter(), ExportFilter: filter.NewAcceptAllFilter(), AddPathSend: routingtable.ClientOptions{ @@ -49,6 +47,7 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { }, }, RouteServerClient: true, + VRF: v, }) b.AddPeer(config.Peer{ @@ -64,7 +63,6 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { RouterID: b.RouterID(), RouteServerClient: true, IPv4: &config.AddressFamilyConfig{ - RIB: rib, ImportFilter: filter.NewAcceptAllFilter(), ExportFilter: filter.NewAcceptAllFilter(), AddPathSend: routingtable.ClientOptions{ @@ -72,5 +70,6 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { }, AddPathRecv: true, }, + VRF: v, }) } diff --git a/examples/bgp/main_ipv6.go b/examples/bgp/main_ipv6.go index f416133ce6007ee8071e76d6da80fb19da8226ea..6dd1d6945cdf7ee7bd3f5259fd76976966dcbcbe 100644 --- a/examples/bgp/main_ipv6.go +++ b/examples/bgp/main_ipv6.go @@ -7,16 +7,15 @@ import ( "time" "github.com/bio-routing/bio-rd/config" + bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/protocols/bgp/server" "github.com/bio-routing/bio-rd/routingtable" "github.com/bio-routing/bio-rd/routingtable/filter" - "github.com/bio-routing/bio-rd/routingtable/locRIB" + "github.com/bio-routing/bio-rd/routingtable/vrf" "github.com/sirupsen/logrus" - - bnet "github.com/bio-routing/bio-rd/net" ) -func startServer(b server.BGPServer, rib *locRIB.LocRIB) { +func startServer(b server.BGPServer, v *vrf.VRF) { err := b.Start(&config.Global{ Listen: true, LocalAddressList: []net.IP{ @@ -39,13 +38,13 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { Passive: true, RouterID: b.RouterID(), IPv6: &config.AddressFamilyConfig{ - RIB: rib, ImportFilter: filter.NewAcceptAllFilter(), ExportFilter: filter.NewDrainFilter(), AddPathSend: routingtable.ClientOptions{ BestOnly: true, }, }, + VRF: v, }) b.AddPeer(config.Peer{ @@ -60,7 +59,6 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { Passive: true, RouterID: b.RouterID(), IPv6: &config.AddressFamilyConfig{ - RIB: rib, ImportFilter: filter.NewDrainFilter(), ExportFilter: filter.NewAcceptAllFilter(), AddPathSend: routingtable.ClientOptions{ diff --git a/examples/bmp/main_bmp.go b/examples/bmp/main_bmp.go index 63de954fed0cbefea47ddd398d522b5d96e00b29..c973e6f51049a691a64ee3fde321524f2f6badcc 100644 --- a/examples/bmp/main_bmp.go +++ b/examples/bmp/main_bmp.go @@ -13,8 +13,8 @@ import ( func main() { logrus.Printf("This is a BMP speaker\n") - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") b := server.NewServer() b.AddRouter(net.IP{10, 0, 255, 0}, 30119, rib4, rib6) diff --git a/examples/fib/main.go b/examples/fib/main.go deleted file mode 100644 index 677ab11574f6b4e2afd037bc2d33b5f8f8b8f73b..0000000000000000000000000000000000000000 --- a/examples/fib/main.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "net" - "os" - "time" - - "github.com/bio-routing/bio-rd/config" - "github.com/bio-routing/bio-rd/protocols/bgp/server" - "github.com/bio-routing/bio-rd/protocols/fib" - "github.com/bio-routing/bio-rd/routingtable/locRIB" - log "github.com/sirupsen/logrus" - - bnet "github.com/bio-routing/bio-rd/net" -) - -func strAddr(s string) uint32 { - ret, _ := bnet.StrToAddr(s) - return ret -} - -func main() { - log.SetLevel(log.DebugLevel) - - f, err := os.OpenFile("/var/log/bio-rd.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) - if err != nil { - log.Fatalf("error opening file: %v", err) - } - defer f.Close() - - log.SetOutput(f) - - log.Info("bio-routing started...\n") - - cfg := &config.Global{ - Listen: true, - LocalAddressList: []net.IP{ - net.IPv4(169, 254, 0, 2), - }, - } - - rib := locRIB.New() - b := server.NewBgpServer() - startBGPServer(b, rib, cfg) - - // FIB communication - n := fib.NewFIB(&config.Netlink{ - HoldTime: time.Second * 15, - UpdateInterval: time.Second * 15, - RoutingTable: config.RtMain, - }, rib) - n.Start() - - go func() { - for { - log.Debugf("LocRIB count: %d", rib.Count()) - log.Debugf(rib.String()) - time.Sleep(time.Second * 10) - } - }() - - select {} -} diff --git a/examples/fib/main_ipv4.go b/examples/fib/main_ipv4.go deleted file mode 100644 index 12bb67ae2305208035c00d46ed634c72a2dee454..0000000000000000000000000000000000000000 --- a/examples/fib/main_ipv4.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "time" - - "github.com/bio-routing/bio-rd/routingtable" - "github.com/bio-routing/bio-rd/routingtable/locRIB" - - "github.com/bio-routing/bio-rd/config" - "github.com/bio-routing/bio-rd/protocols/bgp/server" - "github.com/bio-routing/bio-rd/routingtable/filter" - log "github.com/sirupsen/logrus" - - bnet "github.com/bio-routing/bio-rd/net" -) - -func startBGPServer(b server.BGPServer, rib *locRIB.LocRIB, cfg *config.Global) { - err := b.Start(cfg) - if err != nil { - log.Fatalf("Unable to start BGP server: %v", err) - } - - b.AddPeer(config.Peer{ - AdminEnabled: true, - LocalAS: 65200, - PeerAS: 65100, - PeerAddress: bnet.IPv4FromOctets(169, 254, 0, 1), - LocalAddress: bnet.IPv4FromOctets(169, 254, 0, 2), - ReconnectInterval: time.Second * 20, - HoldTime: time.Second * 20, - KeepAlive: time.Second * 20, - Passive: false, - RouterID: b.RouterID(), - - //AddPathSend: routingtable.ClientOptions{ - // MaxPaths: 10, - //}, - //RouteServerClient: true, - IPv4: &config.AddressFamilyConfig{ - RIB: rib, - ImportFilter: filter.NewAcceptAllFilter(), - ExportFilter: filter.NewAcceptAllFilter(), - AddPathSend: routingtable.ClientOptions{ - MaxPaths: 10, - }, - AddPathRecv: true, - }, - }) -} diff --git a/examples/fib/main_ipv6.go b/examples/fib/main_ipv6.go deleted file mode 100644 index 3a1716e157dc5e60be2f6cb99e6736f03b719a0d..0000000000000000000000000000000000000000 --- a/examples/fib/main_ipv6.go +++ /dev/null @@ -1,72 +0,0 @@ -// +build ipv6 - -package main - -import ( - "net" - "time" - - "github.com/bio-routing/bio-rd/config" - "github.com/bio-routing/bio-rd/protocols/bgp/server" - "github.com/bio-routing/bio-rd/routingtable" - "github.com/bio-routing/bio-rd/routingtable/filter" - "github.com/bio-routing/bio-rd/routingtable/locRIB" - "github.com/sirupsen/logrus" - - bnet "github.com/bio-routing/bio-rd/net" -) - -func startServer(b server.BGPServer, rib *locRIB.LocRIB) { - - err := b.Start(&config.Global{ - Listen: true, - LocalAddressList: []net.IP{ - {0x20, 0x01, 0x6, 0x78, 0x1, 0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0xca, 0xfe}, - }, - }) - if err != nil { - logrus.Fatalf("Unable to start BGP server: %v", err) - } - - b.AddPeer(config.Peer{ - AdminEnabled: true, - LocalAS: 65200, - PeerAS: 202739, - PeerAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 1), - LocalAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0xcafe), - ReconnectInterval: time.Second * 15, - HoldTime: time.Second * 90, - KeepAlive: time.Second * 30, - Passive: true, - RouterID: b.RouterID(), - IPv6: &config.AddressFamilyConfig{ - RIB: rib, - ImportFilter: filter.NewAcceptAllFilter(), - ExportFilter: filter.NewDrainFilter(), - AddPathSend: routingtable.ClientOptions{ - BestOnly: true, - }, - }, - }) - - b.AddPeer(config.Peer{ - AdminEnabled: true, - LocalAS: 65200, - PeerAS: 65400, - PeerAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0xcafe, 0, 0, 0, 5), - LocalAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0xcafe), - ReconnectInterval: time.Second * 15, - HoldTime: time.Second * 90, - KeepAlive: time.Second * 30, - Passive: true, - RouterID: b.RouterID(), - IPv6: &config.AddressFamilyConfig{ - RIB: rib, - ImportFilter: filter.NewDrainFilter(), - ExportFilter: filter.NewAcceptAllFilter(), - AddPathSend: routingtable.ClientOptions{ - BestOnly: true, - }, - }, - }) -} diff --git a/go.mod b/go.mod index 4a127d313e57dbab42d096521192f261a995393a..af9d8336d060b0717f754271dc8b69092f7a266a 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,15 @@ module github.com/bio-routing/bio-rd require ( - github.com/FMNSSun/libhash v0.0.0-20180614155432-dabbc4426b6d github.com/bio-routing/tflow2 v0.0.0-20181230153523-2e308a4a3c3a github.com/golang/protobuf v1.2.1-0.20181128192352-1d3f30b51784 github.com/pkg/errors v0.8.0 - github.com/sirupsen/logrus v1.2.0 + github.com/sirupsen/logrus v1.3.0 github.com/stretchr/testify v1.2.2 github.com/vishvananda/netlink v1.0.0 github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 // indirect - golang.org/x/net v0.0.0-20181220203305-927f97764cc3 + golang.org/x/net v0.0.0-20181220203305-927f97764cc3 // indirect golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect golang.org/x/sys v0.0.0-20181228120256-c6cbdbf9e68a // indirect google.golang.org/genproto v0.0.0-20181221175505-bd9b4fb69e2f // indirect diff --git a/go.sum b/go.sum index 88b6d8345831bdca8862e8b722b00af6724af1ad..e6bac905d83e1094e87e907ec5ca95e0d7773827 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,4 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/FMNSSun/libhash v0.0.0-20180614155432-dabbc4426b6d h1:kLgFLWVyqlIMBCyE1f5e8pfLOoJ/RbFOlVbX27np+h4= -github.com/FMNSSun/libhash v0.0.0-20180614155432-dabbc4426b6d/go.mod h1:o6y2qav+ovGETjay+RIj2kGI/o/LmjnuT/qyvmVPhCc= github.com/bio-routing/tflow2 v0.0.0-20181230153523-2e308a4a3c3a h1:CsHtkAummoG7yhc9+6NRBkoPcTzSSmTfiyzWx5NwFPw= github.com/bio-routing/tflow2 v0.0.0-20181230153523-2e308a4a3c3a/go.mod h1:tjzJ5IykdbWNs1FjmiJWsH6SRBl+aWgxO5I44DAegIw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -23,6 +21,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/protocols/bgp/server/bmp_router_test.go b/protocols/bgp/server/bmp_router_test.go index ace1846154b08ff18e2506337826378be267d603..aa17d74e4a7ba954f5ae4ae0bdc20522dc492418 100644 --- a/protocols/bgp/server/bmp_router_test.go +++ b/protocols/bgp/server/bmp_router_test.go @@ -35,8 +35,8 @@ func TestBMPRouterServe(t *testing.T) { for _, test := range tests { addr := net.IP{10, 20, 30, 40} port := uint16(123) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") conA, conB := net.Pipe() r := newRouter(addr, port, rib4, rib6) @@ -53,8 +53,8 @@ func TestBMPRouterServe(t *testing.T) { func TestStartStopBMP(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(123) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") con := biotesting.NewMockConn() @@ -260,8 +260,8 @@ func TestProcessPeerUpNotification(t *testing.T) { { name: "Regular BGP by RFC4271", router: &router{ - rib4: locRIB.New(), - rib6: locRIB.New(), + rib4: locRIB.New("inet.0"), + rib6: locRIB.New("inet6.0"), neighbors: make(map[[16]byte]*neighbor), }, pkt: &bmppkt.PeerUpNotification{ @@ -300,8 +300,8 @@ func TestProcessPeerUpNotification(t *testing.T) { }, wantFail: false, expected: &router{ - rib4: locRIB.New(), - rib6: locRIB.New(), + rib4: locRIB.New("inet.0"), + rib6: locRIB.New("inet6.0"), neighbors: map[[16]byte]*neighbor{ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 255, 1}: { localAS: 200, @@ -631,16 +631,16 @@ func TestRegisterClients(t *testing.T) { n := &neighbor{ fsm: &FSM{ ipv4Unicast: &fsmAddressFamily{ - adjRIBIn: locRIB.New(), + adjRIBIn: locRIB.New("inet.0"), }, ipv6Unicast: &fsmAddressFamily{ - adjRIBIn: locRIB.New(), + adjRIBIn: locRIB.New("inet6.0"), }, }, } - client4 := locRIB.New() - client6 := locRIB.New() + client4 := locRIB.New("inet.0") + client6 := locRIB.New("inet6.0") ac4 := afiClient{ afi: packet.IPv4AFI, client: client4, @@ -677,8 +677,8 @@ func TestIntegrationPeerUpRouteMonitor(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) conA, conB := net.Pipe() @@ -810,8 +810,8 @@ func TestIntegrationPeerUpRouteMonitorIPv6IPv4(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) conA, conB := net.Pipe() @@ -1020,8 +1020,8 @@ func TestIntegrationPeerUpRouteMonitorIPv4IPv6(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) conA, conB := net.Pipe() @@ -1231,8 +1231,8 @@ func TestIntegrationPeerUpRouteMonitorIPv6(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) conA, conB := net.Pipe() @@ -1383,8 +1383,8 @@ func TestIntegrationIncompleteBMPMsg(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) con := biotesting.NewMockConn() @@ -1461,8 +1461,8 @@ func TestBMPFullRunWithWithdraw(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) con := biotesting.NewMockConn() @@ -1630,8 +1630,8 @@ func TestBMPFullRunWithPeerDownNotification(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) con := biotesting.NewMockConn() @@ -1790,8 +1790,8 @@ func TestBMPFullRunWithTerminationMessage(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) con := biotesting.NewMockConn() @@ -1942,8 +1942,8 @@ func TestIntegrationPeerUpRouteMonitorIPv6WithClientAtEnd(t *testing.T) { addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) conA, conB := net.Pipe() @@ -2087,7 +2087,7 @@ func TestIntegrationPeerUpRouteMonitorIPv6WithClientAtEnd(t *testing.T) { t.Errorf("Unexpected IPv4 route count. Expected: 0 Got: %d", count) } - client6 := locRIB.New() + client6 := locRIB.New("client6") r.subscribeRIBs(client6, packet.IPv6AFI) count = client6.RouteCount() @@ -2702,13 +2702,13 @@ func TestIntegrationPeerUpRouteMonitorIPv6WithClientBeforeBMPPeer(t *testing.T) addr := net.IP{10, 20, 30, 40} port := uint16(12346) - rib4 := locRIB.New() - rib6 := locRIB.New() + rib4 := locRIB.New("inet.0") + rib6 := locRIB.New("inet6.0") r := newRouter(addr, port, rib4, rib6) conA, conB := net.Pipe() - client := locRIB.New() + client := locRIB.New("client") r.subscribeRIBs(client, test.afi) if test.doubleSubscribe { r.subscribeRIBs(client, test.afi) diff --git a/protocols/bgp/server/fsm_test.go b/protocols/bgp/server/fsm_test.go index 5b410321405a2b491d1b5a9639459dd8bd98ee8b..86a8fd78c305781d190ba9cc33811c709e146e34 100644 --- a/protocols/bgp/server/fsm_test.go +++ b/protocols/bgp/server/fsm_test.go @@ -5,12 +5,11 @@ import ( "testing" "time" + bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/protocols/bgp/packet" "github.com/bio-routing/bio-rd/routingtable/filter" "github.com/bio-routing/bio-rd/routingtable/locRIB" "github.com/stretchr/testify/assert" - - bnet "github.com/bio-routing/bio-rd/net" ) // TestFSM255UpdatesIPv4 emulates receiving 255 BGP updates and withdraws. Checks route counts. @@ -19,7 +18,7 @@ func TestFSM255UpdatesIPv4(t *testing.T) { addr: bnet.IPv4FromOctets(169, 254, 100, 100), routerID: bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), ipv4: &peerAddressFamily{ - rib: locRIB.New(), + rib: locRIB.New("inet.0"), importFilter: filter.NewAcceptAllFilter(), exportFilter: filter.NewAcceptAllFilter(), }, @@ -133,7 +132,7 @@ func TestFSM255UpdatesIPv6(t *testing.T) { addr: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0xffff, 0, 0, 0, 1), routerID: bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), ipv6: &peerAddressFamily{ - rib: locRIB.New(), + rib: locRIB.New("inet6.0"), importFilter: filter.NewAcceptAllFilter(), exportFilter: filter.NewAcceptAllFilter(), }, diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go index 29001e7023dbbaf74f09d42955dc57020177d21d..c2db07d765084cb3ce7ec896492ca3dc0c2587ce 100644 --- a/protocols/bgp/server/peer.go +++ b/protocols/bgp/server/peer.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "sync" "time" @@ -136,12 +137,16 @@ func newPeer(c config.Peer, server *bgpServer) (*peer, error) { if c.IPv4 != nil { p.ipv4 = &peerAddressFamily{ - rib: c.IPv4.RIB, + rib: c.VRF.IPv4UnicastRIB(), importFilter: filterOrDefault(c.IPv4.ImportFilter), exportFilter: filterOrDefault(c.IPv4.ExportFilter), addPathReceive: c.IPv4.AddPathRecv, addPathSend: c.IPv4.AddPathSend, } + + if p.ipv4.rib == nil { + return nil, fmt.Errorf("No RIB for IPv4 unicast configured") + } } // If we are a route reflector and no ClusterID was set, use our RouterID @@ -162,13 +167,17 @@ func newPeer(c config.Peer, server *bgpServer) (*peer, error) { if c.IPv6 != nil { p.ipv6 = &peerAddressFamily{ - rib: c.IPv6.RIB, + rib: c.VRF.IPv6UnicastRIB(), importFilter: filterOrDefault(c.IPv6.ImportFilter), exportFilter: filterOrDefault(c.IPv6.ExportFilter), addPathReceive: c.IPv6.AddPathRecv, addPathSend: c.IPv6.AddPathSend, } caps = append(caps, multiProtocolCapability(packet.IPv6AFI)) + + if p.ipv6.rib == nil { + return nil, fmt.Errorf("No RIB for IPv6 unicast configured") + } } p.optOpenParams = append(p.optOpenParams, packet.OptParam{ diff --git a/protocols/bgp/server/update_sender_test.go b/protocols/bgp/server/update_sender_test.go index 3b0c0701ae79a993fd0169f8ba79621b3c15782c..4e75183a294384446b57684566a35273611966ed 100644 --- a/protocols/bgp/server/update_sender_test.go +++ b/protocols/bgp/server/update_sender_test.go @@ -7,16 +7,14 @@ import ( "testing" "time" - "github.com/bio-routing/bio-rd/protocols/bgp/packet" - "github.com/bio-routing/bio-rd/routingtable" - - "github.com/stretchr/testify/assert" - bnet "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/protocols/bgp/packet" "github.com/bio-routing/bio-rd/route" + "github.com/bio-routing/bio-rd/routingtable" "github.com/bio-routing/bio-rd/routingtable/filter" "github.com/bio-routing/bio-rd/routingtable/locRIB" btest "github.com/bio-routing/bio-rd/testing" + "github.com/stretchr/testify/assert" ) func TestSender(t *testing.T) { @@ -881,7 +879,7 @@ func TestSender(t *testing.T) { addr: bnet.IPv4FromOctets(169, 254, 100, 100), }) - rib := locRIB.New() + rib := locRIB.New("inet6.0") if test.afi == packet.IPv6AFI { fsmA.ipv6Unicast = newFSMAddressFamily(packet.IPv6AFI, packet.UnicastSAFI, &peerAddressFamily{ rib: rib, diff --git a/routingtable/locRIB/loc_rib.go b/routingtable/locRIB/loc_rib.go index b1f975f65fad28e31f3fcd327836ad4f518e0f4f..fe4f290551122da42539d9966400f3815eca34fb 100644 --- a/routingtable/locRIB/loc_rib.go +++ b/routingtable/locRIB/loc_rib.go @@ -8,11 +8,12 @@ import ( "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/routingtable" - "github.com/sirupsen/logrus" + log "github.com/sirupsen/logrus" ) // LocRIB represents a routing information base type LocRIB struct { + name string clientManager *routingtable.ClientManager rt *routingtable.RoutingTable mu sync.RWMutex @@ -20,12 +21,14 @@ type LocRIB struct { } // New creates a new routing information base -func New() *LocRIB { +func New(name string) *LocRIB { a := &LocRIB{ + name: name, rt: routingtable.NewRoutingTable(), contributingASNs: routingtable.NewContributingASNs(), } a.clientManager = routingtable.NewClientManager(a) + return a } @@ -64,7 +67,7 @@ func (a *LocRIB) RouteCount() int64 { func (a *LocRIB) AddPath(pfx net.Prefix, p *route.Path) error { a.mu.Lock() defer a.mu.Unlock() - logrus.WithFields(map[string]interface{}{ + log.WithFields(map[string]interface{}{ "Prefix": pfx, "Route": p, }).Debug("AddPath to locRIB") @@ -94,7 +97,7 @@ func (a *LocRIB) RemovePath(pfx net.Prefix, p *route.Path) bool { a.mu.Lock() defer a.mu.Unlock() - logrus.WithFields(map[string]interface{}{ + log.WithFields(map[string]interface{}{ "Prefix": pfx, "Route": p, }).Debug("Remove from locRIB") diff --git a/routingtable/locRIB/loc_rib_test.go b/routingtable/locRIB/loc_rib_test.go index 6b3e24e0715ec5ec8a670c9d6bd94f1a28fab5ad..b2038e9505f06246d2db6a9aee1fa117c5951755 100644 --- a/routingtable/locRIB/loc_rib_test.go +++ b/routingtable/locRIB/loc_rib_test.go @@ -5,7 +5,6 @@ import ( bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/route" - "github.com/stretchr/testify/assert" ) @@ -75,7 +74,7 @@ func TestContainsPfxPath(t *testing.T) { }, } for i, tc := range testCases { - rib := New() + rib := New("inet.0") for _, p := range tc.in { err := rib.AddPath(p.pfx, p.path) assert.Nil(t, err, "could not fill rib in testcase %v", i) @@ -86,7 +85,7 @@ func TestContainsPfxPath(t *testing.T) { } func TestLocRIB_RemovePathUnknown(t *testing.T) { - rib := New() + rib := New("inet.0") assert.True(t, rib.RemovePath(bnet.NewPfx(bnet.IPv4(1), 32), &route.Path{ Type: route.StaticPathType, diff --git a/routingtable/vrf/vrf.go b/routingtable/vrf/vrf.go new file mode 100644 index 0000000000000000000000000000000000000000..c016d864cc9f4f0260aa199550e5f64aaf978547 --- /dev/null +++ b/routingtable/vrf/vrf.go @@ -0,0 +1,105 @@ +package vrf + +import ( + "fmt" + "sync" + + "github.com/bio-routing/bio-rd/routingtable/locRIB" +) + +const ( + afiIPv4 = 1 + afiIPv6 = 2 + safiUnicast = 1 +) + +type addressFamily struct { + afi uint16 + safi uint8 +} + +// VRF a list of RIBs for different address families building a routing instance +type VRF struct { + name string + ribs map[addressFamily]*locRIB.LocRIB + mu sync.Mutex + ribNames map[string]*locRIB.LocRIB +} + +// New creates a new VRF +func New(name string) (*VRF, error) { + v := newUntrackedVRF(name) + v.CreateIPv4UnicastLocRIB("inet.0") + v.CreateIPv6UnicastLocRIB("inet6.0") + + err := globalRegistry.registerVRF(v) + if err != nil { + return nil, err + } + + return v, nil +} + +func newUntrackedVRF(name string) *VRF { + return &VRF{ + name: name, + ribs: make(map[addressFamily]*locRIB.LocRIB), + ribNames: make(map[string]*locRIB.LocRIB), + } +} + +// CreateLocRIB creates a local RIB with the given name +func (v *VRF) createLocRIB(name string, family addressFamily) (*locRIB.LocRIB, error) { + v.mu.Lock() + defer v.mu.Unlock() + + _, found := v.ribNames[name] + if found { + return nil, fmt.Errorf("a table with the name '%s' already exists in VRF '%s'", name, v.name) + } + + rib := locRIB.New(name) + v.ribs[family] = rib + v.ribNames[name] = rib + + return rib, nil +} + +// CreateIPv4UnicastLocRIB creates a LocRIB for the IPv4 unicast address family +func (v *VRF) CreateIPv4UnicastLocRIB(name string) (*locRIB.LocRIB, error) { + return v.createLocRIB(name, addressFamily{afi: afiIPv4, safi: safiUnicast}) +} + +// CreateIPv6UnicastLocRIB creates a LocRIB for the IPv6 unicast address family +func (v *VRF) CreateIPv6UnicastLocRIB(name string) (*locRIB.LocRIB, error) { + return v.createLocRIB(name, addressFamily{afi: afiIPv6, safi: safiUnicast}) +} + +// IPv4UnicastRIB returns the local RIB for the IPv4 unicast address family +func (v *VRF) IPv4UnicastRIB() *locRIB.LocRIB { + return v.ribForAddressFamily(addressFamily{afi: afiIPv4, safi: safiUnicast}) +} + +// IPv6UnicastRIB returns the local RIB for the IPv6 unicast address family +func (v *VRF) IPv6UnicastRIB() *locRIB.LocRIB { + return v.ribForAddressFamily(addressFamily{afi: afiIPv6, safi: safiUnicast}) +} + +func (v *VRF) Name() string { + return v.name +} + +func (v *VRF) ribForAddressFamily(family addressFamily) *locRIB.LocRIB { + v.mu.Lock() + defer v.mu.Unlock() + + rib, _ := v.ribs[family] + + return rib +} + +// RIBByName returns the RIB for a given name. If there is no RIB with this name, found is false +func (v *VRF) RIBByName(name string) (rib *locRIB.LocRIB, found bool) { + rib, found = v.ribNames[name] + return rib, found +} diff --git a/routingtable/vrf/vrf_registry.go b/routingtable/vrf/vrf_registry.go new file mode 100644 index 0000000000000000000000000000000000000000..5af298d450448ebd2375743f70cee50a192b8636 --- /dev/null +++ b/routingtable/vrf/vrf_registry.go @@ -0,0 +1,32 @@ +package vrf + +import ( + "fmt" + "sync" +) + +var globalRegistry *vrfRegistry + +func init() { + globalRegistry = &vrfRegistry{ + vrfs: make(map[string]*VRF), + } +} + +type vrfRegistry struct { + vrfs map[string]*VRF + mu sync.Mutex +} + +func (r *vrfRegistry) registerVRF(v *VRF) error { + r.mu.Lock() + defer r.mu.Unlock() + + _, found := r.vrfs[v.name] + if found { + return fmt.Errorf("a VRF with the name '%s' already exists", v.name) + } + + r.vrfs[v.name] = v + return nil +} diff --git a/routingtable/vrf/vrf_test.go b/routingtable/vrf/vrf_test.go new file mode 100644 index 0000000000000000000000000000000000000000..3b707ccc9640e60080d0d85e54a7dce56fb0b652 --- /dev/null +++ b/routingtable/vrf/vrf_test.go @@ -0,0 +1,55 @@ +package vrf + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewWithDuplicate(t *testing.T) { + _, err := New("master") + assert.Nil(t, err, "no error on first invocation") + + _, err = New("master") + assert.NotNil(t, err, "ambigious VRF name") +} + +func TestIPv4UnicastRIBWith(t *testing.T) { + v := newUntrackedVRF("master") + rib, err := v.CreateIPv4UnicastLocRIB("inet.0") + + assert.Equal(t, rib, v.IPv4UnicastRIB()) + assert.Nil(t, err, "error must be nil") +} + +func TestIPv6UnicastRIB(t *testing.T) { + v := newUntrackedVRF("master") + rib, err := v.CreateIPv6UnicastLocRIB("inet6.0") + + assert.Equal(t, rib, v.IPv6UnicastRIB()) + assert.Nil(t, err, "error must be nil") +} + +func TestCreateLocRIBTwice(t *testing.T) { + v := newUntrackedVRF("master") + _, err := v.CreateIPv6UnicastLocRIB("inet6.0") + assert.Nil(t, err, "error must be nil on first invokation") + + _, err = v.CreateIPv6UnicastLocRIB("inet6.0") + assert.NotNil(t, err, "error must not be nil on second invokation") +} + +func TestRIBByName(t *testing.T) { + v := newUntrackedVRF("master") + rib, _ := v.CreateIPv6UnicastLocRIB("inet6.0") + assert.NotNil(t, rib, "rib must not be nil after creation") + + foundRIB, found := v.RIBByName("inet6.0") + assert.True(t, found) + assert.Exactly(t, rib, foundRIB) +} + +func TestName(t *testing.T) { + v := newUntrackedVRF("foo") + assert.Equal(t, "foo", v.Name()) +}