diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index 7224d4e1047e28c5ab6b1999db01b9dcbd2d5e4d..644dde8f1e633465dbb73b4c9decf69a8fc7835a 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -59,7 +59,7 @@ func (s establishedState) run() (state, string) { func (s *establishedState) init() error { contributingASNs := s.fsm.rib.GetContributingASNs() - s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter, contributingASNs) + s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter, contributingASNs, s.fsm.peer.routerID, s.fsm.peer.clusterID) contributingASNs.Add(s.fsm.peer.localASN) s.fsm.adjRIBIn.Register(s.fsm.rib) diff --git a/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/adjRIBIn/adj_rib_in.go index bf3bab1c8a4aa14d4f969429e4c10eae0aa74731..48fc105ea3ae18047c417ecc47c612da9be159d5 100644 --- a/routingtable/adjRIBIn/adj_rib_in.go +++ b/routingtable/adjRIBIn/adj_rib_in.go @@ -18,14 +18,18 @@ type AdjRIBIn struct { mu sync.RWMutex exportFilter *filter.Filter contributingASNs *routingtable.ContributingASNs + routerID uint32 + clusterID uint32 } // New creates a new Adjacency RIB In -func New(exportFilter *filter.Filter, contributingASNs *routingtable.ContributingASNs) *AdjRIBIn { +func New(exportFilter *filter.Filter, contributingASNs *routingtable.ContributingASNs, routerID uint32, clusterID uint32) *AdjRIBIn { a := &AdjRIBIn{ rt: routingtable.NewRoutingTable(), exportFilter: exportFilter, contributingASNs: contributingASNs, + routerID: routerID, + clusterID: clusterID, } a.ClientManager = routingtable.NewClientManager(a) return a @@ -64,6 +68,20 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error { a.mu.Lock() defer a.mu.Unlock() + // RFC4456 Sect. 8: Ignore route with our RouterID as OriginatorID + if p.BGPPath.OriginatorID == 1 { + return nil + } + + // RFC4456 Sect. 8: Ignore routes which contian our ClusterID in their ClusterList + if len(p.BGPPath.ClusterList) > 0 { + for _, cid := range p.BGPPath.ClusterList { + if cid == a.clusterID { + return nil + } + } + } + oldPaths := a.rt.ReplacePath(pfx, p) a.removePathsFromClients(pfx, oldPaths) diff --git a/routingtable/adjRIBIn/adj_rib_in_test.go b/routingtable/adjRIBIn/adj_rib_in_test.go index 0fb052db2a5e34f26eb2132cf86cd03632f420c7..a3a9cb5f5affcceda905ff362471980564e895d2 100644 --- a/routingtable/adjRIBIn/adj_rib_in_test.go +++ b/routingtable/adjRIBIn/adj_rib_in_test.go @@ -12,6 +12,9 @@ import ( ) func TestAddPath(t *testing.T) { + routerID := net.IPv4FromOctets(1, 1, 1, 1).ToUint32() + clusterID := net.IPv4FromOctets(2, 2, 2, 2).ToUint32() + tests := []struct { name string routes []*route.Route @@ -72,10 +75,39 @@ func TestAddPath(t *testing.T) { }), }, }, + { + name: "Add route with our RouterID as OriginatorID", + routes: []*route.Route{ + route.NewRoute(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 32), &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + LocalPref: 111, + OriginatorID: 1, + }, + }), + }, + expected: []*route.Route{}, + }, + { + name: "Add route with our ClusterID within ClusterList", + routes: []*route.Route{ + route.NewRoute(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 32), &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + LocalPref: 222, + OriginatorID: 23, + ClusterList: []uint32{ + clusterID, + }, + }, + }), + }, + expected: []*route.Route{}, + }, } for _, test := range tests { - adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs()) + adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs(), routerID, clusterID) mc := routingtable.NewRTMockClient() adjRIBIn.ClientManager.Register(mc) @@ -83,12 +115,14 @@ func TestAddPath(t *testing.T) { adjRIBIn.AddPath(route.Prefix(), route.Paths()[0]) } - removePathParams := mc.GetRemovePathParams() - if removePathParams.Pfx != test.removePfx { - t.Errorf("Test %q failed: Call to RemovePath did not propagate prefix properly: Got: %s Want: %s", test.name, removePathParams.Pfx.String(), test.removePfx.String()) - } + if test.removePath != nil { + removePathParams := mc.GetRemovePathParams() + if removePathParams.Pfx != test.removePfx { + t.Errorf("Test %q failed: Call to RemovePath did not propagate prefix properly: Got: %s Want: %s", test.name, removePathParams.Pfx.String(), test.removePfx.String()) + } - assert.Equal(t, test.removePath, removePathParams.Path) + assert.Equal(t, test.removePath, removePathParams.Path) + } assert.Equal(t, test.expected, adjRIBIn.rt.Dump()) } } @@ -167,7 +201,7 @@ func TestRemovePath(t *testing.T) { } for _, test := range tests { - adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs()) + adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs(), 1, 2) for _, route := range test.routes { adjRIBIn.AddPath(route.Prefix(), route.Paths()[0]) }