]>
Commit | Line | Data |
---|---|---|
12919c42 PG |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_bgp_vrf_netns_topo1.py | |
5 | # Part of NetDEF Topology Tests | |
6 | # | |
7 | # Copyright (c) 2018 by 6WIND | |
8 | # | |
9 | # Permission to use, copy, modify, and/or distribute this software | |
10 | # for any purpose with or without fee is hereby granted, provided | |
11 | # that the above copyright notice and this permission notice appear | |
12 | # in all copies. | |
13 | # | |
14 | # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |
15 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
17 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
18 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
19 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
20 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
21 | # OF THIS SOFTWARE. | |
22 | # | |
23 | ||
24 | """ | |
25 | test_bgp_vrf_netns_topo1.py: Test BGP topology with EBGP on NETNS VRF | |
26 | """ | |
27 | ||
28 | import json | |
29 | import os | |
30 | import sys | |
e3060696 | 31 | import functools |
12919c42 | 32 | import pytest |
12919c42 PG |
33 | |
34 | # Save the Current Working Directory to find configuration files. | |
35 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
787e7624 | 36 | sys.path.append(os.path.join(CWD, "../")) |
12919c42 PG |
37 | |
38 | # pylint: disable=C0413 | |
39 | # Import topogen and topotest helpers | |
40 | from lib import topotest | |
41 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
42 | from lib.topolog import logger | |
43 | ||
44 | # Required to instantiate the topology builder class. | |
45 | from mininet.topo import Topo | |
46 | ||
bf3a0a9a DS |
47 | pytestmark = [pytest.mark.bgpd] |
48 | ||
49 | ||
12919c42 PG |
50 | total_ebgp_peers = 1 |
51 | CustomizeVrfWithNetns = True | |
52 | ||
53 | ##################################################### | |
54 | ## | |
55 | ## Network Topology Definition | |
56 | ## | |
57 | ##################################################### | |
58 | ||
787e7624 | 59 | |
12919c42 PG |
60 | class BGPVRFNETNSTopo1(Topo): |
61 | "BGP EBGP VRF NETNS Topology 1" | |
62 | ||
63 | def build(self, **_opts): | |
64 | tgen = get_topogen(self) | |
65 | ||
66 | # Setup Routers | |
787e7624 | 67 | tgen.add_router("r1") |
12919c42 PG |
68 | |
69 | # Setup Switches | |
787e7624 | 70 | switch = tgen.add_switch("s1") |
71 | switch.add_link(tgen.gears["r1"]) | |
12919c42 PG |
72 | |
73 | # Add eBGP ExaBGP neighbors | |
787e7624 | 74 | peer_ip = "10.0.1.101" |
75 | peer_route = "via 10.0.1.1" | |
76 | peer = tgen.add_exabgp_peer("peer1", ip=peer_ip, defaultRoute=peer_route) | |
77 | switch = tgen.gears["s1"] | |
12919c42 PG |
78 | switch.add_link(peer) |
79 | ||
80 | ||
81 | ##################################################### | |
82 | ## | |
83 | ## Tests starting | |
84 | ## | |
85 | ##################################################### | |
86 | ||
787e7624 | 87 | |
12919c42 PG |
88 | def setup_module(module): |
89 | tgen = Topogen(BGPVRFNETNSTopo1, module.__name__) | |
90 | tgen.start_topology() | |
91 | ||
92 | # Get r1 reference | |
787e7624 | 93 | router = tgen.gears["r1"] |
12919c42 PG |
94 | |
95 | # check for zebra capability | |
96 | if CustomizeVrfWithNetns == True: | |
787e7624 | 97 | if router.check_capability(TopoRouter.RD_ZEBRA, "--vrfwnetns") == False: |
98 | return pytest.skip( | |
99 | "Skipping BGP VRF NETNS Test. VRF NETNS backend not available on FRR" | |
100 | ) | |
101 | if os.system("ip netns list") != 0: | |
102 | return pytest.skip( | |
103 | "Skipping BGP VRF NETNS Test. NETNS not available on System" | |
104 | ) | |
12919c42 PG |
105 | # retrieve VRF backend kind |
106 | if CustomizeVrfWithNetns == True: | |
787e7624 | 107 | logger.info("Testing with VRF Namespace support") |
12919c42 PG |
108 | |
109 | # create VRF r1-cust1 | |
110 | # move r1-eth0 to VRF r1-cust1 | |
787e7624 | 111 | cmds = [ |
112 | "if [ -e /var/run/netns/{0}-cust1 ] ; then ip netns del {0}-cust1 ; fi", | |
113 | "ip netns add {0}-cust1", | |
114 | "ip link set dev {0}-eth0 netns {0}-cust1", | |
115 | "ip netns exec {0}-cust1 ifconfig {0}-eth0 up", | |
116 | ] | |
12919c42 | 117 | for cmd in cmds: |
787e7624 | 118 | cmd = cmd.format("r1") |
119 | logger.info("cmd: " + cmd) | |
120 | output = router.run(cmd.format("r1")) | |
1cb05170 | 121 | if output != None and len(output) > 0: |
787e7624 | 122 | logger.info( |
123 | 'Aborting due to unexpected output: cmd="{}" output=\n{}'.format( | |
124 | cmd, output | |
125 | ) | |
126 | ) | |
127 | return pytest.skip( | |
128 | "Skipping BGP VRF NETNS Test. Unexpected output to command: " + cmd | |
129 | ) | |
130 | # run daemons | |
12919c42 PG |
131 | router.load_config( |
132 | TopoRouter.RD_ZEBRA, | |
787e7624 | 133 | os.path.join(CWD, "{}/zebra.conf".format("r1")), |
134 | "--vrfwnetns", | |
12919c42 PG |
135 | ) |
136 | router.load_config( | |
787e7624 | 137 | TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format("r1")) |
12919c42 PG |
138 | ) |
139 | ||
787e7624 | 140 | logger.info("Launching BGP and ZEBRA") |
12919c42 PG |
141 | # BGP and ZEBRA start without underlying VRF |
142 | router.start() | |
143 | # Starting Hosts and init ExaBGP on each of them | |
787e7624 | 144 | logger.info("starting exaBGP on peer1") |
12919c42 | 145 | peer_list = tgen.exabgp_peers() |
e5f0ed14 | 146 | for pname, peer in peer_list.items(): |
12919c42 | 147 | peer_dir = os.path.join(CWD, pname) |
787e7624 | 148 | env_file = os.path.join(CWD, "exabgp.env") |
149 | logger.info("Running ExaBGP peer") | |
12919c42 PG |
150 | peer.start(peer_dir, env_file) |
151 | logger.info(pname) | |
152 | ||
787e7624 | 153 | |
12919c42 PG |
154 | def teardown_module(module): |
155 | tgen = get_topogen() | |
156 | # move back r1-eth0 to default VRF | |
157 | # delete VRF r1-cust1 | |
787e7624 | 158 | cmds = [ |
159 | "ip netns exec {0}-cust1 ip link set {0}-eth0 netns 1", | |
160 | "ip netns delete {0}-cust1", | |
161 | ] | |
12919c42 | 162 | for cmd in cmds: |
787e7624 | 163 | tgen.net["r1"].cmd(cmd.format("r1")) |
12919c42 PG |
164 | |
165 | tgen.stop_topology() | |
166 | ||
787e7624 | 167 | |
12919c42 PG |
168 | def test_bgp_vrf_learn(): |
169 | "Test daemon learnt VRF context" | |
170 | tgen = get_topogen() | |
171 | ||
172 | # Skip if previous fatal error condition is raised | |
173 | if tgen.routers_have_failure(): | |
174 | pytest.skip(tgen.errors) | |
175 | ||
176 | # Expected result | |
787e7624 | 177 | output = tgen.gears["r1"].vtysh_cmd("show vrf", isjson=False) |
178 | logger.info("output is: {}".format(output)) | |
12919c42 | 179 | |
787e7624 | 180 | output = tgen.gears["r1"].vtysh_cmd("show bgp vrfs", isjson=False) |
181 | logger.info("output is: {}".format(output)) | |
12919c42 | 182 | |
e3060696 | 183 | |
12919c42 PG |
184 | def test_bgp_convergence(): |
185 | "Test for BGP topology convergence" | |
186 | tgen = get_topogen() | |
187 | ||
188 | # uncomment if you want to troubleshoot | |
189 | # tgen.mininet_cli() | |
190 | # Skip if previous fatal error condition is raised | |
191 | if tgen.routers_have_failure(): | |
192 | pytest.skip(tgen.errors) | |
193 | ||
787e7624 | 194 | logger.info("waiting for bgp convergence") |
12919c42 PG |
195 | |
196 | # Expected result | |
787e7624 | 197 | router = tgen.gears["r1"] |
198 | if router.has_version("<", "3.0"): | |
199 | reffile = os.path.join(CWD, "r1/summary20.txt") | |
12919c42 | 200 | else: |
787e7624 | 201 | reffile = os.path.join(CWD, "r1/summary.txt") |
12919c42 PG |
202 | |
203 | expected = json.loads(open(reffile).read()) | |
204 | ||
787e7624 | 205 | test_func = functools.partial( |
206 | topotest.router_json_cmp, router, "show bgp vrf r1-cust1 summary json", expected | |
207 | ) | |
e3060696 | 208 | _, res = topotest.run_and_expect(test_func, None, count=90, wait=0.5) |
787e7624 | 209 | assertmsg = "BGP router network did not converge" |
12919c42 PG |
210 | assert res is None, assertmsg |
211 | ||
787e7624 | 212 | |
12919c42 PG |
213 | def test_bgp_vrf_netns(): |
214 | tgen = get_topogen() | |
215 | ||
216 | # Skip if previous fatal error condition is raised | |
217 | if tgen.routers_have_failure(): | |
218 | pytest.skip(tgen.errors) | |
219 | ||
220 | expect = { | |
787e7624 | 221 | "routerId": "10.0.1.1", |
222 | "routes": {}, | |
12919c42 PG |
223 | } |
224 | ||
225 | for subnet in range(0, 10): | |
787e7624 | 226 | netkey = "10.201.{}.0/24".format(subnet) |
227 | expect["routes"][netkey] = [] | |
228 | peer = {"valid": True} | |
229 | expect["routes"][netkey].append(peer) | |
230 | ||
231 | test_func = functools.partial( | |
232 | topotest.router_json_cmp, | |
233 | tgen.gears["r1"], | |
234 | "show ip bgp vrf r1-cust1 ipv4 json", | |
235 | expect, | |
236 | ) | |
e3060696 | 237 | _, res = topotest.run_and_expect(test_func, None, count=12, wait=0.5) |
12919c42 PG |
238 | assertmsg = 'expected routes in "show ip bgp vrf r1-cust1 ipv4" output' |
239 | assert res is None, assertmsg | |
240 | ||
787e7624 | 241 | |
242 | if __name__ == "__main__": | |
12919c42 PG |
243 | |
244 | args = ["-s"] + sys.argv[1:] | |
245 | ret = pytest.main(args) | |
246 | ||
247 | sys.exit(ret) |