diff options
Diffstat (limited to 'tests')
33 files changed, 1440 insertions, 37 deletions
diff --git a/tests/topotests/all_protocol_startup/r1/show_route_map.ref b/tests/topotests/all_protocol_startup/r1/show_route_map.ref index 612d0a729d..894ea59677 100644 --- a/tests/topotests/all_protocol_startup/r1/show_route_map.ref +++ b/tests/topotests/all_protocol_startup/r1/show_route_map.ref @@ -1,6 +1,6 @@ ZEBRA: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -8,8 +8,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap RIP: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -17,8 +17,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap RIPNG: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -26,8 +26,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap OSPF: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -35,8 +35,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap OSPF6: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -44,16 +44,16 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap BGP: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: Call clause: Action: Exit routemap -route-map: bgp-map Invoked: 0 Optimization: enabled Processed Change: false - permit, sequence 10 Invoked 0 +route-map: bgp-map Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + permit, sequence 10 Invoked 0 (X milliseconds total) Match clauses: Set clauses: community 100:100 additive @@ -61,7 +61,7 @@ route-map: bgp-map Invoked: 0 Optimization: enabled Processed Change: false Call clause: Action: Exit routemap - permit, sequence 20 Invoked 0 + permit, sequence 20 Invoked 0 (X milliseconds total) Match clauses: Set clauses: metric 10 diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py index 80bd2505a7..0ffd762734 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -37,6 +37,7 @@ from lib.topogen import Topogen, get_topogen from lib.common_config import ( required_linux_kernel_version, ) +from lib.topolog import logger import json import functools @@ -1422,6 +1423,7 @@ def test_route_map(): .cmd('vtysh -c "show route-map" 2> /dev/null') .rstrip() ) + actual = re.sub(r"\([0-9].* milli", "(X milli", actual) actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) diff = topotest.get_textdiff( diff --git a/tests/topotests/bgp_addpath_graceful_restart/__init__.py b/tests/topotests/bgp_addpath_graceful_restart/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/__init__.py diff --git a/tests/topotests/bgp_addpath_graceful_restart/r1/frr.conf b/tests/topotests/bgp_addpath_graceful_restart/r1/frr.conf new file mode 100644 index 0000000000..0644cf63a8 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/r1/frr.conf @@ -0,0 +1,23 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! +int r1-eth1 + ip address 192.168.2.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.1.2 remote-as auto + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.2.2 remote-as auto + neighbor 192.168.2.2 timers 1 3 + neighbor 192.168.2.2 timers connect 1 + neighbor r1-eth1 interface remote-as auto + neighbor r1-eth1 timers 1 3 + neighbor r1-eth1 timers connect 1 + address-family ipv4 unicast + network 10.0.0.1/32 + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_graceful_restart/r2/frr.conf b/tests/topotests/bgp_addpath_graceful_restart/r2/frr.conf new file mode 100644 index 0000000000..ad236e0680 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/r2/frr.conf @@ -0,0 +1,28 @@ +! +int r2-eth0 + ip address 192.168.1.2/24 +! +int r2-eth1 + ip address 192.168.2.2/24 +! +int r2-eth2 + ip address 192.168.3.2/24 +! +router bgp 65002 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as auto + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + neighbor 192.168.2.1 remote-as auto + neighbor 192.168.2.1 timers 1 3 + neighbor 192.168.2.1 timers connect 1 + neighbor 192.168.3.3 remote-as auto + neighbor 192.168.3.3 timers 1 3 + neighbor 192.168.3.3 timers connect 1 + address-family ipv4 unicast + neighbor 192.168.3.3 addpath-tx-all-paths + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_graceful_restart/r3/frr.conf b/tests/topotests/bgp_addpath_graceful_restart/r3/frr.conf new file mode 100644 index 0000000000..e864003f25 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/r3/frr.conf @@ -0,0 +1,13 @@ +! +int r3-eth0 + ip address 192.168.3.3/24 +! +router bgp 65003 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.3.2 remote-as auto + neighbor 192.168.3.2 timers 1 3 + neighbor 192.168.3.2 timers connect 1 +! diff --git a/tests/topotests/bgp_addpath_graceful_restart/test_bgp_addpath_graceful_restart.py b/tests/topotests/bgp_addpath_graceful_restart/test_bgp_addpath_graceful_restart.py new file mode 100644 index 0000000000..9088c44bdb --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/test_bgp_addpath_graceful_restart.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2024 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +import os +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, get_topogen +from lib.common_config import kill_router_daemons + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r2"), "s3": ("r2", "r3")} + 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_addpath_graceful_restart(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r2 = tgen.gears["r2"] + r3 = tgen.gears["r3"] + + def _bgp_converge(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast summary json")) + expected = { + "peers": { + "192.168.1.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.2.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.3.3": { + "hostname": "r3", + "remoteAs": 65003, + "localAs": 65002, + "pfxSnt": 2, + "state": "Established", + }, + } + } + 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, "Initial peering failed" + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + def _bgp_check_stale_routes(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "10.0.0.1/32": [ + { + "stale": True, + "valid": True, + }, + { + "stale": True, + "valid": True, + "multipath": True, + }, + ] + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_routes, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale routes" + + def _bgp_check_stale_routes_cleared(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "10.0.0.1/32": None, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_routes_cleared, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale routes" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_addpath_llgr/__init__.py b/tests/topotests/bgp_addpath_llgr/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/__init__.py diff --git a/tests/topotests/bgp_addpath_llgr/r1/frr.conf b/tests/topotests/bgp_addpath_llgr/r1/frr.conf new file mode 100644 index 0000000000..0644cf63a8 --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/r1/frr.conf @@ -0,0 +1,23 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! +int r1-eth1 + ip address 192.168.2.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.1.2 remote-as auto + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.2.2 remote-as auto + neighbor 192.168.2.2 timers 1 3 + neighbor 192.168.2.2 timers connect 1 + neighbor r1-eth1 interface remote-as auto + neighbor r1-eth1 timers 1 3 + neighbor r1-eth1 timers connect 1 + address-family ipv4 unicast + network 10.0.0.1/32 + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_llgr/r2/frr.conf b/tests/topotests/bgp_addpath_llgr/r2/frr.conf new file mode 100644 index 0000000000..7f6fff0fda --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/r2/frr.conf @@ -0,0 +1,29 @@ +! +int r2-eth0 + ip address 192.168.1.2/24 +! +int r2-eth1 + ip address 192.168.2.2/24 +! +int r2-eth2 + ip address 192.168.3.2/24 +! +router bgp 65002 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 0 + bgp long-lived-graceful-restart stale-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as auto + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + neighbor 192.168.2.1 remote-as auto + neighbor 192.168.2.1 timers 1 3 + neighbor 192.168.2.1 timers connect 1 + neighbor 192.168.3.3 remote-as auto + neighbor 192.168.3.3 timers 1 3 + neighbor 192.168.3.3 timers connect 1 + address-family ipv4 unicast + neighbor 192.168.3.3 addpath-tx-all-paths + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_llgr/r3/frr.conf b/tests/topotests/bgp_addpath_llgr/r3/frr.conf new file mode 100644 index 0000000000..f36492d7e0 --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/r3/frr.conf @@ -0,0 +1,14 @@ +! +int r3-eth0 + ip address 192.168.3.3/24 +! +router bgp 65003 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 0 + bgp long-lived-graceful-restart stale-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.3.2 remote-as auto + neighbor 192.168.3.2 timers 1 3 + neighbor 192.168.3.2 timers connect 1 +! diff --git a/tests/topotests/bgp_addpath_llgr/test_bgp_addpath_llgr.py b/tests/topotests/bgp_addpath_llgr/test_bgp_addpath_llgr.py new file mode 100644 index 0000000000..fa0314304b --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/test_bgp_addpath_llgr.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2024 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +import os +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, get_topogen +from lib.common_config import kill_router_daemons + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r2"), "s3": ("r2", "r3")} + 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_addpath_llgr(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r2 = tgen.gears["r2"] + r3 = tgen.gears["r3"] + + def _bgp_converge(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast summary json")) + expected = { + "peers": { + "192.168.1.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.2.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.3.3": { + "hostname": "r3", + "remoteAs": 65003, + "localAs": 65002, + "pfxSnt": 2, + "state": "Established", + }, + } + } + 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, "Initial peering failed" + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + def _bgp_check_stale_llgr_routes(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast 10.0.0.1/32 json")) + expected = { + "paths": [ + { + "stale": True, + "valid": True, + "community": {"string": "llgr-stale", "list": ["llgrStale"]}, + }, + { + "stale": True, + "valid": True, + "community": {"string": "llgr-stale", "list": ["llgrStale"]}, + }, + ] + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_llgr_routes, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale LLGR routes" + + def _bgp_check_stale_routes_cleared(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "10.0.0.1/32": None, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_routes_cleared, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale routes" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf b/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf index d4ca392b1a..30cb6647ae 100644 --- a/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf +++ b/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf @@ -11,7 +11,7 @@ router bgp 65001 exit-address-family ! route-map rmap permit 10 - set extcommunity color 1 + set extcommunity color 01:1 set extcommunity rt 80:987 - set extcommunity color 100 55555 200 + set extcommunity color 01:100 01:55555 01:200 exit diff --git a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py index 09091198a8..94a444d5c5 100644 --- a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py +++ b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py @@ -105,7 +105,7 @@ def test_bgp_color_extended_communities(): { "valid": True, "extendedCommunity": { - "string": "RT:80:987 Color:100 Color:200 Color:55555" + "string": "RT:80:987 Color:01:100 Color:01:200 Color:01:55555" }, } ], diff --git a/tests/topotests/high_ecmp/r1/frr.conf b/tests/topotests/high_ecmp/r1/frr.conf new file mode 100644 index 0000000000..4382f94cf1 --- /dev/null +++ b/tests/topotests/high_ecmp/r1/frr.conf @@ -0,0 +1,267 @@ +int lo + ip addr 192.168.1.1/32 +router bgp 1001 + timers bgp 5 20 + no bgp ebgp-requires-policy + neighbor r1-eth0 interface remote-as external + neighbor r1-eth1 interface remote-as external + neighbor r1-eth2 interface remote-as external + neighbor r1-eth3 interface remote-as external + neighbor r1-eth4 interface remote-as external + neighbor r1-eth5 interface remote-as external + neighbor r1-eth6 interface remote-as external + neighbor r1-eth7 interface remote-as external + neighbor r1-eth8 interface remote-as external + neighbor r1-eth9 interface remote-as external + neighbor r1-eth10 interface remote-as external + neighbor r1-eth11 interface remote-as external + neighbor r1-eth12 interface remote-as external + neighbor r1-eth13 interface remote-as external + neighbor r1-eth14 interface remote-as external + neighbor r1-eth15 interface remote-as external + neighbor r1-eth16 interface remote-as external + neighbor r1-eth17 interface remote-as external + neighbor r1-eth18 interface remote-as external + neighbor r1-eth19 interface remote-as external + neighbor r1-eth20 interface remote-as external + neighbor r1-eth21 interface remote-as external + neighbor r1-eth22 interface remote-as external + neighbor r1-eth23 interface remote-as external + neighbor r1-eth24 interface remote-as external + neighbor r1-eth25 interface remote-as external + neighbor r1-eth26 interface remote-as external + neighbor r1-eth27 interface remote-as external + neighbor r1-eth28 interface remote-as external + neighbor r1-eth29 interface remote-as external + neighbor r1-eth30 interface remote-as external + neighbor r1-eth31 interface remote-as external + neighbor r1-eth32 interface remote-as external + neighbor r1-eth33 interface remote-as external + neighbor r1-eth34 interface remote-as external + neighbor r1-eth35 interface remote-as external + neighbor r1-eth36 interface remote-as external + neighbor r1-eth37 interface remote-as external + neighbor r1-eth38 interface remote-as external + neighbor r1-eth39 interface remote-as external + neighbor r1-eth40 interface remote-as external + neighbor r1-eth41 interface remote-as external + neighbor r1-eth42 interface remote-as external + neighbor r1-eth43 interface remote-as external + neighbor r1-eth44 interface remote-as external + neighbor r1-eth45 interface remote-as external + neighbor r1-eth46 interface remote-as external + neighbor r1-eth47 interface remote-as external + neighbor r1-eth48 interface remote-as external + neighbor r1-eth49 interface remote-as external + neighbor r1-eth50 interface remote-as external + neighbor r1-eth51 interface remote-as external + neighbor r1-eth52 interface remote-as external + neighbor r1-eth53 interface remote-as external + neighbor r1-eth54 interface remote-as external + neighbor r1-eth55 interface remote-as external + neighbor r1-eth56 interface remote-as external + neighbor r1-eth57 interface remote-as external + neighbor r1-eth58 interface remote-as external + neighbor r1-eth59 interface remote-as external + neighbor r1-eth60 interface remote-as external + neighbor r1-eth61 interface remote-as external + neighbor r1-eth62 interface remote-as external + neighbor r1-eth63 interface remote-as external + neighbor r1-eth64 interface remote-as external + neighbor r1-eth65 interface remote-as external + neighbor r1-eth66 interface remote-as external + neighbor r1-eth67 interface remote-as external + neighbor r1-eth68 interface remote-as external + neighbor r1-eth69 interface remote-as external + neighbor r1-eth70 interface remote-as external + neighbor r1-eth71 interface remote-as external + neighbor r1-eth72 interface remote-as external + neighbor r1-eth73 interface remote-as external + neighbor r1-eth74 interface remote-as external + neighbor r1-eth75 interface remote-as external + neighbor r1-eth76 interface remote-as external + neighbor r1-eth77 interface remote-as external + neighbor r1-eth78 interface remote-as external + neighbor r1-eth79 interface remote-as external + neighbor r1-eth80 interface remote-as external + neighbor r1-eth81 interface remote-as external + neighbor r1-eth82 interface remote-as external + neighbor r1-eth83 interface remote-as external + neighbor r1-eth84 interface remote-as external + neighbor r1-eth85 interface remote-as external + neighbor r1-eth86 interface remote-as external + neighbor r1-eth87 interface remote-as external + neighbor r1-eth88 interface remote-as external + neighbor r1-eth89 interface remote-as external + neighbor r1-eth90 interface remote-as external + neighbor r1-eth91 interface remote-as external + neighbor r1-eth92 interface remote-as external + neighbor r1-eth93 interface remote-as external + neighbor r1-eth94 interface remote-as external + neighbor r1-eth95 interface remote-as external + neighbor r1-eth96 interface remote-as external + neighbor r1-eth97 interface remote-as external + neighbor r1-eth98 interface remote-as external + neighbor r1-eth99 interface remote-as external + neighbor r1-eth100 interface remote-as external + neighbor r1-eth101 interface remote-as external + neighbor r1-eth102 interface remote-as external + neighbor r1-eth103 interface remote-as external + neighbor r1-eth104 interface remote-as external + neighbor r1-eth105 interface remote-as external + neighbor r1-eth106 interface remote-as external + neighbor r1-eth107 interface remote-as external + neighbor r1-eth108 interface remote-as external + neighbor r1-eth109 interface remote-as external + neighbor r1-eth110 interface remote-as external + neighbor r1-eth111 interface remote-as external + neighbor r1-eth112 interface remote-as external + neighbor r1-eth113 interface remote-as external + neighbor r1-eth114 interface remote-as external + neighbor r1-eth115 interface remote-as external + neighbor r1-eth116 interface remote-as external + neighbor r1-eth117 interface remote-as external + neighbor r1-eth118 interface remote-as external + neighbor r1-eth119 interface remote-as external + neighbor r1-eth120 interface remote-as external + neighbor r1-eth121 interface remote-as external + neighbor r1-eth122 interface remote-as external + neighbor r1-eth123 interface remote-as external + neighbor r1-eth124 interface remote-as external + neighbor r1-eth125 interface remote-as external + neighbor r1-eth126 interface remote-as external + neighbor r1-eth127 interface remote-as external + neighbor r1-eth128 interface remote-as external + neighbor r1-eth129 interface remote-as external + neighbor r1-eth130 interface remote-as external + neighbor r1-eth131 interface remote-as external + neighbor r1-eth132 interface remote-as external + neighbor r1-eth133 interface remote-as external + neighbor r1-eth134 interface remote-as external + neighbor r1-eth135 interface remote-as external + neighbor r1-eth136 interface remote-as external + neighbor r1-eth137 interface remote-as external + neighbor r1-eth138 interface remote-as external + neighbor r1-eth139 interface remote-as external + neighbor r1-eth140 interface remote-as external + neighbor r1-eth141 interface remote-as external + neighbor r1-eth142 interface remote-as external + neighbor r1-eth143 interface remote-as external + neighbor r1-eth144 interface remote-as external + neighbor r1-eth145 interface remote-as external + neighbor r1-eth146 interface remote-as external + neighbor r1-eth147 interface remote-as external + neighbor r1-eth148 interface remote-as external + neighbor r1-eth149 interface remote-as external + neighbor r1-eth150 interface remote-as external + neighbor r1-eth151 interface remote-as external + neighbor r1-eth152 interface remote-as external + neighbor r1-eth153 interface remote-as external + neighbor r1-eth154 interface remote-as external + neighbor r1-eth155 interface remote-as external + neighbor r1-eth156 interface remote-as external + neighbor r1-eth157 interface remote-as external + neighbor r1-eth158 interface remote-as external + neighbor r1-eth159 interface remote-as external + neighbor r1-eth160 interface remote-as external + neighbor r1-eth161 interface remote-as external + neighbor r1-eth162 interface remote-as external + neighbor r1-eth163 interface remote-as external + neighbor r1-eth164 interface remote-as external + neighbor r1-eth165 interface remote-as external + neighbor r1-eth166 interface remote-as external + neighbor r1-eth167 interface remote-as external + neighbor r1-eth168 interface remote-as external + neighbor r1-eth169 interface remote-as external + neighbor r1-eth170 interface remote-as external + neighbor r1-eth171 interface remote-as external + neighbor r1-eth172 interface remote-as external + neighbor r1-eth173 interface remote-as external + neighbor r1-eth174 interface remote-as external + neighbor r1-eth175 interface remote-as external + neighbor r1-eth176 interface remote-as external + neighbor r1-eth177 interface remote-as external + neighbor r1-eth178 interface remote-as external + neighbor r1-eth179 interface remote-as external + neighbor r1-eth180 interface remote-as external + neighbor r1-eth181 interface remote-as external + neighbor r1-eth182 interface remote-as external + neighbor r1-eth183 interface remote-as external + neighbor r1-eth184 interface remote-as external + neighbor r1-eth185 interface remote-as external + neighbor r1-eth186 interface remote-as external + neighbor r1-eth187 interface remote-as external + neighbor r1-eth188 interface remote-as external + neighbor r1-eth189 interface remote-as external + neighbor r1-eth190 interface remote-as external + neighbor r1-eth191 interface remote-as external + neighbor r1-eth192 interface remote-as external + neighbor r1-eth193 interface remote-as external + neighbor r1-eth194 interface remote-as external + neighbor r1-eth195 interface remote-as external + neighbor r1-eth196 interface remote-as external + neighbor r1-eth197 interface remote-as external + neighbor r1-eth198 interface remote-as external + neighbor r1-eth199 interface remote-as external + neighbor r1-eth200 interface remote-as external + neighbor r1-eth201 interface remote-as external + neighbor r1-eth202 interface remote-as external + neighbor r1-eth203 interface remote-as external + neighbor r1-eth204 interface remote-as external + neighbor r1-eth205 interface remote-as external + neighbor r1-eth206 interface remote-as external + neighbor r1-eth207 interface remote-as external + neighbor r1-eth208 interface remote-as external + neighbor r1-eth209 interface remote-as external + neighbor r1-eth210 interface remote-as external + neighbor r1-eth211 interface remote-as external + neighbor r1-eth212 interface remote-as external + neighbor r1-eth213 interface remote-as external + neighbor r1-eth214 interface remote-as external + neighbor r1-eth215 interface remote-as external + neighbor r1-eth216 interface remote-as external + neighbor r1-eth217 interface remote-as external + neighbor r1-eth218 interface remote-as external + neighbor r1-eth219 interface remote-as external + neighbor r1-eth220 interface remote-as external + neighbor r1-eth221 interface remote-as external + neighbor r1-eth222 interface remote-as external + neighbor r1-eth223 interface remote-as external + neighbor r1-eth224 interface remote-as external + neighbor r1-eth225 interface remote-as external + neighbor r1-eth226 interface remote-as external + neighbor r1-eth227 interface remote-as external + neighbor r1-eth228 interface remote-as external + neighbor r1-eth229 interface remote-as external + neighbor r1-eth230 interface remote-as external + neighbor r1-eth231 interface remote-as external + neighbor r1-eth232 interface remote-as external + neighbor r1-eth233 interface remote-as external + neighbor r1-eth234 interface remote-as external + neighbor r1-eth235 interface remote-as external + neighbor r1-eth236 interface remote-as external + neighbor r1-eth237 interface remote-as external + neighbor r1-eth238 interface remote-as external + neighbor r1-eth239 interface remote-as external + neighbor r1-eth240 interface remote-as external + neighbor r1-eth241 interface remote-as external + neighbor r1-eth242 interface remote-as external + neighbor r1-eth243 interface remote-as external + neighbor r1-eth244 interface remote-as external + neighbor r1-eth245 interface remote-as external + neighbor r1-eth246 interface remote-as external + neighbor r1-eth247 interface remote-as external + neighbor r1-eth248 interface remote-as external + neighbor r1-eth249 interface remote-as external + neighbor r1-eth250 interface remote-as external + neighbor r1-eth251 interface remote-as external + neighbor r1-eth252 interface remote-as external + neighbor r1-eth253 interface remote-as external + neighbor r1-eth254 interface remote-as external + neighbor r1-eth255 interface remote-as external + neighbor r1-eth256 interface remote-as external + neighbor r1-eth257 interface remote-as external + neighbor r1-eth258 interface remote-as external + neighbor r1-eth259 interface remote-as external + address-family ipv4 uni + redistribute sharp diff --git a/tests/topotests/high_ecmp/r2/frr.conf b/tests/topotests/high_ecmp/r2/frr.conf new file mode 100644 index 0000000000..a9d65360f5 --- /dev/null +++ b/tests/topotests/high_ecmp/r2/frr.conf @@ -0,0 +1,267 @@ +int lo + ip addr 192.168.1.2/32 +! +router bgp 1002 + timers bgp 5 20 + no bgp ebgp-requires-policy + read-quanta 1 + neighbor r2-eth0 interface remote-as external + neighbor r2-eth1 interface remote-as external + neighbor r2-eth2 interface remote-as external + neighbor r2-eth3 interface remote-as external + neighbor r2-eth4 interface remote-as external + neighbor r2-eth5 interface remote-as external + neighbor r2-eth6 interface remote-as external + neighbor r2-eth7 interface remote-as external + neighbor r2-eth8 interface remote-as external + neighbor r2-eth9 interface remote-as external + neighbor r2-eth10 interface remote-as external + neighbor r2-eth11 interface remote-as external + neighbor r2-eth12 interface remote-as external + neighbor r2-eth13 interface remote-as external + neighbor r2-eth14 interface remote-as external + neighbor r2-eth15 interface remote-as external + neighbor r2-eth16 interface remote-as external + neighbor r2-eth17 interface remote-as external + neighbor r2-eth18 interface remote-as external + neighbor r2-eth19 interface remote-as external + neighbor r2-eth20 interface remote-as external + neighbor r2-eth21 interface remote-as external + neighbor r2-eth22 interface remote-as external + neighbor r2-eth23 interface remote-as external + neighbor r2-eth24 interface remote-as external + neighbor r2-eth25 interface remote-as external + neighbor r2-eth26 interface remote-as external + neighbor r2-eth27 interface remote-as external + neighbor r2-eth28 interface remote-as external + neighbor r2-eth29 interface remote-as external + neighbor r2-eth30 interface remote-as external + neighbor r2-eth31 interface remote-as external + neighbor r2-eth32 interface remote-as external + neighbor r2-eth33 interface remote-as external + neighbor r2-eth34 interface remote-as external + neighbor r2-eth35 interface remote-as external + neighbor r2-eth36 interface remote-as external + neighbor r2-eth37 interface remote-as external + neighbor r2-eth38 interface remote-as external + neighbor r2-eth39 interface remote-as external + neighbor r2-eth40 interface remote-as external + neighbor r2-eth41 interface remote-as external + neighbor r2-eth42 interface remote-as external + neighbor r2-eth43 interface remote-as external + neighbor r2-eth44 interface remote-as external + neighbor r2-eth45 interface remote-as external + neighbor r2-eth46 interface remote-as external + neighbor r2-eth47 interface remote-as external + neighbor r2-eth48 interface remote-as external + neighbor r2-eth49 interface remote-as external + neighbor r2-eth50 interface remote-as external + neighbor r2-eth51 interface remote-as external + neighbor r2-eth52 interface remote-as external + neighbor r2-eth53 interface remote-as external + neighbor r2-eth54 interface remote-as external + neighbor r2-eth55 interface remote-as external + neighbor r2-eth56 interface remote-as external + neighbor r2-eth57 interface remote-as external + neighbor r2-eth58 interface remote-as external + neighbor r2-eth59 interface remote-as external + neighbor r2-eth60 interface remote-as external + neighbor r2-eth61 interface remote-as external + neighbor r2-eth62 interface remote-as external + neighbor r2-eth63 interface remote-as external + neighbor r2-eth64 interface remote-as external + neighbor r2-eth65 interface remote-as external + neighbor r2-eth66 interface remote-as external + neighbor r2-eth67 interface remote-as external + neighbor r2-eth68 interface remote-as external + neighbor r2-eth69 interface remote-as external + neighbor r2-eth70 interface remote-as external + neighbor r2-eth71 interface remote-as external + neighbor r2-eth72 interface remote-as external + neighbor r2-eth73 interface remote-as external + neighbor r2-eth74 interface remote-as external + neighbor r2-eth75 interface remote-as external + neighbor r2-eth76 interface remote-as external + neighbor r2-eth77 interface remote-as external + neighbor r2-eth78 interface remote-as external + neighbor r2-eth79 interface remote-as external + neighbor r2-eth80 interface remote-as external + neighbor r2-eth81 interface remote-as external + neighbor r2-eth82 interface remote-as external + neighbor r2-eth83 interface remote-as external + neighbor r2-eth84 interface remote-as external + neighbor r2-eth85 interface remote-as external + neighbor r2-eth86 interface remote-as external + neighbor r2-eth87 interface remote-as external + neighbor r2-eth88 interface remote-as external + neighbor r2-eth89 interface remote-as external + neighbor r2-eth90 interface remote-as external + neighbor r2-eth91 interface remote-as external + neighbor r2-eth92 interface remote-as external + neighbor r2-eth93 interface remote-as external + neighbor r2-eth94 interface remote-as external + neighbor r2-eth95 interface remote-as external + neighbor r2-eth96 interface remote-as external + neighbor r2-eth97 interface remote-as external + neighbor r2-eth98 interface remote-as external + neighbor r2-eth99 interface remote-as external + neighbor r2-eth100 interface remote-as external + neighbor r2-eth101 interface remote-as external + neighbor r2-eth102 interface remote-as external + neighbor r2-eth103 interface remote-as external + neighbor r2-eth104 interface remote-as external + neighbor r2-eth105 interface remote-as external + neighbor r2-eth106 interface remote-as external + neighbor r2-eth107 interface remote-as external + neighbor r2-eth108 interface remote-as external + neighbor r2-eth109 interface remote-as external + neighbor r2-eth110 interface remote-as external + neighbor r2-eth111 interface remote-as external + neighbor r2-eth112 interface remote-as external + neighbor r2-eth113 interface remote-as external + neighbor r2-eth114 interface remote-as external + neighbor r2-eth115 interface remote-as external + neighbor r2-eth116 interface remote-as external + neighbor r2-eth117 interface remote-as external + neighbor r2-eth118 interface remote-as external + neighbor r2-eth119 interface remote-as external + neighbor r2-eth120 interface remote-as external + neighbor r2-eth121 interface remote-as external + neighbor r2-eth122 interface remote-as external + neighbor r2-eth123 interface remote-as external + neighbor r2-eth124 interface remote-as external + neighbor r2-eth125 interface remote-as external + neighbor r2-eth126 interface remote-as external + neighbor r2-eth127 interface remote-as external + neighbor r2-eth128 interface remote-as external + neighbor r2-eth129 interface remote-as external + neighbor r2-eth130 interface remote-as external + neighbor r2-eth131 interface remote-as external + neighbor r2-eth132 interface remote-as external + neighbor r2-eth133 interface remote-as external + neighbor r2-eth134 interface remote-as external + neighbor r2-eth135 interface remote-as external + neighbor r2-eth136 interface remote-as external + neighbor r2-eth137 interface remote-as external + neighbor r2-eth138 interface remote-as external + neighbor r2-eth139 interface remote-as external + neighbor r2-eth140 interface remote-as external + neighbor r2-eth141 interface remote-as external + neighbor r2-eth142 interface remote-as external + neighbor r2-eth143 interface remote-as external + neighbor r2-eth144 interface remote-as external + neighbor r2-eth145 interface remote-as external + neighbor r2-eth146 interface remote-as external + neighbor r2-eth147 interface remote-as external + neighbor r2-eth148 interface remote-as external + neighbor r2-eth149 interface remote-as external + neighbor r2-eth150 interface remote-as external + neighbor r2-eth151 interface remote-as external + neighbor r2-eth152 interface remote-as external + neighbor r2-eth153 interface remote-as external + neighbor r2-eth154 interface remote-as external + neighbor r2-eth155 interface remote-as external + neighbor r2-eth156 interface remote-as external + neighbor r2-eth157 interface remote-as external + neighbor r2-eth158 interface remote-as external + neighbor r2-eth159 interface remote-as external + neighbor r2-eth160 interface remote-as external + neighbor r2-eth161 interface remote-as external + neighbor r2-eth162 interface remote-as external + neighbor r2-eth163 interface remote-as external + neighbor r2-eth164 interface remote-as external + neighbor r2-eth165 interface remote-as external + neighbor r2-eth166 interface remote-as external + neighbor r2-eth167 interface remote-as external + neighbor r2-eth168 interface remote-as external + neighbor r2-eth169 interface remote-as external + neighbor r2-eth170 interface remote-as external + neighbor r2-eth171 interface remote-as external + neighbor r2-eth172 interface remote-as external + neighbor r2-eth173 interface remote-as external + neighbor r2-eth174 interface remote-as external + neighbor r2-eth175 interface remote-as external + neighbor r2-eth176 interface remote-as external + neighbor r2-eth177 interface remote-as external + neighbor r2-eth178 interface remote-as external + neighbor r2-eth179 interface remote-as external + neighbor r2-eth180 interface remote-as external + neighbor r2-eth181 interface remote-as external + neighbor r2-eth182 interface remote-as external + neighbor r2-eth183 interface remote-as external + neighbor r2-eth184 interface remote-as external + neighbor r2-eth185 interface remote-as external + neighbor r2-eth186 interface remote-as external + neighbor r2-eth187 interface remote-as external + neighbor r2-eth188 interface remote-as external + neighbor r2-eth189 interface remote-as external + neighbor r2-eth190 interface remote-as external + neighbor r2-eth191 interface remote-as external + neighbor r2-eth192 interface remote-as external + neighbor r2-eth193 interface remote-as external + neighbor r2-eth194 interface remote-as external + neighbor r2-eth195 interface remote-as external + neighbor r2-eth196 interface remote-as external + neighbor r2-eth197 interface remote-as external + neighbor r2-eth198 interface remote-as external + neighbor r2-eth199 interface remote-as external + neighbor r2-eth200 interface remote-as external + neighbor r2-eth201 interface remote-as external + neighbor r2-eth202 interface remote-as external + neighbor r2-eth203 interface remote-as external + neighbor r2-eth204 interface remote-as external + neighbor r2-eth205 interface remote-as external + neighbor r2-eth206 interface remote-as external + neighbor r2-eth207 interface remote-as external + neighbor r2-eth208 interface remote-as external + neighbor r2-eth209 interface remote-as external + neighbor r2-eth210 interface remote-as external + neighbor r2-eth211 interface remote-as external + neighbor r2-eth212 interface remote-as external + neighbor r2-eth213 interface remote-as external + neighbor r2-eth214 interface remote-as external + neighbor r2-eth215 interface remote-as external + neighbor r2-eth216 interface remote-as external + neighbor r2-eth217 interface remote-as external + neighbor r2-eth218 interface remote-as external + neighbor r2-eth219 interface remote-as external + neighbor r2-eth220 interface remote-as external + neighbor r2-eth221 interface remote-as external + neighbor r2-eth222 interface remote-as external + neighbor r2-eth223 interface remote-as external + neighbor r2-eth224 interface remote-as external + neighbor r2-eth225 interface remote-as external + neighbor r2-eth226 interface remote-as external + neighbor r2-eth227 interface remote-as external + neighbor r2-eth228 interface remote-as external + neighbor r2-eth229 interface remote-as external + neighbor r2-eth230 interface remote-as external + neighbor r2-eth231 interface remote-as external + neighbor r2-eth232 interface remote-as external + neighbor r2-eth233 interface remote-as external + neighbor r2-eth234 interface remote-as external + neighbor r2-eth235 interface remote-as external + neighbor r2-eth236 interface remote-as external + neighbor r2-eth237 interface remote-as external + neighbor r2-eth238 interface remote-as external + neighbor r2-eth239 interface remote-as external + neighbor r2-eth240 interface remote-as external + neighbor r2-eth241 interface remote-as external + neighbor r2-eth242 interface remote-as external + neighbor r2-eth243 interface remote-as external + neighbor r2-eth244 interface remote-as external + neighbor r2-eth245 interface remote-as external + neighbor r2-eth246 interface remote-as external + neighbor r2-eth247 interface remote-as external + neighbor r2-eth248 interface remote-as external + neighbor r2-eth249 interface remote-as external + neighbor r2-eth250 interface remote-as external + neighbor r2-eth251 interface remote-as external + neighbor r2-eth252 interface remote-as external + neighbor r2-eth253 interface remote-as external + neighbor r2-eth254 interface remote-as external + neighbor r2-eth255 interface remote-as external + neighbor r2-eth256 interface remote-as external + neighbor r2-eth257 interface remote-as external + neighbor r2-eth258 interface remote-as external + neighbor r2-eth259 interface remote-as external diff --git a/tests/topotests/high_ecmp/test_high_ecmp.py b/tests/topotests/high_ecmp/test_high_ecmp.py new file mode 100644 index 0000000000..d28a1ee069 --- /dev/null +++ b/tests/topotests/high_ecmp/test_high_ecmp.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_high_ecmp.py +# +# Copyright (c) 2024 by +# Nvidia Corporation +# Donald Sharp +# + +""" +test_high_ecmp.py: Testing two routers with 256 interfaces and BGP setup + on it. + +""" + +import os +import re +import sys +import pytest +import json + +pytestmark = [pytest.mark.bgpd] + +# 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 +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +##################################################### +## +## Network Topology Definition +## +##################################################### + + +def build_topo(tgen): + + tgen.add_router("r1") + tgen.add_router("r2") + + r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] + + # Let's create 257 interfaces between the two switches + for switch in range(1, 257): + switch = tgen.add_switch("sw{}".format(switch)) + switch.add_link(r1) + switch.add_link(r2) + + +##################################################### +## +## Tests starting +## +##################################################### + + +def setup_module(module): + "Setup topology" + tgen = Topogen(build_topo, module.__name__) + tgen.start_topology() + + # This is a sample of configuration loading. + router_list = tgen.routers() + for rname, router in router_list.items(): + router.load_frr_config( + os.path.join(CWD, "{}/frr.conf".format(rname)), + [ + (TopoRouter.RD_ZEBRA, "-s 180000000"), + (TopoRouter.RD_BGP, None), + (TopoRouter.RD_SHARP, None), + ], + ) + + tgen.start_router() + + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def test_nothing(): + "Do Nothing" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/nhrp_topo/r1/nhrp_shortcut_present.json b/tests/topotests/nhrp_topo/r1/nhrp_shortcut_present.json new file mode 100644 index 0000000000..96632d8463 --- /dev/null +++ b/tests/topotests/nhrp_topo/r1/nhrp_shortcut_present.json @@ -0,0 +1,14 @@ +{ + "attr":{ + "entriesCount":1 + }, + "table":[ + { + "type":"dynamic", + "prefix":"192.168.4.0\/24", + "via":"10.255.255.4", + "identity":"" + } + ] +} + diff --git a/tests/topotests/nhrp_topo/r1/zebra.conf b/tests/topotests/nhrp_topo/r1/zebra.conf index b45670fcb2..c8a216335f 100644 --- a/tests/topotests/nhrp_topo/r1/zebra.conf +++ b/tests/topotests/nhrp_topo/r1/zebra.conf @@ -10,3 +10,4 @@ exit interface r1-eth1 ip address 192.168.1.1/24 ! +ip route 0.0.0.0/0 10.255.255.2 diff --git a/tests/topotests/nhrp_topo/r2/nhrp4_cache.json b/tests/topotests/nhrp_topo/r2/nhrp4_cache.json index 34558e0c28..ee122c59e5 100644 --- a/tests/topotests/nhrp_topo/r2/nhrp4_cache.json +++ b/tests/topotests/nhrp_topo/r2/nhrp4_cache.json @@ -1,10 +1,21 @@ { "attr":{ - "entriesCount":2 + "entriesCount":3 }, "table":[ { "interface":"r2-gre0", + "type":"dynamic", + "protocol":"10.255.255.4", + "nbma":"10.1.1.4", + "claimed_nbma":"10.1.1.4", + "used":false, + "timeout":true, + "auth":false, + "identity":"" + }, + { + "interface":"r2-gre0", "type":"local", "protocol":"10.255.255.2", "nbma":"10.2.1.2", diff --git a/tests/topotests/nhrp_topo/r2/nhrp_route4.json b/tests/topotests/nhrp_topo/r2/nhrp_route4.json index 7393cba893..876b24a9b1 100644 --- a/tests/topotests/nhrp_topo/r2/nhrp_route4.json +++ b/tests/topotests/nhrp_topo/r2/nhrp_route4.json @@ -12,7 +12,31 @@ "installed":true, "internalNextHopNum":1, "internalNextHopActiveNum":1, - "nexthops":[ + "nexthops": [ + { + "fib":true, + "directlyConnected":true, + "interfaceName":"r2-gre0", + "active":true + } + ] + } + ], + "10.255.255.4\/32": [ + { + "prefix":"10.255.255.4\/32", + "prefixLen":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, diff --git a/tests/topotests/nhrp_topo/r2/zebra.conf b/tests/topotests/nhrp_topo/r2/zebra.conf index 9f40d4d72e..756cc6d8c8 100644 --- a/tests/topotests/nhrp_topo/r2/zebra.conf +++ b/tests/topotests/nhrp_topo/r2/zebra.conf @@ -1,3 +1,4 @@ +ip forwarding interface r2-eth0 ip address 10.2.1.2/24 ! @@ -10,3 +11,5 @@ interface r2-gre0 interface r2-eth1 ip address 192.168.2.2/24 ! +ip route 192.168.4.4/24 10.255.255.4 +ip route 192.168.1.1/24 10.255.255.1 diff --git a/tests/topotests/nhrp_topo/r4/nhrp4_cache.json b/tests/topotests/nhrp_topo/r4/nhrp4_cache.json new file mode 100644 index 0000000000..19074e4e6d --- /dev/null +++ b/tests/topotests/nhrp_topo/r4/nhrp4_cache.json @@ -0,0 +1,30 @@ +{ + "attr":{ + "entriesCount":2 + }, + "table":[ + { + "interface":"r4-gre0", + "type":"local", + "protocol":"10.255.255.4", + "nbma":"10.1.1.4", + "claimed_nbma":"10.1.1.4", + "used":false, + "timeout":false, + "auth":false, + "identity":"-" + }, + { + "interface":"r4-gre0", + "type":"nhs", + "protocol":"10.255.255.2", + "nbma":"10.2.1.2", + "claimed_nbma":"10.2.1.2", + "used":false, + "timeout":true, + "auth":false, + "identity":"" + } + ] +} + diff --git a/tests/topotests/nhrp_topo/r4/nhrp_route4.json b/tests/topotests/nhrp_topo/r4/nhrp_route4.json new file mode 100644 index 0000000000..01d627c977 --- /dev/null +++ b/tests/topotests/nhrp_topo/r4/nhrp_route4.json @@ -0,0 +1,26 @@ +{ + "10.255.255.2\/32": [ + { + "prefix": "10.255.255.2\/32", + "prefixLen": 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 + } + ] + } + ] +} diff --git a/tests/topotests/nhrp_topo/r4/nhrpd.conf b/tests/topotests/nhrp_topo/r4/nhrpd.conf new file mode 100644 index 0000000000..df9700c22b --- /dev/null +++ b/tests/topotests/nhrp_topo/r4/nhrpd.conf @@ -0,0 +1,11 @@ +log stdout debugging +debug nhrp all +interface r4-gre0 + ip nhrp authentication secret + ip nhrp holdtime 10 + ip nhrp shortcut + ip nhrp network-id 42 + ip nhrp nhs dynamic nbma 10.2.1.2 + ip nhrp registration no-unique + tunnel source r4-eth0 +exit diff --git a/tests/topotests/nhrp_topo/r4/zebra.conf b/tests/topotests/nhrp_topo/r4/zebra.conf new file mode 100644 index 0000000000..b517dbb05e --- /dev/null +++ b/tests/topotests/nhrp_topo/r4/zebra.conf @@ -0,0 +1,13 @@ +interface r4-eth0 + ip address 10.1.1.4/24 +! +ip route 10.2.1.0/24 10.1.1.3 +interface r4-gre0 + ip address 10.255.255.4/32 + no link-detect + ipv6 nd suppress-ra +exit +interface r4-eth1 + ip address 192.168.4.4/24 +! +ip route 0.0.0.0/0 10.255.255.2 diff --git a/tests/topotests/nhrp_topo/test_nhrp_topo.py b/tests/topotests/nhrp_topo/test_nhrp_topo.py index 8833003107..90e793f273 100644 --- a/tests/topotests/nhrp_topo/test_nhrp_topo.py +++ b/tests/topotests/nhrp_topo/test_nhrp_topo.py @@ -33,18 +33,52 @@ from lib.common_config import required_linux_kernel_version, retry # Required to instantiate the topology builder class. pytestmark = [pytest.mark.nhrpd] +TOPOLOGY = """ + 192.168.2.0/24 + -----+----- + | + | + | + +----------+ + | | + | R2 | + | NHS | + +----------+ + | .2 + | + | + | + GRE P2MP Between + 10.2.1.0/24 + Between Spokes and Hub | + | + 10.255.255.x/32 +----+-----+ + | | + | R3 | + | | + +----+-----+ + |.3 + | + | + +----------+ | +---------+ + | | | | | | | + | |R1 | | | R4 | | +192.168.1.0/24 +-------------|NHC +---------+----------| NHC | ------+ 192.168.4.0/24 + | | |.1 .4| | | + | +----------+ 10.1.1.0/24 +---------+ | +""" def build_topo(tgen): "Build function" - # Create 3 routers. - for routern in range(1, 4): + # Create 4 routers. + for routern in range(1, 5): tgen.add_router("r{}".format(routern)) switch = tgen.add_switch("s1") switch.add_link(tgen.gears["r1"]) switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r4"]) switch = tgen.add_switch("s2") switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r3"]) @@ -53,6 +87,9 @@ def build_topo(tgen): switch = tgen.add_switch("s4") switch.add_link(tgen.gears["r1"]) + switch = tgen.add_switch("s5") + switch.add_link(tgen.gears["r4"]) + def _populate_iface(): tgen = get_topogen() @@ -62,6 +99,7 @@ def _populate_iface(): "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 = [ @@ -84,10 +122,27 @@ def _populate_iface(): output = tgen.net["r1"].cmd(input) logger.info("output: " + output) + input = cmd.format("r4", "4") + logger.info("input: " + input) + output = tgen.net["r4"].cmd(input) + logger.info("output: " + output) + + +def _verify_iptables(): + tgen = get_topogen() + # Verify iptables is installed + # This is needed for creating shortcuts + for rname in ("r1", "r4"): + rc, _, _ = tgen.net[rname].cmd_status("iptables --version") + if rc == 127: + return False + return True + def setup_module(mod): "Sets up the pytest environment" + logger.info("NHRP Topology : \n {}".format(TOPOLOGY)) result = required_linux_kernel_version("5.0") if result is not True: pytest.skip("Kernel requirements are not met") @@ -103,7 +158,7 @@ def setup_module(mod): TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)), ) - if rname in ("r1", "r2"): + if rname in ("r1", "r2", "r4"): router.load_config( TopoRouter.RD_NHRP, os.path.join(CWD, "{}/nhrpd.conf".format(rname)) ) @@ -226,10 +281,10 @@ def test_nhrp_connection(): # force session to reinitialize def relink_session(): - for r in ["r1", "r2"]: + for r in ["r1", "r2", "r4"]: tgen.gears[r].vtysh_cmd("clear ip nhrp cache") - tgen.net[r].cmd("ip l del {}-gre0".format(r)); - _populate_iface(); + tgen.net[r].cmd("ip l del {}-gre0".format(r)) + _populate_iface() @retry(retry_timeout=40, initial_wait=5) def verify_same_password(): @@ -255,24 +310,29 @@ def test_nhrp_connection(): ### Passwords are different logger.info("Modify password and send ping again, should drop") - hubrouter.vtysh_cmd(""" + hubrouter.vtysh_cmd( + """ configure interface r2-gre0 ip nhrp authentication secret12 - """) + """ + ) relink_session() verify_mismatched_password() - + ### Passwords are the same - again logger.info("Recover password and verify conectivity is back") - hubrouter.vtysh_cmd(""" + hubrouter.vtysh_cmd( + """ configure interface r2-gre0 ip nhrp authentication secret - """) + """ + ) relink_session() verify_same_password() + def test_route_install(): "Test use of NHRP routes by other protocols (sharpd here)." tgen = get_topogen() @@ -305,6 +365,134 @@ def test_route_install(): assert result is None, assertmsg +# Initial wait of 30 second because that is +# what the default purge time is for nhrp - +# here we are testing that all of the expected +# retries are sent and logged before a +# shortcut is purged +@retry(retry_timeout=10, initial_wait=30) +def check_retry_debug_info(pingspoke=None): + tgen = get_topogen() + r1 = tgen.gears["r1"] + if pingspoke == None: + pingspoke = r1 + logger.info(f"Check retries are being sent from {pingspoke.name}") + output = pingspoke.cmd("grep -c 'Retrying Resolution Request' nhrpd.log") + # Making sure that we see all expected retries for a 30 second purge time + assertmsg = f"Did not see all expected retries on {pingspoke.name}" + assert output.strip() == "6", assertmsg + logger.info("Check retries are being sent OK") + + +# Helper function to ping between spokes and +# check for either complete or incomplete shortcut +# based on whichever one you are expecting - +# expect_succesful_shortcut inidcates whether +# you are expecting to find a complete shortcut +# (True) or incomplete shortcut (False) as a +# result of the ping +@retry(retry_timeout=10, initial_wait=10) +def create_shortcut(expect_successful_shortcut=True, pingspoke=None, peer_addr=None): + tgen = get_topogen() + r1 = tgen.gears["r1"] + if pingspoke == None: + pingspoke = r1 + if peer_addr == None: + peer_addr = "192.168.4.4" + # Pinging the other spoke in an attempt to create specified type of shortcut + output = pingspoke.cmd(f"ping -c 10 -i .5 {peer_addr}") + print(output) + output = pingspoke.vtysh_cmd("show ip nhrp shortcut") + if expect_successful_shortcut: + logger.info(f"Check shortcut creation from {pingspoke.name} to {peer_addr}") + else: + logger.info( + f"Check incomplete shortcut creation from {pingspoke.name} to {peer_addr}" + ) + + output = pingspoke.vtysh_cmd("show ip nhrp shortcut") + print(output) + if expect_successful_shortcut: + json_file = "{}/{}/nhrp_shortcut_present.json".format(CWD, pingspoke.name) + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, pingspoke, "show ip nhrp shortcut json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + if result is not None: + assertmsg = ( + "Shortcut is not being made between spoke {} and peer {}".format( + pingspoke.name, peer_addr + ) + ) + assert 0, assertmsg + else: + logger.info("Shortcut creation between spokes OK") + else: + # Currentlly, 'show ip nhrp shortcut json' does not show incomplete shortcuts + # so an explicit check for for the 'incompete' keyword needed here + if "incomplete" not in output: + assertmsg = ( + "Incomplete shortcut between spoke {} and peer {} is not seen".format( + pingspoke.name, peer_addr + ) + ) + assert 0, assertmsg + else: + logger.info("Incomplete shortcut creation between spokes OK") + + +# This function tests the NHRP resolution request retries by dropping +# incoming packets (including the NHRP resolution request packets) +# from a receiving spoke in order to stop the NHRP resolution +# responses from ever being sent from that receiving spoke - and in turn +# resolution responses will not reach the sending spoke. +# This will trigger the NHRP resolution request retries which +# can be viewed through log messages. +def test_nhrp_retry_resolution(): + """ " + Verify resolution requests are retried when resolution responses + are not received by a spoke + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + # iptables used to create shortcuts + # and subsequent resolution request retries + if not _verify_iptables(): + pytest.skip("iptables is not installed") + + r1 = tgen.gears["r1"] + r4 = tgen.gears["r4"] + + logger.info("Testing retrying resolution request functionality") + # Make sure that shortcut creation between spokes work + create_shortcut(expect_successful_shortcut=True) + # Clearing shortcut information for spokes + r1.vtysh_cmd("clear ip nhrp shortcut") + r4.vtysh_cmd("clear ip nhrp shortcut") + + # Setting iptables rules to stop incoming packets on r4 + # This should stop resolution requests from reaching + # the receiving router (r4) and hence stop the + # creation of a complete shortcut + r4.cmd("iptables -A INPUT -i r4-eth0 -j DROP") + + # Make sure that nhrp debugging is enabled to read the retry logs + r1.vtysh_cmd( + """ + configure + debug nhrp all + """ + ) + create_shortcut(expect_successful_shortcut=False) + # Look for retry logging output for resolution request retries + check_retry_debug_info() + # Undo iptables rule + r4.cmd("iptables -D INPUT -i r4-eth0 -j DROP") + + def test_memory_leak(): "Run the memory leak test and report results." tgen = get_topogen() diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini index b234a84252..ef95ea1b95 100644 --- a/tests/topotests/pytest.ini +++ b/tests/topotests/pytest.ini @@ -32,7 +32,7 @@ log_file_date_format = %Y-%m-%d %H:%M:%S junit_logging = all junit_log_passing_tests = true -norecursedirs = .git example_munet example_test example_topojson_test lib munet docker +norecursedirs = .git example_munet example_test example_topojson_test lib munet docker high_ecmp # Directory to store test results and run logs in, default shown # rundir = /tmp/topotests diff --git a/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_blackhole.json b/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_blackhole.json new file mode 100644 index 0000000000..c8ea930370 --- /dev/null +++ b/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_blackhole.json @@ -0,0 +1,24 @@ +{ + "0.0.0.0/0":[ + { + "prefix":"0.0.0.0/0", + "prefixLen":0, + "protocol":"kernel", + "vrfName":"default", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":254, + "nexthops":[ + { + "fib":true, + "unreachable":true, + "blackhole":true, + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py index 7dbeb6f1cc..eda8c88706 100644 --- a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py +++ b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py @@ -202,6 +202,27 @@ def test_zebra_kernel_route_add(): assert result, "Connected Route should have been added\n{}".format(_) +def test_zebra_kernel_route_blackhole_add(): + "Test that a blackhole route is not affected by interface's link change" + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r1"] + router.run("ip route add blackhole default") + router.run("ip link set dev r1-eth1 down") + + kernel = "{}/{}/ip_route_kernel_blackhole.json".format(CWD, router.name) + expected = json.loads(open(kernel).read()) + + test_func = partial( + topotest.router_json_cmp, router, "show ip route 0.0.0.0/0 json", expected + ) + result, _ = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result, "Blackhole Route should have not been removed\n{}".format(_) + + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/zebra_rib/r1/sharp_rmap.ref b/tests/topotests/zebra_rib/r1/sharp_rmap.ref index 47a9eb6a49..d80a5f661e 100644 --- a/tests/topotests/zebra_rib/r1/sharp_rmap.ref +++ b/tests/topotests/zebra_rib/r1/sharp_rmap.ref @@ -1,6 +1,6 @@ ZEBRA: -route-map: sharp Invoked: 500 Optimization: enabled Processed Change: false - permit, sequence 10 Invoked 244 +route-map: sharp Invoked: 500 (X milliseconds total) Optimization: enabled Processed Change: false + permit, sequence 10 Invoked 244 (X milliseconds total) Match clauses: ip address 10 Set clauses: @@ -8,7 +8,7 @@ route-map: sharp Invoked: 500 Optimization: enabled Processed Change: false Call clause: Action: Exit routemap - permit, sequence 20 Invoked 256 + permit, sequence 20 Invoked 256 (X milliseconds total) Match clauses: Set clauses: src 192.168.213.1 diff --git a/tests/topotests/zebra_rib/r1/static_rmap.ref b/tests/topotests/zebra_rib/r1/static_rmap.ref index 2de98bd514..68e4a5f7b6 100644 --- a/tests/topotests/zebra_rib/r1/static_rmap.ref +++ b/tests/topotests/zebra_rib/r1/static_rmap.ref @@ -1,6 +1,6 @@ ZEBRA: -route-map: static Invoked: 2 Optimization: enabled Processed Change: false - permit, sequence 10 Invoked 2 +route-map: static Invoked: 2 (X milliseconds total) Optimization: enabled Processed Change: false + permit, sequence 10 Invoked 2 (X milliseconds total) Match clauses: Set clauses: src 192.168.215.1 diff --git a/tests/topotests/zebra_rib/test_zebra_rib.py b/tests/topotests/zebra_rib/test_zebra_rib.py index c0a79ed79d..d1aee46b40 100644 --- a/tests/topotests/zebra_rib/test_zebra_rib.py +++ b/tests/topotests/zebra_rib/test_zebra_rib.py @@ -246,6 +246,7 @@ def test_route_map_usage(): def check_static_map_correct_runs(): actual = r1.vtysh_cmd("show route-map static") + actual = re.sub(r"\([0-9].* milli", "(X milli", actual) actual = ("\n".join(actual.splitlines()) + "\n").rstrip() return topotest.get_textdiff( actual, @@ -266,6 +267,7 @@ def test_route_map_usage(): def check_sharp_map_correct_runs(): actual = r1.vtysh_cmd("show route-map sharp") + actual = re.sub(r"\([0-9].* milli", "(X milli", actual) actual = ("\n".join(actual.splitlines()) + "\n").rstrip() return topotest.get_textdiff( actual, |
