]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
Merge pull request #9350 from ton31337/feature/autocomplete_for_community_lists
[mirror_frr.git] / tests / topotests / bgp_evpn_overlay_index_gateway / test_bgp_evpn_overlay_index_gateway.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2020 by VMware, Inc. ("VMware")
4 # Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
5 # in this file.
6 #
7 # Permission to use, copy, modify, and/or distribute this software
8 # for any purpose with or without fee is hereby granted, provided
9 # that the above copyright notice and this permission notice appear
10 # in all copies.
11 #
12 # THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
13 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
15 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
16 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
18 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
19 # OF THIS SOFTWARE.
20 #
21
22 """
23 test_bgp_evpn_overlay_index_gateway.py: Test EVPN gateway IP overlay index functionality
24 Following functionality is covered:
25
26 +--------+ BGP +--------+ BGP +--------+ +--------+
27 SN1 | | IPv4/v6 | | EVPN | | | |
28 ======+ Host1 +---------+ PE1 +------+ PE2 +------+ Host2 +
29 | | | | | | | |
30 +--------+ +--------+ +--------+ +--------+
31
32 Host1 is connected to PE1 and host2 is connected to PE2
33 Host1 and PE1 have IPv4/v6 BGP sessions.
34 PE1 and PE2 gave EVPN session.
35 Host1 advertises IPv4/v6 prefixes to PE1.
36 PE1 advertises these prefixes to PE2 as EVPN type-5 routes.
37 Gateway IP for these EVPN type-5 routes is host1 IP.
38 Host1 MAC/IP is advertised by PE1 as EVPN type-2 route
39
40 Following testcases are covered:
41 TC_1:
42 Check BGP and zebra states for above topology at PE1 and PE2.
43
44 TC_2:
45 Stop advertising prefixes from host1. It should withdraw type-5 routes. Check states at PE1 and PE2
46 Advertise the prefixes again. Check states.
47
48 TC_3:
49 Shut down VxLAN interface at PE1. This should withdraw type-2 routes. Check states at PE1 and PE2.
50 Enable VxLAN interface again. Check states.
51 """
52
53 import os
54 import sys
55 import json
56 from functools import partial
57 import pytest
58 import time
59 import platform
60
61 #Current Working Directory
62 CWD = os.path.dirname(os.path.realpath(__file__))
63 sys.path.append(os.path.join(CWD, "../"))
64
65 # pylint: disable=C0413
66 # Import topogen and topotest helpers
67 from lib import topotest
68 from lib.topogen import Topogen, TopoRouter, get_topogen
69 from lib.topolog import logger
70 from lib.common_config import (
71 step,
72 write_test_header,
73 write_test_footer,
74 generate_support_bundle,
75 )
76
77 # Required to instantiate the topology builder class.
78 from mininet.topo import Topo
79
80 pytestmark = [pytest.mark.bgpd]
81
82
83 #Global variables
84 PES = ['PE1', 'PE2']
85 HOSTS = ['host1', 'host2']
86 PE_SUFFIX = {'PE1': '1', 'PE2': '2'}
87 HOST_SUFFIX = {'host1': '1', 'host2': '2'}
88 TRIGGERS = ["base", "no_rt5", "no_rt2"]
89
90
91 class TemplateTopo(Topo):
92 """Test topology builder"""
93
94 def build(self, *_args, **_opts):
95 """Build function"""
96 tgen = get_topogen(self)
97
98 # This function only purpose is to define allocation and relationship
99 # between routers and add links.
100
101 # Create routers
102 for pe in PES:
103 tgen.add_router(pe)
104 for host in HOSTS:
105 tgen.add_router(host)
106
107 krel = platform.release()
108 logger.info('Kernel version ' + krel)
109
110 #Add links
111 tgen.add_link(tgen.gears['PE1'], tgen.gears['PE2'], 'PE1-eth0', 'PE2-eth0')
112 tgen.add_link(tgen.gears['PE1'], tgen.gears['host1'], 'PE1-eth1', 'host1-eth0')
113 tgen.add_link(tgen.gears['PE2'], tgen.gears['host2'], 'PE2-eth1', 'host2-eth0')
114
115
116 def setup_module(mod):
117 "Sets up the pytest environment"
118
119 testsuite_run_time = time.asctime(time.localtime(time.time()))
120 logger.info("Testsuite start time: {}".format(testsuite_run_time))
121 logger.info("=" * 40)
122
123 logger.info("Running setup_module to create topology")
124
125 # This function initiates the topology build with Topogen...
126 tgen = Topogen(TemplateTopo, mod.__name__)
127 # ... and here it calls Mininet initialization functions.
128
129 kernelv = platform.release()
130 if topotest.version_cmp(kernelv, "4.15") < 0:
131 logger.info("For EVPN, kernel version should be minimum 4.15. Kernel present {}".format(kernelv))
132 return
133
134 if topotest.version_cmp(kernelv, '4.15') == 0:
135 l3mdev_accept = 1
136 logger.info('setting net.ipv4.tcp_l3mdev_accept={}'.format(l3mdev_accept))
137 else:
138 l3mdev_accept = 0
139
140 # Starting topology, create tmp files which are loaded to routers
141 # to start deamons and then start routers
142 tgen.start_topology()
143
144 # Configure MAC address for hosts as these MACs are advertised with EVPN type-2 routes
145 for (name, host) in tgen.gears.items():
146 if name not in HOSTS:
147 continue
148
149 host_mac = "1a:2b:3c:4d:5e:6{}".format(HOST_SUFFIX[name])
150 host.run("ip link set dev {}-eth0 down").format(name)
151 host.run("ip link set dev {0}-eth0 address {1}".format(name, host_mac))
152 host.run("ip link set dev {}-eth0 up").format(name)
153
154 # Configure PE VxLAN and Bridge interfaces
155 for (name, pe) in tgen.gears.items():
156 if name not in PES:
157 continue
158 vtep_ip = "10.100.0.{}".format(PE_SUFFIX[name])
159 bridge_ip = "50.0.1.{}/24".format(PE_SUFFIX[name])
160 bridge_ipv6 = "50:0:1::{}/48".format(PE_SUFFIX[name])
161
162 pe.run("ip link add vrf-blue type vrf table 10")
163 pe.run("ip link set dev vrf-blue up")
164 pe.run("ip link add vxlan100 type vxlan id 100 dstport 4789 local {}".format(vtep_ip))
165 pe.run("ip link add name br100 type bridge stp_state 0")
166 pe.run("ip link set dev vxlan100 master br100")
167 pe.run("ip link set dev {}-eth1 master br100".format(name))
168 pe.run("ip addr add {} dev br100".format(bridge_ip))
169 pe.run("ip link set up dev br100")
170 pe.run("ip link set up dev vxlan100")
171 pe.run("ip link set up dev {}-eth1".format(name))
172 pe.run("ip link set dev br100 master vrf-blue")
173 pe.run("ip -6 addr add {} dev br100".format(bridge_ipv6))
174
175 pe.run("ip link add vxlan1000 type vxlan id 1000 dstport 4789 local {}".format(vtep_ip))
176 pe.run("ip link add name br1000 type bridge stp_state 0")
177 pe.run("ip link set dev vxlan1000 master br100")
178 pe.run("ip link set up dev br1000")
179 pe.run("ip link set up dev vxlan1000")
180 pe.run("ip link set dev br1000 master vrf-blue")
181
182 pe.run("sysctl -w net.ipv4.ip_forward=1")
183 pe.run("sysctl -w net.ipv6.conf.all.forwarding=1")
184 pe.run("sysctl -w net.ipv4.udp_l3mdev_accept={}".format(l3mdev_accept))
185 pe.run("sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept))
186
187 # For all registred routers, load the zebra configuration file
188 for (name, router) in tgen.routers().items():
189 router.load_config(
190 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(name))
191 )
192 router.load_config(
193 TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(name))
194 )
195
196 # After loading the configurations, this function loads configured daemons.
197 tgen.start_router()
198
199 logger.info("Running setup_module() done")
200
201
202 def teardown_module(mod):
203 """Teardown the pytest environment"""
204
205 logger.info("Running teardown_module to delete topology")
206
207 tgen = get_topogen()
208
209 # Stop toplogy and Remove tmp files
210 tgen.stop_topology()
211
212 logger.info(
213 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
214 )
215 logger.info("=" * 40)
216
217
218 def evpn_gateway_ip_show_op_check(trigger=" "):
219 """
220 This function checks CLI O/P for commands mentioned in show_commands for a given trigger
221 :param trigger: Should be a trigger present in TRIGGERS
222 :return: Returns a tuple (result: None for success, retmsg: Log message to be printed on failure)
223 """
224 tgen = get_topogen()
225
226 if trigger not in TRIGGERS:
227 return "Unexpected trigger", "Unexpected trigger {}".format(trigger)
228
229 show_commands = {'bgp_vni_routes': 'show bgp l2vpn evpn route vni 100 json',
230 'bgp_vrf_ipv4' : 'show bgp vrf vrf-blue ipv4 json',
231 'bgp_vrf_ipv6' : 'show bgp vrf vrf-blue ipv6 json',
232 'zebra_vrf_ipv4': 'show ip route vrf vrf-blue json',
233 'zebra_vrf_ipv6': 'show ipv6 route vrf vrf-blue json'}
234
235 for (name, pe) in tgen.gears.items():
236 if name not in PES:
237 continue
238
239 for (cmd_key, command) in show_commands.items():
240 expected_op_file = "{0}/{1}/{2}_{3}.json".format(CWD, name, cmd_key, trigger)
241 expected_op = json.loads(open(expected_op_file).read())
242
243 test_func = partial(topotest.router_json_cmp, pe, command, expected_op)
244 ret, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
245 assertmsg = '"{0}" JSON output mismatch for {1}'.format(name, command)
246 if result is not None:
247 return result, assertmsg
248
249 return None, "Pass"
250
251
252 def test_evpn_gateway_ip_basic_topo(request):
253 """
254 Tets EVPN overlay index gateway IP functionality. VErify show O/Ps on PE1 and PE2
255 """
256
257 tgen = get_topogen()
258 tc_name = request.node.name
259 write_test_header(tc_name)
260
261 kernelv = platform.release()
262 if topotest.version_cmp(kernelv, "4.15") < 0:
263 logger.info("For EVPN, kernel version should be minimum 4.15")
264 write_test_footer(tc_name)
265 return
266
267 if tgen.routers_have_failure():
268 pytest.skip(tgen.errors)
269
270 step("Check O/Ps for EVPN gateway IP overlay Index functionality at PE1 and PE2")
271
272 result, assertmsg = evpn_gateway_ip_show_op_check("base")
273
274 if result is not None:
275 generate_support_bundle()
276 assert result is None, assertmsg
277
278 write_test_footer(tc_name)
279
280
281 def test_evpn_gateway_ip_flap_rt5(request):
282 """
283 Withdraw EVPN type-5 routes and check O/Ps at PE1 and PE2
284 """
285 tgen = get_topogen()
286 tc_name = request.node.name
287 write_test_header(tc_name)
288
289 kernelv = platform.release()
290 if topotest.version_cmp(kernelv, "4.15") < 0:
291 logger.info("For EVPN, kernel version should be minimum 4.15")
292 write_test_footer(tc_name)
293 return
294
295 if tgen.routers_have_failure():
296 pytest.skip(tgen.errors)
297
298 h1 = tgen.gears['host1']
299
300 step("Withdraw type-5 routes")
301
302 h1.run('vtysh -c "config t" \
303 -c "router bgp 111" \
304 -c "address-family ipv4" \
305 -c "no network 100.0.0.21/32"')
306 h1.run('vtysh -c "config t" \
307 -c "router bgp 111" \
308 -c "address-family ipv6" \
309 -c "no network 100::21/128"')
310
311 result, assertmsg = evpn_gateway_ip_show_op_check("no_rt5")
312 if result is not None:
313 generate_support_bundle()
314 assert result is None, assertmsg
315
316 step("Advertise type-5 routes again")
317
318 h1.run('vtysh -c "config t" \
319 -c "router bgp 111" \
320 -c "address-family ipv4" \
321 -c "network 100.0.0.21/32"')
322 h1.run('vtysh -c "config t" \
323 -c "router bgp 111" \
324 -c "address-family ipv6" \
325 -c "network 100::21/128"')
326
327 result, assertmsg = evpn_gateway_ip_show_op_check("base")
328 if result is not None:
329 generate_support_bundle()
330
331 assert result is None, assertmsg
332
333 write_test_footer(tc_name)
334
335
336 def test_evpn_gateway_ip_flap_rt2(request):
337 """
338 Withdraw EVPN type-2 routes and check O/Ps at PE1 and PE2
339 """
340 tgen = get_topogen()
341 tc_name = request.node.name
342 write_test_header(tc_name)
343
344 kernelv = platform.release()
345 if topotest.version_cmp(kernelv, "4.15") < 0:
346 logger.info("For EVPN, kernel version should be minimum 4.15")
347 write_test_footer(tc_name)
348 return
349
350 if tgen.routers_have_failure():
351 pytest.skip(tgen.errors)
352
353
354 step("Shut down VxLAN interface at PE1 which results in withdraw of type-2 routes")
355
356 pe1 = tgen.gears['PE1']
357
358 pe1.run('ip link set dev vxlan100 down')
359
360 result, assertmsg = evpn_gateway_ip_show_op_check("no_rt2")
361 if result is not None:
362 generate_support_bundle()
363 assert result is None, assertmsg
364
365 step("Bring up VxLAN interface at PE1 and advertise type-2 routes again")
366
367 pe1.run('ip link set dev vxlan100 up')
368
369 result, assertmsg = evpn_gateway_ip_show_op_check("base")
370 if result is not None:
371 generate_support_bundle()
372 assert result is None, assertmsg
373
374 write_test_footer(tc_name)
375
376
377 def test_memory_leak():
378 """Run the memory leak test and report results"""
379 tgen = get_topogen()
380 if not tgen.is_memleak_enabled():
381 pytest.skip("Memory leak test/report is disabled")
382
383 tgen.report_memory_leaks()
384
385 if __name__ == "__main__":
386 args = ["-s"] + sys.argv[1:]
387 sys.exit(pytest.main(args))