]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/bgp_auth/test_bgp_auth.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2020 by Volta Networks
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
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
25 test_bgp_auth.py: Test BGP Md5 Authentication
29 | +------| R1 |------+ |
35 | R2 |------------| R3 |
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
52 from time
import sleep
54 # Save the Current Working Directory to find configuration files.
55 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
56 sys
.path
.append(os
.path
.join(CWD
, "../"))
58 # pylint: disable=C0413
59 # Import topogen and topotest helpers
60 from lib
import topotest
61 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
63 # Required to instantiate the topology builder class.
66 ERROR_LIST
= ["Malformed", "Failure", "Unknown", "Incomplete"]
68 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.ospfd
]
71 class InvalidCLIError(Exception):
72 """Raise when the CLI command is wrong"""
82 switch
= tgen
.add_switch("s1")
83 switch
.add_link(tgen
.gears
["R1"])
84 switch
.add_link(tgen
.gears
["R2"])
87 switch
= tgen
.add_switch("s2")
88 switch
.add_link(tgen
.gears
["R1"])
89 switch
.add_link(tgen
.gears
["R3"])
92 switch
= tgen
.add_switch("s3")
93 switch
.add_link(tgen
.gears
["R2"])
94 switch
.add_link(tgen
.gears
["R3"])
97 switch
= tgen
.add_switch("s4")
98 switch
.add_link(tgen
.gears
["R1"])
99 switch
.add_link(tgen
.gears
["R2"])
102 switch
= tgen
.add_switch("s5")
103 switch
.add_link(tgen
.gears
["R1"])
104 switch
.add_link(tgen
.gears
["R3"])
107 switch
= tgen
.add_switch("s6")
108 switch
.add_link(tgen
.gears
["R2"])
109 switch
.add_link(tgen
.gears
["R3"])
112 switch
= tgen
.add_switch("s7")
113 switch
.add_link(tgen
.gears
["R1"])
114 switch
.add_link(tgen
.gears
["R2"])
117 switch
= tgen
.add_switch("s8")
118 switch
.add_link(tgen
.gears
["R1"])
119 switch
.add_link(tgen
.gears
["R3"])
122 switch
= tgen
.add_switch("s9")
123 switch
.add_link(tgen
.gears
["R2"])
124 switch
.add_link(tgen
.gears
["R3"])
127 def setup_module(mod
):
128 "Sets up the pytest environment"
129 # This function initiates the topology build with Topogen...
130 tgen
= Topogen(build_topo
, mod
.__name
__)
131 # ... and here it calls Mininet initialization functions.
132 tgen
.start_topology()
134 r1
= tgen
.gears
["R1"]
135 r2
= tgen
.gears
["R2"]
136 r3
= tgen
.gears
["R3"]
139 r1
.run("ip link add blue type vrf table 1001")
140 r1
.run("ip link set up dev blue")
141 r2
.run("ip link add blue type vrf table 1001")
142 r2
.run("ip link set up dev blue")
143 r3
.run("ip link add blue type vrf table 1001")
144 r3
.run("ip link set up dev blue")
146 r1
.run("ip link add lo1 type dummy")
147 r1
.run("ip link set lo1 master blue")
148 r1
.run("ip link set up dev lo1")
149 r2
.run("ip link add lo1 type dummy")
150 r2
.run("ip link set up dev lo1")
151 r2
.run("ip link set lo1 master blue")
152 r3
.run("ip link add lo1 type dummy")
153 r3
.run("ip link set up dev lo1")
154 r3
.run("ip link set lo1 master blue")
156 r1
.run("ip link set R1-eth2 master blue")
157 r1
.run("ip link set R1-eth3 master blue")
158 r2
.run("ip link set R2-eth2 master blue")
159 r2
.run("ip link set R2-eth3 master blue")
160 r3
.run("ip link set R3-eth2 master blue")
161 r3
.run("ip link set R3-eth3 master blue")
163 r1
.run("ip link set up dev R1-eth2")
164 r1
.run("ip link set up dev R1-eth3")
165 r2
.run("ip link set up dev R2-eth2")
166 r2
.run("ip link set up dev R2-eth3")
167 r3
.run("ip link set up dev R3-eth2")
168 r3
.run("ip link set up dev R3-eth3")
171 r1
.run("ip link add red type vrf table 1002")
172 r1
.run("ip link set up dev red")
173 r2
.run("ip link add red type vrf table 1002")
174 r2
.run("ip link set up dev red")
175 r3
.run("ip link add red type vrf table 1002")
176 r3
.run("ip link set up dev red")
178 r1
.run("ip link add lo2 type dummy")
179 r1
.run("ip link set lo2 master red")
180 r1
.run("ip link set up dev lo2")
181 r2
.run("ip link add lo2 type dummy")
182 r2
.run("ip link set up dev lo2")
183 r2
.run("ip link set lo2 master red")
184 r3
.run("ip link add lo2 type dummy")
185 r3
.run("ip link set up dev lo2")
186 r3
.run("ip link set lo2 master red")
188 r1
.run("ip link set R1-eth4 master red")
189 r1
.run("ip link set R1-eth5 master red")
190 r2
.run("ip link set R2-eth4 master red")
191 r2
.run("ip link set R2-eth5 master red")
192 r3
.run("ip link set R3-eth4 master red")
193 r3
.run("ip link set R3-eth5 master red")
195 r1
.run("ip link set up dev R1-eth4")
196 r1
.run("ip link set up dev R1-eth5")
197 r2
.run("ip link set up dev R2-eth4")
198 r2
.run("ip link set up dev R2-eth5")
199 r3
.run("ip link set up dev R3-eth4")
200 r3
.run("ip link set up dev R3-eth5")
202 # This is a sample of configuration loading.
203 router_list
= tgen
.routers()
205 # For all registred routers, load the zebra configuration file
206 for rname
, router
in router_list
.items():
208 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
211 TopoRouter
.RD_OSPF
, os
.path
.join(CWD
, "{}/ospfd.conf".format(rname
))
214 TopoRouter
.RD_BGP
, os
.path
.join(CWD
, "{}/bgpd.conf".format(rname
))
217 # After loading the configurations, this function loads configured daemons.
221 def teardown_module(mod
):
222 "Teardown the pytest environment"
225 # This function tears down the whole topology.
233 vrf_str
= "vrf {}".format(vrf
)
238 def peer_name(rtr
, prefix
, vrf
):
239 "generate VRF string for CLI"
247 return "TWO_GROUP" + vrf_str
249 return "THREE_GROUP" + vrf_str
258 "print failure disagnostics"
261 router_list
= tgen
.routers()
262 for rname
, router
in router_list
.items():
264 print(router
.vtysh_cmd("show run"))
265 print(router
.vtysh_cmd("show ip route {}".format(vrf_str(vrf
))))
266 print(router
.vtysh_cmd("show bgp {} neighbor".format(vrf_str(vrf
))))
269 def configure(conf_file
):
270 "configure from a file"
273 router_list
= tgen
.routers()
274 for rname
, router
in router_list
.items():
276 os
.path
.join(CWD
, "{}/{}").format(router
.name
, conf_file
), "r+"
278 new_config
= cfg
.read()
280 output
= router
.vtysh_multicmd(new_config
, pretty_output
=False)
281 for out_err
in ERROR_LIST
:
282 if out_err
.lower() in output
.lower():
283 raise InvalidCLIError("%s" % output
)
287 "clear bgp configuration for a vrf"
290 r1
= tgen
.gears
["R1"]
291 r2
= tgen
.gears
["R2"]
292 r3
= tgen
.gears
["R3"]
294 r1
.vtysh_cmd("conf t\nno router bgp 65001")
295 r2
.vtysh_cmd("conf t\nno router bgp 65002")
296 r3
.vtysh_cmd("conf t\nno router bgp 65003")
297 r1
.vtysh_cmd("conf t\nno router bgp 65001 vrf blue")
298 r2
.vtysh_cmd("conf t\nno router bgp 65002 vrf blue")
299 r3
.vtysh_cmd("conf t\nno router bgp 65003 vrf blue")
300 r1
.vtysh_cmd("conf t\nno router bgp 65001 vrf red")
301 r2
.vtysh_cmd("conf t\nno router bgp 65002 vrf red")
302 r3
.vtysh_cmd("conf t\nno router bgp 65003 vrf red")
305 def configure_bgp(conf_file
):
306 "configure bgp from file"
313 "clear ospf configuration for a vrf"
316 router_list
= tgen
.routers()
317 for rname
, router
in router_list
.items():
318 router
.vtysh_cmd("conf t\nno router ospf")
319 router
.vtysh_cmd("conf t\nno router ospf vrf blue")
320 router
.vtysh_cmd("conf t\nno router ospf vrf red")
323 def configure_ospf(conf_file
):
324 "configure bgp from file"
330 def check_neigh_state(router
, peer
, state
, vrf
=""):
331 "check BGP neighbor state on a router"
338 neigh_output
= router
.vtysh_cmd("show bgp neighbors {} json".format(peer
))
340 neigh_output
= router
.vtysh_cmd(
341 "show bgp vrf {} neighbors {} json".format(vrf
, peer
)
343 neigh_output_json
= json
.loads(neigh_output
)
344 if peer
in neigh_output_json
.keys():
345 if neigh_output_json
[peer
]["bgpState"] == state
:
351 assertmsg
= "{} could not peer {} state expected {} got {} ".format(
352 router
.name
, peer
, state
, neigh_output_json
[peer
]["bgpState"]
356 assert matched
== True, assertmsg
359 def check_all_peers_established(vrf
=""):
360 "standard check for extablished peers per vrf"
363 r1
= tgen
.gears
["R1"]
364 r2
= tgen
.gears
["R2"]
365 r3
= tgen
.gears
["R3"]
366 # do r1 last as he might be the dynamic one
367 check_neigh_state(r2
, "1.1.1.1", "Established", vrf
)
368 check_neigh_state(r2
, "3.3.3.3", "Established", vrf
)
369 check_neigh_state(r3
, "1.1.1.1", "Established", vrf
)
370 check_neigh_state(r3
, "2.2.2.2", "Established", vrf
)
371 check_neigh_state(r1
, "2.2.2.2", "Established", vrf
)
372 check_neigh_state(r1
, "3.3.3.3", "Established", vrf
)
375 def check_vrf_peer_remove_passwords(vrf
="", prefix
="no"):
376 "selectively remove passwords checking state"
379 r1
= tgen
.gears
["R1"]
380 r2
= tgen
.gears
["R2"]
381 r3
= tgen
.gears
["R3"]
383 check_all_peers_established(vrf
)
386 "conf t\nrouter bgp 65001 {}\nno neighbor {} password".format(
387 vrf_str(vrf
), peer_name("R2", prefix
, vrf
)
391 check_neigh_state(r2
, "1.1.1.1", "Connect", vrf
)
392 check_neigh_state(r2
, "3.3.3.3", "Established", vrf
)
393 check_neigh_state(r3
, "1.1.1.1", "Established", vrf
)
394 check_neigh_state(r3
, "2.2.2.2", "Established", vrf
)
395 # don't check dynamic downed peers - they are removed
397 check_neigh_state(r1
, "2.2.2.2", "Connect", vrf
)
398 check_neigh_state(r1
, "3.3.3.3", "Established", vrf
)
401 "conf t\nrouter bgp 65002 {}\nno neighbor 1.1.1.1 password".format(vrf_str(vrf
))
403 check_all_peers_established(vrf
)
406 "conf t\nrouter bgp 65001 {}\nno neighbor {} password".format(
407 vrf_str(vrf
), peer_name("R3", prefix
, vrf
)
410 check_neigh_state(r2
, "1.1.1.1", "Established", vrf
)
411 check_neigh_state(r2
, "3.3.3.3", "Established", vrf
)
412 check_neigh_state(r3
, "1.1.1.1", "Connect", vrf
)
413 check_neigh_state(r3
, "2.2.2.2", "Established", vrf
)
414 check_neigh_state(r1
, "2.2.2.2", "Established", vrf
)
415 # don't check dynamic downed peers - they are removed
417 check_neigh_state(r1
, "3.3.3.3", "Connect", vrf
)
420 "conf t\nrouter bgp 65003 {}\nno neighbor 1.1.1.1 password".format(vrf_str(vrf
))
422 check_all_peers_established(vrf
)
425 "conf t\nrouter bgp 65002 {}\nno neighbor 3.3.3.3 password".format(vrf_str(vrf
))
427 check_neigh_state(r2
, "1.1.1.1", "Established", vrf
)
428 check_neigh_state(r2
, "3.3.3.3", "Connect", vrf
)
429 check_neigh_state(r3
, "1.1.1.1", "Established", vrf
)
430 check_neigh_state(r3
, "2.2.2.2", "Connect", vrf
)
431 check_neigh_state(r1
, "2.2.2.2", "Established", vrf
)
432 check_neigh_state(r1
, "3.3.3.3", "Established", vrf
)
435 "conf t\nrouter bgp 65003 {}\nno neighbor 2.2.2.2 password".format(vrf_str(vrf
))
437 check_all_peers_established(vrf
)
440 def check_vrf_peer_change_passwords(vrf
="", prefix
="no"):
441 "selectively change passwords checking state"
444 r1
= tgen
.gears
["R1"]
445 r2
= tgen
.gears
["R2"]
446 r3
= tgen
.gears
["R3"]
447 check_all_peers_established(vrf
)
450 "conf t\nrouter bgp 65001 {}\nneighbor {} password change1".format(
451 vrf_str(vrf
), peer_name("R2", prefix
, vrf
)
454 check_neigh_state(r2
, "1.1.1.1", "Connect", vrf
)
455 check_neigh_state(r2
, "3.3.3.3", "Established", vrf
)
456 check_neigh_state(r3
, "1.1.1.1", "Established", vrf
)
457 check_neigh_state(r3
, "2.2.2.2", "Established", vrf
)
458 # don't check dynamic downed peers - they are removed
460 check_neigh_state(r1
, "2.2.2.2", "Connect", vrf
)
461 check_neigh_state(r1
, "3.3.3.3", "Established", vrf
)
464 "conf t\nrouter bgp 65002 {}\nneighbor 1.1.1.1 password change1".format(
468 check_all_peers_established(vrf
)
471 "conf t\nrouter bgp 65001 {}\nneighbor {} password change2".format(
472 vrf_str(vrf
), peer_name("R3", prefix
, vrf
)
475 check_neigh_state(r2
, "1.1.1.1", "Established", vrf
)
476 check_neigh_state(r2
, "3.3.3.3", "Established", vrf
)
477 check_neigh_state(r3
, "1.1.1.1", "Connect", vrf
)
478 check_neigh_state(r3
, "2.2.2.2", "Established", vrf
)
479 check_neigh_state(r1
, "2.2.2.2", "Established", vrf
)
480 # don't check dynamic downed peers - they are removed
482 check_neigh_state(r1
, "3.3.3.3", "Connect", vrf
)
485 "conf t\nrouter bgp 65003 {}\nneighbor 1.1.1.1 password change2".format(
489 check_all_peers_established(vrf
)
492 "conf t\nrouter bgp 65002 {}\nneighbor 3.3.3.3 password change3".format(
496 check_neigh_state(r2
, "1.1.1.1", "Established", vrf
)
497 check_neigh_state(r2
, "3.3.3.3", "Connect", vrf
)
498 check_neigh_state(r3
, "1.1.1.1", "Established", vrf
)
499 check_neigh_state(r3
, "2.2.2.2", "Connect", vrf
)
500 check_neigh_state(r1
, "2.2.2.2", "Established", vrf
)
501 check_neigh_state(r1
, "3.3.3.3", "Established", vrf
)
504 "conf t\nrouter bgp 65003 {}\nneighbor 2.2.2.2 password change3".format(
508 check_all_peers_established(vrf
)
511 def test_default_peer_established():
512 "default vrf 3 peers same password"
514 configure_bgp("bgpd.conf")
515 configure_ospf("ospfd.conf")
516 check_all_peers_established()
520 def test_default_peer_remove_passwords():
521 "selectively remove passwords checking state"
523 configure_bgp("bgpd.conf")
524 configure_ospf("ospfd.conf")
525 check_vrf_peer_remove_passwords()
528 def test_default_peer_change_passwords():
529 "selectively change passwords checking state"
531 configure_bgp("bgpd.conf")
532 configure_ospf("ospfd.conf")
533 check_vrf_peer_change_passwords()
536 def test_default_prefix_peer_established():
537 "default vrf 3 peers same password with prefix config"
539 # only supported in kernel > 5.3
540 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
543 configure_bgp("bgpd_prefix.conf")
544 configure_ospf("ospfd.conf")
545 check_all_peers_established()
549 def test_prefix_peer_remove_passwords():
550 "selectively remove passwords checking state with prefix config"
552 # only supported in kernel > 5.3
553 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
556 configure_bgp("bgpd_prefix.conf")
557 configure_ospf("ospfd.conf")
558 check_vrf_peer_remove_passwords(prefix
="yes")
561 def test_prefix_peer_change_passwords():
562 "selecively change passwords checkig state with prefix config"
564 # only supported in kernel > 5.3
565 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
568 configure_bgp("bgpd_prefix.conf")
569 configure_ospf("ospfd.conf")
570 check_vrf_peer_change_passwords(prefix
="yes")
573 def test_vrf_peer_established():
574 "default vrf 3 peers same password with VRF config"
576 # clean routers and load vrf config
577 configure_bgp("bgpd_vrf.conf")
578 configure_ospf("ospfd_vrf.conf")
579 check_all_peers_established("blue")
583 def test_vrf_peer_remove_passwords():
584 "selectively remove passwords checking state with VRF config"
586 configure_bgp("bgpd_vrf.conf")
587 configure_ospf("ospfd_vrf.conf")
588 check_vrf_peer_remove_passwords(vrf
="blue")
591 def test_vrf_peer_change_passwords():
592 "selectively change passwords checking state with VRF config"
594 configure_bgp("bgpd_vrf.conf")
595 configure_ospf("ospfd_vrf.conf")
596 check_vrf_peer_change_passwords(vrf
="blue")
599 def test_vrf_prefix_peer_established():
600 "default vrf 3 peers same password with VRF prefix config"
602 # only supported in kernel > 5.3
603 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
606 configure_bgp("bgpd_vrf_prefix.conf")
607 configure_ospf("ospfd_vrf.conf")
608 check_all_peers_established("blue")
611 def test_vrf_prefix_peer_remove_passwords():
612 "selectively remove passwords checking state with VRF prefix config"
614 # only supported in kernel > 5.3
615 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
618 configure_bgp("bgpd_vrf_prefix.conf")
619 configure_ospf("ospfd_vrf.conf")
620 check_vrf_peer_remove_passwords(vrf
="blue", prefix
="yes")
623 def test_vrf_prefix_peer_change_passwords():
624 "selectively change passwords checking state with VRF prefix config"
626 # only supported in kernel > 5.3
627 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
630 configure_bgp("bgpd_vrf_prefix.conf")
631 configure_ospf("ospfd_vrf.conf")
632 check_vrf_peer_change_passwords(vrf
="blue", prefix
="yes")
635 def test_multiple_vrf_peer_established():
636 "default vrf 3 peers same password with multiple VRFs"
638 configure_bgp("bgpd_multi_vrf.conf")
639 configure_ospf("ospfd_multi_vrf.conf")
640 check_all_peers_established("blue")
641 check_all_peers_established("red")
645 def test_multiple_vrf_peer_remove_passwords():
646 "selectively remove passwords checking state with multiple VRFs"
648 configure_bgp("bgpd_multi_vrf.conf")
649 configure_ospf("ospfd_multi_vrf.conf")
650 check_vrf_peer_remove_passwords("blue")
651 check_all_peers_established("red")
652 check_vrf_peer_remove_passwords("red")
653 check_all_peers_established("blue")
657 def test_multiple_vrf_peer_change_passwords():
658 "selectively change passwords checking state with multiple VRFs"
660 configure_bgp("bgpd_multi_vrf.conf")
661 configure_ospf("ospfd_multi_vrf.conf")
662 check_vrf_peer_change_passwords("blue")
663 check_all_peers_established("red")
664 check_vrf_peer_change_passwords("red")
665 check_all_peers_established("blue")
669 def test_multiple_vrf_prefix_peer_established():
670 "default vrf 3 peers same password with multilpe VRFs and prefix config"
672 # only supported in kernel > 5.3
673 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
676 configure_bgp("bgpd_multi_vrf_prefix.conf")
677 configure_ospf("ospfd_multi_vrf.conf")
678 check_all_peers_established("blue")
679 check_all_peers_established("red")
683 def test_multiple_vrf_prefix_peer_remove_passwords():
684 "selectively remove passwords checking state with multiple vrfs and prefix config"
686 # only supported in kernel > 5.3
687 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
690 configure_bgp("bgpd_multi_vrf_prefix.conf")
691 configure_ospf("ospfd_multi_vrf.conf")
692 check_vrf_peer_remove_passwords(vrf
="blue", prefix
="yes")
693 check_all_peers_established("red")
694 check_vrf_peer_remove_passwords(vrf
="red", prefix
="yes")
695 check_all_peers_established("blue")
699 def test_multiple_vrf_prefix_peer_change_passwords():
700 "selectively change passwords checking state with multiple vrfs and prefix config"
702 # only supported in kernel > 5.3
703 if topotest
.version_cmp(platform
.release(), "5.3") < 0:
706 configure_bgp("bgpd_multi_vrf_prefix.conf")
707 configure_ospf("ospfd_multi_vrf.conf")
708 check_vrf_peer_change_passwords(vrf
="blue", prefix
="yes")
709 check_all_peers_established("red")
710 check_vrf_peer_change_passwords(vrf
="red", prefix
="yes")
711 check_all_peers_established("blue")
715 def test_memory_leak():
716 "Run the memory leak test and report results."
718 if not tgen
.is_memleak_enabled():
719 pytest
.skip("Memory leak test/report is disabled")
721 tgen
.report_memory_leaks()
724 if __name__
== "__main__":
725 args
= ["-s"] + sys
.argv
[1:]
726 sys
.exit(pytest
.main(args
))