diff options
25 files changed, 646 insertions, 17 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index a1d0a8512c..b03171b4c8 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -3734,6 +3734,9 @@ void vpn_leak_postchange_all(void) if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF) continue; + if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) + continue; + vpn_leak_postchange( BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, @@ -3753,6 +3756,9 @@ void vpn_leak_postchange_all(void) if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF) continue; + if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) + continue; + vpn_leak_postchange( BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index ae14abe9e3..828fa711b2 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1703,7 +1703,7 @@ DEFUN (no_router_bgp, continue; if (CHECK_FLAG(tmp_bgp->vrf_flags, BGP_VRF_AUTO)) - continue; + bgp_delete(tmp_bgp); if (CHECK_FLAG( tmp_bgp->af_flags[AFI_IP] diff --git a/tests/topotests/bgp_duplicate_nexthop/r1/bgpd.conf b/tests/topotests/bgp_duplicate_nexthop/r1/bgpd.conf index 31f06dbb90..8084962587 100644 --- a/tests/topotests/bgp_duplicate_nexthop/r1/bgpd.conf +++ b/tests/topotests/bgp_duplicate_nexthop/r1/bgpd.conf @@ -1,5 +1,6 @@ router bgp 64500 bgp router-id 192.0.2.1 + timers bgp 3 9 no bgp ebgp-requires-policy neighbor rrserver peer-group neighbor rrserver remote-as 64500 diff --git a/tests/topotests/bgp_duplicate_nexthop/r3/bgpd.conf b/tests/topotests/bgp_duplicate_nexthop/r3/bgpd.conf index 2b03f51a23..7312dba407 100644 --- a/tests/topotests/bgp_duplicate_nexthop/r3/bgpd.conf +++ b/tests/topotests/bgp_duplicate_nexthop/r3/bgpd.conf @@ -1,4 +1,5 @@ router bgp 64500 view one + timers bgp 3 9 bgp router-id 192.0.2.3 neighbor rr peer-group neighbor rr remote-as 64500 diff --git a/tests/topotests/bgp_duplicate_nexthop/r5/bgpd.conf b/tests/topotests/bgp_duplicate_nexthop/r5/bgpd.conf index 272183b1ac..e46d7c5ed4 100644 --- a/tests/topotests/bgp_duplicate_nexthop/r5/bgpd.conf +++ b/tests/topotests/bgp_duplicate_nexthop/r5/bgpd.conf @@ -1,4 +1,5 @@ router bgp 64500 + timers bgp 3 9 bgp router-id 192.0.2.5 no bgp ebgp-requires-policy no bgp network import-check diff --git a/tests/topotests/bgp_duplicate_nexthop/r6/bgpd.conf b/tests/topotests/bgp_duplicate_nexthop/r6/bgpd.conf index 68bd36eb8a..3aa9adb18b 100644 --- a/tests/topotests/bgp_duplicate_nexthop/r6/bgpd.conf +++ b/tests/topotests/bgp_duplicate_nexthop/r6/bgpd.conf @@ -1,4 +1,5 @@ router bgp 64500 + timers bgp 3 9 bgp router-id 192.0.2.6 no bgp ebgp-requires-policy no bgp network import-check diff --git a/tests/topotests/bgp_duplicate_nexthop/test_bgp_duplicate_nexthop.py b/tests/topotests/bgp_duplicate_nexthop/test_bgp_duplicate_nexthop.py index 83fae71bf5..b458c64e33 100644 --- a/tests/topotests/bgp_duplicate_nexthop/test_bgp_duplicate_nexthop.py +++ b/tests/topotests/bgp_duplicate_nexthop/test_bgp_duplicate_nexthop.py @@ -212,7 +212,7 @@ def check_ipv4_prefix_with_multiple_nexthops(prefix, multipath=True): test_func = functools.partial( ip_check_path_selection, tgen.gears["r1"], prefix, expected ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=120, wait=0.5) assert ( result is None ), f"Failed to check that {prefix} uses the IGP label 16055 and 16006" diff --git a/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py b/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py index cf1d3cb2b8..146687d588 100644 --- a/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py +++ b/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py @@ -151,17 +151,28 @@ def teardown_module(_mod): tgen.stop_topology() -def check_bgp_vpnv4_prefix_presence(router, prefix): +def check_bgp_vpnv4_prefix_presence(router, prefix, table_version): "Check the presence of a prefix" tgen = get_topogen() dump = router.vtysh_cmd("show bgp ipv4 vpn {} json".format(prefix), isjson=True) if not dump: return "{}, prefix ipv4 vpn {} is not installed yet".format(router.name, prefix) + + for _, paths in dump.items(): + for path in paths["paths"]: + new_version = path["version"] + if new_version <= table_version: + return "{}, prefix ipv4 vpn {} has not been updated yet".format( + router.name, prefix + ) + return None -def bgp_vpnv4_table_check(router, group, label_list=None, label_value_expected=None): +def bgp_vpnv4_table_check( + router, group, label_list=None, label_value_expected=None, table_version=0 +): """ Dump and check that vpnv4 entries have the same MPLS label value * 'router': the router to check @@ -173,7 +184,9 @@ def bgp_vpnv4_table_check(router, group, label_list=None, label_value_expected=N stored_label_inited = False for prefix in group: - test_func = functools.partial(check_bgp_vpnv4_prefix_presence, router, prefix) + test_func = functools.partial( + check_bgp_vpnv4_prefix_presence, router, prefix, table_version + ) success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5) assert success, "{}, prefix ipv4 vpn {} is not installed yet".format( router.name, prefix @@ -218,7 +231,7 @@ def bgp_vpnv4_table_check(router, group, label_list=None, label_value_expected=N ) -def bgp_vpnv4_table_check_all(router, label_list=None, same=False): +def bgp_vpnv4_table_check_all(router, label_list=None, same=False, table_version=0): """ Dump and check that vpnv4 entries are correctly configured with specific label values * 'router': the router to check @@ -236,6 +249,7 @@ def bgp_vpnv4_table_check_all(router, label_list=None, same=False): + PREFIXES_REDIST + PREFIXES_CONNECTED, label_list=label_list, + table_version=table_version, ) else: for group in ( @@ -245,7 +259,9 @@ def bgp_vpnv4_table_check_all(router, label_list=None, same=False): PREFIXES_REDIST, PREFIXES_CONNECTED, ): - bgp_vpnv4_table_check(router, group=group, label_list=label_list) + bgp_vpnv4_table_check( + router, group=group, label_list=label_list, table_version=table_version + ) def check_show_mpls_table(router, blacklist=None, label_list=None, whitelist=None): @@ -350,6 +366,11 @@ def check_show_mpls_table_entry_label_not_found(router, inlabel): return None +def get_table_version(router): + table = router.vtysh_cmd("show bgp ipv4 vpn json", isjson=True) + return table["tableVersion"] + + def mpls_entry_get_interface(router, label): """ Assert that the label is in MPLS table @@ -686,6 +707,7 @@ def test_changing_default_label_value(): old_len != 1 ), "r1, number of labels used should be greater than 1, oberved {} ".format(old_len) + table_version = get_table_version(router) logger.info("r1, vrf1, changing the default MPLS label value to export to 222") router.vtysh_cmd( "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nlabel vpn export 222\n", @@ -705,7 +727,7 @@ def test_changing_default_label_value(): # check label repartition is ok logger.info("r1, vpnv4 table, check the number of labels used after modification") label_list = set() - bgp_vpnv4_table_check_all(router, label_list) + bgp_vpnv4_table_check_all(router, label_list, table_version=table_version) new_len = len(label_list) assert ( old_len == new_len @@ -734,6 +756,7 @@ def test_unconfigure_allocation_mode_nexthop(): logger.info("Unconfiguring allocation mode per nexthop") router = tgen.gears["r1"] + table_version = get_table_version(router) router.vtysh_cmd( "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nno label vpn export allocation-mode per-nexthop\n", isjson=False, @@ -752,7 +775,9 @@ def test_unconfigure_allocation_mode_nexthop(): # Check vpnv4 routes from r1 logger.info("Checking vpnv4 routes on r1") label_list = set() - bgp_vpnv4_table_check_all(router, label_list=label_list, same=True) + bgp_vpnv4_table_check_all( + router, label_list=label_list, same=True, table_version=table_version + ) assert len(label_list) == 1, "r1, multiple Label values found for vpnv4 updates" new_label = label_list.pop() @@ -782,6 +807,8 @@ def test_reconfigure_allocation_mode_nexthop(): logger.info("Reconfiguring allocation mode per nexthop") router = tgen.gears["r1"] + + table_version = get_table_version(router) router.vtysh_cmd( "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nlabel vpn export allocation-mode per-nexthop\n", isjson=False, @@ -800,7 +827,9 @@ def test_reconfigure_allocation_mode_nexthop(): # Check vpnv4 routes from r1 logger.info("Checking vpnv4 routes on r1") label_list = set() - bgp_vpnv4_table_check_all(router, label_list=label_list) + bgp_vpnv4_table_check_all( + router, label_list=label_list, table_version=table_version + ) assert len(label_list) != 1, "r1, only 1 label values found for vpnv4 updates" # Check mpls table with all values diff --git a/tests/topotests/bgp_vpnv6_per_nexthop_label/test_bgp_vpnv6_per_nexthop_label.py b/tests/topotests/bgp_vpnv6_per_nexthop_label/test_bgp_vpnv6_per_nexthop_label.py index f8d26427eb..5fef6e9e60 100644 --- a/tests/topotests/bgp_vpnv6_per_nexthop_label/test_bgp_vpnv6_per_nexthop_label.py +++ b/tests/topotests/bgp_vpnv6_per_nexthop_label/test_bgp_vpnv6_per_nexthop_label.py @@ -150,17 +150,28 @@ def teardown_module(_mod): tgen.stop_topology() -def check_bgp_vpnv6_prefix_presence(router, prefix): +def check_bgp_vpnv6_prefix_presence(router, prefix, table_version): "Check the presence of a prefix" tgen = get_topogen() dump = router.vtysh_cmd("show bgp ipv6 vpn {} json".format(prefix), isjson=True) if not dump: return "{}, prefix ipv6 vpn {} is not installed yet".format(router.name, prefix) + + for _, paths in dump.items(): + for path in paths["paths"]: + new_version = path["version"] + if new_version <= table_version: + return "{}, prefix ipv6 vpn {} has not been updated yet".format( + router.name, prefix + ) + return None -def bgp_vpnv6_table_check(router, group, label_list=None, label_value_expected=None): +def bgp_vpnv6_table_check( + router, group, label_list=None, label_value_expected=None, table_version=0 +): """ Dump and check that vpnv6 entries have the same MPLS label value * 'router': the router to check @@ -172,7 +183,9 @@ def bgp_vpnv6_table_check(router, group, label_list=None, label_value_expected=N stored_label_inited = False for prefix in group: - test_func = functools.partial(check_bgp_vpnv6_prefix_presence, router, prefix) + test_func = functools.partial( + check_bgp_vpnv6_prefix_presence, router, prefix, table_version + ) success, _ = topotest.run_and_expect(test_func, None, count=10, wait=0.5) assert success, "{}, prefix ipv6 vpn {} is not installed yet".format( router.name, prefix @@ -214,7 +227,7 @@ def bgp_vpnv6_table_check(router, group, label_list=None, label_value_expected=N ) -def bgp_vpnv6_table_check_all(router, label_list=None, same=False): +def bgp_vpnv6_table_check_all(router, label_list=None, same=False, table_version=0): """ Dump and check that vpnv6 entries are correctly configured with specific label values * 'router': the router to check @@ -231,6 +244,7 @@ def bgp_vpnv6_table_check_all(router, label_list=None, same=False): + PREFIXES_REDIST_R14 + PREFIXES_CONNECTED, label_list=label_list, + table_version=table_version, ) else: for group in ( @@ -239,7 +253,9 @@ def bgp_vpnv6_table_check_all(router, label_list=None, same=False): PREFIXES_REDIST_R14, PREFIXES_CONNECTED, ): - bgp_vpnv6_table_check(router, group=group, label_list=label_list) + bgp_vpnv6_table_check( + router, group=group, label_list=label_list, table_version=table_version + ) def check_show_mpls_table(router, blacklist=None, label_list=None, whitelist=None): @@ -345,6 +361,11 @@ def check_show_mpls_table_entry_label_not_found(router, inlabel): return None +def get_table_version(router): + table = router.vtysh_cmd("show bgp ipv6 vpn json", isjson=True) + return table["tableVersion"] + + def mpls_entry_get_interface(router, label): """ Assert that the label is in MPLS table @@ -691,6 +712,7 @@ def test_changing_default_label_value(): old_len != 1 ), "r1, number of labels used should be greater than 1, oberved {} ".format(old_len) + table_version = get_table_version(router) logger.info("r1, vrf1, changing the default MPLS label value to export to 222") router.vtysh_cmd( "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv6 unicast\nlabel vpn export 222\n", @@ -710,7 +732,7 @@ def test_changing_default_label_value(): # check label repartition is ok logger.info("r1, VPNv6 table, check the number of labels used after modification") label_list = set() - bgp_vpnv6_table_check_all(router, label_list) + bgp_vpnv6_table_check_all(router, label_list, table_version=table_version) new_len = len(label_list) assert ( old_len == new_len @@ -786,6 +808,7 @@ def test_reconfigure_allocation_mode_nexthop(): logger.info("Reconfiguring allocation mode per nexthop") router = tgen.gears["r1"] + table_version = get_table_version(router) dump = router.vtysh_cmd( "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv6 unicast\nlabel vpn export allocation-mode per-nexthop\n", isjson=False, @@ -804,7 +827,9 @@ def test_reconfigure_allocation_mode_nexthop(): # Check vpnv6 routes from r1 logger.info("Checking VPNv6 routes on r1") label_list = set() - bgp_vpnv6_table_check_all(router, label_list=label_list) + bgp_vpnv6_table_check_all( + router, label_list=label_list, table_version=table_version + ) assert len(label_list) != 1, "r1, only 1 label values found for VPNv6 updates" # Check mpls table with all values diff --git a/tests/topotests/msdp_topo2/r1/bgpd.conf b/tests/topotests/msdp_topo2/r1/bgpd.conf new file mode 100644 index 0000000000..67f04d8eab --- /dev/null +++ b/tests/topotests/msdp_topo2/r1/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.1.2 remote-as 65002 + neighbor 192.168.3.3 remote-as 65003 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo2/r1/pimd.conf b/tests/topotests/msdp_topo2/r1/pimd.conf new file mode 100644 index 0000000000..58a4c21e40 --- /dev/null +++ b/tests/topotests/msdp_topo2/r1/pimd.conf @@ -0,0 +1,20 @@ +! debug pim +! debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.1 +! +interface r1-eth0 + ip pim +! +interface r1-eth1 + ip pim +! +interface r1-eth2 + ip pim + ip igmp +! +ip msdp peer 192.168.1.2 source 192.168.1.1 +ip msdp peer 192.168.3.3 source 192.168.3.1 +ip pim rp 10.254.254.1 diff --git a/tests/topotests/msdp_topo2/r1/zebra.conf b/tests/topotests/msdp_topo2/r1/zebra.conf new file mode 100644 index 0000000000..3219fad36d --- /dev/null +++ b/tests/topotests/msdp_topo2/r1/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +! +interface r1-eth0 + ip address 192.168.1.1/24 +! +interface r1-eth1 + ip address 192.168.3.1/24 +! +interface r1-eth2 + ip address 192.168.6.1/24 +! +interface lo + ip address 10.254.254.1/32 +! diff --git a/tests/topotests/msdp_topo2/r2/bgpd.conf b/tests/topotests/msdp_topo2/r2/bgpd.conf new file mode 100644 index 0000000000..b9f316898c --- /dev/null +++ b/tests/topotests/msdp_topo2/r2/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as 65001 + neighbor 192.168.2.5 remote-as 65005 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo2/r2/pimd.conf b/tests/topotests/msdp_topo2/r2/pimd.conf new file mode 100644 index 0000000000..66e630264c --- /dev/null +++ b/tests/topotests/msdp_topo2/r2/pimd.conf @@ -0,0 +1,16 @@ +! debug pim +! debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.2 +! +interface r2-eth0 + ip pim +! +interface r2-eth1 + ip pim +! +ip msdp peer 192.168.1.1 source 192.168.1.2 +ip msdp peer 192.168.2.5 source 192.168.2.2 +ip pim rp 10.254.254.2 diff --git a/tests/topotests/msdp_topo2/r2/zebra.conf b/tests/topotests/msdp_topo2/r2/zebra.conf new file mode 100644 index 0000000000..740b51a4f0 --- /dev/null +++ b/tests/topotests/msdp_topo2/r2/zebra.conf @@ -0,0 +1,11 @@ +ip forwarding +! +interface r2-eth0 + ip address 192.168.1.2/24 +! +interface r2-eth1 + ip address 192.168.2.2/24 +! +interface lo + ip address 10.254.254.2/32 +! diff --git a/tests/topotests/msdp_topo2/r3/bgpd.conf b/tests/topotests/msdp_topo2/r3/bgpd.conf new file mode 100644 index 0000000000..ecd25b050e --- /dev/null +++ b/tests/topotests/msdp_topo2/r3/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65003 + no bgp ebgp-requires-policy + neighbor 192.168.3.1 remote-as 65001 + neighbor 192.168.4.4 remote-as 65004 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo2/r3/pimd.conf b/tests/topotests/msdp_topo2/r3/pimd.conf new file mode 100644 index 0000000000..e8e53268e3 --- /dev/null +++ b/tests/topotests/msdp_topo2/r3/pimd.conf @@ -0,0 +1,16 @@ +! debug pim +! debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.3 +! +interface r3-eth0 + ip pim +! +interface r3-eth1 + ip pim +! +ip msdp peer 192.168.3.1 source 192.168.3.3 +ip msdp peer 192.168.4.4 source 192.168.4.3 +ip pim rp 10.254.254.3 diff --git a/tests/topotests/msdp_topo2/r3/zebra.conf b/tests/topotests/msdp_topo2/r3/zebra.conf new file mode 100644 index 0000000000..d1be65f636 --- /dev/null +++ b/tests/topotests/msdp_topo2/r3/zebra.conf @@ -0,0 +1,11 @@ +ip forwarding +! +interface r3-eth0 + ip address 192.168.3.3/24 +! +interface r3-eth1 + ip address 192.168.4.3/24 +! +interface lo + ip address 10.254.254.3/32 +! diff --git a/tests/topotests/msdp_topo2/r4/bgpd.conf b/tests/topotests/msdp_topo2/r4/bgpd.conf new file mode 100644 index 0000000000..430517bc2b --- /dev/null +++ b/tests/topotests/msdp_topo2/r4/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65004 + no bgp ebgp-requires-policy + neighbor 192.168.4.3 remote-as 65003 + neighbor 192.168.5.5 remote-as 65005 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo2/r4/pimd.conf b/tests/topotests/msdp_topo2/r4/pimd.conf new file mode 100644 index 0000000000..32e3c613fa --- /dev/null +++ b/tests/topotests/msdp_topo2/r4/pimd.conf @@ -0,0 +1,16 @@ +! debug pim +! debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.4 +! +interface r4-eth0 + ip pim +! +interface r4-eth1 + ip pim +! +ip msdp peer 192.168.4.3 source 192.168.4.4 +ip msdp peer 192.168.5.5 source 192.168.5.4 +ip pim rp 10.254.254.4 diff --git a/tests/topotests/msdp_topo2/r4/zebra.conf b/tests/topotests/msdp_topo2/r4/zebra.conf new file mode 100644 index 0000000000..045d2e8070 --- /dev/null +++ b/tests/topotests/msdp_topo2/r4/zebra.conf @@ -0,0 +1,11 @@ +ip forwarding +! +interface r4-eth0 + ip address 192.168.4.4/24 +! +interface r4-eth1 + ip address 192.168.5.4/24 +! +interface lo + ip address 10.254.254.4/32 +! diff --git a/tests/topotests/msdp_topo2/r5/bgpd.conf b/tests/topotests/msdp_topo2/r5/bgpd.conf new file mode 100644 index 0000000000..053dd3d3ef --- /dev/null +++ b/tests/topotests/msdp_topo2/r5/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65005 + no bgp ebgp-requires-policy + neighbor 192.168.2.2 remote-as 65002 + neighbor 192.168.5.4 remote-as 65004 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo2/r5/pimd.conf b/tests/topotests/msdp_topo2/r5/pimd.conf new file mode 100644 index 0000000000..e6cdd14c82 --- /dev/null +++ b/tests/topotests/msdp_topo2/r5/pimd.conf @@ -0,0 +1,20 @@ +! debug pim +! debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.5 +! +interface r5-eth0 + ip pim +! +interface r5-eth1 + ip pim +! +interface r5-eth2 + ip pim + ip igmp +! +ip msdp peer 192.168.2.2 source 192.168.2.5 +ip msdp peer 192.168.5.4 source 192.168.5.5 +ip pim rp 10.254.254.5 diff --git a/tests/topotests/msdp_topo2/r5/zebra.conf b/tests/topotests/msdp_topo2/r5/zebra.conf new file mode 100644 index 0000000000..195e003510 --- /dev/null +++ b/tests/topotests/msdp_topo2/r5/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +! +interface r5-eth0 + ip address 192.168.2.5/24 +! +interface r5-eth1 + ip address 192.168.5.5/24 +! +interface r5-eth2 + ip address 192.168.7.5/24 +! +interface lo + ip address 10.254.254.5/32 +! diff --git a/tests/topotests/msdp_topo2/test_msdp_topo2.py b/tests/topotests/msdp_topo2/test_msdp_topo2.py new file mode 100755 index 0000000000..def5368f41 --- /dev/null +++ b/tests/topotests/msdp_topo2/test_msdp_topo2.py @@ -0,0 +1,376 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_msdp_topo1.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2024 by +# Adriano Marto Reis <adrianomarto@gmail.com> +# + +""" +test_msdp_topo2.py: Test the FRR PIM MSDP peer. + + ────────────────────► + shortest path + ┌──┐ + ┌───────┤r2├───────┐ +sender │ s1 └──┘ s2 │ receiver + ┌──┐ ┌─┴┐ ┌─┴┐ ┌──┐ + │h1├────┤r1│ │r5├────┤h2│ + └──┘ s6 └─┬┘ └─┬┘ s7 └──┘ + │ ┌──┐ ┌──┐ │ + └───┤r3├────┤r4├───┘ + s3 └──┘ s4 └──┘ s5 +""" + +import os +import sys +import json +from functools import partial +import pytest + +# 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 + +# Required to instantiate the topology builder class. +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +from lib.pim import McastTesterHelper + +pytestmark = [pytest.mark.bgpd, pytest.mark.pimd] + +app_helper = McastTesterHelper() + +MCAST_ADDR = "229.1.2.3" + +def build_topo(tgen): + "Build function" + + for routern in range(1, 6): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r5"]) + + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r3"]) + + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r4"]) + + switch = tgen.add_switch("s5") + switch.add_link(tgen.gears["r4"]) + switch.add_link(tgen.gears["r5"]) + + switch = tgen.add_switch("s6") + tgen.add_host("h1", "192.168.6.100/24", "via 192.168.6.1") + switch.add_link(tgen.gears["h1"]) + switch.add_link(tgen.gears["r1"]) + + switch = tgen.add_switch("s7") + tgen.add_host("h2", "192.168.7.100/24", "via 192.168.7.5") + switch.add_link(tgen.gears["h2"]) + switch.add_link(tgen.gears["r5"]) + + +def setup_module(mod): + "Sets up the pytest environment" + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + for rname, router in router_list.items(): + + daemon_file = "{}/{}/zebra.conf".format(CWD, rname) + if os.path.isfile(daemon_file): + router.load_config(TopoRouter.RD_ZEBRA, daemon_file) + + daemon_file = "{}/{}/bgpd.conf".format(CWD, rname) + if os.path.isfile(daemon_file): + router.load_config(TopoRouter.RD_BGP, daemon_file) + + daemon_file = "{}/{}/pimd.conf".format(CWD, rname) + if os.path.isfile(daemon_file): + router.load_config(TopoRouter.RD_PIM, daemon_file) + + tgen.start_router() + + app_helper.init(tgen) + + +def teardown_module(): + "Teardown the pytest environment" + tgen = get_topogen() + app_helper.cleanup() + tgen.stop_topology() + + +def test_bgp_convergence(): + """ + Wait for BGP protocol convergence + All the loopback addresses (10.254.254.x) must be reachable from all + routers. + """ + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + routes = { + "r1": "10.254.254.1/32", + "r2": "10.254.254.2/32", + "r3": "10.254.254.3/32", + "r4": "10.254.254.4/32", + "r5": "10.254.254.5/32", + } + + for router1 in routes.keys(): + for router2, route in routes.items(): + if router1 != router2: + logger.info("waiting route {} in {}".format(route, router1)) + test_func = partial( + topotest.router_json_cmp, + tgen.gears[router1], + "show ip route json", + {route: [{"protocol": "bgp"}]}, + ) + _, result = topotest.run_and_expect(test_func, None, count=130, wait=1) + assertmsg = '"{}" convergence failure'.format(router1) + assert result is None, assertmsg + + +def test_msdp_peers(): + """ + Waits for the MSPD peer connections to be established. + """ + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + expected_msdp_peers = { + "r1": { + "192.168.1.2": { + "peer": "192.168.1.2", + "local": "192.168.1.1", + "state": "established", + }, + "192.168.3.3": { + "peer": "192.168.3.3", + "local": "192.168.3.1", + "state": "established", + }, + }, + "r2": { + "192.168.1.1": { + "peer": "192.168.1.1", + "local": "192.168.1.2", + "state": "established", + }, + "192.168.2.5": { + "peer": "192.168.2.5", + "local": "192.168.2.2", + "state": "established", + }, + }, + "r3": { + "192.168.3.1": { + "peer": "192.168.3.1", + "local": "192.168.3.3", + "state": "established", + }, + "192.168.4.4": { + "peer": "192.168.4.4", + "local": "192.168.4.3", + "state": "established", + }, + }, + "r4": { + "192.168.4.3": { + "peer": "192.168.4.3", + "local": "192.168.4.4", + "state": "established", + }, + "192.168.5.5": { + "peer": "192.168.5.5", + "local": "192.168.5.4", + "state": "established", + }, + }, + "r5": { + "192.168.2.2": { + "peer": "192.168.2.2", + "local": "192.168.2.5", + "state": "established", + }, + "192.168.5.4": { + "peer": "192.168.5.4", + "local": "192.168.5.5", + "state": "established", + }, + }, + } + + for router, peers in expected_msdp_peers.items(): + logger.info("Waiting for {} msdp peer data".format(router)) + test_function = partial( + topotest.router_json_cmp, + tgen.gears[router], + "show ip msdp peer json", + peers, + ) + _, val = topotest.run_and_expect(test_function, None, count=30, wait=1) + assert val is None, "multicast route convergence failure" + + +def test_msdp_sa(): + """ + Waits for the MSDP SA to be propagated. + The MSDP SA must be present on all routers. The MSDP SA must indicate + the original RP. + """ + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + app_helper.run("h1", ["--send=0.7", MCAST_ADDR, "h1-eth0"]) + app_helper.run("h2", [MCAST_ADDR, "h2-eth0"]) + + expected_sa_r1 = { + MCAST_ADDR: { + "192.168.6.100": { + "source": "192.168.6.100", + "group": MCAST_ADDR, + "rp": "-", + "local": "yes", + } + } + } + + expected_sa_r2_r3_r4_r5 = { + MCAST_ADDR: { + "192.168.6.100": { + "source": "192.168.6.100", + "group": MCAST_ADDR, + "rp": "10.254.254.1", + "local": "no", + } + } + } + + expected_sa = { + "r1": expected_sa_r1, + "r2": expected_sa_r2_r3_r4_r5, + "r3": expected_sa_r2_r3_r4_r5, + "r4": expected_sa_r2_r3_r4_r5, + "r5": expected_sa_r2_r3_r4_r5, + } + + for router, sa in expected_sa.items(): + logger.info("Waiting for {} msdp peer data".format(router)) + test_function = partial( + topotest.router_json_cmp, + tgen.gears[router], + "show ip msdp sa json", + sa, + ) + _, val = topotest.run_and_expect(test_function, None, count=30, wait=1) + assert val is None, "multicast route convergence failure" + + +def test_mroute(): + """ + Wait for the multicast routes. + The multicast routes must connect the shortest path between h1 and h2: + h1 ─► r1 ─► r2 ─► r5 ─► h2 + + The routers r3 and r4 must have no multicast routes, as they are not + included in the shortest path between h1 and h2. + """ + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + app_helper.run("h1", ["--send=0.7", MCAST_ADDR, "h1-eth0"]) + app_helper.run("h2", [MCAST_ADDR, "h2-eth0"]) + + expected_mroutes = { + "r1": { + MCAST_ADDR: { + "192.168.6.100": { + "iif": "r1-eth2", + "oil": { + "r1-eth0": {"source": "192.168.6.100", "group": MCAST_ADDR}, + "r1-eth1": None, + }, + }, + }, + }, + "r2": { + MCAST_ADDR: { + "192.168.6.100": { + "iif": "r2-eth0", + "oil": { + "r2-eth1": {"source": "192.168.6.100", "group": MCAST_ADDR}, + }, + }, + }, + }, + "r3": { + }, + "r4": { + }, + "r5": { + MCAST_ADDR: { + "192.168.6.100": { + "iif": "r5-eth0", + "oil": { + "r5-eth1": None, + "r5-eth2": {"source": "192.168.6.100", "group": MCAST_ADDR}, + }, + }, + }, + }, + } + + for router, mroute in expected_mroutes.items(): + logger.info("Waiting for {} mroute data".format(router)) + test_function = partial( + topotest.router_json_cmp, + tgen.gears[router], + "show ip mroute json", + mroute, + ) + _, val = topotest.run_and_expect(test_function, None, count=30, wait=1) + assert val is None, "mroute convergence failure" + + +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip("Memory leak test/report is disabled") + tgen.report_memory_leaks() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) |
