From 10fbe25d94169678a31f9e6b450e204c45e7994f Mon Sep 17 00:00:00 2001
From: Maximilian Wilhelm <max@sdn.clinic>
Date: Wed, 4 Jul 2018 16:18:45 +0200
Subject: [PATCH] Propagate RouterID and ClusterID to AdjRIBIn, verify received
 routes accordingly and add tests.

Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
---
 protocols/bgp/server/fsm_established.go  |  2 +-
 routingtable/adjRIBIn/adj_rib_in.go      | 20 +++++++++-
 routingtable/adjRIBIn/adj_rib_in_test.go | 48 ++++++++++++++++++++----
 3 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index 7224d4e1..644dde8f 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 bf3bab1c..48fc105e 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 0fb052db..a3a9cb5f 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])
 		}
-- 
GitLab