summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMagesh GV <mageshgv@gmail.com>2019-09-30 10:36:54 -0700
committerFUJITA Tomonori <fujita.tomonori@gmail.com>2019-10-02 20:45:44 +0900
commit6f3cb401644fcba0353ac06de261dd40100daa84 (patch)
tree0602d523c17bccf5ebf5ee15eb8c5c07bd19d39a
parent93beafeec5ec667602afe506f2692db81344d5a7 (diff)
Update adjrib for LLGR and preserve aslooped attr
Fixes LLGR community cleared on softreset. Fixes AS Path looped routes added back to rib on Graceful Restart.
-rw-r--r--internal/pkg/table/adj.go30
-rw-r--r--internal/pkg/table/adj_test.go47
-rw-r--r--internal/pkg/table/path.go9
-rw-r--r--pkg/server/peer.go18
-rw-r--r--test/scenario_test/long_lived_graceful_restart_test.py51
5 files changed, 128 insertions, 27 deletions
diff --git a/internal/pkg/table/adj.go b/internal/pkg/table/adj.go
index 4b9d7c5f..d63537f8 100644
--- a/internal/pkg/table/adj.go
+++ b/internal/pkg/table/adj.go
@@ -173,11 +173,39 @@ func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path {
for i, p := range d.knownPathList {
n := p.Clone(false)
n.MarkStale(true)
+ n.SetAsLooped(p.IsAsLooped())
d.knownPathList[i] = n
- pathList = append(pathList, n)
+ if !n.IsAsLooped() {
+ pathList = append(pathList, n)
+ }
+ }
+ return false
+ })
+ return pathList
+}
+
+func (adj *AdjRib) MarkLLGRStaleOrDrop(rfList []bgp.RouteFamily) []*Path {
+ pathList := make([]*Path, 0, adj.Count(rfList))
+ adj.walk(rfList, func(d *Destination) bool {
+ for i, p := range d.knownPathList {
+ if p.HasNoLLGR() {
+ n := p.Clone(true)
+ n.SetDropped(true)
+ pathList = append(pathList, n)
+ } else {
+ n := p.Clone(false)
+ n.SetAsLooped(p.IsAsLooped())
+ n.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false)
+ if p.IsAsLooped() {
+ d.knownPathList[i] = n
+ } else {
+ pathList = append(pathList, n)
+ }
+ }
}
return false
})
+ adj.Update(pathList)
return pathList
}
diff --git a/internal/pkg/table/adj_test.go b/internal/pkg/table/adj_test.go
index 8513bc97..9e48538f 100644
--- a/internal/pkg/table/adj_test.go
+++ b/internal/pkg/table/adj_test.go
@@ -69,14 +69,19 @@ func TestStale(t *testing.T) {
p1 := NewPath(pi, nlri1, false, attrs, time.Now(), false)
nlri2 := bgp.NewIPAddrPrefix(24, "20.20.20.0")
p2 := NewPath(pi, nlri2, false, attrs, time.Now(), false)
+ p2.SetAsLooped(true)
+
family := p1.GetRouteFamily()
families := []bgp.RouteFamily{family}
adj := NewAdjRib(families)
adj.Update([]*Path{p1, p2})
assert.Equal(t, adj.Count([]bgp.RouteFamily{family}), 2)
+ assert.Equal(t, adj.Accepted([]bgp.RouteFamily{family}), 1)
- adj.StaleAll(families)
+ stalePathList := adj.StaleAll(families)
+ // As looped path should not be returned
+ assert.Equal(t, 1, len(stalePathList))
for _, p := range adj.PathList([]bgp.RouteFamily{family}, false) {
assert.True(t, p.IsStale())
@@ -86,7 +91,45 @@ func TestStale(t *testing.T) {
p3 := NewPath(pi, nlri3, false, attrs, time.Now(), false)
adj.Update([]*Path{p1, p3})
- adj.DropStale(families)
+ droppedPathList := adj.DropStale(families)
+ assert.Equal(t, 2, len(droppedPathList))
assert.Equal(t, adj.Count([]bgp.RouteFamily{family}), 1)
assert.Equal(t, 1, len(adj.table[family].destinations))
}
+
+func TestLLGRStale(t *testing.T) {
+ pi := &PeerInfo{}
+ attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeOrigin(0)}
+
+ nlri1 := bgp.NewIPAddrPrefix(24, "20.20.10.0")
+ p1 := NewPath(pi, nlri1, false, attrs, time.Now(), false)
+
+ nlri2 := bgp.NewIPAddrPrefix(24, "20.20.20.0")
+ p2 := NewPath(pi, nlri2, false, attrs, time.Now(), false)
+ p2.SetAsLooped(true) // Not accepted
+
+ nlri3 := bgp.NewIPAddrPrefix(24, "20.20.30.0")
+ p3 := NewPath(pi, nlri3, false, attrs, time.Now(), false)
+ p3.SetAsLooped(true)
+ // Not accepted and then dropped on MarkLLGRStaleOrDrop
+ p3.SetCommunities([]uint32{uint32(bgp.COMMUNITY_NO_LLGR)}, false)
+
+ nlri4 := bgp.NewIPAddrPrefix(24, "20.20.40.0")
+ p4 := NewPath(pi, nlri4, false, attrs, time.Now(), false)
+ // dropped on MarkLLGRStaleOrDrop
+ p4.SetCommunities([]uint32{uint32(bgp.COMMUNITY_NO_LLGR)}, false)
+
+ family := p1.GetRouteFamily()
+ families := []bgp.RouteFamily{family}
+
+ adj := NewAdjRib(families)
+ adj.Update([]*Path{p1, p2, p3, p4})
+ assert.Equal(t, adj.Count([]bgp.RouteFamily{family}), 4)
+ assert.Equal(t, adj.Accepted([]bgp.RouteFamily{family}), 2)
+
+ pathList := adj.MarkLLGRStaleOrDrop(families)
+ assert.Equal(t, 3, len(pathList)) // Does not return aslooped path that is retained in adjrib
+ assert.Equal(t, adj.Count([]bgp.RouteFamily{family}), 2)
+ assert.Equal(t, adj.Accepted([]bgp.RouteFamily{family}), 1)
+ assert.Equal(t, 2, len(adj.table[family].destinations))
+}
diff --git a/internal/pkg/table/path.go b/internal/pkg/table/path.go
index 32616d2e..9f68fde3 100644
--- a/internal/pkg/table/path.go
+++ b/internal/pkg/table/path.go
@@ -398,6 +398,15 @@ func (path *Path) SetDropped(y bool) {
path.dropped = y
}
+func (path *Path) HasNoLLGR() bool {
+ for _, c := range path.GetCommunities() {
+ if c == uint32(bgp.COMMUNITY_NO_LLGR) {
+ return true
+ }
+ }
+ return false
+}
+
func (path *Path) IsLLGRStale() bool {
for _, c := range path.GetCommunities() {
if c == uint32(bgp.COMMUNITY_LLGR_STALE) {
diff --git a/pkg/server/peer.go b/pkg/server/peer.go
index 7d85ec52..a7843f49 100644
--- a/pkg/server/peer.go
+++ b/pkg/server/peer.go
@@ -333,23 +333,7 @@ func (peer *peer) llgrRestartTimerExpired(family bgp.RouteFamily) bool {
}
func (peer *peer) markLLGRStale(fs []bgp.RouteFamily) []*table.Path {
- paths := peer.adjRibIn.PathList(fs, true)
- for i, p := range paths {
- doStale := true
- for _, c := range p.GetCommunities() {
- if c == uint32(bgp.COMMUNITY_NO_LLGR) {
- doStale = false
- p = p.Clone(true)
- break
- }
- }
- if doStale {
- p = p.Clone(false)
- p.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false)
- }
- paths[i] = p
- }
- return paths
+ return peer.adjRibIn.MarkLLGRStaleOrDrop(fs)
}
func (peer *peer) stopPeerRestarting() {
diff --git a/test/scenario_test/long_lived_graceful_restart_test.py b/test/scenario_test/long_lived_graceful_restart_test.py
index 0ea38ff1..1fb5edac 100644
--- a/test/scenario_test/long_lived_graceful_restart_test.py
+++ b/test/scenario_test/long_lived_graceful_restart_test.py
@@ -95,6 +95,11 @@ class GoBGPTestBase(unittest.TestCase):
time.sleep(1)
self.assertEqual(len(g1.get_global_rib('10.0.0.0/24')), 1)
+ # check llgr-stale community is added to 10.0.0.0/24
+ r = g1.get_global_rib('10.0.0.0/24')[0]['paths'][0]
+ comms = list(chain.from_iterable([attr['communities'] for attr in r['attrs'] if attr['type'] == 8]))
+ self.assertTrue(0xffff0006 in comms)
+
# 10.10.0.0/24 is announced with no-llgr community
# must not exist in the rib
self.assertEqual(len(g1.get_global_rib('10.10.0.0/24')), 0)
@@ -102,24 +107,56 @@ class GoBGPTestBase(unittest.TestCase):
for p in d['paths']:
self.assertTrue(p['stale'])
+ # check llgr-stale community is present in received route 10.0.0.0/24
self.assertEqual(len(g3.get_global_rib('10.0.0.0/24')), 1)
- # check llgr-stale community is added to 10.0.0.0/24
r = g3.get_global_rib('10.0.0.0/24')[0]['paths'][0]
comms = list(chain.from_iterable([attr['communities'] for attr in r['attrs'] if attr['type'] == 8]))
self.assertTrue(0xffff0006 in comms)
+
# g4 is not llgr capable, llgr-stale route must be
# withdrawn
self.assertEqual(len(g4.get_global_rib('10.0.0.0/24')), 0)
- g2.start_gobgp(graceful_restart=True)
- g2.local('gobgp global rib add 10.0.0.0/24')
- g2.local('gobgp global rib add 10.10.0.0/24')
+ def test_03_softreset_preserves_llgr_community(self):
+ g1 = self.bgpds['g1']
+ g2 = self.bgpds['g2']
+ g3 = self.bgpds['g3']
+ g4 = self.bgpds['g4']
- def test_03_neighbor_established(self):
+ g1.softreset(g2)
+ time.sleep(1)
+
+ # 10.10.0.0/24 received with no-llgr community is not reinstalled to rib
+ self.assertEqual(len(g1.get_global_rib('10.10.0.0/24')), 0)
+ # Stale flags are not cleared
+ for d in g1.get_global_rib():
+ for p in d['paths']:
+ self.assertTrue(p['stale'])
+
+ # check llgr-stale community is not cleared from 10.0.0.0/24
+ r = g1.get_global_rib('10.0.0.0/24')[0]['paths'][0]
+ comms = list(chain.from_iterable([attr['communities'] for attr in r['attrs'] if attr['type'] == 8]))
+ self.assertTrue(0xffff0006 in comms)
+
+ # check llgr-stale community is not cleared in route 10.0.0.0/24 on g3
+ self.assertEqual(len(g3.get_global_rib('10.0.0.0/24')), 1)
+ r = g3.get_global_rib('10.0.0.0/24')[0]['paths'][0]
+ comms = list(chain.from_iterable([attr['communities'] for attr in r['attrs'] if attr['type'] == 8]))
+ self.assertTrue(0xffff0006 in comms)
+
+ # g4 is not llgr capable, llgr-stale route must not be advertized on softreset g1
+ self.assertEqual(len(g4.get_global_rib('10.0.0.0/24')), 0)
+
+ def test_04_neighbor_established(self):
g1 = self.bgpds['g1']
g2 = self.bgpds['g2']
# g3 = self.bgpds['g3']
# g4 = self.bgpds['g4']
+
+ g2.start_gobgp(graceful_restart=True)
+ g2.local('gobgp global rib add 10.0.0.0/24')
+ g2.local('gobgp global rib add 10.10.0.0/24')
+
g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g2)
time.sleep(1)
self.assertEqual(len(g1.get_global_rib('10.0.0.0/24')), 1)
@@ -128,7 +165,7 @@ class GoBGPTestBase(unittest.TestCase):
for p in d['paths']:
self.assertFalse(p.get('stale', False))
- def test_04_llgr_stale_route_depreferenced(self):
+ def test_05_llgr_stale_route_depreferenced(self):
g1 = self.bgpds['g1']
g2 = self.bgpds['g2']
g3 = self.bgpds['g3']
@@ -156,7 +193,7 @@ class GoBGPTestBase(unittest.TestCase):
self.assertEqual(len(rib), 1)
self.assertTrue(g2.asn in rib[0]['paths'][0]['aspath'])
- def test_05_llgr_restart_timer_expire(self):
+ def test_06_llgr_restart_timer_expire(self):
time.sleep(LONG_LIVED_GRACEFUL_RESTART_TIME + 5)
g3 = self.bgpds['g3']
rib = g3.get_global_rib('10.10.0.0/24')