Skip to content

Commit ed1e90a

Browse files
committed
tests: Updated topotest and documentation
Added topotest and documentation for BGP wide GR configurations Signed-off-by: Pooja Jagadeesh Doijode <[email protected]>
1 parent 20a686a commit ed1e90a

File tree

4 files changed

+416
-22
lines changed

4 files changed

+416
-22
lines changed

doc/user/bgp.rst

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,52 @@ Default global mode is helper and default peer per mode is inherit from global.
10801080
If per peer mode is configured, the GR mode of this particular peer will
10811081
override the global mode.
10821082

1083+
.. _bgp-GR-config-mode-cmd:
1084+
1085+
BGP GR Config Mode Commands
1086+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
1087+
1088+
.. clicmd:: bgp graceful-restart
1089+
1090+
This command will enable BGP graceful restart functionality for all BGP instances.
1091+
1092+
.. clicmd:: bgp graceful-restart-disable
1093+
1094+
This command will disable both the functionality graceful restart and helper
1095+
mode for all BGP instances
1096+
1097+
.. clicmd:: bgp graceful-restart select-defer-time (0-3600)
1098+
1099+
This is command, will set deferral time to value specified.
1100+
1101+
.. clicmd:: bgp graceful-restart rib-stale-time (1-3600)
1102+
1103+
This is command, will set the time for which stale routes are kept in RIB.
1104+
1105+
.. clicmd:: bgp graceful-restart restart-time (0-4095)
1106+
1107+
Set the time to wait to delete stale routes before a BGP open message
1108+
is received.
1109+
1110+
Using with Long-lived Graceful Restart capability, this is recommended
1111+
setting this timer to 0 and control stale routes with
1112+
``bgp long-lived-graceful-restart stale-time``.
1113+
1114+
Default value is 120.
1115+
1116+
.. clicmd:: bgp graceful-restart stalepath-time (1-4095)
1117+
1118+
This is command, will set the max time (in seconds) to hold onto
1119+
restarting peer's stale paths.
1120+
1121+
It also controls Enhanced Route-Refresh timer.
1122+
1123+
If this command is configured and the router does not receive a Route-Refresh EoRR
1124+
message, the router removes the stale routes from the BGP table after the timer
1125+
expires. The stale path timer is started when the router receives a Route-Refresh
1126+
BoRR message
1127+
1128+
10831129
.. _bgp-GR-global-mode-cmd:
10841130

10851131
BGP GR Global Mode Commands

tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@
8181
import sys
8282
import time
8383
import pytest
84+
import functools
85+
import json
8486

8587
# Save the Current Working Directory to find configuration files.
8688
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -91,6 +93,7 @@
9193
# Import topogen and topotest helpers
9294
from lib.topogen import Topogen, get_topogen
9395
from lib.topolog import logger
96+
from lib import topotest
9497

9598
# Required to instantiate the topology builder class.
9699

@@ -1680,6 +1683,304 @@ def BGP_GR_TC_52_p1(request):
16801683
write_test_footer(tc_name)
16811684

16821685

