summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/lib/quagga.py150
-rw-r--r--test/scenario_test/bgp_router_test.py20
-rw-r--r--test/scenario_test/ibgp_router_test.py25
-rw-r--r--test/scenario_test/route_reflector_test.py11
-rw-r--r--test/scenario_test/route_server_ipv4_v6_test.py17
-rw-r--r--test/scenario_test/route_server_test.py23
6 files changed, 177 insertions, 69 deletions
diff --git a/test/lib/quagga.py b/test/lib/quagga.py
index e657b439..0b5ecdd1 100644
--- a/test/lib/quagga.py
+++ b/test/lib/quagga.py
@@ -14,11 +14,11 @@
# limitations under the License.
from __future__ import absolute_import
+
import re
from fabric import colors
from fabric.utils import indent
-from itertools import chain
import netaddr
from lib.base import (
@@ -63,13 +63,16 @@ class QuaggaBGPContainer(BGPContainer):
daemons.append('zebra')
return daemons
- def _wait_for_boot(self):
- for daemon in self._get_enabled_daemons():
- def _f():
- ret = self.local("vtysh -d {0} -c 'show run' > /dev/null 2>&1; echo $?".format(daemon), capture=True)
- return ret == '0'
+ def _is_running(self):
+ def f(d):
+ return self.local(
+ 'vtysh -d {0} -c "show version"'
+ ' > /dev/null 2>&1; echo $?'.format(d), capture=True) == '0'
- wait_for_completion(_f)
+ return all([f(d) for d in self._get_enabled_daemons()])
+
+ def _wait_for_boot(self):
+ wait_for_completion(self._is_running)
def run(self):
super(QuaggaBGPContainer, self).run()
@@ -215,16 +218,6 @@ class QuaggaBGPContainer(BGPContainer):
c << 'neighbor {0} activate'.format(n_addr)
c << 'exit-address-family'
- for route in chain.from_iterable(self.routes.itervalues()):
- if route['rf'] == 'ipv4':
- c << 'network {0}'.format(route['prefix'])
- elif route['rf'] == 'ipv6':
- c << 'address-family ipv6 unicast'
- c << 'network {0}'.format(route['prefix'])
- c << 'exit-address-family'
- else:
- raise Exception('unsupported route faily: {0}'.format(route['rf']))
-
if self.zebra:
if version == 6:
c << 'address-family ipv6 unicast'
@@ -281,6 +274,129 @@ class QuaggaBGPContainer(BGPContainer):
self.local('pkill {0} -SIGHUP'.format(daemon), capture=True)
self._wait_for_boot()
+ def _vtysh_add_route_map(self, path):
+ supported_attributes = (
+ 'next-hop',
+ 'as-path',
+ 'community',
+ 'med',
+ 'local-pref',
+ 'extended-community',
+ )
+ if not any([path[k] for k in supported_attributes]):
+ return ''
+
+ c = CmdBuffer(' ')
+ route_map_name = 'RM-{0}'.format(path['prefix'])
+ c << "vtysh -c 'configure terminal'"
+ c << "-c 'route-map {0} permit 10'".format(route_map_name)
+ if path['next-hop']:
+ if path['rf'] == 'ipv4':
+ c << "-c 'set ip next-hop {0}'".format(path['next-hop'])
+ elif path['rf'] == 'ipv6':
+ c << "-c 'set ipv6 next-hop {0}'".format(path['next-hop'])
+ else:
+ raise ValueError('Unsupported address family: {0}'.format(path['rf']))
+ if path['as-path']:
+ as_path = ' '.join([str(n) for n in path['as-path']])
+ c << "-c 'set as-path prepend {0}'".format(as_path)
+ if path['community']:
+ comm = ' '.join(path['community'])
+ c << "-c 'set community {0}'".format(comm)
+ if path['med']:
+ c << "-c 'set metric {0}'".format(path['med'])
+ if path['local-pref']:
+ c << "-c 'set local-preference {0}'".format(path['local-pref'])
+ if path['extended-community']:
+ # Note: Currently only RT is supported.
+ extcomm = ' '.join(path['extended-community'])
+ c << "-c 'set extcommunity rt {0}'".format(extcomm)
+ self.local(str(c), capture=True)
+
+ return route_map_name
+
+ def add_route(self, route, rf='ipv4', attribute=None, aspath=None,
+ community=None, med=None, extendedcommunity=None,
+ nexthop=None, matchs=None, thens=None,
+ local_pref=None, identifier=None, reload_config=False):
+ if not self._is_running():
+ raise RuntimeError('Quagga/Zebra is not yet running')
+
+ if rf not in ('ipv4', 'ipv6'):
+ raise ValueError('Unsupported address family: {0}'.format(rf))
+
+ self.routes.setdefault(route, [])
+ path = {
+ 'prefix': route,
+ 'rf': rf,
+ 'next-hop': nexthop,
+ 'as-path': aspath,
+ 'community': community,
+ 'med': med,
+ 'local-pref': local_pref,
+ 'extended-community': extendedcommunity,
+ # Note: The following settings are not yet supported on this
+ # implementation.
+ 'attr': None,
+ 'identifier': None,
+ 'matchs': None,
+ 'thens': None,
+ }
+
+ # Prepare route-map before adding prefix
+ route_map_name = self._vtysh_add_route_map(path)
+ path['route_map'] = route_map_name
+
+ c = CmdBuffer(' ')
+ c << "vtysh -c 'configure terminal'"
+ c << "-c 'router bgp {0}'".format(self.asn)
+ if rf == 'ipv6':
+ c << "-c 'address-family ipv6'"
+ if route_map_name:
+ c << "-c 'network {0} route-map {1}'".format(route, route_map_name)
+ else:
+ c << "-c 'network {0}'".format(route)
+ self.local(str(c), capture=True)
+
+ self.routes[route].append(path)
+
+ def _vtysh_del_route_map(self, path):
+ route_map_name = path.get('route_map', '')
+ if not route_map_name:
+ return
+
+ c = CmdBuffer(' ')
+ c << "vtysh -c 'configure terminal'"
+ c << "-c 'no route-map {0}'".format(route_map_name)
+ self.local(str(c), capture=True)
+
+ def del_route(self, route, identifier=None, reload_config=False):
+ if not self._is_running():
+ raise RuntimeError('Quagga/Zebra is not yet running')
+
+ path = None
+ new_paths = []
+ for p in self.routes.get(route, []):
+ if p['identifier'] != identifier:
+ new_paths.append(p)
+ else:
+ path = p
+ if not path:
+ return
+
+ rf = path['rf']
+ c = CmdBuffer(' ')
+ c << "vtysh -c 'configure terminal'"
+ c << "-c 'router bgp {0}'".format(self.asn)
+ c << "-c 'address-family {0} unicast'".format(rf)
+ c << "-c 'no network {0}'".format(route)
+ self.local(str(c), capture=True)
+
+ # Delete route-map after deleting prefix
+ self._vtysh_del_route_map(path)
+
+ self.routes[route] = new_paths
+
class RawQuaggaBGPContainer(QuaggaBGPContainer):
def __init__(self, name, config, ctn_image_name='osrg/quagga', zebra=False):
diff --git a/test/scenario_test/bgp_router_test.py b/test/scenario_test/bgp_router_test.py
index 1a92a1b3..7d93ba53 100644
--- a/test/scenario_test/bgp_router_test.py
+++ b/test/scenario_test/bgp_router_test.py
@@ -59,21 +59,17 @@ class GoBGPTestBase(unittest.TestCase):
qs = [q1, q2, q3]
ctns = [g1, q1, q2, q3]
- # advertise a route from q1, q2, q3
- for idx, q in enumerate(qs):
- route = '10.0.{0}.0/24'.format(idx + 1)
- q.add_route(route)
-
initial_wait_time = max(ctn.run() for ctn in ctns)
-
time.sleep(initial_wait_time)
for q in qs:
- g1.add_peer(q, reload_config=False, passwd='passwd')
+ g1.add_peer(q, passwd='passwd')
q.add_peer(g1, passwd='passwd', passive=True)
- g1.create_config()
- g1.reload_config()
+ # advertise a route from q1, q2, q3
+ for idx, q in enumerate(qs):
+ route = '10.0.{0}.0/24'.format(idx + 1)
+ q.add_route(route)
cls.gobgp = g1
cls.quaggas = {'q1': q1, 'q2': q2, 'q3': q3}
@@ -145,14 +141,14 @@ class GoBGPTestBase(unittest.TestCase):
def test_05_add_quagga(self):
q4 = QuaggaBGPContainer(name='q4', asn=65004, router_id='192.168.0.5')
self.quaggas['q4'] = q4
-
- q4.add_route('10.0.4.0/24')
-
initial_wait_time = q4.run()
time.sleep(initial_wait_time)
+
self.gobgp.add_peer(q4)
q4.add_peer(self.gobgp)
+ q4.add_route('10.0.4.0/24')
+
self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q4)
def test_06_check_global_rib(self):
diff --git a/test/scenario_test/ibgp_router_test.py b/test/scenario_test/ibgp_router_test.py
index ed476122..59815e6e 100644
--- a/test/scenario_test/ibgp_router_test.py
+++ b/test/scenario_test/ibgp_router_test.py
@@ -51,13 +51,7 @@ class GoBGPTestBase(unittest.TestCase):
qs = [q1, q2]
ctns = [g1, q1, q2]
- # advertise a route from q1, q2
- for idx, c in enumerate(qs):
- route = '10.0.{0}.0/24'.format(idx + 1)
- c.add_route(route)
-
initial_wait_time = max(ctn.run() for ctn in ctns)
-
time.sleep(initial_wait_time)
# ibgp peer. loop topology
@@ -65,6 +59,11 @@ class GoBGPTestBase(unittest.TestCase):
a.add_peer(b)
b.add_peer(a)
+ # advertise a route from q1, q2
+ for idx, c in enumerate(qs):
+ route = '10.0.{0}.0/24'.format(idx + 1)
+ c.add_route(route)
+
cls.gobgp = g1
cls.quaggas = {'q1': q1, 'q2': q2}
@@ -163,14 +162,14 @@ class GoBGPTestBase(unittest.TestCase):
def test_07_add_ebgp_peer(self):
q3 = QuaggaBGPContainer(name='q3', asn=65001, router_id='192.168.0.4')
self.quaggas['q3'] = q3
-
- q3.add_route('10.0.3.0/24')
-
initial_wait_time = q3.run()
time.sleep(initial_wait_time)
+
self.gobgp.add_peer(q3)
q3.add_peer(self.gobgp)
+ q3.add_route('10.0.3.0/24')
+
self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q3)
def test_08_check_global_rib(self):
@@ -246,15 +245,15 @@ class GoBGPTestBase(unittest.TestCase):
def test_15_add_ebgp_peer(self):
q4 = QuaggaBGPContainer(name='q4', asn=65001, router_id='192.168.0.5')
self.quaggas['q4'] = q4
-
- prefix = '10.0.4.0/24'
- q4.add_route(prefix)
-
initial_wait_time = q4.run()
time.sleep(initial_wait_time)
+
self.gobgp.add_peer(q4)
q4.add_peer(self.gobgp)
+ prefix = '10.0.4.0/24'
+ q4.add_route(prefix)
+
self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q4)
q1 = self.quaggas['q1']
diff --git a/test/scenario_test/route_reflector_test.py b/test/scenario_test/route_reflector_test.py
index a5516dec..29846d53 100644
--- a/test/scenario_test/route_reflector_test.py
+++ b/test/scenario_test/route_reflector_test.py
@@ -61,13 +61,7 @@ class GoBGPTestBase(unittest.TestCase):
qs = [q1, q2, q3, q4]
ctns = [g1, q1, q2, q3, q4]
- # advertise a route from q1, q2
- for idx, c in enumerate(qs):
- route = '10.0.{0}.0/24'.format(idx + 1)
- c.add_route(route)
-
initial_wait_time = max(ctn.run() for ctn in ctns)
-
time.sleep(initial_wait_time)
# g1 as a route reflector
@@ -80,6 +74,11 @@ class GoBGPTestBase(unittest.TestCase):
g1.add_peer(q4)
q4.add_peer(g1)
+ # advertise a route from q1, q2
+ for idx, c in enumerate(qs):
+ route = '10.0.{0}.0/24'.format(idx + 1)
+ c.add_route(route)
+
cls.gobgp = g1
cls.quaggas = {'q1': q1, 'q2': q2, 'q3': q3, 'q4': q4}
diff --git a/test/scenario_test/route_server_ipv4_v6_test.py b/test/scenario_test/route_server_ipv4_v6_test.py
index 9d7e15a7..07f77e4a 100644
--- a/test/scenario_test/route_server_ipv4_v6_test.py
+++ b/test/scenario_test/route_server_ipv4_v6_test.py
@@ -52,16 +52,7 @@ class GoBGPIPv6Test(unittest.TestCase):
v4 = [q1, q2]
v6 = [q3, q4]
- for idx, q in enumerate(v4):
- route = '10.0.{0}.0/24'.format(idx + 1)
- q.add_route(route)
-
- for idx, q in enumerate(v6):
- route = '2001:{0}::/96'.format(idx + 1)
- q.add_route(route, rf='ipv6')
-
initial_wait_time = max(ctn.run() for ctn in ctns)
-
time.sleep(initial_wait_time)
for ctn in v4:
@@ -72,6 +63,14 @@ class GoBGPIPv6Test(unittest.TestCase):
g1.add_peer(ctn, is_rs_client=True, v6=True)
ctn.add_peer(g1, v6=True)
+ for idx, q in enumerate(v4):
+ route = '10.0.{0}.0/24'.format(idx + 1)
+ q.add_route(route)
+
+ for idx, q in enumerate(v6):
+ route = '2001:{0}::/96'.format(idx + 1)
+ q.add_route(route, rf='ipv6')
+
cls.gobgp = g1
cls.quaggas = {'q1': q1, 'q2': q2, 'q3': q3, 'q4': q4}
cls.ipv4s = {'q1': q1, 'q2': q2}
diff --git a/test/scenario_test/route_server_test.py b/test/scenario_test/route_server_test.py
index a99f1f8b..149adfd2 100644
--- a/test/scenario_test/route_server_test.py
+++ b/test/scenario_test/route_server_test.py
@@ -56,21 +56,20 @@ class GoBGPTestBase(unittest.TestCase):
q2 = rs_clients[1]
q3 = rs_clients[2]
- # advertise a route from route-server-clients
- routes = []
- for idx, rs_client in enumerate(rs_clients):
- route = '10.0.{0}.0/24'.format(idx + 1)
- rs_client.add_route(route)
- routes.append(route)
-
initial_wait_time = max(ctn.run() for ctn in ctns)
-
time.sleep(initial_wait_time)
for rs_client in rs_clients:
g1.add_peer(rs_client, is_rs_client=True, passwd='passwd', passive=True, prefix_limit=10)
rs_client.add_peer(g1, passwd='passwd')
+ # advertise a route from route-server-clients
+ routes = []
+ for idx, rs_client in enumerate(rs_clients):
+ route = '10.0.{0}.0/24'.format(idx + 1)
+ rs_client.add_route(route)
+ routes.append(route)
+
cls.gobgp = g1
cls.quaggas = {'q1': q1, 'q2': q2, 'q3': q3}
@@ -148,15 +147,15 @@ class GoBGPTestBase(unittest.TestCase):
def test_05_add_rs_client(self):
q4 = QuaggaBGPContainer(name='q4', asn=65004, router_id='192.168.0.5')
self.quaggas['q4'] = q4
-
- route = '10.0.4.0/24'
- q4.add_route(route)
-
initial_wait_time = q4.run()
time.sleep(initial_wait_time)
+
self.gobgp.add_peer(q4, is_rs_client=True)
q4.add_peer(self.gobgp)
+ route = '10.0.4.0/24'
+ q4.add_route(route)
+
self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q4)
# check advertised routes are stored in gobgp's local-rib