From a14508657ae6923d22a127aff5045805058b4e2a Mon Sep 17 00:00:00 2001 From: Daniel Czerwonk <daniel@dan-nrw.de> Date: Fri, 6 Jul 2018 22:38:58 +0200 Subject: [PATCH] allow multiple families per peer --- config/peer.go | 13 ++++++-- main_ipv4.go | 18 +++++++---- main_ipv6.go | 20 +++++++----- protocols/bgp/server/family_routing.go | 16 ++++++---- protocols/bgp/server/fsm.go | 10 ++++-- protocols/bgp/server/fsm_established.go | 32 +++++++++++++------ protocols/bgp/server/fsm_test.go | 12 ++++--- protocols/bgp/server/peer.go | 37 ++++++++++++++++------ protocols/bgp/server/server.go | 7 ++-- protocols/bgp/server/server_test.go | 9 ++++-- protocols/bgp/server/update_sender_test.go | 25 ++++++++++----- 11 files changed, 133 insertions(+), 66 deletions(-) diff --git a/config/peer.go b/config/peer.go index 12124c7c..02d31988 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 65293f07..0d3c5a7c 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 160007cc..2d4a2410 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 a5115480..64332ac6 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 05a83eec..521e5b98 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 78f7f194..f615b19a 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 e39d3d6a..15249537 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 02cf053b..4f101d81 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 db6ae24f..1bccb7b6 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 fffe879c..896c3201 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 646bf5d0..19e9a99c 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 { -- GitLab