diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 3d6a0d3733..1d69eb685a 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -870,7 +870,9 @@ class Router(Node): if self.daemons[daemon] == 0 or daemon == 'zebra' or daemon == 'staticd': continue daemon_path = os.path.join(self.daemondir, daemon) - self.cmd('{0} > {1}.out 2> {1}.err &'.format(daemon_path, daemon)) + self.cmd('{0} {1} > {2}.out 2> {2}.err &'.format( + daemon_path, self.daemons_options.get(daemon, ''), daemon + )) self.waitOutput() logger.debug('{}: {} {} started'.format(self, self.routertype, daemon)) def getStdErr(self, daemon): diff --git a/tests/topotests/lm-proxy-topo1/ce1/bgpd.conf b/tests/topotests/lm-proxy-topo1/ce1/bgpd.conf new file mode 100644 index 0000000000..33cb3d3209 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/ce1/bgpd.conf @@ -0,0 +1,9 @@ +debug bgp vpn label +! +router bgp 9101 + bgp router-id 10.1.1.2 + neighbor 10.1.1.1 remote-as 7777 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/lm-proxy-topo1/ce1/zebra.conf b/tests/topotests/lm-proxy-topo1/ce1/zebra.conf new file mode 100644 index 0000000000..7118cc6b88 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/ce1/zebra.conf @@ -0,0 +1,11 @@ +debug zebra events +debug zebra packet +! +interface lo + ip address 66.1.0.1/32 +! +interface ce1-eth0 + ip address 10.1.1.2/30 +! +ip forwarding +! diff --git a/tests/topotests/lm-proxy-topo1/ce2/bgpd.conf b/tests/topotests/lm-proxy-topo1/ce2/bgpd.conf new file mode 100644 index 0000000000..358be342a4 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/ce2/bgpd.conf @@ -0,0 +1,9 @@ +debug bgp vpn label +! +router bgp 9102 + bgp router-id 10.1.2.2 + neighbor 10.1.2.1 remote-as 7777 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/lm-proxy-topo1/ce2/zebra.conf b/tests/topotests/lm-proxy-topo1/ce2/zebra.conf new file mode 100644 index 0000000000..8b4e3e31d7 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/ce2/zebra.conf @@ -0,0 +1,11 @@ +debug zebra events +debug zebra packet +! +interface lo + ip address 66.1.0.2/32 +! +interface ce2-eth0 + ip address 10.1.2.2/30 +! +ip forwarding +! diff --git a/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.dot b/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.dot new file mode 100644 index 0000000000..71e6f34ba0 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.dot @@ -0,0 +1,102 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph template { + label="Test Topology - Label Manager proxy"; + + # Routers + + lm [ shape=doubleoctagon, + label="label manager", + fillcolor="#f08080", + style=filled + ]; + ce1 [ + shape=doubleoctagon, + label="ce1", + fillcolor="#f08080", + style=filled + ]; + ce2 [ + shape=doubleoctagon + label="ce2", + fillcolor="#f08080", + style=filled + ]; + pe1 [ + shape=doubleoctagon, + label="pe1", + fillcolor="#f08080", + style=filled + ]; + pe2 [ + shape=doubleoctagon + label="pe2", + fillcolor="#f08080", + style=filled + ]; + p1 [ + shape=doubleoctagon + label="p1", + fillcolor="#f08080", + style=filled + ]; + + # Switches + + s1 [ + shape=oval, + label="s1\n10.1.1.0/30", + fillcolor="#d0e0d0", + style=filled + ]; + s2 [ + shape=oval, + label="s2\n77.0.1.0/24", + fillcolor="#d0e0d0", + style=filled + ]; + s3 [ + shape=oval, + label="s3\n77.0.2.0/24", + fillcolor="#d0e0d0", + style=filled + ]; + s4 [ + shape=oval, + label="s4\n10.1.2.0/30", + fillcolor="#d0e0d0", + style=filled + ]; + + # Connections + + ce1 -- s1 [label="eth0\n.2"]; + pe1 -- s1 [label="eth0\n.1"]; + + pe1 -- s2 [label="eth1\n.1"]; + p1 -- s2 [label="eth0\n.2"]; + + pe2 -- s3 [label="eth1\n.1"]; + p1 -- s3 [label="eth1\n.2"]; + + ce2 -- s4 [label="eth0\n.2"]; + pe2 -- s4 [label="eth0\n.1"]; + + lm -- ce1; + lm -- pe1; + lm -- p1; + lm -- pe2; + lm -- ce2; +} diff --git a/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.pdf b/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.pdf new file mode 100644 index 0000000000..7f7e09ed09 Binary files /dev/null and b/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.pdf differ diff --git a/tests/topotests/lm-proxy-topo1/lm/zebra.conf b/tests/topotests/lm-proxy-topo1/lm/zebra.conf new file mode 100644 index 0000000000..3c14f3bb3a --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/lm/zebra.conf @@ -0,0 +1,3 @@ +debug zebra events +debug zebra packet +! diff --git a/tests/topotests/lm-proxy-topo1/p1/ldpd.conf b/tests/topotests/lm-proxy-topo1/p1/ldpd.conf new file mode 100644 index 0000000000..f86c47e6cc --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/p1/ldpd.conf @@ -0,0 +1,9 @@ +! +mpls ldp + router-id 7.0.0.101 + address-family ipv4 + discovery transport-address 7.0.0.101 + interface p1-eth0 + interface p1-eth1 + exit-address-family +! diff --git a/tests/topotests/lm-proxy-topo1/p1/ospfd.conf b/tests/topotests/lm-proxy-topo1/p1/ospfd.conf new file mode 100644 index 0000000000..721426cb15 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/p1/ospfd.conf @@ -0,0 +1,7 @@ +! +router ospf + ospf router-id 7.0.0.101 + network 7.0.0.101/32 area 0 + network 77.0.1.0/24 area 0 + network 77.0.2.0/24 area 0 +! diff --git a/tests/topotests/lm-proxy-topo1/p1/zebra.conf b/tests/topotests/lm-proxy-topo1/p1/zebra.conf new file mode 100644 index 0000000000..bb2fc2f96e --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/p1/zebra.conf @@ -0,0 +1,12 @@ +debug zebra events +debug zebra packet +! +interface lo + ip address 7.0.0.101/32 +! +interface p1-eth0 + ip address 77.0.1.2/24 +! +interface p1-eth1 + ip address 77.0.2.2/24 +! diff --git a/tests/topotests/lm-proxy-topo1/pe1/bgpd.conf b/tests/topotests/lm-proxy-topo1/pe1/bgpd.conf new file mode 100644 index 0000000000..b9bab30c30 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe1/bgpd.conf @@ -0,0 +1,26 @@ +debug bgp vpn label +! +router bgp 7777 + bgp router-id 7.0.0.1 + neighbor 7.0.0.2 remote-as 7777 + neighbor 7.0.0.2 update-source 7.0.0.1 + address-family ipv4 unicast + no neighbor 7.0.0.2 activate + exit-address-family + address-family ipv4 vpn + neighbor 7.0.0.2 activate + exit-address-family +! +router bgp 7777 vrf A + bgp router-id 10.1.1.1 + neighbor 10.1.1.2 remote-as 9101 + address-family ipv4 unicast + label vpn export auto + rd vpn export 110:1 + rt vpn both 152:100 + import vpn + export vpn + redistribute connected + redistribute ospf + exit-address-family +! diff --git a/tests/topotests/lm-proxy-topo1/pe1/ldpd.conf b/tests/topotests/lm-proxy-topo1/pe1/ldpd.conf new file mode 100644 index 0000000000..1b11f19fd3 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe1/ldpd.conf @@ -0,0 +1,8 @@ +! +mpls ldp + router-id 7.0.0.1 + address-family ipv4 + discovery transport-address 7.0.0.1 + interface pe1-eth1 + exit-address-family +! diff --git a/tests/topotests/lm-proxy-topo1/pe1/ospfd.conf b/tests/topotests/lm-proxy-topo1/pe1/ospfd.conf new file mode 100644 index 0000000000..334c2547bf --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe1/ospfd.conf @@ -0,0 +1,6 @@ +! +router ospf + ospf router-id 7.0.0.1 + network 77.0.0.0/16 area 0 + redistribute connected +! diff --git a/tests/topotests/lm-proxy-topo1/pe1/zebra.conf b/tests/topotests/lm-proxy-topo1/pe1/zebra.conf new file mode 100644 index 0000000000..ec1413234b --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe1/zebra.conf @@ -0,0 +1,14 @@ +debug zebra events +debug zebra packet +! +interface lo + ip address 7.0.0.1/32 +! +interface pe1-eth0 vrf A + ip address 10.1.1.1/30 +! +interface pe1-eth1 + ip address 77.0.1.1/24 +! +ip forwarding +! diff --git a/tests/topotests/lm-proxy-topo1/pe2/bgpd.conf b/tests/topotests/lm-proxy-topo1/pe2/bgpd.conf new file mode 100644 index 0000000000..f1ec2a48e8 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe2/bgpd.conf @@ -0,0 +1,26 @@ +debug bgp vpn label +! +router bgp 7777 + bgp router-id 7.0.0.2 + neighbor 7.0.0.1 remote-as 7777 + neighbor 7.0.0.1 update-source 7.0.0.2 + address-family ipv4 unicast + no neighbor 7.0.0.1 activate + exit-address-family + address-family ipv4 vpn + neighbor 7.0.0.1 activate + exit-address-family +! +router bgp 7777 vrf A + bgp router-id 10.1.2.1 + neighbor 10.1.2.2 remote-as 9102 + address-family ipv4 unicast + label vpn export auto + rd vpn export 110:2 + rt vpn both 152:100 + import vpn + export vpn + redistribute connected + redistribute ospf + exit-address-family +! diff --git a/tests/topotests/lm-proxy-topo1/pe2/ldpd.conf b/tests/topotests/lm-proxy-topo1/pe2/ldpd.conf new file mode 100644 index 0000000000..727364fe9f --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe2/ldpd.conf @@ -0,0 +1,8 @@ +! +mpls ldp + router-id 7.0.0.2 + address-family ipv4 + discovery transport-address 7.0.0.2 + interface pe2-eth1 + exit-address-family +! diff --git a/tests/topotests/lm-proxy-topo1/pe2/ospfd.conf b/tests/topotests/lm-proxy-topo1/pe2/ospfd.conf new file mode 100644 index 0000000000..068de09a98 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe2/ospfd.conf @@ -0,0 +1,6 @@ +! +router ospf + ospf router-id 7.0.0.2 + network 77.0.0.0/16 area 0 + redistribute connected +! diff --git a/tests/topotests/lm-proxy-topo1/pe2/zebra.conf b/tests/topotests/lm-proxy-topo1/pe2/zebra.conf new file mode 100644 index 0000000000..0302fd8018 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/pe2/zebra.conf @@ -0,0 +1,14 @@ +debug zebra events +debug zebra packet +! +interface lo + ip address 7.0.0.2/32 +! +interface pe2-eth1 + ip address 77.0.2.1/24 +! +interface pe2-eth0 vrf A + ip address 10.1.2.1/30 +! +ip forwarding +! diff --git a/tests/topotests/lm-proxy-topo1/test_lm-proxy-topo1.py b/tests/topotests/lm-proxy-topo1/test_lm-proxy-topo1.py new file mode 100644 index 0000000000..7acbb1ee62 --- /dev/null +++ b/tests/topotests/lm-proxy-topo1/test_lm-proxy-topo1.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python + +# +# test_lm-proxy-topo1.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2018 by Volta Networks, Inc. +# +# Requirements, so the test is not skipped: +# - Linux kernel with VRF support +# - 'ip' command with VRF support (e.g. iproute2-ss180129 works) +# - FRR BGP daemon supporting label manager using instance id +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +import os +import sys +import pytest + +from functools import partial + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../')) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. +from mininet.topo import Topo + +vrf_name = 'A' + +class NetworkTopo(Topo): + "Label Manager proxy topology" + + # Relationship between routers, switches, and hosts + def build(self, *_args, **_opts): + "Build function" + + tgen = get_topogen(self) + + # FRR routers + + for router in ['lm', 'ce1', 'pe1', 'p1', 'pe2', 'ce2']: + tgen.add_router(router); + + # Connections + + switch = tgen.add_switch('s1') + switch.add_link(tgen.gears['ce1'], nodeif='ce1-eth0') + switch.add_link(tgen.gears['pe1'], nodeif='pe1-eth0') + + switch = tgen.add_switch('s2') + switch.add_link(tgen.gears['pe1'], nodeif='pe1-eth1') + switch.add_link(tgen.gears['p1'], nodeif='p1-eth0') + + switch = tgen.add_switch('s3') + switch.add_link(tgen.gears['p1'], nodeif='p1-eth1') + switch.add_link(tgen.gears['pe2'], nodeif='pe2-eth1') + + switch = tgen.add_switch('s4') + switch.add_link(tgen.gears['ce2'], nodeif='ce2-eth0') + switch.add_link(tgen.gears['pe2'], nodeif='pe2-eth0') + +# Test environment handling + +def vrf_destroy(router, vrf): + router.run('ip link delete dev ' + vrf) + +def vrf_setup(router, eth_in, vrf, vrf_table): + cmds = ['ip link set dev lo up', + 'echo 10000 > /proc/sys/net/mpls/platform_labels', + 'ip link add dev ' + vrf + ' type vrf table ' + vrf_table, + 'ip link set ' + vrf + ' up', + 'ip link set ' + eth_in + ' vrf ' + vrf, + 'echo 1 > /proc/sys/net/mpls/conf/' + vrf + '/input' + ] + vrf_destroy(router, vrf) + for cmd in cmds: + logger.info('[vrf_setup] cmd: ' + cmd) + out = router.run(cmd) + if out != None and len(out) > 0: + logger.info('[vrf_setup] "{}" error: out="{}"'.format(cmd, out)) + +def setup_module(mod): + "pytest environment setup" + + tgen = Topogen(NetworkTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + # Load router configuration + + ldp_id = 1 + bgp_id = 101 + lm_sock = '../lm/label_mgr.sock' + + for rname, router in router_list.iteritems(): + if rname == 'lm' : + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname)), + '-z ' + lm_sock + ) + continue + + rtype = ''.join([i for i in rname if not i.isdigit()]) + + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname)), + '-l ' + lm_sock + ) + + if router.check_capability(TopoRouter.RD_ZEBRA, '--vrfwnetns') == False: + return pytest.skip('Skipping test: no VRF support') + + if rtype == 'ce' or rtype == 'pe': + if router.check_capability(TopoRouter.RD_BGP, '--int_num') == False: + return pytest.skip('Skipping test: no BGP LM support') + router.load_config( + TopoRouter.RD_BGP, + os.path.join(CWD, '{}/bgpd.conf'.format(rname)), + '-I %d' % bgp_id + ) + bgp_id += 1 + + if rtype == 'pe' or rtype == 'p': + router.load_config( + TopoRouter.RD_OSPF, + os.path.join(CWD, '{}/ospfd.conf'.format(rname)) + ) + router.load_config( + TopoRouter.RD_LDP, + os.path.join(CWD, '{}/ldpd.conf'.format(rname)), + '-n %d' % ldp_id + ) + ldp_id += 1 + + # Prepare VRF's + + router = tgen.gears['pe1'] + out = router.run('ip -h 2>&1 | grep vrf | wc -l') + if int(out) == 0: + return pytest.skip('Skipping test: ip/iproute2 has no VRF support') + + vrf_setup(tgen.gears['pe1'], 'pe1-eth0', vrf_name, '1') + vrf_setup(tgen.gears['pe2'], 'pe2-eth0', vrf_name, '1') + + # Start routers + + tgen.start_router(tgen.gears['lm']) + for rname, router in router_list.iteritems(): + if rname != 'lm': + tgen.start_router(router) + +def teardown_module(mod): + tgen = get_topogen() + for router in ['pe1', 'pe2']: + vrf_destroy(tgen.gears[router], vrf_name) + tgen.stop_topology() + +def test_lm_proxy(): + logger.info('Test: label manager (LDP and BGP)') + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + cmd = 'show mpls ldp binding' + + router = tgen.gears['p1'] + + def check_labels(router, cmd): + output = router.vtysh_cmd(cmd, isjson=False) + logger.info('chk_labels [' + cmd + ']: ' + output) + return output.count('\n') + + test_func = partial(check_labels, router, cmd) + result, diff = topotest.run_and_expect(test_func, 12, count=6, wait=30) + assert result, 'wrong labels' + +if __name__ == '__main__': + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) +