diff options
Diffstat (limited to 'test/scenario_test')
-rw-r--r-- | test/scenario_test/ci-scripts/jenkins-build-script.sh | 45 | ||||
-rw-r--r-- | test/scenario_test/flow_spec_test.py | 85 | ||||
-rw-r--r-- | test/scenario_test/lib/base.py | 10 | ||||
-rw-r--r-- | test/scenario_test/lib/exabgp.py | 71 | ||||
-rw-r--r-- | test/scenario_test/lib/gobgp.py | 13 | ||||
-rw-r--r-- | test/scenario_test/lib/quagga.py | 14 | ||||
-rw-r--r-- | test/scenario_test/route_server_ipv4_v6_test.py | 2 |
7 files changed, 191 insertions, 49 deletions
diff --git a/test/scenario_test/ci-scripts/jenkins-build-script.sh b/test/scenario_test/ci-scripts/jenkins-build-script.sh index 13ae6f9a..e4f8d3e2 100644 --- a/test/scenario_test/ci-scripts/jenkins-build-script.sh +++ b/test/scenario_test/ci-scripts/jenkins-build-script.sh @@ -28,45 +28,50 @@ set +e sudo -E pip install -r pip-requires.txt # route server test -sudo -E python route_server_test.py --gobgp-image $GOBGP_IMAGE --go-path $GOROOT/bin -s --with-xunit +sudo -E python route_server_test.py --gobgp-image $GOBGP_IMAGE --test-prefix rs -s --with-xunit --xunit-file=${WS}/nosetest.xml RET1=$? -mv nosetests.xml ${WS}/nosetest.xml # route server ipv4 ipv6 test -sudo -E python route_server_ipv4_v6_test.py --gobgp-image $GOBGP_IMAGE --go-path $GOROOT/bin -s --with-xunit +sudo -E python route_server_ipv4_v6_test.py --gobgp-image $GOBGP_IMAGE --test-prefix v6 -s --with-xunit --xunit-file=${WS}/nosetest_ip.xml RET2=$? -mv nosetests.xml ${WS}/nosetest_ip.xml # route server malformed message test -sudo -E python route_server_malformed_test.py --gobgp-image $GOBGP_IMAGE --go-path $GOROOT/bin -s --with-xunit +sudo -E python route_server_malformed_test.py --gobgp-image $GOBGP_IMAGE --go-path $GOROOT/bin -s --with-xunit --xunit-file=${WS}/nosetest_malformed.xml RET3=$? -mv nosetests.xml ${WS}/nosetest_malformed.xml # route server policy test -sudo -E python route_server_policy_test.py --gobgp-image $GOBGP_IMAGE --go-path $GOROOT/bin -s --with-xunit +sudo -E python route_server_policy_test.py --gobgp-image $GOBGP_IMAGE --go-path $GOROOT/bin -s --with-xunit --xunit-file=${WS}/nosetest_policy.xml RET4=$? -mv nosetests.xml ${WS}/nosetest_policy.xml + +if [ $RET1 != 0 ] || [ $RET2 != 0 ] || [ $RET3 != 0 ] || [ $RET4 != 0 ]; then + exit 1 +fi + +PIDS=() # bgp router test sudo -E python bgp_router_test.py --gobgp-image $GOBGP_IMAGE --test-prefix bgp -s -x --with-xunit --xunit-file=${WS}/nosetest_bgp.xml & -PID5=$! +PIDS=("${PIDS[@]}" $!) # ibgp router test sudo -E python ibgp_router_test.py --gobgp-image $GOBGP_IMAGE --test-prefix ibgp -s -x --with-xunit --xunit-file=${WS}/nosetest_ibgp.xml & -PID6=$! +PIDS=("${PIDS[@]}" $!) # evpn test sudo -E python evpn_test.py --gobgp-image $GOBGP_IMAGE --test-prefix evpn -s -x --with-xunit --xunit-file=${WS}/nosetest_evpn.xml& -PID7=$! +PIDS=("${PIDS[@]}" $!) -wait $PID5 -RET5=$? -wait $PID6 -RET6=$? -wait $PID7 -RET7=$? +# flowspec test +sudo -E python flow_spec_test.py --gobgp-image $GOBGP_IMAGE --test-prefix flow -s -x --with-xunit --xunit-file=${WS}/nosetest_flow.xml& +PIDS=("${PIDS[@]}" $!) -if [ $RET1 != 0 ] || [ $RET2 != 0 ] || [ $RET3 != 0 ] || [ $RET4 != 0 ] || [ $RET5 != 0 ] || [ $RET6 != 0 ] || [ $RET7 != 0 ]; then - exit 1 -fi +for (( i = 0; i < ${#PIDS[@]}; ++i )) +do + wait ${PIDS[$i]} + if [ $? != 0 ]; then + exit 1 + fi +done + +echo 'all tests passed successfully' exit 0 diff --git a/test/scenario_test/flow_spec_test.py b/test/scenario_test/flow_spec_test.py new file mode 100644 index 00000000..e29f9c91 --- /dev/null +++ b/test/scenario_test/flow_spec_test.py @@ -0,0 +1,85 @@ +# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +from fabric.api import local +from lib import base +from lib.gobgp import * +from lib.exabgp import * +import sys +import os +import time +import nose +from noseplugin import OptionParser, parser_option +from itertools import combinations + + +class GoBGPTestBase(unittest.TestCase): + + @classmethod + def setUpClass(cls): + gobgp_ctn_image_name = parser_option.gobgp_image + base.TEST_PREFIX = parser_option.test_prefix + + g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1', + ctn_image_name=gobgp_ctn_image_name, + log_level=parser_option.gobgp_log_level) + e1 = ExaBGPContainer(name='e1', asn=65000, router_id='192.168.0.2') + + ctns = [g1, e1] + + # advertise a route from q1, q2 + matchs = ['destination 10.0.0.0/24', 'source 20.0.0.0/24'] + thens = ['discard'] + e1.add_route(route='flow1', rf='ipv4-flowspec', matchs=matchs, thens=thens) + matchs2 = ['tcp-flags syn', 'protocol tcp udp', "packet-length '>1000&<2000'"] + thens2 = ['rate-limit 9600', 'redirect 0.10:100', 'mark 20', 'action sample'] + g1.add_route(route='flow1', rf='ipv4-flowspec', matchs=matchs2, thens=thens2) + + initial_wait_time = max(ctn.run() for ctn in ctns) + + time.sleep(initial_wait_time) + + br01 = Bridge(name='br01', subnet='192.168.10.0/24', self_ip=True) + [br01.addif(ctn) for ctn in ctns] + + # ibgp peer. loop topology + for a, b in combinations(ctns, 2): + a.add_peer(b, flowspec=True) + b.add_peer(a, flowspec=True) + + cls.gobgp = g1 + cls.exabgp = e1 + cls.bridges = {'br01': br01} + + # test each neighbor state is turned establish + def test_01_neighbor_established(self): + self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=self.exabgp) + + def test_02_check_gobgp_global_rib(self): + self.assertTrue(len(self.gobgp.get_global_rib(rf='ipv4-flowspec')) == 2) + + +if __name__ == '__main__': + if os.geteuid() is not 0: + print "you are not root." + sys.exit(1) + output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) + if int(output) is not 0: + print "docker not found" + sys.exit(1) + + nose.main(argv=sys.argv, addplugins=[OptionParser()], + defaultTest=sys.argv[0]) diff --git a/test/scenario_test/lib/base.py b/test/scenario_test/lib/base.py index a9bc1b09..f9bdae12 100644 --- a/test/scenario_test/lib/base.py +++ b/test/scenario_test/lib/base.py @@ -218,7 +218,8 @@ class BGPContainer(Container): def add_peer(self, peer, passwd='', evpn=False, is_rs_client=False, policies=None, passive=False, - is_rr_client=False, cluster_id=''): + is_rr_client=False, cluster_id='', + flowspec=False): neigh_addr = '' local_addr = '' for me, you in itertools.product(self.ip_addrs, peer.ip_addrs): @@ -235,6 +236,7 @@ class BGPContainer(Container): self.peers[peer] = {'neigh_addr': neigh_addr, 'passwd': passwd, 'evpn': evpn, + 'flowspec': flowspec, 'is_rs_client': is_rs_client, 'is_rr_client': is_rr_client, 'cluster_id': cluster_id, @@ -257,10 +259,12 @@ class BGPContainer(Container): def enable_peer(self, peer): raise Exception('implement enable_peer() method') - def add_route(self, route, rf='ipv4', attribute=''): + def add_route(self, route, rf='ipv4', attribute=None, matchs=None, thens=None): self.routes[route] = {'prefix': route, 'rf': rf, - 'attr': attribute} + 'attr': attribute, + 'matchs': matchs, + 'thens' : thens} if self.is_running: self.create_config() self.reload_config() diff --git a/test/scenario_test/lib/exabgp.py b/test/scenario_test/lib/exabgp.py index 91919101..9d211342 100644 --- a/test/scenario_test/lib/exabgp.py +++ b/test/scenario_test/lib/exabgp.py @@ -29,10 +29,9 @@ class ExaBGPContainer(BGPContainer): def _start_exabgp(self): cmd = CmdBuffer(' ') - cmd << 'docker exec -d {0}'.format(self.name) cmd << 'env exabgp.log.destination={0}/exabgpd.log'.format(self.SHARED_VOLUME) cmd << './exabgp/sbin/exabgp {0}/exabgpd.conf'.format(self.SHARED_VOLUME) - local(str(cmd), capture=True) + self.local(str(cmd), flag='-d') def _update_exabgp(self): c = CmdBuffer() @@ -51,9 +50,8 @@ class ExaBGPContainer(BGPContainer): local(cmd, capture=True) cmd = 'chmod 755 {0}/update.sh'.format(self.config_dir) local(cmd, capture=True) - cmd = 'docker exec {0} {1}/update.sh'.format(self.name, - self.SHARED_VOLUME) - local(cmd, capture=True) + cmd = '{0}/update.sh'.format(self.SHARED_VOLUME) + self.local(cmd) def run(self): super(ExaBGPContainer, self).run() @@ -78,13 +76,48 @@ class ExaBGPContainer(BGPContainer): cmd << ' local-as {0};'.format(self.asn) cmd << ' peer-as {0};'.format(peer.asn) - cmd << ' static {' - for route, attr in self.routes.iteritems(): - if attr == '': - cmd << ' route {0} next-hop {1};'.format(route, local_addr) - else: - cmd << ' route {0} next-hop {1} attribute {2};'.format(route, local_addr, attr) - cmd << ' }' + routes = [r for r in self.routes.values() if r['rf'] == 'ipv4'] + + if len(routes) > 0: + cmd << ' static {' + for route in routes: + if route['attr']: + cmd << ' route {0} next-hop {1};'.format(route['prefix'], local_addr) + else: + cmd << ' route {0} next-hop {1} attribute {2};'.format(route['prefix'], local_addr, attr) + cmd << ' }' + + routes = [r for r in self.routes.values() if r['rf'] == 'ipv4-flowspec'] + + if len(routes) > 0: + cmd << ' flow {' + for route in routes: + cmd << ' route {0}{{'.format(route['prefix']) + cmd << ' match {' + for match in route['matchs']: + cmd << ' {0};'.format(match) +# cmd << ' source {0};'.format(route['prefix']) +# cmd << ' destination 192.168.0.1/32;' +# cmd << ' destination-port =3128 >8080&<8088;' +# cmd << ' source-port >1024;' +# cmd << ' port =14 =15 >10&<156;' +# cmd << ' protocol udp;' # how to specify multiple ip protocols +# cmd << ' packet-length >1000&<2000;' +# cmd << ' tcp-flags !syn;' + cmd << ' }' + cmd << ' then {' + for then in route['thens']: + cmd << ' {0};'.format(then) +# cmd << ' accept;' +# cmd << ' discard;' +# cmd << ' rate-limit 9600;' +# cmd << ' redirect 1.2.3.4:100;' +# cmd << ' redirect 100:100;' +# cmd << ' mark 10;' +# cmd << ' action sample-terminal;' + cmd << ' }' + cmd << ' }' + cmd << ' }' cmd << '}' with open('{0}/exabgpd.conf'.format(self.config_dir), 'w') as f: @@ -92,8 +125,12 @@ class ExaBGPContainer(BGPContainer): f.write(str(cmd)) def reload_config(self): - cmd = 'docker exec {0} /usr/bin/pkill exabgp -SIGALRM'.format(self.name) - try: - local(cmd, capture=True) - except: - self._start_exabgp() + ps = self.local('ps', capture=True) + running = False + for line in ps.split('\n')[1:]: + if 'python' in line: + running = True + if running: + self.local('/usr/bin/pkill python -SIGUSR1') + else: + self._start_exabgp() diff --git a/test/scenario_test/lib/gobgp.py b/test/scenario_test/lib/gobgp.py index e1da72c8..63f65928 100644 --- a/test/scenario_test/lib/gobgp.py +++ b/test/scenario_test/lib/gobgp.py @@ -148,6 +148,9 @@ class GoBGPContainer(BGPContainer): afi_safi_list.append({'AfiSafiName': 'encap'}) afi_safi_list.append({'AfiSafiName': 'rtc'}) + if info['flowspec']: + afi_safi_list.append({'AfiSafiName': 'ipv4-flowspec'}) + n = {'NeighborConfig': {'NeighborAddress': info['neigh_addr'].split('/')[0], 'PeerAs': peer.asn, @@ -182,6 +185,12 @@ class GoBGPContainer(BGPContainer): cmd = '/usr/bin/pkill gobgpd -SIGHUP' self.local(cmd) for v in self.routes.itervalues(): - cmd = 'gobgp global '\ - 'rib add {0} -a {1}'.format(v['prefix'], v['rf']) + if v['rf'] == 'ipv4' or v['rf'] == 'ipv6': + cmd = 'gobgp global '\ + 'rib add {0} -a {1}'.format(v['prefix'], v['rf']) + elif v['rf']== 'ipv4-flowspec': + cmd = 'gobgp global '\ + 'rib add match {0} then {1} -a {2}'.format(' '.join(v['matchs']), ' '.join(v['thens']), v['rf']) + else: + raise Exception('unsupported route faily: {0}'.format(rf)) self.local(cmd) diff --git a/test/scenario_test/lib/quagga.py b/test/scenario_test/lib/quagga.py index 1099866a..e4de3ef1 100644 --- a/test/scenario_test/lib/quagga.py +++ b/test/scenario_test/lib/quagga.py @@ -161,14 +161,16 @@ class QuaggaBGPContainer(BGPContainer): c << 'neighbor {0} activate'.format(n_addr) c << 'exit-address-family' - for route in self.routes.iterkeys(): - version = netaddr.IPNetwork(route).version - if version == 4: - c << 'network {0}'.format(route) - elif version == 6: + for route in 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) + c << 'network {0}'.format(route['prefix']) c << 'exit-address-family' + else: + raise Exception('unsupported route faily: {0}'.format(route['rf'])) + for name, policy in self.policies.iteritems(): c << 'access-list {0} {1} {2}'.format(name, policy['type'], diff --git a/test/scenario_test/route_server_ipv4_v6_test.py b/test/scenario_test/route_server_ipv4_v6_test.py index 03033260..d05874f5 100644 --- a/test/scenario_test/route_server_ipv4_v6_test.py +++ b/test/scenario_test/route_server_ipv4_v6_test.py @@ -53,7 +53,7 @@ class GoBGPIPv6Test(unittest.TestCase): for idx, q in enumerate(v6): route = '2001:{0}::/96'.format(idx+1) - q.add_route(route) + q.add_route(route, rf='ipv6') initial_wait_time = max(ctn.run() for ctn in ctns) |