Skip to content

Commit

Permalink
bgpd: Updated topotest and documentation
Browse files Browse the repository at this point in the history
Added topotest and documentation for BGP wide GR configurations

Signed-off-by: Pooja Jagadeesh Doijode <[email protected]>
  • Loading branch information
Pdoijode committed May 31, 2024
1 parent dde73af commit cb6b85a
Show file tree
Hide file tree
Showing 3 changed files with 414 additions and 17 deletions.
46 changes: 46 additions & 0 deletions doc/user/bgp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,52 @@ Default global mode is helper and default peer per mode is inherit from global.
If per peer mode is configured, the GR mode of this particular peer will
override the global mode.

.. _bgp-GR-config-mode-cmd:

BGP GR Config Mode Commands
^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. clicmd:: bgp graceful-restart

This command will enable BGP graceful restart functionality for all BGP instances.

.. clicmd:: bgp graceful-restart-disable

This command will disable both the functionality graceful restart and helper
mode for all BGP instances

.. clicmd:: bgp graceful-restart select-defer-time (0-3600)

This is command, will set deferral time to value specified.

.. clicmd:: bgp graceful-restart rib-stale-time (1-3600)

This is command, will set the time for which stale routes are kept in RIB.

.. clicmd:: bgp graceful-restart restart-time (0-4095)

Set the time to wait to delete stale routes before a BGP open message
is received.

Using with Long-lived Graceful Restart capability, this is recommended
setting this timer to 0 and control stale routes with
``bgp long-lived-graceful-restart stale-time``.

Default value is 120.

.. clicmd:: bgp graceful-restart stalepath-time (1-4095)

This is command, will set the max time (in seconds) to hold onto
restarting peer's stale paths.

It also controls Enhanced Route-Refresh timer.

If this command is configured and the router does not receive a Route-Refresh EoRR
message, the router removes the stale routes from the BGP table after the timer
expires. The stale path timer is started when the router receives a Route-Refresh
BoRR message


.. _bgp-GR-global-mode-cmd:

BGP GR Global Mode Commands
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
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__))
Expand All @@ -91,6 +93,7 @@
# 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.

Expand Down Expand Up @@ -1679,6 +1682,311 @@ 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:]
Expand Down
Loading

0 comments on commit cb6b85a

Please sign in to comment.