1686+
def test_BGP_GR_TC_53_p1(request):
1687+
"""
1688+
Test Objective : Peer-level inherit from BGP wide Restarting
1689+
Global Mode : GR Restart
1690+
PerPeer Mode : None
1691+
GR Mode effective : GR Restart
1692+
1693+
"""
1694+
1695+
tgen = get_topogen()
1696+
tc_name = request.node.name
1697+
write_test_header(tc_name)
1698+
1699+
# Check router status
1700+
check_router_status(tgen)
1701+
1702+
# Don't run this test if we have any failure.
1703+
if tgen.routers_have_failure():
1704+
pytest.skip(tgen.errors)
1705+
1706+
# Creating configuration from JSON
1707+
reset_config_on_routers(tgen)
1708+
1709+
step("Configure R1 as GR restarting node in global level")
1710+
1711+
input_dict = {
1712+
"r1": {"graceful-restart": {"graceful-restart": True}},
1713+
"r2": {"graceful-restart": {"graceful-restart-helper": True}},
1714+
}
1715+
1716+
output = tgen.gears["r1"].vtysh_cmd(
1717+
"""
1718+
configure terminal
1719+
bgp graceful-restart
1720+
!
1721+
"""
1722+
)
1723+
1724+
step("Verify that R2 receives GR restarting capabilities" " from R1")
1725+
1726+
for addr_type in ADDR_TYPES:
1727+
result = verify_graceful_restart(
1728+
tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
1729+
)
1730+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1731+
result = verify_graceful_restart(
1732+
tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
1733+
)
1734+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1735+
1736+
for addr_type in ADDR_TYPES:
1737+
dut = "r1"
1738+
peer = "r2"
1739+
protocol = "bgp"
1740+
next_hop = next_hop_per_address_family(
1741+
tgen, dut, peer, addr_type, NEXT_HOP_IP_2
1742+
)
1743+
input_topo = {"r2": topo["routers"]["r2"]}
1744+
result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
1745+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1746+
1747+
dut = "r2"
1748+
peer = "r1"
1749+
next_hop = next_hop_per_address_family(
1750+
tgen, dut, peer, addr_type, NEXT_HOP_IP_1
1751+
)
1752+
input_topo = {"r1": topo["routers"]["r1"]}
1753+
result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
1754+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1755+
result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
1756+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1757+
1758+
step("Kill BGPd on router R1")
1759+
1760+
kill_router_daemons(tgen, "r1", ["bgpd"])
1761+
1762+
step(
1763+
"Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
1764+
)
1765+
1766+
for addr_type in ADDR_TYPES:
1767+
dut = "r1"
1768+
peer = "r2"
1769+
protocol = "bgp"
1770+
next_hop = next_hop_per_address_family(
1771+
tgen, dut, peer, addr_type, NEXT_HOP_IP_2
1772+
)
1773+
input_topo = {"r2": topo["routers"]["r2"]}
1774+
result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
1775+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1776+
1777+
dut = "r2"
1778+
peer = "r1"
1779+
next_hop = next_hop_per_address_family(
1780+
tgen, dut, peer, addr_type, NEXT_HOP_IP_1
1781+
)
1782+
input_topo = {"r1": topo["routers"]["r1"]}
1783+
result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
1784+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1785+
result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
1786+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1787+
1788+
# Configure graceful-restart-disable at config global level verify that the functionality works
1789+
step("Bring up BGP on R1 and configure graceful-restart-disable")
1790+
1791+
start_router_daemons(tgen, "r1", ["bgpd"])
1792+
1793+
input_dict = {
1794+
"r1": {"graceful-restart": {"graceful-restart-disable": True}},
1795+
"r2": {"graceful-restart": {"graceful-restart-helper": True}},
1796+
}
1797+
1798+
output = tgen.gears["r1"].vtysh_cmd(
1799+
"""
1800+
configure terminal
1801+
bgp graceful-restart-disable
1802+
!
1803+
"""
1804+
)
1805+
1806+
step("Verify on R2 that R1 does't advertise any GR capabilities")
1807+
1808+
for addr_type in ADDR_TYPES:
1809+
result = verify_graceful_restart(
1810+
tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
1811+
)
1812+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1813+
result = verify_graceful_restart(
1814+
tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
1815+
)
1816+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1817+
1818+
for addr_type in ADDR_TYPES:
1819+
dut = "r1"
1820+
peer = "r2"
1821+
protocol = "bgp"
1822+
next_hop = next_hop_per_address_family(
1823+
tgen, dut, peer, addr_type, NEXT_HOP_IP_2
1824+
)
1825+
input_topo = {"r2": topo["routers"]["r2"]}
1826+
result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
1827+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1828+
1829+
dut = "r2"
1830+
peer = "r1"
1831+
next_hop = next_hop_per_address_family(
1832+
tgen, dut, peer, addr_type, NEXT_HOP_IP_1
1833+
)
1834+
input_topo = {"r1": topo["routers"]["r1"]}
1835+
result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
1836+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1837+
result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
1838+
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
1839+
1840+
step("Kill BGP on R1")
1841+
1842+
kill_router_daemons(tgen, "r1", ["bgpd"])
1843+
1844+
step("Verify on R2 and R1 that none of the routers keep stale entries")
1845+
1846+
for addr_type in ADDR_TYPES:
1847+
dut = "r1"
1848+
peer = "r2"
1849+
protocol = "bgp"
1850+
next_hop = next_hop_per_address_family(
1851+
tgen, dut, peer, addr_type, NEXT_HOP_IP_2
1852+
)
1853+
input_topo = {"r2": topo["routers"]["r2"]}
1854+
result = verify_rib(
1855+
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
1856+
)
1857+
assert result is not True, (
1858+
"Testcase {} : Failed \n "
1859+
"Expected: Routes should not be present in {} FIB \n "
1860+
"Found: {}".format(tc_name, dut, result)
1861+
)
1862+
1863+
dut = "r2"
1864+
peer = "r1"
1865+
next_hop = next_hop_per_address_family(
1866+
tgen, dut, peer, addr_type, NEXT_HOP_IP_1
1867+
)
1868+
input_topo = {"r1": topo["routers"]["r1"]}
1869+
result = verify_bgp_rib(
1870+
tgen, addr_type, dut, input_topo, next_hop, expected=False
1871+
)
1872+
assert result is not True, (
1873+
"Testcase {} : Failed \n "
1874+
"Expected: Routes should not be present in {} BGP RIB \n "
1875+
"Found: {}".format(tc_name, dut, result)
1876+
)
1877+
1878+
result = verify_rib(
1879+
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
1880+
)
1881+
assert result is not True, (
1882+
"Testcase {} : Failed \n "
1883+
"Expected: Routes should not be present in {} FIB \n "
1884+
"Found: {}".format(tc_name, dut, result)
1885+
)
1886+
1887+
step(
1888+
"Bring up BGP on R1, enable GR and configure bgp graceful-restart restart-time at global level"
1889+
)
1890+
1891+
start_router_daemons(tgen, "r1", ["bgpd"])
1892+
1893+
output = tgen.gears["r1"].vtysh_cmd(
1894+
"""
1895+
configure terminal
1896+
no bgp graceful-restart-disable
1897+
bgp graceful-restart
1898+
bgp graceful-restart stalepath-time 420
1899+
bgp graceful-restart restart-time 240
1900+
bgp graceful-restart select-defer-time 420
1901+
!
1902+
"""
1903+
)
1904+
1905+
step("Verify on R2 that R1 sent the updated GR restart-time")
1906+
1907+
def _bgp_check_if_gr_restart_time_was_updated():
1908+
output = json.loads(tgen.gears["r2"].vtysh_cmd("show bgp neighbor json"))
1909+
1910+
expected = {
1911+
"192.168.0.1": {
1912+
"gracefulRestartInfo": {
1913+
"localGrMode": "Helper*",
1914+
"remoteGrMode": "Restart",
1915+
"timers": {
1916+
"configuredRestartTimer": 120,
1917+
"receivedRestartTimer": 240,
1918+
},
1919+
},
1920+
},
1921+
"fd00::1": {
1922+
"gracefulRestartInfo": {
1923+
"localGrMode": "Helper*",
1924+
"remoteGrMode": "Restart",
1925+
"timers": {
1926+
"configuredRestartTimer": 120,
1927+
"receivedRestartTimer": 240,
1928+
},
1929+
},
1930+
},
1931+
}
1932+
return topotest.json_cmp(output, expected)
1933+
1934+
test_func = functools.partial(
1935+
_bgp_check_if_gr_restart_time_was_updated,
1936+
)
1937+
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
1938+
assert result is None, "R2 did not receive the updated GR restart-time of 240s"
1939+
1940+
def _bgp_check_if_gr_timer_on_restarting_node_was_updated():
1941+
output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json"))
1942+
1943+
expected = {
1944+
"192.168.0.2": {
1945+
"gracefulRestartInfo": {
1946+
"localGrMode": "Restart*",
1947+
"remoteGrMode": "Helper",
1948+
"timers": {
1949+
"configuredRestartTimer": 240,
1950+
"receivedRestartTimer": 120,
1951+
},
1952+
"ipv4Unicast": {
1953+
"timers": {"stalePathTimer": 420, "selectionDeferralTimer": 420}
1954+
},
1955+
},
1956+
},
1957+
"fd00::2": {
1958+
"gracefulRestartInfo": {
1959+
"localGrMode": "Restart*",
1960+
"remoteGrMode": "Helper",
1961+
"timers": {
1962+
"configuredRestartTimer": 240,
1963+
"receivedRestartTimer": 120,
1964+
},
1965+
"ipv6Unicast": {
1966+
"timers": {"stalePathTimer": 420, "selectionDeferralTimer": 420}
1967+
},
1968+
},
1969+
},
1970+
}
1971+
return topotest.json_cmp(output, expected)
1972+
1973+
test_func = functools.partial(
1974+
_bgp_check_if_gr_timer_on_restarting_node_was_updated,
1975+
)
1976+
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
1977+
assert (
1978+
result is None
1979+
), "R1 did not update the GR select-deferral and stale-path timer to 420s"
1980+
1981+
write_test_footer(tc_name)
1982+
1983+
16831984
if __name__ == "__main__":
16841985
args = ["-s"] + sys.argv[1:]
16851986
sys.exit(pytest.main(args))

0 commit comments

Comments
 (0)