summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorPooja Jagadeesh Doijode <pdoijode@nvidia.com>2024-06-27 02:34:44 +0200
committerPooja Jagadeesh Doijode <pdoijode@nvidia.com>2024-07-01 22:02:52 +0200
commitecbca1ae1be5e4e3f68bc712696f28d01909803c (patch)
tree730882490f33171fad4f1ebd27543031512882c8 /tests
parentbgpd: Refine debug logs for zebra GR registration (diff)
downloadfrr-ecbca1ae1be5e4e3f68bc712696f28d01909803c.tar.xz
frr-ecbca1ae1be5e4e3f68bc712696f28d01909803c.zip
tests: Updated topotest and documentation
Added topotest and documentation for BGP wide GR configurations Signed-off-by: Pooja Jagadeesh Doijode <pdoijode@nvidia.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py301
-rw-r--r--tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py10
-rw-r--r--tests/topotests/lib/bgp.py77
3 files changed, 366 insertions, 22 deletions
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py
index 31aaa0b8a..de4b94032 100644
--- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py
@@ -81,6 +81,8 @@ import os
import sys
import time
import pytest
+import functools
+import json
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -91,6 +93,7 @@ sys.path.append(os.path.join("../lib/"))
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
from lib.topolog import logger
+from lib import topotest
# Required to instantiate the topology builder class.
@@ -1680,6 +1683,304 @@ def BGP_GR_TC_52_p1(request):
write_test_footer(tc_name)
+def test_BGP_GR_TC_53_p1(request):
+ """
+ Test Objective : Peer-level inherit from BGP wide Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Configure R1 as GR restarting node in global level")
+
+ input_dict = {
+ "r1": {"graceful-restart": {"graceful-restart": True}},
+ "r2": {"graceful-restart": {"graceful-restart-helper": True}},
+ }
+
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ bgp graceful-restart
+ !
+ """
+ )
+
+ step("Verify that R2 receives GR restarting capabilities" " from R1")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGPd on router R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Configure graceful-restart-disable at config global level verify that the functionality works
+ step("Bring up BGP on R1 and configure graceful-restart-disable")
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ input_dict = {
+ "r1": {"graceful-restart": {"graceful-restart-disable": True}},
+ "r2": {"graceful-restart": {"graceful-restart-helper": True}},
+ }
+
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ bgp graceful-restart-disable
+ !
+ """
+ )
+
+ step("Verify on R2 that R1 does't advertise any GR capabilities")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step("Verify on R2 and R1 that none of the routers keep stale entries")
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, input_topo, next_hop, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
+
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
+
+ step(
+ "Bring up BGP on R1, enable GR and configure bgp graceful-restart restart-time at global level"
+ )
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ no bgp graceful-restart-disable
+ bgp graceful-restart
+ bgp graceful-restart stalepath-time 420
+ bgp graceful-restart restart-time 240
+ bgp graceful-restart select-defer-time 420
+ !
+ """
+ )
+
+ step("Verify on R2 that R1 sent the updated GR restart-time")
+
+ def _bgp_check_if_gr_restart_time_was_updated():
+ output = json.loads(tgen.gears["r2"].vtysh_cmd("show bgp neighbor json"))
+
+ expected = {
+ "192.168.0.1": {
+ "gracefulRestartInfo": {
+ "localGrMode": "Helper*",
+ "remoteGrMode": "Restart",
+ "timers": {
+ "configuredRestartTimer": 120,
+ "receivedRestartTimer": 240,
+ },
+ },
+ },
+ "fd00::1": {
+ "gracefulRestartInfo": {
+ "localGrMode": "Helper*",
+ "remoteGrMode": "Restart",
+ "timers": {
+ "configuredRestartTimer": 120,
+ "receivedRestartTimer": 240,
+ },
+ },
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_check_if_gr_restart_time_was_updated,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "R2 did not receive the updated GR restart-time of 240s"
+
+ def _bgp_check_if_gr_timer_on_restarting_node_was_updated():
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json"))
+
+ expected = {
+ "192.168.0.2": {
+ "gracefulRestartInfo": {
+ "localGrMode": "Restart*",
+ "remoteGrMode": "Helper",
+ "timers": {
+ "configuredRestartTimer": 240,
+ "receivedRestartTimer": 120,
+ },
+ "ipv4Unicast": {
+ "timers": {"stalePathTimer": 420, "selectionDeferralTimer": 420}
+ },
+ },
+ },
+ "fd00::2": {
+ "gracefulRestartInfo": {
+ "localGrMode": "Restart*",
+ "remoteGrMode": "Helper",
+ "timers": {
+ "configuredRestartTimer": 240,
+ "receivedRestartTimer": 120,
+ },
+ "ipv6Unicast": {
+ "timers": {"stalePathTimer": 420, "selectionDeferralTimer": 420}
+ },
+ },
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_check_if_gr_timer_on_restarting_node_was_updated,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert (
+ result is None
+ ), "R1 did not update the GR select-deferral and stale-path timer to 420s"
+
+ write_test_footer(tc_name)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py b/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
index 16459a25a..5d8338d6e 100644
--- a/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
+++ b/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
@@ -195,16 +195,16 @@ def test_bgp_administrative_reset_gr():
step("Reset and shutdown R1")
_bgp_clear_r1_and_shutdown()
- step("Check if Hard Reset notification wasn't sent from R2")
- test_func = functools.partial(_bgp_check_hard_reset)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
- assert result is None, "Failed to send Administrative Reset notification from R2"
-
step("Check if stale routes are retained on R1")
test_func = functools.partial(_bgp_check_gr_notification_stale)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "Failed to see retained stale routes on R1"
+ step("Check if Hard Reset notification wasn't sent from R2")
+ test_func = functools.partial(_bgp_check_hard_reset)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to send Administrative Reset notification from R2"
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 4250c405f..3f4ed6e0b 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -3266,27 +3266,48 @@ def verify_graceful_restart(
lmode = None
rmode = None
- # Local GR mode
- if "address_family" in input_dict[dut]["bgp"]:
- bgp_neighbors = input_dict[dut]["bgp"]["address_family"][addr_type][
- "unicast"
- ]["neighbor"][peer]["dest_link"]
- for dest_link, data in bgp_neighbors.items():
+ # Local GR mode
+ if "bgp" not in input_dict[dut] and "graceful-restart" in input_dict[dut]:
if (
- "graceful-restart-helper" in data
- and data["graceful-restart-helper"]
+ "graceful-restart" in input_dict[dut]["graceful-restart"]
+ and input_dict[dut]["graceful-restart"][
+ "graceful-restart"
+ ]
):
- lmode = "Helper"
- elif "graceful-restart" in data and data["graceful-restart"]:
- lmode = "Restart"
+ lmode = "Restart*"
elif (
- "graceful-restart-disable" in data
- and data["graceful-restart-disable"]
+ "graceful-restart-disable"
+ in input_dict[dut]["graceful-restart"]
+ and input_dict[dut]["graceful-restart"][
+ "graceful-restart-disable"
+ ]
):
- lmode = "Disable"
+ lmode = "Disable*"
else:
- lmode = None
+ lmode = "Helper*"
+
+ if lmode is None:
+ if "address_family" in input_dict[dut]["bgp"]:
+ bgp_neighbors = input_dict[dut]["bgp"]["address_family"][addr_type][
+ "unicast"
+ ]["neighbor"][peer]["dest_link"]
+
+ for dest_link, data in bgp_neighbors.items():
+ if (
+ "graceful-restart-helper" in data
+ and data["graceful-restart-helper"]
+ ):
+ lmode = "Helper"
+ elif "graceful-restart" in data and data["graceful-restart"]:
+ lmode = "Restart"
+ elif (
+ "graceful-restart-disable" in data
+ and data["graceful-restart-disable"]
+ ):
+ lmode = "Disable"
+ else:
+ lmode = None
if lmode is None:
if "graceful-restart" in input_dict[dut]["bgp"]:
@@ -3314,7 +3335,8 @@ def verify_graceful_restart(
return True
# Remote GR mode
- if "address_family" in input_dict[peer]["bgp"]:
+
+ if "bgp" in input_dict[peer] and "address_family" in input_dict[peer]["bgp"]:
bgp_neighbors = input_dict[peer]["bgp"]["address_family"][addr_type][
"unicast"
]["neighbor"][dut]["dest_link"]
@@ -3336,7 +3358,7 @@ def verify_graceful_restart(
rmode = None
if rmode is None:
- if "graceful-restart" in input_dict[peer]["bgp"]:
+ if "bgp" in input_dict[peer] and "graceful-restart" in input_dict[peer]["bgp"]:
if (
"graceful-restart"
in input_dict[peer]["bgp"]["graceful-restart"]
@@ -3355,6 +3377,27 @@ def verify_graceful_restart(
rmode = "Disable"
else:
rmode = "Helper"
+
+ if rmode is None:
+ if "bgp" not in input_dict[peer] and "graceful-restart" in input_dict[peer]:
+ if (
+ "graceful-restart"
+ in input_dict[peer]["graceful-restart"]
+ and input_dict[peer]["graceful-restart"][
+ "graceful-restart"
+ ]
+ ):
+ rmode = "Restart"
+ elif (
+ "graceful-restart-disable"
+ in input_dict[peer]["graceful-restart"]
+ and input_dict[peer]["graceful-restart"][
+ "graceful-restart-disable"
+ ]
+ ):
+ rmode = "Disable"
+ else:
+ rmode = "Helper"
else:
rmode = "Helper"