]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/bgp_auth/test_bgp_auth2.py
tests: Break up test_bgp_auth.py into 4 test scripts
[mirror_frr.git] / tests / topotests / bgp_auth / test_bgp_auth2.py
1 #!/usr/bin/env python
2
3 #
4 # test_bgp_auth.py
5 # Part of NetDEF Topology Tests
6 #
7 # Copyright (c) 2020 by Volta Networks
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_auth.py: Test BGP Md5 Authentication
26
27 +------+
28 +--------| |--------+
29 | +------| R1 |------+ |
30 | | -----| |----+ | |
31 | | | +------+ | | |
32 | | | | | |
33 +------+ +------+
34 | |------------| |
35 | R2 |------------| R3 |
36 | |------------| |
37 +------+ +------+
38
39
40 setup is 3 routers with 3 links between each each link in a different vrf
41 Default, blue and red respectively
42 Tests check various fiddling with passwords and checking that the peer
43 establishment is as expected and passwords are not leaked across sockets
44 for bgp instances
45 """
46 # pylint: disable=C0413
47
48 import json
49 import os
50 import platform
51 import sys
52 from time import sleep
53
54 import pytest
55 from lib import common_config, topotest
56 from lib.common_config import (
57 save_initial_config_on_routers,
58 reset_with_new_configs,
59 )
60 from lib.topogen import Topogen, TopoRouter, get_topogen
61
62 pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
63
64 CWD = os.path.dirname(os.path.realpath(__file__))
65
66
67 def build_topo(tgen):
68 tgen.add_router("R1")
69 tgen.add_router("R2")
70 tgen.add_router("R3")
71
72 tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
73 tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
74 tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
75 tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
76 tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
77 tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
78 tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
79 tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
80 tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
81
82
83 def setup_module(mod):
84 "Sets up the pytest environment"
85 # This function initiates the topology build with Topogen...
86 tgen = Topogen(build_topo, mod.__name__)
87 # ... and here it calls Mininet initialization functions.
88 tgen.start_topology()
89
90 r1 = tgen.gears["R1"]
91 r2 = tgen.gears["R2"]
92 r3 = tgen.gears["R3"]
93
94 # blue vrf
95 r1.cmd_raises("ip link add blue type vrf table 1001")
96 r1.cmd_raises("ip link set up dev blue")
97 r2.cmd_raises("ip link add blue type vrf table 1001")
98 r2.cmd_raises("ip link set up dev blue")
99 r3.cmd_raises("ip link add blue type vrf table 1001")
100 r3.cmd_raises("ip link set up dev blue")
101
102 r1.cmd_raises("ip link add lo1 type dummy")
103 r1.cmd_raises("ip link set lo1 master blue")
104 r1.cmd_raises("ip link set up dev lo1")
105 r2.cmd_raises("ip link add lo1 type dummy")
106 r2.cmd_raises("ip link set up dev lo1")
107 r2.cmd_raises("ip link set lo1 master blue")
108 r3.cmd_raises("ip link add lo1 type dummy")
109 r3.cmd_raises("ip link set up dev lo1")
110 r3.cmd_raises("ip link set lo1 master blue")
111
112 r1.cmd_raises("ip link set R1-eth2 master blue")
113 r1.cmd_raises("ip link set R1-eth3 master blue")
114 r2.cmd_raises("ip link set R2-eth2 master blue")
115 r2.cmd_raises("ip link set R2-eth3 master blue")
116 r3.cmd_raises("ip link set R3-eth2 master blue")
117 r3.cmd_raises("ip link set R3-eth3 master blue")
118
119 r1.cmd_raises("ip link set up dev R1-eth2")
120 r1.cmd_raises("ip link set up dev R1-eth3")
121 r2.cmd_raises("ip link set up dev R2-eth2")
122 r2.cmd_raises("ip link set up dev R2-eth3")
123 r3.cmd_raises("ip link set up dev R3-eth2")
124 r3.cmd_raises("ip link set up dev R3-eth3")
125
126 # red vrf
127 r1.cmd_raises("ip link add red type vrf table 1002")
128 r1.cmd_raises("ip link set up dev red")
129 r2.cmd_raises("ip link add red type vrf table 1002")
130 r2.cmd_raises("ip link set up dev red")
131 r3.cmd_raises("ip link add red type vrf table 1002")
132 r3.cmd_raises("ip link set up dev red")
133
134 r1.cmd_raises("ip link add lo2 type dummy")
135 r1.cmd_raises("ip link set lo2 master red")
136 r1.cmd_raises("ip link set up dev lo2")
137 r2.cmd_raises("ip link add lo2 type dummy")
138 r2.cmd_raises("ip link set up dev lo2")
139 r2.cmd_raises("ip link set lo2 master red")
140 r3.cmd_raises("ip link add lo2 type dummy")
141 r3.cmd_raises("ip link set up dev lo2")
142 r3.cmd_raises("ip link set lo2 master red")
143
144 r1.cmd_raises("ip link set R1-eth4 master red")
145 r1.cmd_raises("ip link set R1-eth5 master red")
146 r2.cmd_raises("ip link set R2-eth4 master red")
147 r2.cmd_raises("ip link set R2-eth5 master red")
148 r3.cmd_raises("ip link set R3-eth4 master red")
149 r3.cmd_raises("ip link set R3-eth5 master red")
150
151 r1.cmd_raises("ip link set up dev R1-eth4")
152 r1.cmd_raises("ip link set up dev R1-eth5")
153 r2.cmd_raises("ip link set up dev R2-eth4")
154 r2.cmd_raises("ip link set up dev R2-eth5")
155 r3.cmd_raises("ip link set up dev R3-eth4")
156 r3.cmd_raises("ip link set up dev R3-eth5")
157
158 r1.cmd_raises("sysctl -w net.ipv4.tcp_l3mdev_accept=1")
159 r2.cmd_raises("sysctl -w net.ipv4.tcp_l3mdev_accept=1")
160 r3.cmd_raises("sysctl -w net.ipv4.tcp_l3mdev_accept=1")
161
162 # This is a sample of configuration loading.
163 router_list = tgen.routers()
164
165 # For all registered routers, load the zebra configuration file
166 for rname, router in router_list.items():
167 router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
168 router.load_config(TopoRouter.RD_OSPF)
169 router.load_config(TopoRouter.RD_BGP)
170
171 # After copying the configurations, this function loads configured daemons.
172 tgen.start_router()
173
174 # Save the initial router config. reset_config_on_routers will return to this config.
175 save_initial_config_on_routers(tgen)
176
177
178 def teardown_module(mod):
179 "Teardown the pytest environment"
180 tgen = get_topogen()
181
182 # This function tears down the whole topology.
183 tgen.stop_topology()
184
185
186 def vrf_str(vrf):
187 if vrf == "":
188 vrf_str = ""
189 else:
190 vrf_str = "vrf {}".format(vrf)
191
192 return vrf_str
193
194
195 def peer_name(rtr, prefix, vrf):
196 "generate VRF string for CLI"
197 if vrf == "":
198 vrf_str = ""
199 else:
200 vrf_str = "_" + vrf
201
202 if prefix == "yes":
203 if rtr == "R2":
204 return "TWO_GROUP" + vrf_str
205 else:
206 return "THREE_GROUP" + vrf_str
207 else:
208 if rtr == "R2":
209 return "2.2.2.2"
210 else:
211 return "3.3.3.3"
212
213
214 def print_diag(vrf):
215 "print failure disagnostics"
216
217 tgen = get_topogen()
218 router_list = tgen.routers()
219 for rname, router in router_list.items():
220 print(rname + ":")
221 print(router.vtysh_cmd("show run"))
222 print(router.vtysh_cmd("show ip route {}".format(vrf_str(vrf))))
223 print(router.vtysh_cmd("show bgp {} neighbor".format(vrf_str(vrf))))
224
225
226 @common_config.retry(retry_timeout=190)
227 def _check_neigh_state(router, peer, state, vrf=""):
228 "check BGP neighbor state on a router"
229
230 neigh_output = router.vtysh_cmd(
231 "show bgp {} neighbors {} json".format(vrf_str(vrf), peer)
232 )
233
234 peer_state = "Unknown"
235 neigh_output_json = json.loads(neigh_output)
236 if peer in neigh_output_json:
237 peer_state = neigh_output_json[peer]["bgpState"]
238 if peer_state == state:
239 return True
240 return "{} peer with {} expected state {} got {} ".format(
241 router.name, peer, state, peer_state
242 )
243
244
245 def check_neigh_state(router, peer, state, vrf=""):
246 "check BGP neighbor state on a router"
247
248 assertmsg = _check_neigh_state(router, peer, state, vrf)
249 assert assertmsg is True, assertmsg
250
251
252 def check_all_peers_established(vrf=""):
253 "standard check for extablished peers per vrf"
254
255 tgen = get_topogen()
256 r1 = tgen.gears["R1"]
257 r2 = tgen.gears["R2"]
258 r3 = tgen.gears["R3"]
259 # do r1 last as he might be the dynamic one
260 check_neigh_state(r2, "1.1.1.1", "Established", vrf)
261 check_neigh_state(r2, "3.3.3.3", "Established", vrf)
262 check_neigh_state(r3, "1.1.1.1", "Established", vrf)
263 check_neigh_state(r3, "2.2.2.2", "Established", vrf)
264 check_neigh_state(r1, "2.2.2.2", "Established", vrf)
265 check_neigh_state(r1, "3.3.3.3", "Established", vrf)
266
267
268 def check_vrf_peer_remove_passwords(vrf="", prefix="no"):
269 "selectively remove passwords checking state"
270
271 tgen = get_topogen()
272 r1 = tgen.gears["R1"]
273 r2 = tgen.gears["R2"]
274 r3 = tgen.gears["R3"]
275
276 check_all_peers_established(vrf)
277
278 r1.vtysh_cmd(
279 "conf t\nrouter bgp 65001 {}\nno neighbor {} password".format(
280 vrf_str(vrf), peer_name("R2", prefix, vrf)
281 )
282 )
283
284 check_neigh_state(r2, "1.1.1.1", "Connect", vrf)
285 check_neigh_state(r2, "3.3.3.3", "Established", vrf)
286 check_neigh_state(r3, "1.1.1.1", "Established", vrf)
287 check_neigh_state(r3, "2.2.2.2", "Established", vrf)
288 # don't check dynamic downed peers - they are removed
289 if prefix == "no":
290 check_neigh_state(r1, "2.2.2.2", "Connect", vrf)
291 check_neigh_state(r1, "3.3.3.3", "Established", vrf)
292
293 r2.vtysh_cmd(
294 "conf t\nrouter bgp 65002 {}\nno neighbor 1.1.1.1 password".format(vrf_str(vrf))
295 )
296 check_all_peers_established(vrf)
297
298 r1.vtysh_cmd(
299 "conf t\nrouter bgp 65001 {}\nno neighbor {} password".format(
300 vrf_str(vrf), peer_name("R3", prefix, vrf)
301 )
302 )
303 check_neigh_state(r2, "1.1.1.1", "Established", vrf)
304 check_neigh_state(r2, "3.3.3.3", "Established", vrf)
305 check_neigh_state(r3, "1.1.1.1", "Connect", vrf)
306 check_neigh_state(r3, "2.2.2.2", "Established", vrf)
307 check_neigh_state(r1, "2.2.2.2", "Established", vrf)
308 # don't check dynamic downed peers - they are removed
309 if prefix == "no":
310 check_neigh_state(r1, "3.3.3.3", "Connect", vrf)
311
312 r3.vtysh_cmd(
313 "conf t\nrouter bgp 65003 {}\nno neighbor 1.1.1.1 password".format(vrf_str(vrf))
314 )
315 check_all_peers_established(vrf)
316
317 r2.vtysh_cmd(
318 "conf t\nrouter bgp 65002 {}\nno neighbor 3.3.3.3 password".format(vrf_str(vrf))
319 )
320 check_neigh_state(r2, "1.1.1.1", "Established", vrf)
321 check_neigh_state(r2, "3.3.3.3", "Connect", vrf)
322 check_neigh_state(r3, "1.1.1.1", "Established", vrf)
323 check_neigh_state(r3, "2.2.2.2", "Connect", vrf)
324 check_neigh_state(r1, "2.2.2.2", "Established", vrf)
325 check_neigh_state(r1, "3.3.3.3", "Established", vrf)
326
327 r3.vtysh_cmd(
328 "conf t\nrouter bgp 65003 {}\nno neighbor 2.2.2.2 password".format(vrf_str(vrf))
329 )
330 check_all_peers_established(vrf)
331
332
333 def check_vrf_peer_change_passwords(vrf="", prefix="no"):
334 "selectively change passwords checking state"
335
336 tgen = get_topogen()
337 r1 = tgen.gears["R1"]
338 r2 = tgen.gears["R2"]
339 r3 = tgen.gears["R3"]
340 check_all_peers_established(vrf)
341
342 r1.vtysh_cmd(
343 "conf t\nrouter bgp 65001 {}\nneighbor {} password change1".format(
344 vrf_str(vrf), peer_name("R2", prefix, vrf)
345 )
346 )
347 check_neigh_state(r2, "1.1.1.1", "Connect", vrf)
348 check_neigh_state(r2, "3.3.3.3", "Established", vrf)
349 check_neigh_state(r3, "1.1.1.1", "Established", vrf)
350 check_neigh_state(r3, "2.2.2.2", "Established", vrf)
351 # don't check dynamic downed peers - they are removed
352 if prefix == "no":
353 check_neigh_state(r1, "2.2.2.2", "Connect", vrf)
354 check_neigh_state(r1, "3.3.3.3", "Established", vrf)
355
356 r2.vtysh_cmd(
357 "conf t\nrouter bgp 65002 {}\nneighbor 1.1.1.1 password change1".format(
358 vrf_str(vrf)
359 )
360 )
361 check_all_peers_established(vrf)
362
363 r1.vtysh_cmd(
364 "conf t\nrouter bgp 65001 {}\nneighbor {} password change2".format(
365 vrf_str(vrf), peer_name("R3", prefix, vrf)
366 )
367 )
368 check_neigh_state(r2, "1.1.1.1", "Established", vrf)
369 check_neigh_state(r2, "3.3.3.3", "Established", vrf)
370 check_neigh_state(r3, "1.1.1.1", "Connect", vrf)
371 check_neigh_state(r3, "2.2.2.2", "Established", vrf)
372 check_neigh_state(r1, "2.2.2.2", "Established", vrf)
373 # don't check dynamic downed peers - they are removed
374 if prefix == "no":
375 check_neigh_state(r1, "3.3.3.3", "Connect", vrf)
376
377 r3.vtysh_cmd(
378 "conf t\nrouter bgp 65003 {}\nneighbor 1.1.1.1 password change2".format(
379 vrf_str(vrf)
380 )
381 )
382 check_all_peers_established(vrf)
383
384 r2.vtysh_cmd(
385 "conf t\nrouter bgp 65002 {}\nneighbor 3.3.3.3 password change3".format(
386 vrf_str(vrf)
387 )
388 )
389 check_neigh_state(r2, "1.1.1.1", "Established", vrf)
390 check_neigh_state(r2, "3.3.3.3", "Connect", vrf)
391 check_neigh_state(r3, "1.1.1.1", "Established", vrf)
392 check_neigh_state(r3, "2.2.2.2", "Connect", vrf)
393 check_neigh_state(r1, "2.2.2.2", "Established", vrf)
394 check_neigh_state(r1, "3.3.3.3", "Established", vrf)
395
396 r3.vtysh_cmd(
397 "conf t\nrouter bgp 65003 {}\nneighbor 2.2.2.2 password change3".format(
398 vrf_str(vrf)
399 )
400 )
401 check_all_peers_established(vrf)
402
403
404 def test_vrf_prefix_peer_established(tgen):
405 "default vrf 3 peers same password with VRF prefix config"
406
407 # only supported in kernel > 5.3
408 if topotest.version_cmp(platform.release(), "5.3") < 0:
409 return
410
411 reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
412 check_all_peers_established("blue")
413
414
415 def test_vrf_prefix_peer_remove_passwords(tgen):
416 "selectively remove passwords checking state with VRF prefix config"
417
418 # only supported in kernel > 5.3
419 if topotest.version_cmp(platform.release(), "5.3") < 0:
420 return
421
422 reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
423 check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
424
425
426 def test_vrf_prefix_peer_change_passwords(tgen):
427 "selectively change passwords checking state with VRF prefix config"
428
429 # only supported in kernel > 5.3
430 if topotest.version_cmp(platform.release(), "5.3") < 0:
431 return
432
433 reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
434 check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
435
436
437 def test_multiple_vrf_peer_established(tgen):
438 "default vrf 3 peers same password with multiple VRFs"
439
440 reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
441 check_all_peers_established("blue")
442 check_all_peers_established("red")
443
444
445 def test_multiple_vrf_peer_remove_passwords(tgen):
446 "selectively remove passwords checking state with multiple VRFs"
447
448 reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
449 check_vrf_peer_remove_passwords("blue")
450 check_all_peers_established("red")
451 check_vrf_peer_remove_passwords("red")
452 check_all_peers_established("blue")
453
454
455 def test_memory_leak(tgen):
456 "Run the memory leak test and report results."
457 if not tgen.is_memleak_enabled():
458 pytest.skip("Memory leak test/report is disabled")
459
460 tgen.report_memory_leaks()
461
462
463 if __name__ == "__main__":
464 args = ["-s"] + sys.argv[1:]
465 sys.exit(pytest.main(args))