summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/server.go2
-rw-r--r--table/path.go25
-rw-r--r--test/scenario_test/bgp_router_test.py60
-rw-r--r--test/scenario_test/lib/base.py18
-rw-r--r--test/scenario_test/lib/gobgp.py30
5 files changed, 105 insertions, 30 deletions
diff --git a/server/server.go b/server/server.go
index 683fcc6d..57f7c7ee 100644
--- a/server/server.go
+++ b/server/server.go
@@ -675,8 +675,6 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
pattr := make([]bgp.PathAttributeInterface, 0)
pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP))
- asparam := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{peerInfo.AS})
- pattr = append(pattr, bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{asparam}))
rf := grpcReq.RouteFamily
path, ok := grpcReq.Data.(*api.Path)
diff --git a/table/path.go b/table/path.go
index 51be91af..bd368ec6 100644
--- a/table/path.go
+++ b/table/path.go
@@ -102,18 +102,21 @@ func (path *Path) UpdatePathAttrs(global *config.Global, peer *config.Neighbor)
// segment, and places that segment into the AS_PATH.
idx, originalAsPath := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
if idx < 0 {
- log.Fatal("missing AS_PATH mandatory attribute")
- }
- asPath := cloneAsPath(originalAsPath.(*bgp.PathAttributeAsPath))
- path.pathAttrs[idx] = asPath
- fst := asPath.Value[0].(*bgp.As4PathParam)
- if len(asPath.Value) > 0 && fst.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ &&
- fst.ASLen() < 255 {
- fst.AS = append([]uint32{global.As}, fst.AS...)
- fst.Num += 1
- } else {
p := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{global.As})
- asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...)
+ asPath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{p})
+ path.pathAttrs = append(path.pathAttrs, asPath)
+ } else {
+ asPath := cloneAsPath(originalAsPath.(*bgp.PathAttributeAsPath))
+ path.pathAttrs[idx] = asPath
+ fst := asPath.Value[0].(*bgp.As4PathParam)
+ if len(asPath.Value) > 0 && fst.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ &&
+ fst.ASLen() < 255 {
+ fst.AS = append([]uint32{global.As}, fst.AS...)
+ fst.Num += 1
+ } else {
+ p := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{global.As})
+ asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...)
+ }
}
// MED Handling
diff --git a/test/scenario_test/bgp_router_test.py b/test/scenario_test/bgp_router_test.py
index 3bd5a82c..8b17e380 100644
--- a/test/scenario_test/bgp_router_test.py
+++ b/test/scenario_test/bgp_router_test.py
@@ -116,14 +116,11 @@ class GoBGPTestBase(unittest.TestCase):
def test_03_check_gobgp_adj_out_rib(self):
for q in self.quaggas.itervalues():
for path in self.gobgp.get_adj_rib_out(q):
- asps = (p['as_paths'] for p in path['attrs'] if p['type'] == BGP_ATTR_TYPE_AS_PATH)
- asps = chain.from_iterable(asps)
- asns = (asp['asns'] for asp in asps)
- asns = chain.from_iterable(asns)
+ asns = self.gobgp._get_as_path(path)
self.assertTrue(self.gobgp.asn in asns)
# check routes are properly advertised to all BGP speaker
- def test_03_check_quagga_global_rib(self):
+ def test_04_check_quagga_global_rib(self):
for q in self.quaggas.itervalues():
done = False
for _ in range(self.retry_limit):
@@ -146,7 +143,7 @@ class GoBGPTestBase(unittest.TestCase):
# should not reach here
self.assertTrue(False)
- def test_04_add_quagga(self):
+ def test_05_add_quagga(self):
q4 = QuaggaBGPContainer(name='q4', asn=65004, router_id='192.168.0.5')
self.quaggas['q4'] = q4
@@ -160,22 +157,22 @@ class GoBGPTestBase(unittest.TestCase):
self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q4)
- def test_05_check_global_rib(self):
+ def test_06_check_global_rib(self):
self.test_02_check_gobgp_global_rib()
- self.test_03_check_quagga_global_rib()
+ self.test_04_check_quagga_global_rib()
- def test_06_stop_one_quagga(self):
+ def test_07_stop_one_quagga(self):
q4 = self.quaggas['q4']
q4.stop()
self.gobgp.wait_for(expected_state=BGP_FSM_ACTIVE, peer=q4)
del self.quaggas['q4']
# check gobgp properly send withdrawal message with q4's route
- def test_07_check_global_rib(self):
+ def test_08_check_global_rib(self):
self.test_02_check_gobgp_global_rib()
- self.test_03_check_quagga_global_rib()
+ self.test_04_check_quagga_global_rib()
- def test_08_add_distant_relative(self):
+ def test_09_add_distant_relative(self):
q1 = self.quaggas['q1']
q2 = self.quaggas['q2']
q3 = self.quaggas['q3']
@@ -232,6 +229,45 @@ class GoBGPTestBase(unittest.TestCase):
if not done:
self.assertTrue(False)
+ def test_10_originate_path(self):
+ self.gobgp.add_route('10.10.0.0/24')
+ dst = self.gobgp.get_global_rib('10.10.0.0/24')
+ self.assertTrue(len(dst) == 1)
+ self.assertTrue(len(dst[0]['paths']) == 1)
+ path = dst[0]['paths'][0]
+ self.assertTrue(path['nexthop'] == '0.0.0.0')
+ self.assertTrue(len(self.gobgp._get_as_path(path)) == 0)
+
+ def test_11_check_adj_rib_out(self):
+ for q in self.quaggas.itervalues():
+ paths = self.gobgp.get_adj_rib_out(q, '10.10.0.0/24')
+ self.assertTrue(len(paths) == 1)
+ path = paths[0]
+ peer_info = self.gobgp.peers[q]
+ local_addr = peer_info['local_addr'].split('/')[0]
+ self.assertTrue(path['nexthop'] == local_addr)
+ self.assertTrue(self.gobgp._get_as_path(path) == [self.gobgp.asn])
+
+ def test_12_disable_peer(self):
+ q1 = self.quaggas['q1']
+ self.gobgp.disable_peer(q1)
+ self.gobgp.wait_for(expected_state=BGP_FSM_IDLE, peer=q1)
+
+ for route in q1.routes.iterkeys():
+ dst = self.gobgp.get_global_rib(route)
+ self.assertTrue(len(dst) == 0)
+
+ for q in self.quaggas.itervalues():
+ paths = self.gobgp.get_adj_rib_out(q, route)
+ self.assertTrue(len(paths) == 0)
+
+ def test_13_enable_peer(self):
+ q1 = self.quaggas['q1']
+ self.gobgp.enable_peer(q1)
+ self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1)
+
+ def test_14_check_adj_rib_out(self):
+ self.test_11_check_adj_rib_out()
if __name__ == '__main__':
if os.geteuid() is not 0:
diff --git a/test/scenario_test/lib/base.py b/test/scenario_test/lib/base.py
index 119e188c..5dec078f 100644
--- a/test/scenario_test/lib/base.py
+++ b/test/scenario_test/lib/base.py
@@ -35,6 +35,7 @@ BGP_ATTR_TYPE_NEXT_HOP = 3
BGP_ATTR_TYPE_MULTI_EXIT_DISC = 4
BGP_ATTR_TYPE_LOCAL_PREF = 5
+
def get_bridges():
return local("brctl show | awk 'NR > 1{print $1}'",
capture=True).split('\n')
@@ -196,9 +197,11 @@ class BGPContainer(Container):
policies=None, passive=False,
is_rr_client=False, cluster_id=''):
neigh_addr = ''
+ local_addr = ''
for me, you in itertools.product(self.ip_addrs, peer.ip_addrs):
if me[2] == you[2]:
neigh_addr = you[1]
+ local_addr = me[1]
if neigh_addr == '':
raise Exception('peer {0} seems not ip reachable'.format(peer))
@@ -213,7 +216,8 @@ class BGPContainer(Container):
'is_rr_client': is_rr_client,
'cluster_id': cluster_id,
'policies': policies,
- 'passive': passive}
+ 'passive': passive,
+ 'local_addr': local_addr}
if self.is_running:
self.create_config()
self.reload_config()
@@ -224,8 +228,16 @@ class BGPContainer(Container):
self.create_config()
self.reload_config()
- def add_route(self, route, attribute=''):
- self.routes[route] = attribute
+ def disable_peer(self, peer):
+ raise Exception('implement disable_peer() method')
+
+ def enable_peer(self, peer):
+ raise Exception('implement enable_peer() method')
+
+ def add_route(self, route, rf='ipv4', attribute=''):
+ self.routes[route] = {'prefix': route,
+ 'rf': rf,
+ 'attr': attribute}
if self.is_running:
self.create_config()
self.reload_config()
diff --git a/test/scenario_test/lib/gobgp.py b/test/scenario_test/lib/gobgp.py
index 4e26b922..3b7ec5ba 100644
--- a/test/scenario_test/lib/gobgp.py
+++ b/test/scenario_test/lib/gobgp.py
@@ -18,6 +18,7 @@ import json
import toml
import subprocess
import select
+from itertools import chain
class GoBGPContainer(BGPContainer):
@@ -52,6 +53,28 @@ class GoBGPContainer(BGPContainer):
self._start_gobgp()
return self.WAIT_FOR_BOOT
+ def _get_as_path(self, path):
+ asps = (p['as_paths'] for p in path['attrs'] if
+ p['type'] == BGP_ATTR_TYPE_AS_PATH)
+ asps = chain.from_iterable(asps)
+ asns = (asp['asns'] for asp in asps)
+ return list(chain.from_iterable(asns))
+
+ def _trigger_peer_cmd(self, cmd, peer):
+ if peer not in self.peers:
+ raise Exception('not found peer {0}'.format(peer.router_id))
+ peer_addr = self.peers[peer]['neigh_addr'].split('/')[0]
+ cmd = "docker exec {0} gobgp neighbor {1} {2}".format(self.name,
+ peer_addr,
+ cmd)
+ local(str(cmd), capture=True)
+
+ def disable_peer(self, peer):
+ self._trigger_peer_cmd('disable', peer)
+
+ def enable_peer(self, peer):
+ self._trigger_peer_cmd('enable', peer)
+
def get_local_rib(self, peer, rf='ipv4'):
if peer not in self.peers:
raise Exception('not found peer {0}'.format(peer.router_id))
@@ -80,7 +103,7 @@ class GoBGPContainer(BGPContainer):
gobgp = '/go/bin/gobgp'
cmd = 'docker exec {0} {1} neighbor {2}'\
' adj-{3} {4} -a {5} -j'.format(self.name, gobgp, peer_addr,
- adj_type, prefix, rf)
+ adj_type, prefix, rf)
output = local(cmd, capture=True)
return json.loads(output)
@@ -135,7 +158,6 @@ class GoBGPContainer(BGPContainer):
continue
raise Exception('timeout')
-
def create_config(self):
config = {'Global': {'As': self.asn, 'RouterId': self.router_id}}
for peer, info in self.peers.iteritems():
@@ -188,3 +210,7 @@ class GoBGPContainer(BGPContainer):
def reload_config(self):
cmd = 'docker exec {0} /usr/bin/pkill gobgpd -SIGHUP'.format(self.name)
local(cmd, capture=True)
+ for v in self.routes.itervalues():
+ cmd = 'docker exec {0} gobgp global '\
+ 'rib add {1} -a {2}'.format(self.name, v['prefix'], v['rf'])
+ local(cmd, capture=True)