diff options
Diffstat (limited to 'tests')
26 files changed, 803 insertions, 188 deletions
diff --git a/tests/topotests/bgp_aggregate_address_topo1/r1/bgp_192_168_0_1.json b/tests/topotests/bgp_aggregate_address_topo1/r1/bgp_192_168_0_1.json new file mode 100644 index 0000000000..8c0da8dc92 --- /dev/null +++ b/tests/topotests/bgp_aggregate_address_topo1/r1/bgp_192_168_0_1.json @@ -0,0 +1,41 @@ +{ + "prefix":"192.168.0.1/32", + "paths":[ + { + "aspath":{ + "string":"65001", + "segments":[ + { + "type":"as-sequence", + "list":[ + 65001 + ] + } + ], + "length":1 + }, + "suppressed":true, + "origin":"IGP", + "metric":10, + "valid":true, + "bestpath":{ + "overall":true, + "selectionReason":"First path received" + }, + "nexthops":[ + { + "ip":"10.0.0.2", + "afi":"ipv4", + "metric":0, + "accessible":true, + "used":true + } + ], + "peer":{ + "peerId":"10.0.0.2", + "routerId":"10.254.254.3", + "type":"external" + } + } + ] +} diff --git a/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py b/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py index 370d01e525..a0a1027c98 100644 --- a/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py +++ b/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py @@ -13,6 +13,7 @@ Test BGP aggregate address features. """ +import json import os import sys import pytest @@ -265,6 +266,24 @@ match ip address acl-sup-three ) +def test_check_bgp_attribute(): + "Dump the suppressed attribute of the 192.168.0.1/32 prefix in r1." + tgen = get_topogen() + + logger.info("Test that the BGP path to 192.168.0.1 is as expected.") + expected = json.loads(open("{}/r1/bgp_192_168_0_1.json".format(CWD)).read()) + + test_func = functools.partial( + topotest.router_json_cmp, + tgen.gears["r1"], + "show bgp ipv4 192.168.0.1/32 json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = '"r1" BGP 192.168.0.1 route output failed' + assert result is None, assertmsg + + def test_memory_leak(): "Run the memory leak test and report results." tgen = get_topogen() diff --git a/tests/topotests/bgp_bfd_session/r1/frr.conf b/tests/topotests/bgp_bfd_session/r1/frr.conf index a1560b09fa..cea1ff8147 100644 --- a/tests/topotests/bgp_bfd_session/r1/frr.conf +++ b/tests/topotests/bgp_bfd_session/r1/frr.conf @@ -11,4 +11,16 @@ router bgp 65000 neighbor 192.168.1.3 bfd neighbor 192.168.1.3 ebgp-multihop 20 neighbor 192.168.1.3 update-source r1-eth0 + neighbor PG peer-group + neighbor PG remote-as auto + neighbor PG bfd + neighbor PG ebgp-multihop 15 + neighbor PG update-source 10.0.0.1 + neighbor 192.168.1.4 peer-group PG + neighbor PG2 peer-group + neighbor PG2 remote-as auto + neighbor PG2 bfd + neighbor PG2 ebgp-multihop 25 + neighbor 192.168.1.5 peer-group PG2 + neighbor 192.168.1.5 update-source 10.0.0.1 exit diff --git a/tests/topotests/bgp_bfd_session/test_bgp_bfd_session.py b/tests/topotests/bgp_bfd_session/test_bgp_bfd_session.py index adf557af7b..0dbb2f089b 100644 --- a/tests/topotests/bgp_bfd_session/test_bgp_bfd_session.py +++ b/tests/topotests/bgp_bfd_session/test_bgp_bfd_session.py @@ -85,7 +85,29 @@ def test_bgp_bfd_session(): "diagnostic": "ok", "remote-diagnostic": "ok", "type": "dynamic", - } + }, + { + "multihop": True, + "peer": "192.168.1.4", + "local": "10.0.0.1", + "vrf": "default", + "minimum-ttl": 241, + "status": "down", + "diagnostic": "ok", + "remote-diagnostic": "ok", + "type": "dynamic", + }, + { + "multihop": True, + "peer": "192.168.1.5", + "local": "10.0.0.1", + "vrf": "default", + "minimum-ttl": 231, + "status": "down", + "diagnostic": "ok", + "remote-diagnostic": "ok", + "type": "dynamic", + }, ] return topotest.json_cmp(output, expected) diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp_1.py b/tests/topotests/bgp_bmp/test_bgp_bmp_1.py index be3e07929a..1d7aa97473 100644 --- a/tests/topotests/bgp_bmp/test_bgp_bmp_1.py +++ b/tests/topotests/bgp_bmp/test_bgp_bmp_1.py @@ -78,7 +78,7 @@ def setup_module(mod): "tcpdump -nni r1-eth0 -s 0 -w {} &".format(pcap_file), stdout=None ) - for rname, router in tgen.routers().items(): + for _, (rname, router) in enumerate(tgen.routers().items(), 1): logger.info("Loading router %s" % rname) router.load_frr_config( os.path.join(CWD, "{}/frr.conf".format(rname)), diff --git a/tests/topotests/bgp_dynamic_capability/r2/frr.conf b/tests/topotests/bgp_dynamic_capability/r2/frr.conf index 621e9381e3..cca07078ea 100644 --- a/tests/topotests/bgp_dynamic_capability/r2/frr.conf +++ b/tests/topotests/bgp_dynamic_capability/r2/frr.conf @@ -18,7 +18,6 @@ router bgp 65002 neighbor 192.168.1.1 timers connect 1 neighbor 192.168.1.1 capability dynamic neighbor 192.168.1.1 capability extended-nexthop - neighbor 192.168.1.1 addpath-rx-paths-limit 20 neighbor 2001:db8::1 remote-as external neighbor 2001:db8::1 timers 1 3 neighbor 2001:db8::1 timers connect 1 @@ -27,6 +26,9 @@ router bgp 65002 ! address-family ipv4 unicast redistribute connected + neighbor 192.168.1.1 addpath-tx-all-paths + neighbor 192.168.1.1 disable-addpath-rx + neighbor 192.168.1.1 addpath-rx-paths-limit 20 exit-address-family ! address-family ipv6 unicast diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_path_limit.py index 91df89b1b5..22e4fe687b 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_path_limit.py @@ -9,8 +9,6 @@ Test if Addpath/Paths-Limit capabilities are adjusted dynamically. T1: Enable Addpath/Paths-Limit capabilities and check if they are exchanged dynamically T2: Disable paths limit and check if it's exchanged dynamically -T3: Disable Addpath capability RX and check if it's exchanged dynamically -T4: Disable Addpath capability and check if it's exchanged dynamically """ import os @@ -65,12 +63,12 @@ def test_bgp_addpath_paths_limit(): "dynamic": "advertisedAndReceived", "addPath": { "ipv4Unicast": { - "txAdvertisedAndReceived": False, + "txAdvertisedAndReceived": True, "txAdvertised": True, - "txReceived": False, - "rxAdvertisedAndReceived": True, + "txReceived": True, + "rxAdvertisedAndReceived": False, "rxAdvertised": True, - "rxReceived": True, + "rxReceived": False, } }, "pathsLimit": { @@ -105,7 +103,6 @@ def test_bgp_addpath_paths_limit(): configure terminal router bgp address-family ipv4 unicast - neighbor 192.168.1.1 addpath-tx-all-paths neighbor 192.168.1.1 addpath-rx-paths-limit 21 """ ) @@ -122,9 +119,9 @@ def test_bgp_addpath_paths_limit(): "txAdvertisedAndReceived": True, "txAdvertised": True, "txReceived": True, - "rxAdvertisedAndReceived": True, + "rxAdvertisedAndReceived": False, "rxAdvertised": True, - "rxReceived": True, + "rxReceived": False, } }, "pathsLimit": { @@ -143,7 +140,7 @@ def test_bgp_addpath_paths_limit(): "messageStats": { "notificationsRecv": 0, "notificationsSent": 0, - "capabilityRecv": 2, + "capabilityRecv": 1, }, } } @@ -181,58 +178,6 @@ def test_bgp_addpath_paths_limit(): "txAdvertisedAndReceived": True, "txAdvertised": True, "txReceived": True, - "rxAdvertisedAndReceived": True, - "rxAdvertised": True, - "rxReceived": True, - } - }, - "pathsLimit": { - "ipv4Unicast": { - "advertisedAndReceived": True, - "advertisedPathsLimit": 10, - "receivedPathsLimit": 0, - } - }, - }, - "messageStats": { - "notificationsRecv": 0, - "notificationsSent": 0, - "capabilityRecv": 3, - }, - } - } - return topotest.json_cmp(output, expected) - - test_func = functools.partial( - _disable_paths_limit, - ) - _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) - assert result is None, "Something went wrong after disabling paths limit" - - ### - # T3: Disable Addpath capability RX and check if it's exchanged dynamically - ### - r2.vtysh_cmd( - """ - configure terminal - router bgp - address-family ipv4 unicast - neighbor 192.168.1.1 disable-addpath-rx - """ - ) - - def _disable_addpath_rx(): - output = json.loads(r1.vtysh_cmd("show bgp neighbor json")) - expected = { - "192.168.1.2": { - "bgpState": "Established", - "neighborCapabilities": { - "dynamic": "advertisedAndReceived", - "addPath": { - "ipv4Unicast": { - "txAdvertisedAndReceived": True, - "txAdvertised": True, - "txReceived": True, "rxAdvertisedAndReceived": False, "rxAdvertised": True, "rxReceived": False, @@ -249,63 +194,17 @@ def test_bgp_addpath_paths_limit(): "messageStats": { "notificationsRecv": 0, "notificationsSent": 0, - "capabilityRecv": 4, - }, - } - } - return topotest.json_cmp(output, expected) - - test_func = functools.partial( - _disable_addpath_rx, - ) - _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) - assert result is None, "Something went wrong after disabling Addpath RX flags" - - ### - # T4: Disable Addpath capability and check if it's exchanged dynamically - ### - r1.vtysh_cmd( - """ - configure terminal - router bgp - address-family ipv4 unicast - no neighbor 192.168.1.2 addpath-tx-all-paths - """ - ) - - def _disable_addpath(): - output = json.loads(r1.vtysh_cmd("show bgp neighbor json")) - expected = { - "192.168.1.2": { - "bgpState": "Established", - "neighborCapabilities": { - "dynamic": "advertisedAndReceived", - "addPath": { - "ipv4Unicast": { - "txAdvertisedAndReceived": False, - "txAdvertised": False, - "txReceived": True, - "rxAdvertisedAndReceived": False, - "rxAdvertised": True, - "rxReceived": False, - } - }, - }, - "messageStats": { - "notificationsRecv": 0, - "notificationsSent": 0, - "capabilitySent": 1, - "capabilityRecv": 4, + "capabilityRecv": 2, }, } } return topotest.json_cmp(output, expected) test_func = functools.partial( - _disable_addpath, + _disable_paths_limit, ) _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) - assert result is None, "Something went wrong when disabling Addpath capability" + assert result is None, "Something went wrong after disabling paths limit" if __name__ == "__main__": diff --git a/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes.json b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes.json index 7532ce9331..cfab5726ed 100644 --- a/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes.json +++ b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes.json @@ -2,8 +2,8 @@ "bgpLocalRouterId":"192.168.100.21", "defaultLocPrf":100, "localAS":65000, - "192.168.101.41:2":{ - "rd":"192.168.101.41:2", + "65000:201":{ + "rd":"65000:201", "[5]:[0]:[32]:[192.168.101.41]":{ "prefix":"[5]:[0]:[32]:[192.168.101.41]", "prefixLen":352, @@ -65,8 +65,8 @@ ] } }, - "192.168.102.21:2":{ - "rd":"192.168.102.21:2", + "65000:101":{ + "rd":"65000:101", "[5]:[0]:[32]:[192.168.102.21]":{ "prefix":"[5]:[0]:[32]:[192.168.102.21]", "prefixLen":352, diff --git a/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes_all.json b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes_all.json index a14ba1291e..444c67e442 100644 --- a/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes_all.json +++ b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes_all.json @@ -2,8 +2,8 @@ "bgpLocalRouterId":"192.168.100.21", "defaultLocPrf":100, "localAS":65000, - "192.168.101.41:2":{ - "rd":"192.168.101.41:2", + "65000:201":{ + "rd":"65000:201", "[5]:[0]:[32]:[192.168.101.41]":{ "prefix":"[5]:[0]:[32]:[192.168.101.41]", "prefixLen":352, @@ -125,8 +125,8 @@ ] } }, - "192.168.102.21:2":{ - "rd":"192.168.102.21:2", + "65000:101":{ + "rd":"65000:101", "[5]:[0]:[32]:[192.168.102.21]":{ "prefix":"[5]:[0]:[32]:[192.168.102.21]", "prefixLen":352, diff --git a/tests/topotests/bgp_evpn_rt5/r1/bgpd.conf b/tests/topotests/bgp_evpn_rt5/r1/frr.conf index c8c4faf222..e4a8059988 100644 --- a/tests/topotests/bgp_evpn_rt5/r1/bgpd.conf +++ b/tests/topotests/bgp_evpn_rt5/r1/frr.conf @@ -1,15 +1,36 @@ +! debug zebra vxlan +! debug zebra kernel +! debug zebra dplane +! debug zebra rib ! debug bgp neighbor-events ! debug bgp updates ! debug bgp zebra +vrf r1-vrf-101 + vni 101 + exit-vrf +! +interface r1-eth0 + ip address 192.168.100.21/24 +! +interface loop101 vrf r1-vrf-101 + ip address 192.168.102.21/32 + ipv6 address fd00::1/128 +! router bgp 65000 bgp router-id 192.168.100.21 bgp log-neighbor-changes no bgp default ipv4-unicast + no bgp ebgp-requires-policy neighbor 192.168.100.41 remote-as 65000 neighbor 192.168.100.41 capability extended-nexthop + neighbor 192.168.100.61 remote-as 65500 + neighbor 192.168.100.61 capability extended-nexthop ! address-family l2vpn evpn neighbor 192.168.100.41 activate + neighbor 192.168.100.41 route-map rmap_r1 in + neighbor 192.168.100.61 activate + neighbor 192.168.100.61 route-map rmap_r3 in advertise-all-vni exit-address-family ! @@ -24,7 +45,17 @@ router bgp 65000 vrf r1-vrf-101 network fd00::1/128 exit-address-family address-family l2vpn evpn + rd 65000:101 + route-target both 65:101 advertise ipv4 unicast advertise ipv6 unicast exit-address-family ! +route-map rmap_r3 deny 1 + match evpn vni 102 +exit +route-map rmap_r1 permit 1 + match evpn vni 101 +exit + + diff --git a/tests/topotests/bgp_evpn_rt5/r1/zebra.conf b/tests/topotests/bgp_evpn_rt5/r1/zebra.conf deleted file mode 100644 index c3d508c2b6..0000000000 --- a/tests/topotests/bgp_evpn_rt5/r1/zebra.conf +++ /dev/null @@ -1,23 +0,0 @@ -log stdout - -hostname r1 -password zebra - -! debug zebra vxlan -! debug zebra kernel -! debug zebra dplane -! debug zebra rib -log stdout -vrf r1-vrf-101 - vni 101 - exit-vrf -! -interface r1-eth0 - ip address 192.168.100.21/24 -! -interface loop101 vrf r1-vrf-101 - ip address 192.168.102.21/32 - ipv6 address fd00::1/128 -! - - diff --git a/tests/topotests/bgp_evpn_rt5/r2/bgp_l2vpn_evpn_routes.json b/tests/topotests/bgp_evpn_rt5/r2/bgp_l2vpn_evpn_routes.json index 597bca5fd3..3a55a7a38d 100644 --- a/tests/topotests/bgp_evpn_rt5/r2/bgp_l2vpn_evpn_routes.json +++ b/tests/topotests/bgp_evpn_rt5/r2/bgp_l2vpn_evpn_routes.json @@ -2,8 +2,8 @@ "bgpLocalRouterId":"192.168.100.41", "defaultLocPrf":100, "localAS":65000, - "192.168.101.41:2":{ - "rd":"192.168.101.41:2", + "65000:201":{ + "rd":"65000:201", "[5]:[0]:[32]:[192.168.101.41]":{ "prefix":"[5]:[0]:[32]:[192.168.101.41]", "prefixLen":352, @@ -63,8 +63,8 @@ ] } }, - "192.168.102.21:2":{ - "rd":"192.168.102.21:2", + "65000:101":{ + "rd":"65000:101", "[5]:[0]:[32]:[192.168.102.21]":{ "prefix":"[5]:[0]:[32]:[192.168.102.21]", "prefixLen":352, diff --git a/tests/topotests/bgp_evpn_rt5/r2/bgpd.conf b/tests/topotests/bgp_evpn_rt5/r2/frr.conf index 4f1d8e4a37..0bb4b7cab5 100644 --- a/tests/topotests/bgp_evpn_rt5/r2/bgpd.conf +++ b/tests/topotests/bgp_evpn_rt5/r2/frr.conf @@ -1,6 +1,19 @@ +! debug zebra vxlan ! debug bgp neighbor-events ! debug bgp updates ! debug bgp zebra + +vrf r2-vrf-101 + vni 101 + exit-vrf +! +interface loop101 vrf r2-vrf-101 + ip address 192.168.101.41/32 + ipv6 address fd00::2/128 +! +interface r2-eth0 + ip address 192.168.100.41/24 +! router bgp 65000 bgp router-id 192.168.100.41 bgp log-neighbor-changes @@ -27,6 +40,8 @@ router bgp 65000 vrf r2-vrf-101 network fd00::3/128 exit-address-family address-family l2vpn evpn + rd 65000:201 + route-target both 65:101 advertise ipv4 unicast route-map rmap4 advertise ipv6 unicast route-map rmap6 exit-address-family @@ -47,3 +62,4 @@ exit route-map rmap6 deny 2 match ipv6 address acl6_2 exit + diff --git a/tests/topotests/bgp_evpn_rt5/r2/zebra.conf b/tests/topotests/bgp_evpn_rt5/r2/zebra.conf deleted file mode 100644 index 7db40cb59c..0000000000 --- a/tests/topotests/bgp_evpn_rt5/r2/zebra.conf +++ /dev/null @@ -1,19 +0,0 @@ -log stdout - -hostname r2 -password zebra - -! debug zebra vxlan - -vrf r2-vrf-101 - vni 101 - exit-vrf -! -interface loop101 vrf r2-vrf-101 - ip address 192.168.101.41/32 - ipv6 address fd00::2/128 -! -interface r2-eth0 - ip address 192.168.100.41/24 -! - diff --git a/tests/topotests/bgp_evpn_rt5/r3/frr.conf b/tests/topotests/bgp_evpn_rt5/r3/frr.conf new file mode 100644 index 0000000000..3f3851bd8c --- /dev/null +++ b/tests/topotests/bgp_evpn_rt5/r3/frr.conf @@ -0,0 +1,46 @@ +! debug bgp neighbor-events +! debug bgp updates +! debug bgp zebra +vrf r3-vrf-102 + vni 102 + exit-vrf +! +interface r3-eth0 + ip address 192.168.100.61/24 +! +interface loop102 vrf r3-vrf-102 + ip address 192.168.102.61/32 + ipv6 address fd00:6::1/128 +! +router bgp 65500 + bgp router-id 192.168.100.61 + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy + neighbor 192.168.100.21 remote-as 65000 + neighbor 192.168.100.21 capability extended-nexthop + ! + address-family l2vpn evpn + neighbor 192.168.100.21 activate + advertise-all-vni + exit-address-family +! +router bgp 65000 vrf r3-vrf-102 + bgp router-id 192.168.100.61 + bgp log-neighbor-changes + no bgp network import-check + address-family ipv4 unicast + network 192.168.102.102/32 + exit-address-family + address-family ipv6 unicast + network fd00:102::1/128 + exit-address-family + address-family l2vpn evpn + rd 65000:302 + route-target both 65:101 + advertise ipv4 unicast + advertise ipv6 unicast + exit-address-family + ! + + diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py index c874cbed66..2b8355af09 100644 --- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py +++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py @@ -42,10 +42,12 @@ def build_topo(tgen): tgen.add_router("r1") tgen.add_router("r2") + tgen.add_router("r3") switch = tgen.add_switch("s1") switch.add_link(tgen.gears["r1"]) switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) switch = tgen.add_switch("s2") switch.add_link(tgen.gears["r1"]) @@ -53,6 +55,9 @@ def build_topo(tgen): switch = tgen.add_switch("s3") switch.add_link(tgen.gears["r2"]) + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r3"]) + def setup_module(mod): "Sets up the pytest environment" @@ -71,16 +76,16 @@ def setup_module(mod): ) return pytest.skip("Skipping BGP EVPN RT5 NETNS Test. Kernel not supported") - # create VRF vrf-101 on R1 and R2 + # create VRF vrf-101 on R1, R2, R3 # create loop101 cmds_vrflite = [ - "ip link add {}-vrf-101 type vrf table 101", - "ip ru add oif {}-vrf-101 table 101", - "ip ru add iif {}-vrf-101 table 101", - "ip link set dev {}-vrf-101 up", - "ip link add loop101 type dummy", - "ip link set dev loop101 master {}-vrf-101", - "ip link set dev loop101 up", + "ip link add {0}-vrf-{1} type vrf table {1}", + "ip ru add oif {0}-vrf-{1} table {1}", + "ip ru add iif {0}-vrf-{1} table {1}", + "ip link set dev {0}-vrf-{1} up", + "ip link add loop{1} type dummy", + "ip link set dev loop{1} master {0}-vrf-{1}", + "ip link set dev loop{1} up", ] cmds_r2 = [ # config routing 101 @@ -92,6 +97,15 @@ def setup_module(mod): "ip link set vxlan-101 up type bridge_slave learning off flood off mcast_flood off", ] + cmds_r3 = [ # config routing 102 + "ip link add name bridge-102 up type bridge stp_state 0", + "ip link set bridge-102 master {}-vrf-102", + "ip link set dev bridge-102 up", + "ip link add name vxlan-102 type vxlan id 102 dstport 4789 dev r3-eth0 local 192.168.100.61", + "ip link set dev vxlan-102 master bridge-102", + "ip link set vxlan-102 up type bridge_slave learning off flood off mcast_flood off", + ] + # cmds_r1_netns_method3 = [ # "ip link add name vxlan-{1} type vxlan id {1} dstport 4789 dev {0}-eth0 local 192.168.100.21", # "ip link set dev vxlan-{1} netns {0}-vrf-{1}", @@ -111,8 +125,8 @@ def setup_module(mod): router = tgen.gears["r2"] for cmd in cmds_vrflite: - logger.info("cmd to r2: " + cmd.format("r2")) - output = router.cmd_raises(cmd.format("r2")) + logger.info("cmd to r2: " + cmd.format("r2", 101)) + output = router.cmd_raises(cmd.format("r2", 101)) logger.info("result: " + output) for cmd in cmds_r2: @@ -120,6 +134,17 @@ def setup_module(mod): output = router.cmd_raises(cmd.format("r2")) logger.info("result: " + output) + router = tgen.gears["r3"] + for cmd in cmds_vrflite: + logger.info("cmd to r3: " + cmd.format("r3", 102)) + output = router.cmd_raises(cmd.format("r3", 102)) + logger.info("result: " + output) + + for cmd in cmds_r3: + logger.info("cmd to r3: " + cmd.format("r3")) + output = router.cmd_raises(cmd.format("r3")) + logger.info("result: " + output) + tgen.net["r1"].cmd_raises( "ip link add name vxlan-101 type vxlan id 101 dstport 4789 dev r1-eth0 local 192.168.100.21" ) @@ -134,19 +159,13 @@ def setup_module(mod): tgen.net["r1"].cmd_raises("ip -n r1-vrf-101 link set bridge-101 up") tgen.net["r1"].cmd_raises("ip -n r1-vrf-101 link set vxlan-101 up") - for rname, router in router_list.items(): + for rname, router in tgen.routers().items(): + logger.info("Loading router %s" % rname) if rname == "r1": router.use_netns_vrf() - router.load_config( - TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) - ) + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) else: - router.load_config( - TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) - ) - router.load_config( - TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) - ) + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) # Initialize all routers. tgen.start_router() diff --git a/tests/topotests/bgp_peer_solo/r1/frr.conf b/tests/topotests/bgp_peer_solo/r1/frr.conf new file mode 100644 index 0000000000..6ef3688b83 --- /dev/null +++ b/tests/topotests/bgp_peer_solo/r1/frr.conf @@ -0,0 +1,10 @@ +! +int r1-eth0 + ip address 10.255.0.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 10.255.0.2 timers 1 3 + neighbor 10.255.0.2 timers connect 1 + neighbor 10.255.0.2 remote-as external +! diff --git a/tests/topotests/bgp_peer_solo/r2/frr.conf b/tests/topotests/bgp_peer_solo/r2/frr.conf new file mode 100644 index 0000000000..c58e327418 --- /dev/null +++ b/tests/topotests/bgp_peer_solo/r2/frr.conf @@ -0,0 +1,14 @@ +! +int r2-eth0 + ip address 10.255.0.2/24 +! +router bgp 65002 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 10.255.0.1 remote-as external + neighbor 10.255.0.1 timers 1 3 + neighbor 10.255.0.1 timers connect 1 + address-family ipv4 unicast + network 10.0.0.1/32 + exit-address-family +! diff --git a/tests/topotests/bgp_peer_solo/test_bgp_peer_solo.py b/tests/topotests/bgp_peer_solo/test_bgp_peer_solo.py new file mode 100644 index 0000000000..6bd2430aea --- /dev/null +++ b/tests/topotests/bgp_peer_solo/test_bgp_peer_solo.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +import os +import re +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +from lib import topotest +from lib.topogen import Topogen, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2")} + tgen = Topogen(topodef, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for _, (rname, router) in enumerate(router_list.items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_peer_solo(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears["r1"] + + def _bgp_converge(): + output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast summary json")) + print("output=", output) + expected = { + "peers": { + "10.255.0.2": { + "remoteAs": 65002, + "state": "Established", + "peerState": "OK", + }, + }, + "totalPeers": 1, + } + + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_converge, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't converge initial state" + + def _bgp_advertised(): + output = json.loads(r1.vtysh_cmd("show bgp ipv4 neighbors 10.255.0.2 advertised-routes json")) + print("output adv=", output) + expected = { + "advertisedRoutes": { + "10.0.0.1/32": {}, + }, + "totalPrefixCounter": 1, + } + + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_advertised, + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result is None, "Should contain an advertised route" + + # + # Apply solo option + # + r1.vtysh_cmd( + """ + configure terminal + router bgp 65001 + neighbor 10.255.0.2 solo + """ + ) + + def _bgp_no_advertised(): + output = json.loads(r1.vtysh_cmd("show bgp ipv4 neighbors 10.255.0.2 advertised-routes json")) + expected = { + "totalPrefixCounter": 0, + } + + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_no_advertised, + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result is None, "Shouldn't contain advertised routes" + + # + # Unset solo option + # + r1.vtysh_cmd( + """ + configure terminal + router bgp 65001 + no neighbor 10.255.0.2 solo + """ + ) + + test_func = functools.partial( + _bgp_advertised, + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result is None, "Should contain an advertised route" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_table_direct_topo1/__init__.py b/tests/topotests/bgp_table_direct_topo1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_table_direct_topo1/__init__.py diff --git a/tests/topotests/bgp_table_direct_topo1/r1/frr.conf b/tests/topotests/bgp_table_direct_topo1/r1/frr.conf new file mode 100644 index 0000000000..c45e3456a4 --- /dev/null +++ b/tests/topotests/bgp_table_direct_topo1/r1/frr.conf @@ -0,0 +1,31 @@ +log commands +! +debug bgp zebra +debug zebra events +! +ip route 10.254.254.1/32 lo table 2000 +ip route 10.254.254.2/32 lo table 2000 +ip route 10.254.254.3/32 lo table 2000 +! +interface r1-eth0 + ip address 192.168.10.1/24 +! +interface r1-eth1 vrf blue + ip address 192.168.20.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.10.2 remote-as external + address-family ipv4 unicast + redistribute table-direct 2000 + exit-address-family +! +router bgp 65001 vrf blue + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.20.2 remote-as external + address-family ipv4 unicast + redistribute table-direct 2000 + exit-address-family +!
\ No newline at end of file diff --git a/tests/topotests/bgp_table_direct_topo1/r2/frr.conf b/tests/topotests/bgp_table_direct_topo1/r2/frr.conf new file mode 100644 index 0000000000..04787be0b3 --- /dev/null +++ b/tests/topotests/bgp_table_direct_topo1/r2/frr.conf @@ -0,0 +1,10 @@ +log commands +! +interface r2-eth0 + ip address 192.168.10.2/24 +! +router bgp 65002 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.10.1 remote-as external +!
\ No newline at end of file diff --git a/tests/topotests/bgp_table_direct_topo1/r3/frr.conf b/tests/topotests/bgp_table_direct_topo1/r3/frr.conf new file mode 100644 index 0000000000..2530b28bfd --- /dev/null +++ b/tests/topotests/bgp_table_direct_topo1/r3/frr.conf @@ -0,0 +1,10 @@ +log commands +! +interface r3-eth0 + ip address 192.168.20.2/24 +! +router bgp 65003 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.20.1 remote-as external +!
\ No newline at end of file diff --git a/tests/topotests/bgp_table_direct_topo1/test_bgp_table_direct_topo1.py b/tests/topotests/bgp_table_direct_topo1/test_bgp_table_direct_topo1.py new file mode 100644 index 0000000000..70257be3e7 --- /dev/null +++ b/tests/topotests/bgp_table_direct_topo1/test_bgp_table_direct_topo1.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_bgp_table_direct_topo1.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2025 by +# Network Device Education Foundation, Inc. ("NetDEF") +# + +""" +test_bgp_table_direct_topo1.py: Test the FRR PIM MSDP peer. +""" + +import os +import sys +import json +from functools import partial +import re +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() + + +def build_topo(tgen): + """ + +----+ +----+ + | r1 | <-> | r2 | + +----+ +----+ + | + | +----+ + --------| r3 | + +----+ + """ + + # Create 3 routers + for routern in range(1, 4): + tgen.add_router(f"r{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["r1"]) + switch.add_link(tgen.gears["r3"]) + + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + for _, router in router_list.items(): + router.load_frr_config(os.path.join(CWD, f"{router.name}/frr.conf")) + + tgen.gears["r1"].run("ip link add blue type vrf table 10") + tgen.gears["r1"].run("ip link set blue up") + tgen.gears["r1"].run("ip link set r1-eth1 master blue") + + # Initialize all routers. + tgen.start_router() + + app_helper.init(tgen) + + +def teardown_module(): + "Teardown the pytest environment" + tgen = get_topogen() + app_helper.cleanup() + tgen.stop_topology() + + +def expect_bgp_route(router, iptype, route, missing=False): + "Wait until route is present on RIB for protocol." + if missing: + logger.info("waiting route {} go missing in {}".format(route, router)) + else: + logger.info("waiting route {} in {}".format(route, router)) + + tgen = get_topogen() + expected_output = {route: [{"protocol": "bgp"}]} + wait_time = 130 + if missing: + expected_output = {route: None} + wait_time = 5 + + test_func = partial( + topotest.router_json_cmp, + tgen.gears[router], + "show {} route json".format(iptype), + expected_output + ) + + _, result = topotest.run_and_expect(test_func, None, count=130, wait=1) + assertmsg = f'"{router}" convergence failure' + assert result is None, assertmsg + + +def test_bgp_convergence(): + "Wait for BGP protocol convergence" + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("waiting for protocols to converge") + + # Wait for R2 + expect_bgp_route("r2", "ip", "10.254.254.1/32") + expect_bgp_route("r2", "ip", "10.254.254.2/32") + expect_bgp_route("r2", "ip", "10.254.254.3/32") + + # Wait for R3 + expect_bgp_route("r3", "ip", "10.254.254.1/32") + expect_bgp_route("r3", "ip", "10.254.254.2/32") + expect_bgp_route("r3", "ip", "10.254.254.3/32") + + +def test_route_change_convergence(): + "Change routes in table 2000 to test zebra redistribution." + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + tgen.gears["r1"].vtysh_cmd(""" + configure terminal + no ip route 10.254.254.2/32 lo table 2000 + ip route 10.254.254.10/32 lo table 2000 + """) + + # Check R2 + expect_bgp_route("r2", "ip", "10.254.254.2/32", missing=True) + expect_bgp_route("r2", "ip", "10.254.254.10/32") + + # Check R3 + expect_bgp_route("r3", "ip", "10.254.254.2/32", missing=True) + expect_bgp_route("r3", "ip", "10.254.254.10/32") + + +def test_configuration_removal_convergence(): + "Remove table direct configuration and check if routes went missing." + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + tgen.gears["r1"].vtysh_cmd(""" + configure terminal + router bgp 65001 + address-family ipv4 unicast + no redistribute table-direct 2000 + exit-address-family + exit + + router bgp 65001 vrf blue + address-family ipv4 unicast + no redistribute table-direct 2000 + exit-address-family + exit + """) + + # Check R2 + expect_bgp_route("r2", "ip", "10.254.254.1/32", missing=True) + expect_bgp_route("r2", "ip", "10.254.254.3/32", missing=True) + expect_bgp_route("r2", "ip", "10.254.254.10/32", missing=True) + + # Check R3 + expect_bgp_route("r3", "ip", "10.254.254.1/32", missing=True) + expect_bgp_route("r3", "ip", "10.254.254.3/32", missing=True) + expect_bgp_route("r3", "ip", "10.254.254.10/32", missing=True) + + +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)) diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_advertised_10_125_0_2.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_advertised_10_125_0_2.json new file mode 100644 index 0000000000..7891982653 --- /dev/null +++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_advertised_10_125_0_2.json @@ -0,0 +1,105 @@ +{ + "bgpLocalRouterId":"192.0.2.1", + "defaultLocPrf":100, + "localAS":65500, + "advertisedRoutes":{ + "192.0.2.1:1":{ + "rd":"192.0.2.1:1", + "10.101.0.0/24":{ + "prefix":"10.101.0.0/24", + "advertisedTo":{ + "10.125.0.2":{ + "hostname":"r2" + } + }, + "paths":[{ + "aspath":{ + "string":"Local", + "segments":[], + "length":0 + }, + "nhVrfName":"vrf1", + "announceNexthopSelf":true, + "origin":"incomplete", + "metric":0, + "locPrf":100, + "weight":32768, + "valid":true, + "sourced":true, + "local":true, + "bestpath":{ + "overall":true, + "selectionReason":"First path received" + }, + "extendedCommunity":{ + "string":"RT:192.0.2.1:100" + }, + "originatorId":"192.0.2.1", + "remoteLabel":101, + "nexthops":[{ + "ip":"0.0.0.0", + "hostname":"r1", + "afi":"ipv4", + "metric":0, + "accessible":true, + "used":true + }], + "peer":{ + "peerId":"0.0.0.0", + "routerId":"192.0.2.1" + } + }] + } + }, + "192.0.2.1:3":{ + "rd":"192.0.2.1:3", + "10.103.0.0/24":{ + "prefix":"10.103.0.0/24", + "advertisedTo":{ + "10.125.0.2":{ + "hostname":"r2" + } + }, + "paths":[{ + "aspath":{ + "string":"Local", + "segments":[], + "length":0 + }, + "nhVrfName":"vrf3", + "announceNexthopSelf":true, + "origin":"incomplete", + "metric":0, + "locPrf":100, + "weight":32768, + "valid":true, + "sourced":true, + "local":true, + "bestpath":{ + "overall":true, + "selectionReason":"First path received" + }, + "extendedCommunity":{ + "string":"RT:192.0.2.1:300" + }, + "originatorId":"192.0.2.1", + "remoteLabel":103, + "nexthops":[{ + "ip":"0.0.0.0", + "hostname":"r1", + "afi":"ipv4", + "metric":0, + "accessible":true, + "used":true + }], + "peer":{ + "peerId":"0.0.0.0", + "routerId":"192.0.2.1" + } + }] + } + } + }, + "totalPrefixCounter":2, + "filteredPrefixCounter":0 +} diff --git a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py index ee84e375fb..ada37c28c1 100644 --- a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py +++ b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py @@ -218,6 +218,29 @@ def check_show_bgp_ipv4_vpn(rname, json_file): assert result is None, assertmsg +def check_show_bgp_ipv4_vpn_peer_advertised_routes(rname, peer, json_file): + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + router = tgen.gears[rname] + + logger.info( + "Checking VPNv4 advertised routes for on {} for peer {}".format(rname, peer) + ) + + json_file = "{}/{}/{}".format(CWD, router.name, json_file) + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp ipv4 vpn neighbors {} advertised-routes detail json".format(peer), + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + def check_show_bgp_vrf_ipv4(rname, json_file): tgen = get_topogen() if tgen.routers_have_failure(): @@ -563,6 +586,21 @@ router bgp 65500 check_show_bgp_vrf_ipv4(rname, "ipv4_vrf_all_routes_init.json") +def test_bgp_advertised_routes_step13(): + """ + Dump advertised routes from r1 to r2 + Check that the localpref attribute is set on the show command + """ + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + check_show_bgp_ipv4_vpn_peer_advertised_routes( + "r1", "10.125.0.2", "ipv4_vpn_routes_advertised_10_125_0_2.json" + ) + + def test_memory_leak(): "Run the memory leak test and report results." tgen = get_topogen() |
