diff --git a/config/peer.go b/config/peer.go index 12124c7c6d3f44928dfaa5a1b9a05fa3bbf645a7..02d319883b0a0dc8dd375792baab20dfb568e5c5 100644 --- a/config/peer.go +++ b/config/peer.go @@ -3,6 +3,8 @@ package config import ( "time" + "github.com/bio-routing/bio-rd/routingtable/locRIB" + bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/routingtable" "github.com/bio-routing/bio-rd/routingtable/filter" @@ -22,10 +24,15 @@ type Peer struct { RouterID uint32 AddPathSend routingtable.ClientOptions AddPathRecv bool - ImportFilter *filter.Filter - ExportFilter *filter.Filter RouteServerClient bool RouteReflectorClient bool RouteReflectorClusterID uint32 - IPv6 bool + IPv4 *AddressFamilyConfig + IPv6 *AddressFamilyConfig +} + +type AddressFamilyConfig struct { + RIB *locRIB.LocRIB + ImportFilter *filter.Filter + ExportFilter *filter.Filter } diff --git a/main_ipv4.go b/main_ipv4.go index 65293f07853d5819abdb96a6ab5def218f0c2320..0d3c5a7cd4b0ce93fbe645136bd588cfbc872c2b 100644 --- a/main_ipv4.go +++ b/main_ipv4.go @@ -43,10 +43,13 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { AddPathSend: routingtable.ClientOptions{ MaxPaths: 10, }, - ImportFilter: filter.NewAcceptAllFilter(), - ExportFilter: filter.NewAcceptAllFilter(), + IPv4: &config.AddressFamilyConfig{ + RIB: rib, + ImportFilter: filter.NewAcceptAllFilter(), + ExportFilter: filter.NewAcceptAllFilter(), + }, RouteServerClient: true, - }, rib) + }) b.AddPeer(config.Peer{ AdminEnabled: true, @@ -63,8 +66,11 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { MaxPaths: 10, }, AddPathRecv: true, - ImportFilter: filter.NewAcceptAllFilter(), - ExportFilter: filter.NewAcceptAllFilter(), RouteServerClient: true, - }, rib) + IPv4: &config.AddressFamilyConfig{ + RIB: rib, + ImportFilter: filter.NewAcceptAllFilter(), + ExportFilter: filter.NewAcceptAllFilter(), + }, + }) } diff --git a/main_ipv6.go b/main_ipv6.go index 160007cc76481b968cfc98de0c459f1422b3b157..2d4a24100e2e1eea680fa63368235495846456ac 100644 --- a/main_ipv6.go +++ b/main_ipv6.go @@ -41,10 +41,12 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { AddPathSend: routingtable.ClientOptions{ BestOnly: true, }, - ImportFilter: filter.NewAcceptAllFilter(), - ExportFilter: filter.NewDrainFilter(), - IPv6: true, - }, rib) + IPv6: &config.AddressFamilyConfig{ + RIB: rib, + ImportFilter: filter.NewAcceptAllFilter(), + ExportFilter: filter.NewDrainFilter(), + }, + }) b.AddPeer(config.Peer{ AdminEnabled: true, @@ -60,8 +62,10 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { AddPathSend: routingtable.ClientOptions{ BestOnly: true, }, - ImportFilter: filter.NewDrainFilter(), - ExportFilter: filter.NewAcceptAllFilter(), - IPv6: true, - }, rib) + IPv6: &config.AddressFamilyConfig{ + RIB: rib, + ImportFilter: filter.NewDrainFilter(), + ExportFilter: filter.NewAcceptAllFilter(), + }, + }) } diff --git a/protocols/bgp/server/family_routing.go b/protocols/bgp/server/family_routing.go index a5115480729e485f5ad518ff0fc781207be618f0..64332ac66c27ad5d6bfdf44bde260359629b40f9 100644 --- a/protocols/bgp/server/family_routing.go +++ b/protocols/bgp/server/family_routing.go @@ -32,23 +32,25 @@ type familyRouting struct { initialized bool } -func newFamilyRouting(afi uint16, safi uint8, rib *locRIB.LocRIB, fsm *FSM) *familyRouting { +func newFamilyRouting(afi uint16, safi uint8, params *familyParameters, fsm *FSM) *familyRouting { return &familyRouting{ - afi: afi, - safi: safi, - rib: rib, - fsm: fsm, + afi: afi, + safi: safi, + fsm: fsm, + rib: params.rib, + importFilter: params.importFilter, + exportFilter: params.exportFilter, } } func (f *familyRouting) init(n *routingtable.Neighbor) { contributingASNs := f.rib.GetContributingASNs() - f.adjRIBIn = adjRIBIn.New(f.fsm.peer.importFilter, contributingASNs, f.fsm.peer.routerID, f.fsm.peer.clusterID) + f.adjRIBIn = adjRIBIn.New(f.importFilter, contributingASNs, f.fsm.peer.routerID, f.fsm.peer.clusterID) contributingASNs.Add(f.fsm.peer.localASN) f.adjRIBIn.Register(f.rib) - f.adjRIBOut = adjRIBOut.New(n, f.fsm.peer.exportFilter) + f.adjRIBOut = adjRIBOut.New(n, f.exportFilter) clientOptions := routingtable.ClientOptions{ BestOnly: true, } diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go index 05a83eecf8781bc42292ff0a81ca57c4d3eca55d..521e5b985270ae474021b37858c6309eafb8d3cb 100644 --- a/protocols/bgp/server/fsm.go +++ b/protocols/bgp/server/fsm.go @@ -97,8 +97,14 @@ func newFSM2(peer *peer) *FSM { stopMsgRecvCh: make(chan struct{}), options: &types.Options{}, } - f.ipv4Unicast = newFamilyRouting(packet.IPv4AFI, packet.UnicastSAFI, peer.rib, f) - f.ipv6Unicast = newFamilyRouting(packet.IPv6AFI, packet.UnicastSAFI, peer.rib, f) + + if peer.ipv4 != nil { + f.ipv4Unicast = newFamilyRouting(packet.IPv4AFI, packet.UnicastSAFI, peer.ipv4, f) + } + + if peer.ipv6 != nil { + f.ipv6Unicast = newFamilyRouting(packet.IPv6AFI, packet.UnicastSAFI, peer.ipv6, f) + } return f } diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index 78f7f1948116e9cf4b2c6967201b1cf83b33f14b..f615b19a032f0e85e61ad744d4daede2026e19f3 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -78,15 +78,26 @@ func (s *establishedState) init() error { ClusterID: s.fsm.peer.clusterID, } - s.fsm.ipv4Unicast.init(n) - s.fsm.ipv6Unicast.init(n) + if s.fsm.ipv4Unicast != nil { + s.fsm.ipv4Unicast.init(n) + } + + if s.fsm.ipv6Unicast != nil { + s.fsm.ipv6Unicast.init(n) + } + s.fsm.ribsInitialized = true return nil } func (s *establishedState) uninit() { - s.fsm.ipv4Unicast.dispose() - s.fsm.ipv6Unicast.dispose() + if s.fsm.ipv4Unicast != nil { + s.fsm.ipv4Unicast.dispose() + } + + if s.fsm.ipv6Unicast != nil { + s.fsm.ipv6Unicast.dispose() + } } func (s *establishedState) manualStop() (state, string) { @@ -184,9 +195,13 @@ func (s *establishedState) update(msg *packet.BGPMessage) (state, string) { switch afi { case packet.IPv4AFI: - s.fsm.ipv4Unicast.processUpdate(u) + if s.fsm.ipv4Unicast != nil { + s.fsm.ipv4Unicast.processUpdate(u) + } case packet.IPv6AFI: - s.fsm.ipv6Unicast.processUpdate(u) + if s.fsm.ipv6Unicast != nil { + s.fsm.ipv6Unicast.processUpdate(u) + } } return newEstablishedState(s.fsm), s.fsm.reason @@ -197,10 +212,7 @@ func (s *establishedState) addressFamilyForUpdate(u *packet.BGPUpdate) (afi uint return packet.IPv4AFI, packet.UnicastSAFI } - cur := u.PathAttributes - for cur != nil { - cur = cur.Next - + for cur := u.PathAttributes; cur != nil; cur = cur.Next { if cur.TypeCode == packet.MultiProtocolReachNLRICode { a := cur.Value.(packet.MultiProtocolReachNLRI) return a.AFI, a.SAFI diff --git a/protocols/bgp/server/fsm_test.go b/protocols/bgp/server/fsm_test.go index e39d3d6ae3ef69edc680910deaad13171d7d293b..15249537ac5b12e72c32cef04cb30c1b30b8185b 100644 --- a/protocols/bgp/server/fsm_test.go +++ b/protocols/bgp/server/fsm_test.go @@ -16,11 +16,13 @@ import ( // TestFSM100Updates emulates receiving 100 BGP updates and withdraws. Checks route counts. func TestFSM100Updates(t *testing.T) { fsmA := newFSM2(&peer{ - addr: bnet.IPv4FromOctets(169, 254, 100, 100), - rib: locRIB.New(), - importFilter: filter.NewAcceptAllFilter(), - exportFilter: filter.NewAcceptAllFilter(), - routerID: bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), + addr: bnet.IPv4FromOctets(169, 254, 100, 100), + routerID: bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), + ipv4: &familyParameters{ + rib: locRIB.New(), + importFilter: filter.NewAcceptAllFilter(), + exportFilter: filter.NewAcceptAllFilter(), + }, }) fsmA.holdTimer = time.NewTimer(time.Second * 90) diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go index 02cf053bf000c5d1dd232c2243b7b617062a8fcf..4f101d815a7789a26564b6d37527026746404e5e 100644 --- a/protocols/bgp/server/peer.go +++ b/protocols/bgp/server/peer.go @@ -28,7 +28,6 @@ type peer struct { fsms []*FSM fsmsMu sync.Mutex - rib *locRIB.LocRIB routerID uint32 addPathSend routingtable.ClientOptions addPathRecv bool @@ -36,11 +35,18 @@ type peer struct { keepaliveTime time.Duration holdTime time.Duration optOpenParams []packet.OptParam - importFilter *filter.Filter - exportFilter *filter.Filter routeServerClient bool routeReflectorClient bool clusterID uint32 + + ipv4 *familyParameters + ipv6 *familyParameters +} + +type familyParameters struct { + rib *locRIB.LocRIB + importFilter *filter.Filter + exportFilter *filter.Filter } func (p *peer) snapshot() PeerInfo { @@ -103,37 +109,41 @@ func isEstablishedState(s state) bool { // NewPeer creates a new peer with the given config. If an connection is established, the adjRIBIN of the peer is connected // to the given rib. To actually connect the peer, call Start() on the returned peer. -func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error) { +func newPeer(c config.Peer, server *bgpServer) (*peer, error) { if c.LocalAS == 0 { c.LocalAS = server.localASN } + p := &peer{ server: server, addr: c.PeerAddress, peerASN: c.PeerAS, localASN: c.LocalAS, fsms: make([]*FSM, 0), - rib: rib, addPathSend: c.AddPathSend, addPathRecv: c.AddPathRecv, reconnectInterval: c.ReconnectInterval, keepaliveTime: c.KeepAlive, holdTime: c.HoldTime, optOpenParams: make([]packet.OptParam, 0), - importFilter: filterOrDefault(c.ImportFilter), - exportFilter: filterOrDefault(c.ExportFilter), routeServerClient: c.RouteServerClient, routeReflectorClient: c.RouteReflectorClient, clusterID: c.RouteReflectorClusterID, } + if c.IPv4 != nil { + p.ipv4 = &familyParameters{ + rib: c.IPv4.RIB, + importFilter: filterOrDefault(c.IPv4.ImportFilter), + exportFilter: filterOrDefault(c.IPv4.ExportFilter), + } + } + // If we are a route reflector and no ClusterID was set, use our RouterID if p.routeReflectorClient && p.clusterID == 0 { p.clusterID = c.RouterID } - p.fsms = append(p.fsms, NewActiveFSM2(p)) - caps := make(packet.Capabilities, 0) addPathEnabled, addPathCap := handleAddPathCapability(c) @@ -143,7 +153,12 @@ func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error caps = append(caps, asn4Capability(c)) - if c.IPv6 { + if c.IPv6 != nil { + p.ipv6 = &familyParameters{ + rib: c.IPv6.RIB, + importFilter: filterOrDefault(c.IPv6.ImportFilter), + exportFilter: filterOrDefault(c.IPv6.ExportFilter), + } caps = append(caps, multiProtocolCapability(packet.IPv6AFI)) } @@ -152,6 +167,8 @@ func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error Value: caps, }) + p.fsms = append(p.fsms, NewActiveFSM2(p)) + return p, nil } diff --git a/protocols/bgp/server/server.go b/protocols/bgp/server/server.go index db6ae24f310cf027114e5e95aee7fee3211aac8b..1bccb7b64e617223a8445346630f016e8aa764ab 100644 --- a/protocols/bgp/server/server.go +++ b/protocols/bgp/server/server.go @@ -9,7 +9,6 @@ import ( "github.com/bio-routing/bio-rd/config" "github.com/bio-routing/bio-rd/protocols/bgp/packet" - "github.com/bio-routing/bio-rd/routingtable/locRIB" log "github.com/sirupsen/logrus" ) @@ -28,7 +27,7 @@ type bgpServer struct { type BGPServer interface { RouterID() uint32 Start(*config.Global) error - AddPeer(config.Peer, *locRIB.LocRIB) error + AddPeer(config.Peer) error GetPeerInfoAll() map[string]PeerInfo } @@ -112,8 +111,8 @@ func (b *bgpServer) incomingConnectionWorker() { } } -func (b *bgpServer) AddPeer(c config.Peer, rib *locRIB.LocRIB) error { - peer, err := newPeer(c, rib, b) +func (b *bgpServer) AddPeer(c config.Peer) error { + peer, err := newPeer(c, b) if err != nil { return err } diff --git a/protocols/bgp/server/server_test.go b/protocols/bgp/server/server_test.go index fffe879ce078deaa77a6a795d357f64ef74e3796..896c3201b01799c3317a5f1e4e1ad1eed194f2bd 100644 --- a/protocols/bgp/server/server_test.go +++ b/protocols/bgp/server/server_test.go @@ -41,10 +41,13 @@ func TestBgpServerPeerSnapshot(t *testing.T) { AddPathSend: routingtable.ClientOptions{ MaxPaths: 10, }, - ImportFilter: filter.NewDrainFilter(), - ExportFilter: filter.NewAcceptAllFilter(), + IPv4: &config.AddressFamilyConfig{ + RIB: rib, + ImportFilter: filter.NewDrainFilter(), + ExportFilter: filter.NewAcceptAllFilter(), + }, } - s.AddPeer(pc, rib) + s.AddPeer(pc) info = s.GetPeerInfoAll() if want, got := 1, len(info); want != got { diff --git a/protocols/bgp/server/update_sender_test.go b/protocols/bgp/server/update_sender_test.go index 646bf5d09829b5fcfe699a5e64f946b12d2df929..19e9a99c94add48259f0de37cbbf9330f7c926dc 100644 --- a/protocols/bgp/server/update_sender_test.go +++ b/protocols/bgp/server/update_sender_test.go @@ -868,12 +868,25 @@ func TestSender(t *testing.T) { for _, test := range tests { fsmA := newFSM2(&peer{ - addr: bnet.IPv4FromOctets(169, 254, 100, 100), - rib: locRIB.New(), - importFilter: filter.NewAcceptAllFilter(), - exportFilter: filter.NewAcceptAllFilter(), + addr: bnet.IPv4FromOctets(169, 254, 100, 100), }) + rib := locRIB.New() + if test.afi == packet.IPv6AFI { + fsmA.options.SupportsMultiProtocol = true + fsmA.ipv6Unicast = newFamilyRouting(packet.IPv6AFI, packet.UnicastSAFI, &familyParameters{ + rib: rib, + importFilter: filter.NewAcceptAllFilter(), + exportFilter: filter.NewAcceptAllFilter(), + }, fsmA) + } else { + fsmA.ipv4Unicast = newFamilyRouting(packet.IPv4AFI, packet.UnicastSAFI, &familyParameters{ + rib: rib, + importFilter: filter.NewAcceptAllFilter(), + exportFilter: filter.NewAcceptAllFilter(), + }, fsmA) + } + fsmA.holdTimer = time.NewTimer(time.Second * 90) fsmA.keepaliveTimer = time.NewTimer(time.Second * 30) fsmA.connectRetryTimer = time.NewTimer(time.Second * 120) @@ -886,10 +899,6 @@ func TestSender(t *testing.T) { } } - if test.afi == packet.IPv6AFI { - fsmA.options.SupportsMultiProtocol = true - } - updateSender := newUpdateSender(fsmA, test.afi, packet.UnicastSAFI) for _, pathPfx := range test.paths {