diff options
Diffstat (limited to '')
40 files changed, 1355 insertions, 176 deletions
diff --git a/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json index e3703bf..39ed61f 100644 --- a/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json +++ b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 3, "routerId": "192.168.255.1", "defaultLocPrf": 100, "localAS": "1.1", diff --git a/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json index 1af4ff7..3013317 100644 --- a/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json +++ b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 3, "routerId": "192.168.255.2", "defaultLocPrf": 100, "localAS": 65538, diff --git a/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg index 7fb9210..dccec7d 100644 --- a/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg +++ b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg @@ -1,8 +1,8 @@ neighbor 10.0.0.1 { - router-id 10.0.0.2; - local-address 10.0.0.2; - local-as 65001; - peer-as 65002; + router-id 10.0.0.254; + local-address 10.0.0.254; + local-as 65254; + peer-as 65001; capability { route-refresh; @@ -12,13 +12,28 @@ neighbor 10.0.0.1 { route 192.168.100.101/32 { atomic-aggregate; community 65001:101; - next-hop 10.0.0.2; + next-hop 10.0.0.254; } route 192.168.100.102/32 { - originator-id 10.0.0.2; + originator-id 10.0.0.254; community 65001:102; - next-hop 10.0.0.2; + next-hop 10.0.0.254; + } + } +} + +neighbor 10.0.0.2 { + router-id 10.0.0.254; + local-address 10.0.0.254; + local-as 65254; + peer-as 65254; + + static { + route 192.168.100.101/32 { + # AIGP invalid attribute: flagged as transitive + optional. + attribute [0x1a 0xc0 0x00000064]; + next-hop 10.0.0.254; } } } diff --git a/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf b/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf deleted file mode 100644 index c96f354..0000000 --- a/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf +++ /dev/null @@ -1,6 +0,0 @@ -! -router bgp 65002 - no bgp ebgp-requires-policy - neighbor 10.0.0.2 remote-as external - neighbor 10.0.0.2 timers 3 10 -! diff --git a/tests/topotests/bgp_path_attribute_discard/r1/frr.conf b/tests/topotests/bgp_path_attribute_discard/r1/frr.conf new file mode 100644 index 0000000..ae7fbdd --- /dev/null +++ b/tests/topotests/bgp_path_attribute_discard/r1/frr.conf @@ -0,0 +1,9 @@ +! +interface r1-eth0 + ip address 10.0.0.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 10.0.0.254 remote-as external + neighbor 10.0.0.254 timers 3 10 +! diff --git a/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf b/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf deleted file mode 100644 index 51a1b26..0000000 --- a/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf +++ /dev/null @@ -1,4 +0,0 @@ -! -interface r1-eth0 - ip address 10.0.0.1/24 -! diff --git a/tests/topotests/bgp_path_attribute_discard/r2/frr.conf b/tests/topotests/bgp_path_attribute_discard/r2/frr.conf new file mode 100644 index 0000000..1dafbdd --- /dev/null +++ b/tests/topotests/bgp_path_attribute_discard/r2/frr.conf @@ -0,0 +1,10 @@ +! +interface r2-eth0 + ip address 10.0.0.2/24 +! +router bgp 65254 + no bgp ebgp-requires-policy + neighbor 10.0.0.254 remote-as internal + neighbor 10.0.0.254 timers 3 10 + neighbor 10.0.0.254 path-attribute discard 26 +! diff --git a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py index c97cd0b..bd8cd8e 100644 --- a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py +++ b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py @@ -31,10 +31,12 @@ pytestmark = [pytest.mark.bgpd] def build_topo(tgen): r1 = tgen.add_router("r1") - peer1 = tgen.add_exabgp_peer("peer1", ip="10.0.0.2", defaultRoute="via 10.0.0.1") + r2 = tgen.add_router("r2") + peer1 = tgen.add_exabgp_peer("peer1", ip="10.0.0.254", defaultRoute="via 10.0.0.1") switch = tgen.add_switch("s1") switch.add_link(r1) + switch.add_link(r2) switch.add_link(peer1) @@ -42,10 +44,10 @@ def setup_module(mod): tgen = Topogen(build_topo, mod.__name__) tgen.start_topology() - router = tgen.gears["r1"] - router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf")) - router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "r1/bgpd.conf")) - router.start() + for _, (rname, router) in enumerate(tgen.routers().items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() peer = tgen.gears["peer1"] peer.start(os.path.join(CWD, "peer1"), os.path.join(CWD, "exabgp.env")) @@ -63,6 +65,7 @@ def test_bgp_path_attribute_discard(): pytest.skip(tgen.errors) r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] def _bgp_converge(): output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json detail")) @@ -103,7 +106,7 @@ def test_bgp_path_attribute_discard(): """ configure terminal router bgp - neighbor 10.0.0.2 path-attribute discard 6 8 + neighbor 10.0.0.254 path-attribute discard 6 8 """ ) @@ -139,6 +142,28 @@ def test_bgp_path_attribute_discard(): result is None ), "Failed to discard path attributes (atomic-aggregate, community)" + def _bgp_check_if_aigp_invalid_attribute_discarded(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json detail")) + expected = { + "routes": { + "192.168.100.101/32": { + "paths": [ + { + "valid": True, + "aigpMetric": None, + } + ], + }, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_check_if_aigp_invalid_attribute_discarded) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) + assert ( + result is None + ), "Failed to discard AIGP invalid path attribute (iBGP session)" + def test_memory_leak(): "Run the memory leak test and report results." diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json index 6fc43e1..f054fab 100644 --- a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json @@ -1,6 +1,5 @@ { "vrfName": "default", - "tableVersion": 2, "routerId": "192.0.2.1", "defaultLocPrf": 100, "localAS": 1, diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json index 538e895..60bcb75 100644 --- a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json @@ -1,6 +1,5 @@ { "vrfName": "default", - "tableVersion": 2, "routerId": "192.0.2.2", "defaultLocPrf": 100, "localAS": 2, diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json index 25b7a86..0fdd3d6 100644 --- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 2, "routerId": "1.1.1.1", "defaultLocPrf": 100, "localAS": 1, diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json index 2cd47b9..03bbcc0 100644 --- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 2, "routerId": "2.2.2.2", "defaultLocPrf": 100, "localAS": 2, diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py index ef813e9..13c38a9 100644 --- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py +++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py @@ -116,7 +116,7 @@ def test_vrf_route_leak_donna(): "nexthops": [ { "fib": True, - "interfaceName": "lo", + "interfaceName": "dummy0", "vrf": "default", "active": True, }, @@ -214,149 +214,6 @@ def test_vrf_route_leak_eva(): assert result, "BGP VRF EVA check failed:\n{}".format(diff) -def test_vrf_route_leak_donna(): - logger.info("Ensure that routes are leaked back and forth") - tgen = get_topogen() - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - r1 = tgen.gears["r1"] - - # Test DONNA VRF. - expect = { - "10.0.0.0/24": [ - { - "protocol": "connected", - } - ], - "10.0.1.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "EVA", - "vrf": "EVA", - "active": True, - }, - ], - }, - ], - "10.0.2.0/24": [{"protocol": "connected"}], - "10.0.3.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "EVA", - "vrf": "EVA", - "active": True, - }, - ], - }, - ], - "10.0.4.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "lo", - "vrf": "default", - "active": True, - }, - ], - }, - ], - "172.16.101.0/24": [ - { - "protocol": "bgp", - "nexthops": [ - { - "interfaceIndex": 0, - "interfaceName": "unknown", - "vrf": "Unknown", - }, - ], - }, - ], - } - - test_func = partial( - topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect - ) - result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5) - assert result, "BGP VRF DONNA check failed:\n{}".format(diff) - - -def test_vrf_route_leak_eva(): - logger.info("Ensure that routes are leaked back and forth") - tgen = get_topogen() - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - r1 = tgen.gears["r1"] - - # Test EVA VRF. - expect = { - "10.0.0.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "DONNA", - "vrf": "DONNA", - "active": True, - }, - ], - }, - ], - "10.0.1.0/24": [ - { - "protocol": "connected", - } - ], - "10.0.2.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "DONNA", - "vrf": "DONNA", - "active": True, - }, - ], - }, - ], - "10.0.3.0/24": [ - { - "protocol": "connected", - } - ], - "172.16.101.0/24": [ - { - "protocol": "bgp", - "nexthops": [ - { - "interfaceIndex": 0, - "interfaceName": "unknown", - "vrf": "Unknown", - }, - ], - }, - ], - } - def test_vrf_route_leak_default(): logger.info("Ensure that routes are leaked back and forth") diff --git a/tests/topotests/evpn_pim_1/spine/bgp.summ.json b/tests/topotests/evpn_pim_1/spine/bgp.summ.json index 7f37ced..b5b03e8 100644 --- a/tests/topotests/evpn_pim_1/spine/bgp.summ.json +++ b/tests/topotests/evpn_pim_1/spine/bgp.summ.json @@ -2,7 +2,6 @@ "routerId":"192.168.100.1", "as":65001, "vrfName":"default", - "tableVersion":7, "peerCount":2, "peers":{ "192.168.1.2":{ diff --git a/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json new file mode 100644 index 0000000..a94dd9f --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json @@ -0,0 +1,40 @@ +{ + "attr": { + "entriesCount": 3 + }, + "table": [ + { + "interface": "r1-gre0", + "type": "dynamic", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r1-gre0", + "type": "local", + "protocol": "176.16.1.1", + "nbma": "192.168.1.1", + "claimed_nbma": "192.168.1.1", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r1-gre0", + "type": "dynamic", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r1/nhrp_route.json b/tests/topotests/nhrp_redundancy/r1/nhrp_route.json new file mode 100644 index 0000000..b5f3e29 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/nhrp_route.json @@ -0,0 +1,48 @@ +{ + "176.16.1.4\/32": [ + { + "prefix": "176.16.1.4\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r1-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r1-gre0", + "active": true + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r1/nhrpd.conf b/tests/topotests/nhrp_redundancy/r1/nhrpd.conf new file mode 100644 index 0000000..ad48ce3 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/nhrpd.conf @@ -0,0 +1,9 @@ +!debug nhrp all +nhrp nflog-group 1 +interface r1-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp redirect + tunnel source r1-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r1/zebra.conf b/tests/topotests/nhrp_redundancy/r1/zebra.conf new file mode 100644 index 0000000..0f11563 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/zebra.conf @@ -0,0 +1,12 @@ +ip forwarding +interface r1-eth0 + ip address 192.168.1.1/24 +! +ip route 192.168.2.0/24 192.168.1.6 +interface r1-gre0 + ip address 176.16.1.1/32 + no link-detect + ipv6 nd suppress-ra +! +ip route 4.4.4.0/24 176.16.1.4 +ip route 5.5.5.0/24 176.16.1.5 diff --git a/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json new file mode 100644 index 0000000..91557a1 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json @@ -0,0 +1,40 @@ +{ + "attr": { + "entriesCount": 3 + }, + "table": [ + { + "interface": "r2-gre0", + "type": "local", + "protocol": "176.16.1.2", + "nbma": "192.168.1.2", + "claimed_nbma": "192.168.1.2", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r2-gre0", + "type": "dynamic", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r2-gre0", + "type": "dynamic", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r2/nhrp_route.json b/tests/topotests/nhrp_redundancy/r2/nhrp_route.json new file mode 100644 index 0000000..f1fa6e5 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/nhrp_route.json @@ -0,0 +1,48 @@ +{ + "176.16.1.4\/32": [ + { + "prefix": "176.16.1.4\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r2-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r2-gre0", + "active": true + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r2/nhrpd.conf b/tests/topotests/nhrp_redundancy/r2/nhrpd.conf new file mode 100644 index 0000000..4d63f07 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/nhrpd.conf @@ -0,0 +1,9 @@ +!debug nhrp all +nhrp nflog-group 1 +interface r2-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp redirect + tunnel source r2-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r2/zebra.conf b/tests/topotests/nhrp_redundancy/r2/zebra.conf new file mode 100644 index 0000000..1a9c4ff --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/zebra.conf @@ -0,0 +1,12 @@ +ip forwarding +interface r2-eth0 + ip address 192.168.1.2/24 +! +ip route 192.168.2.0/24 192.168.1.6 +interface r2-gre0 + ip address 176.16.1.2/32 + no link-detect + ipv6 nd suppress-ra +! +ip route 4.4.4.0/24 176.16.1.4 +ip route 5.5.5.0/24 176.16.1.5 diff --git a/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json new file mode 100644 index 0000000..ef3ab69 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json @@ -0,0 +1,40 @@ +{ + "attr": { + "entriesCount": 3 + }, + "table": [ + { + "interface": "r3-gre0", + "type": "dynamic", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r3-gre0", + "type": "local", + "protocol": "176.16.1.3", + "nbma": "192.168.1.3", + "claimed_nbma": "192.168.1.3", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r3-gre0", + "type": "dynamic", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r3/nhrp_route.json b/tests/topotests/nhrp_redundancy/r3/nhrp_route.json new file mode 100644 index 0000000..3d548c0 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/nhrp_route.json @@ -0,0 +1,48 @@ +{ + "176.16.1.4\/32": [ + { + "prefix": "176.16.1.4\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r3-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r3-gre0", + "active": true + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r3/nhrpd.conf b/tests/topotests/nhrp_redundancy/r3/nhrpd.conf new file mode 100644 index 0000000..87cc216 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/nhrpd.conf @@ -0,0 +1,9 @@ +!debug nhrp all +nhrp nflog-group 1 +interface r3-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp redirect + tunnel source r3-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r3/zebra.conf b/tests/topotests/nhrp_redundancy/r3/zebra.conf new file mode 100644 index 0000000..980cfbc --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/zebra.conf @@ -0,0 +1,12 @@ +ip forwarding +interface r3-eth0 + ip address 192.168.1.3/24 +! +ip route 192.168.2.0/24 192.168.1.6 +interface r3-gre0 + ip address 176.16.1.3/32 + no link-detect + ipv6 nd suppress-ra +! +ip route 4.4.4.0/24 176.16.1.4 +ip route 5.5.5.0/24 176.16.1.5
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json new file mode 100644 index 0000000..f87ebcf --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json @@ -0,0 +1,51 @@ +{ + "attr": { + "entriesCount": 4 + }, + "table": [ + { + "interface": "r4-gre0", + "type": "nhs", + "protocol": "176.16.1.2", + "nbma": "192.168.1.2", + "claimed_nbma": "192.168.1.2", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r4-gre0", + "type": "local", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r4-gre0", + "type": "nhs", + "protocol": "176.16.1.3", + "nbma": "192.168.1.3", + "claimed_nbma": "192.168.1.3", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r4-gre0", + "type": "nhs", + "protocol": "176.16.1.1", + "nbma": "192.168.1.1", + "claimed_nbma": "192.168.1.1", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_route.json b/tests/topotests/nhrp_redundancy/r4/nhrp_route.json new file mode 100644 index 0000000..4f1faee --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrp_route.json @@ -0,0 +1,71 @@ +{ + "176.16.1.1\/32": [ + { + "prefix": "176.16.1.1\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.2\/32": [ + { + "prefix": "176.16.1.2\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.3\/32": [ + { + "prefix": "176.16.1.3\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json b/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json new file mode 100644 index 0000000..f8efff2 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json @@ -0,0 +1,118 @@ +{ + "5.5.5.5\/32": [ + { + "prefix": "5.5.5.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "ip": "176.16.1.5", + "afi": "ipv4", + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.1\/32": [ + { + "prefix": "176.16.1.1\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.2\/32": [ + { + "prefix": "176.16.1.2\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.3\/32": [ + { + "prefix": "176.16.1.3\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrpd.conf b/tests/topotests/nhrp_redundancy/r4/nhrpd.conf new file mode 100644 index 0000000..8a52f33 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrpd.conf @@ -0,0 +1,11 @@ +!debug nhrp all +interface r4-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp nhs dynamic nbma 192.168.1.1 + ip nhrp nhs dynamic nbma 192.168.1.2 + ip nhrp nhs dynamic nbma 192.168.1.3 + ip nhrp shortcut + tunnel source r4-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r4/zebra.conf b/tests/topotests/nhrp_redundancy/r4/zebra.conf new file mode 100644 index 0000000..e4a9a6f --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/zebra.conf @@ -0,0 +1,16 @@ +ip forwarding +interface r4-eth0 + ip address 192.168.2.4/24 +! +ip route 192.168.1.0/24 192.168.2.6 +interface r4-gre0 + ip address 176.16.1.4/32 + no link-detect + ipv6 nd suppress-ra +! +interface r4-eth1 + ip address 4.4.4.4/24 +! +ip route 0.0.0.0/0 176.16.1.1 50 +ip route 0.0.0.0/0 176.16.1.2 60 +ip route 0.0.0.0/0 176.16.1.3 70
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json new file mode 100644 index 0000000..bc041c6 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json @@ -0,0 +1,51 @@ +{ + "attr": { + "entriesCount": 4 + }, + "table": [ + { + "interface": "r5-gre0", + "type": "nhs", + "protocol": "176.16.1.2", + "nbma": "192.168.1.2", + "claimed_nbma": "192.168.1.2", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r5-gre0", + "type": "nhs", + "protocol": "176.16.1.3", + "nbma": "192.168.1.3", + "claimed_nbma": "192.168.1.3", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r5-gre0", + "type": "nhs", + "protocol": "176.16.1.1", + "nbma": "192.168.1.1", + "claimed_nbma": "192.168.1.1", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r5-gre0", + "type": "local", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r5/nhrp_route.json b/tests/topotests/nhrp_redundancy/r5/nhrp_route.json new file mode 100644 index 0000000..1d1c16f --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/nhrp_route.json @@ -0,0 +1,71 @@ +{ + "176.16.1.1\/32": [ + { + "prefix": "176.16.1.1\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r5-gre0", + "active": true + } + ] + } + ], + "176.16.1.2\/32": [ + { + "prefix": "176.16.1.2\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r5-gre0", + "active": true + } + ] + } + ], + "176.16.1.3\/32": [ + { + "prefix": "176.16.1.3\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r5-gre0", + "active": true + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r5/nhrpd.conf b/tests/topotests/nhrp_redundancy/r5/nhrpd.conf new file mode 100644 index 0000000..7241ed5 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/nhrpd.conf @@ -0,0 +1,11 @@ +!debug nhrp all +interface r5-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp nhs dynamic nbma 192.168.1.1 + ip nhrp nhs dynamic nbma 192.168.1.2 + ip nhrp nhs dynamic nbma 192.168.1.3 + ip nhrp registration no-unique + ip nhrp shortcut + tunnel source r5-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r5/zebra.conf b/tests/topotests/nhrp_redundancy/r5/zebra.conf new file mode 100644 index 0000000..9b1e1c0 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/zebra.conf @@ -0,0 +1,16 @@ +ip forwarding +interface r5-eth0 + ip address 192.168.2.5/24 +! +ip route 192.168.1.0/24 192.168.2.6 +interface r5-gre0 + ip address 176.16.1.5/32 + no link-detect + ipv6 nd suppress-ra +! +interface r5-eth1 + ip address 5.5.5.5/24 +! +ip route 0.0.0.0/0 176.16.1.1 50 +ip route 0.0.0.0/0 176.16.1.2 60 +ip route 0.0.0.0/0 176.16.1.3 70 diff --git a/tests/topotests/nhrp_redundancy/r6/zebra.conf b/tests/topotests/nhrp_redundancy/r6/zebra.conf new file mode 100644 index 0000000..63a37cd --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r6/zebra.conf @@ -0,0 +1,7 @@ +ip forwarding +interface r6-eth0 + ip address 192.168.1.6/24 +! +interface r6-eth1 + ip address 192.168.2.6/24 +exit diff --git a/tests/topotests/nhrp_redundancy/r7/zebra.conf b/tests/topotests/nhrp_redundancy/r7/zebra.conf new file mode 100644 index 0000000..5747b40 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r7/zebra.conf @@ -0,0 +1,4 @@ +interface r7-eth0 + ip address 4.4.4.7/24 +! +ip route 0.0.0.0/0 4.4.4.4 diff --git a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot new file mode 100644 index 0000000..c169436 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot @@ -0,0 +1,103 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph template { + label="nhrp-topo-redundant-nhs"; + + # Routers + r1 [ + shape=doubleoctagon, + label="NHS 1", + fillcolor="#f08080", + style=filled, + ]; + r2 [ + shape=doubleoctagon + label="NHS 2", + fillcolor="#f08080", + style=filled, + ]; + r3 [ + shape=doubleoctagon + label="NHS 3", + fillcolor="#f08080", + style=filled, + ]; + r4 [ + shape=doubleoctagon + label="NHC 1", + fillcolor="#f08080", + style=filled, + ]; + r5 [ + shape=doubleoctagon + label="NHC 2", + fillcolor="#f08080", + style=filled, + ]; + r6 [ + shape=doubleoctagon + label="router", + fillcolor="#f08080", + style=filled, + ]; + r7 [ + shape=doubleoctagon + label="host", + fillcolor="#f08080", + style=filled, + ]; + + # Switches + sw1 [ + shape=oval, + label="sw1\n192.168.1.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + sw2 [ + shape=oval, + label="sw2\n192.168.2.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + sw3 [ + shape=oval, + label="sw3\n4.4.4.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + sw4 [ + shape=oval, + label="sw4\n5.5.5.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + r1 -- sw1 [label="eth0"]; + r2 -- sw1 [label="eth0"]; + r3 -- sw1 [label="eth0"]; + r6 -- sw1 [label="eth0"]; + + r4 -- sw2 [label="eth0"]; + r5 -- sw2 [label="eth0"]; + r6 -- sw2 [label="eth1"]; + + r4 -- sw3 [label="eth1"]; + r7 -- sw3 [label="eth0"]; + + r5 -- sw4 [label="eth1"]; + +} diff --git a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py new file mode 100644 index 0000000..81a22eb --- /dev/null +++ b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py @@ -0,0 +1,423 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0-or-later +# +# test_nhrp_redundancy.py +# +# Copyright 2024, LabN Consulting, L.L.C. +# Dave LeRoy +# + +import os +import sys +import json +from time import sleep +from functools import partial +import pytest + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from lib.common_config import ( + required_linux_kernel_version, + shutdown_bringup_interface, + retry, +) + +""" +test_nhrp_redundancy.py: Test NHS redundancy for NHRP +""" + +TOPOLOGY = """ ++------------+ +------------+ +------------+ +| | | | | | +| | | | | | +| NHS 1 | | NHS 2 | | NHS 3 | +| | | | | | ++-----+------+ +-----+------+ +-----+------+ + |.1 |.2 |.3 + | | | + | | 192.168.1.0/24 | +------+-------------------------------+------------------+-------------+------ + | + |.6 + GRE P2MP between all NHS and NHC +-----+------+ + 172.16.1.x/32 | | + | | + | Router | + | | + +-----+------+ + | + | + ---------+----------------+-------------+------ + | 192.168.2.0/24 | + | | + | |.4 |.5 ++------------+ | +-------+----+ +------+-----+ | +| | | | | | | | +| | +--------+ | | | | +| Host |.7 | | NHC 1 | | NHC 2 +-----+5.5.5.0/24 +| +---------+ | | | | | ++------------+ | +------------+ +------------+ | + | | + 4.4.4.0/24 +""" + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# Required to instantiate the topology builder class. + +pytestmark = [pytest.mark.nhrpd] + + +def build_topo(tgen): + "Build function" + + # Create 7 routers + for routern in range(1, 8): + tgen.add_router("r{}".format(routern)) + + # Interconnect routers 1, 2, 3, 6 + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r6"]) + + # Interconnect routers 4, 5, 6 + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r4"]) + switch.add_link(tgen.gears["r5"]) + switch.add_link(tgen.gears["r6"]) + + # Connect router 4, 7 + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r4"]) + switch.add_link(tgen.gears["r7"]) + + # Connect router 5 + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r5"]) + + +def _populate_iface(): + tgen = get_topogen() + cmds_tot_hub = [ + "ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 192.168.1.{1} remote 0.0.0.0", + "ip link set dev {0}-gre0 up", + "echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6", + "iptables -A FORWARD -i {0}-gre0 -o {0}-gre0 -m hashlimit --hashlimit-upto 4/minute --hashlimit-burst 1 --hashlimit-mode srcip,dstip --hashlimit-srcmask 24 --hashlimit-dstmask 24 --hashlimit-name loglimit-0 -j NFLOG --nflog-group 1 --nflog-range 128", + ] + + cmds_tot = [ + "ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 192.168.2.{1} remote 0.0.0.0", + "ip link set dev {0}-gre0 up", + "echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6", + ] + + for cmd in cmds_tot_hub: + # Router 1 + input = cmd.format("r1", "1") + logger.info("input: " + input) + output = tgen.net["r1"].cmd(input) + logger.info("output: " + output) + + # Router 2 + input = cmd.format("r2", "2") + logger.info("input: " + input) + output = tgen.net["r2"].cmd(input) + logger.info("output: " + output) + + # Router 3 + input = cmd.format("r3", "3") + logger.info("input: " + input) + output = tgen.net["r3"].cmd(input) + logger.info("output: " + output) + + for cmd in cmds_tot: + input = cmd.format("r4", "4") + logger.info("input: " + input) + output = tgen.net["r4"].cmd(input) + logger.info("output: " + output) + + input = cmd.format("r5", "5") + logger.info("input: " + input) + output = tgen.net["r5"].cmd(input) + logger.info("output: " + output) + + +def _verify_iptables(): + tgen = get_topogen() + # Verify iptables is installed. Required for shortcuts + rc, _, _ = tgen.net["r1"].cmd_status("iptables") + return False if rc == 127 else True + + +def setup_module(mod): + logger.info("NHRP Redundant NHS:\n {}".format(TOPOLOGY)) + + result = required_linux_kernel_version("5.0") + if result is not True: + pytest.skip("Kernel requirements are not met") + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + # Starting Routers + router_list = tgen.routers() + _populate_iface() + + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, "{}/zebra.conf".format(rname)), + ) + if rname in ("r1", "r2", "r3", "r4", "r5"): + router.load_config( + TopoRouter.RD_NHRP, os.path.join(CWD, "{}/nhrpd.conf".format(rname)) + ) + + # Initialize all routers. + tgen.start_router() + + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + tgen.stop_topology() + + +def test_protocols_convergence(): + """ + Assert that all protocols have converged before checking for the NHRP + statuses as they depend on it. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Checking NHRP cache and IPv4 routes for convergence") + router_list = tgen.routers() + + # Check NHRP cache on servers and clients + for rname, router in router_list.items(): + + json_file = "{}/{}/nhrp_cache.json".format(CWD, router.name) + if not os.path.isfile(json_file): + logger.info("skipping file {}".format(json_file)) + continue + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip nhrp cache json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip nhrp cache") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Check NHRP IPV4 routes on servers and clients + for rname, router in router_list.items(): + + json_file = "{}/{}/nhrp_route.json".format(CWD, router.name) + if not os.path.isfile(json_file): + logger.info("skipping file {}".format(json_file)) + continue + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Test connectivity from 1 NHRP server to all clients + pingrouter = tgen.gears["r1"] + logger.info("Check Ping IPv4 from R1 to R4 = 176.16.1.4)") + output = pingrouter.run("ping 176.16.1.4 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R1 to R4 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R1 to R4 OK") + + logger.info("Check Ping IPv4 from R1 to R5 = 176.16.1.5)") + output = pingrouter.run("ping 176.16.1.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R1 to R5 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R1 to R5 OK") + + # Test connectivity from 1 NHRP client to all servers + pingrouter = tgen.gears["r4"] + logger.info("Check Ping IPv4 from R4 to R1 = 176.16.1.1)") + output = pingrouter.run("ping 176.16.1.1 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R4 to R1 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R4 to R1 OK") + + logger.info("Check Ping IPv4 from R4 to R2 = 176.16.1.2)") + output = pingrouter.run("ping 176.16.1.2 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R4 to R2 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R4 to R2 OK") + + logger.info("Check Ping IPv4 from R4 to R3 = 176.16.1.3)") + output = pingrouter.run("ping 176.16.1.3 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R4 to R3 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R4 to R3 OK") + + +@retry(retry_timeout=30, initial_wait=5) +def verify_shortcut_path(): + """ + Verifying that traffic flows through shortcut path + """ + tgen = get_topogen() + pingrouter = tgen.gears["r7"] + logger.info("Check Ping IPv4 from R7 to R5 = 5.5.5.5") + + output = pingrouter.run("ping 5.5.5.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R7 to R5 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R7 to R5 OK") + + +def test_redundancy_shortcut(): + """ + Assert that if shortcut created and then NHS goes down, there is no traffic disruption + Stop traffic and verify next time traffic started, shortcut is initiated by backup NHS + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + if not _verify_iptables(): + pytest.skip("iptables not installed") + + logger.info("Testing NHRP shortcuts with redundant servers") + + # Verify R4 nhrp routes before shortcut creation + router = tgen.gears["r4"] + json_file = "{}/{}/nhrp_route.json".format(CWD, router.name) + assertmsg = "No nhrp_route file found" + assert os.path.isfile(json_file), assertmsg + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Initiate shortcut by pinging between clients + pingrouter = tgen.gears["r7"] + logger.info("Check Ping IPv4 from R7 to R5 via shortcut = 5.5.5.5") + + output = pingrouter.run("ping 5.5.5.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R7 to R5 via shortcut should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R7 to R5 via shortcut OK") + + # Now check that NHRP shortcut route installed + json_file = "{}/{}/nhrp_route_shortcut.json".format(CWD, router.name) + assertmsg = "No nhrp_route file found" + assert os.path.isfile(json_file), assertmsg + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Bring down primary GRE interface and verify shortcut is not disturbed + logger.info("Bringing down R1, primary NHRP server.") + shutdown_bringup_interface(tgen, "r1", "r1-gre0", False) + + # Verify shortcut is still active + pingrouter = tgen.gears["r7"] + logger.info("Check Ping IPv4 from R7 to R5 via shortcut = 5.5.5.5") + + output = pingrouter.run("ping 5.5.5.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R7 to R5 via shortcut should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R7 to R5 via shortcut OK") + + # Now verify shortcut is purged with lack of traffic + json_file = "{}/{}/nhrp_route.json".format(CWD, router.name) + assertmsg = "No nhrp_route file found" + assert os.path.isfile(json_file), assertmsg + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + +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/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt index 6ab1bb8..1495c88 100644 --- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt +++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt @@ -1,9 +1,9 @@ VRF ray: B 10.0.1.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX -B 10.0.2.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX +B 10.0.2.0/24 [20/0] is directly connected, r2-eth0 (vrf default) inactive, weight 1, XX:XX:XX B>* 10.0.3.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX O>* 10.0.4.0/24 [110/20] via 10.0.40.4, r2-eth2, weight 1, XX:XX:XX -B 10.0.20.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX +B 10.0.20.0/24 [20/0] is directly connected, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX B>* 10.0.30.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX O 10.0.40.0/24 [110/10] is directly connected, r2-eth2, weight 1, XX:XX:XX C>* 10.0.40.0/24 is directly connected, r2-eth2, XX:XX:XX |