From: Soumya Roy Date: Mon, 7 Apr 2025 21:38:32 +0000 (+0000) Subject: test: Test for bgp route delete X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=93458dcf7a5917df699ce50e1880f384d3a991f7;p=matthieu%2Ffrr.git test: Test for bgp route delete This fix add tests to verify routes/path are getting deleted properly, when the advertising neighbor is shutdown Signed-off-by: Soumya Roy --- diff --git a/tests/topotests/high_ecmp/r1/frr_unnumbered_bgp.conf b/tests/topotests/high_ecmp/r1/frr_unnumbered_bgp.conf index f48eb23405..7f83c6a25c 100644 --- a/tests/topotests/high_ecmp/r1/frr_unnumbered_bgp.conf +++ b/tests/topotests/high_ecmp/r1/frr_unnumbered_bgp.conf @@ -517,3 +517,209 @@ router bgp 1001 address-family ipv4 uni redistribute sharp + +address-family ipv6 unicast + redistribute sharp + neighbor r1-eth0 activate + neighbor r1-eth1 activate + neighbor r1-eth2 activate + neighbor r1-eth3 activate + neighbor r1-eth4 activate + neighbor r1-eth5 activate + neighbor r1-eth6 activate + neighbor r1-eth7 activate + neighbor r1-eth8 activate + neighbor r1-eth9 activate + neighbor r1-eth10 activate + neighbor r1-eth11 activate + neighbor r1-eth12 activate + neighbor r1-eth13 activate + neighbor r1-eth14 activate + neighbor r1-eth15 activate + neighbor r1-eth16 activate + neighbor r1-eth17 activate + neighbor r1-eth18 activate + neighbor r1-eth19 activate + neighbor r1-eth20 activate + neighbor r1-eth21 activate + neighbor r1-eth22 activate + neighbor r1-eth23 activate + neighbor r1-eth24 activate + neighbor r1-eth25 activate + neighbor r1-eth26 activate + neighbor r1-eth27 activate + neighbor r1-eth28 activate + neighbor r1-eth29 activate + neighbor r1-eth30 activate + neighbor r1-eth31 activate + neighbor r1-eth32 activate + neighbor r1-eth33 activate + neighbor r1-eth34 activate + neighbor r1-eth35 activate + neighbor r1-eth36 activate + neighbor r1-eth37 activate + neighbor r1-eth38 activate + neighbor r1-eth39 activate + neighbor r1-eth40 activate + neighbor r1-eth41 activate + neighbor r1-eth42 activate + neighbor r1-eth43 activate + neighbor r1-eth44 activate + neighbor r1-eth45 activate + neighbor r1-eth46 activate + neighbor r1-eth47 activate + neighbor r1-eth48 activate + neighbor r1-eth49 activate + neighbor r1-eth50 activate + neighbor r1-eth51 activate + neighbor r1-eth52 activate + neighbor r1-eth53 activate + neighbor r1-eth54 activate + neighbor r1-eth55 activate + neighbor r1-eth56 activate + neighbor r1-eth57 activate + neighbor r1-eth58 activate + neighbor r1-eth59 activate + neighbor r1-eth60 activate + neighbor r1-eth61 activate + neighbor r1-eth62 activate + neighbor r1-eth63 activate + neighbor r1-eth64 activate + neighbor r1-eth65 activate + neighbor r1-eth66 activate + neighbor r1-eth67 activate + neighbor r1-eth68 activate + neighbor r1-eth69 activate + neighbor r1-eth70 activate + neighbor r1-eth71 activate + neighbor r1-eth72 activate + neighbor r1-eth73 activate + neighbor r1-eth74 activate + neighbor r1-eth75 activate + neighbor r1-eth76 activate + neighbor r1-eth77 activate + neighbor r1-eth78 activate + neighbor r1-eth79 activate + neighbor r1-eth80 activate + neighbor r1-eth81 activate + neighbor r1-eth82 activate + neighbor r1-eth83 activate + neighbor r1-eth84 activate + neighbor r1-eth85 activate + neighbor r1-eth86 activate + neighbor r1-eth87 activate + neighbor r1-eth88 activate + neighbor r1-eth89 activate + neighbor r1-eth90 activate + neighbor r1-eth91 activate + neighbor r1-eth92 activate + neighbor r1-eth93 activate + neighbor r1-eth94 activate + neighbor r1-eth95 activate + neighbor r1-eth96 activate + neighbor r1-eth97 activate + neighbor r1-eth98 activate + neighbor r1-eth99 activate + neighbor r1-eth100 activate + neighbor r1-eth101 activate + neighbor r1-eth102 activate + neighbor r1-eth103 activate + neighbor r1-eth104 activate + neighbor r1-eth105 activate + neighbor r1-eth106 activate + neighbor r1-eth107 activate + neighbor r1-eth108 activate + neighbor r1-eth109 activate + neighbor r1-eth110 activate + neighbor r1-eth111 activate + neighbor r1-eth112 activate + neighbor r1-eth113 activate + neighbor r1-eth114 activate + neighbor r1-eth115 activate + neighbor r1-eth116 activate + neighbor r1-eth117 activate + neighbor r1-eth118 activate + neighbor r1-eth119 activate + neighbor r1-eth120 activate + neighbor r1-eth121 activate + neighbor r1-eth122 activate + neighbor r1-eth123 activate + neighbor r1-eth124 activate + neighbor r1-eth125 activate + neighbor r1-eth126 activate + neighbor r1-eth127 activate + neighbor r1-eth128 activate + neighbor r1-eth129 activate + neighbor r1-eth130 activate + neighbor r1-eth131 activate + neighbor r1-eth132 activate + neighbor r1-eth133 activate + neighbor r1-eth134 activate + neighbor r1-eth135 activate + neighbor r1-eth136 activate + neighbor r1-eth137 activate + neighbor r1-eth138 activate + neighbor r1-eth139 activate + neighbor r1-eth140 activate + neighbor r1-eth141 activate + neighbor r1-eth142 activate + neighbor r1-eth143 activate + neighbor r1-eth144 activate + neighbor r1-eth145 activate + neighbor r1-eth146 activate + neighbor r1-eth147 activate + neighbor r1-eth148 activate + neighbor r1-eth149 activate + neighbor r1-eth150 activate + neighbor r1-eth151 activate + neighbor r1-eth152 activate + neighbor r1-eth153 activate + neighbor r1-eth154 activate + neighbor r1-eth155 activate + neighbor r1-eth156 activate + neighbor r1-eth157 activate + neighbor r1-eth158 activate + neighbor r1-eth159 activate + neighbor r1-eth160 activate + neighbor r1-eth161 activate + neighbor r1-eth162 activate + neighbor r1-eth163 activate + neighbor r1-eth164 activate + neighbor r1-eth165 activate + neighbor r1-eth166 activate + neighbor r1-eth167 activate + neighbor r1-eth168 activate + neighbor r1-eth169 activate + neighbor r1-eth170 activate + neighbor r1-eth171 activate + neighbor r1-eth172 activate + neighbor r1-eth173 activate + neighbor r1-eth174 activate + neighbor r1-eth175 activate + neighbor r1-eth176 activate + neighbor r1-eth177 activate + neighbor r1-eth178 activate + neighbor r1-eth179 activate + neighbor r1-eth180 activate + neighbor r1-eth181 activate + neighbor r1-eth182 activate + neighbor r1-eth183 activate + neighbor r1-eth184 activate + neighbor r1-eth185 activate + neighbor r1-eth186 activate + neighbor r1-eth187 activate + neighbor r1-eth188 activate + neighbor r1-eth189 activate + neighbor r1-eth190 activate + neighbor r1-eth191 activate + neighbor r1-eth192 activate + neighbor r1-eth193 activate + neighbor r1-eth194 activate + neighbor r1-eth195 activate + neighbor r1-eth196 activate + neighbor r1-eth197 activate + neighbor r1-eth198 activate + neighbor r1-eth199 activate + neighbor r1-eth200 activate + exit-address-family +exit \ No newline at end of file diff --git a/tests/topotests/high_ecmp/r2/frr_unnumbered_bgp.conf b/tests/topotests/high_ecmp/r2/frr_unnumbered_bgp.conf index 0b12e83e1f..9428af3440 100644 --- a/tests/topotests/high_ecmp/r2/frr_unnumbered_bgp.conf +++ b/tests/topotests/high_ecmp/r2/frr_unnumbered_bgp.conf @@ -515,3 +515,208 @@ router bgp 1002 neighbor r2-eth513 interface remote-as external neighbor r2-eth514 interface remote-as external + address-family ipv6 unicast + redistribute sharp + neighbor r2-eth0 activate + neighbor r2-eth1 activate + neighbor r2-eth2 activate + neighbor r2-eth3 activate + neighbor r2-eth4 activate + neighbor r2-eth5 activate + neighbor r2-eth6 activate + neighbor r2-eth7 activate + neighbor r2-eth8 activate + neighbor r2-eth9 activate + neighbor r2-eth10 activate + neighbor r2-eth11 activate + neighbor r2-eth12 activate + neighbor r2-eth13 activate + neighbor r2-eth14 activate + neighbor r2-eth15 activate + neighbor r2-eth16 activate + neighbor r2-eth17 activate + neighbor r2-eth18 activate + neighbor r2-eth19 activate + neighbor r2-eth20 activate + neighbor r2-eth21 activate + neighbor r2-eth22 activate + neighbor r2-eth23 activate + neighbor r2-eth24 activate + neighbor r2-eth25 activate + neighbor r2-eth26 activate + neighbor r2-eth27 activate + neighbor r2-eth28 activate + neighbor r2-eth29 activate + neighbor r2-eth30 activate + neighbor r2-eth31 activate + neighbor r2-eth32 activate + neighbor r2-eth33 activate + neighbor r2-eth34 activate + neighbor r2-eth35 activate + neighbor r2-eth36 activate + neighbor r2-eth37 activate + neighbor r2-eth38 activate + neighbor r2-eth39 activate + neighbor r2-eth40 activate + neighbor r2-eth41 activate + neighbor r2-eth42 activate + neighbor r2-eth43 activate + neighbor r2-eth44 activate + neighbor r2-eth45 activate + neighbor r2-eth46 activate + neighbor r2-eth47 activate + neighbor r2-eth48 activate + neighbor r2-eth49 activate + neighbor r2-eth50 activate + neighbor r2-eth51 activate + neighbor r2-eth52 activate + neighbor r2-eth53 activate + neighbor r2-eth54 activate + neighbor r2-eth55 activate + neighbor r2-eth56 activate + neighbor r2-eth57 activate + neighbor r2-eth58 activate + neighbor r2-eth59 activate + neighbor r2-eth60 activate + neighbor r2-eth61 activate + neighbor r2-eth62 activate + neighbor r2-eth63 activate + neighbor r2-eth64 activate + neighbor r2-eth65 activate + neighbor r2-eth66 activate + neighbor r2-eth67 activate + neighbor r2-eth68 activate + neighbor r2-eth69 activate + neighbor r2-eth70 activate + neighbor r2-eth71 activate + neighbor r2-eth72 activate + neighbor r2-eth73 activate + neighbor r2-eth74 activate + neighbor r2-eth75 activate + neighbor r2-eth76 activate + neighbor r2-eth77 activate + neighbor r2-eth78 activate + neighbor r2-eth79 activate + neighbor r2-eth80 activate + neighbor r2-eth81 activate + neighbor r2-eth82 activate + neighbor r2-eth83 activate + neighbor r2-eth84 activate + neighbor r2-eth85 activate + neighbor r2-eth86 activate + neighbor r2-eth87 activate + neighbor r2-eth88 activate + neighbor r2-eth89 activate + neighbor r2-eth90 activate + neighbor r2-eth91 activate + neighbor r2-eth92 activate + neighbor r2-eth93 activate + neighbor r2-eth94 activate + neighbor r2-eth95 activate + neighbor r2-eth96 activate + neighbor r2-eth97 activate + neighbor r2-eth98 activate + neighbor r2-eth99 activate + neighbor r2-eth100 activate + neighbor r2-eth101 activate + neighbor r2-eth102 activate + neighbor r2-eth103 activate + neighbor r2-eth104 activate + neighbor r2-eth105 activate + neighbor r2-eth106 activate + neighbor r2-eth107 activate + neighbor r2-eth108 activate + neighbor r2-eth109 activate + neighbor r2-eth110 activate + neighbor r2-eth111 activate + neighbor r2-eth112 activate + neighbor r2-eth113 activate + neighbor r2-eth114 activate + neighbor r2-eth115 activate + neighbor r2-eth116 activate + neighbor r2-eth117 activate + neighbor r2-eth118 activate + neighbor r2-eth119 activate + neighbor r2-eth120 activate + neighbor r2-eth121 activate + neighbor r2-eth122 activate + neighbor r2-eth123 activate + neighbor r2-eth124 activate + neighbor r2-eth125 activate + neighbor r2-eth126 activate + neighbor r2-eth127 activate + neighbor r2-eth128 activate + neighbor r2-eth129 activate + neighbor r2-eth130 activate + neighbor r2-eth131 activate + neighbor r2-eth132 activate + neighbor r2-eth133 activate + neighbor r2-eth134 activate + neighbor r2-eth135 activate + neighbor r2-eth136 activate + neighbor r2-eth137 activate + neighbor r2-eth138 activate + neighbor r2-eth139 activate + neighbor r2-eth140 activate + neighbor r2-eth141 activate + neighbor r2-eth142 activate + neighbor r2-eth143 activate + neighbor r2-eth144 activate + neighbor r2-eth145 activate + neighbor r2-eth146 activate + neighbor r2-eth147 activate + neighbor r2-eth148 activate + neighbor r2-eth149 activate + neighbor r2-eth150 activate + neighbor r2-eth151 activate + neighbor r2-eth152 activate + neighbor r2-eth153 activate + neighbor r2-eth154 activate + neighbor r2-eth155 activate + neighbor r2-eth156 activate + neighbor r2-eth157 activate + neighbor r2-eth158 activate + neighbor r2-eth159 activate + neighbor r2-eth160 activate + neighbor r2-eth161 activate + neighbor r2-eth162 activate + neighbor r2-eth163 activate + neighbor r2-eth164 activate + neighbor r2-eth165 activate + neighbor r2-eth166 activate + neighbor r2-eth167 activate + neighbor r2-eth168 activate + neighbor r2-eth169 activate + neighbor r2-eth170 activate + neighbor r2-eth171 activate + neighbor r2-eth172 activate + neighbor r2-eth173 activate + neighbor r2-eth174 activate + neighbor r2-eth175 activate + neighbor r2-eth176 activate + neighbor r2-eth177 activate + neighbor r2-eth178 activate + neighbor r2-eth179 activate + neighbor r2-eth180 activate + neighbor r2-eth181 activate + neighbor r2-eth182 activate + neighbor r2-eth183 activate + neighbor r2-eth184 activate + neighbor r2-eth185 activate + neighbor r2-eth186 activate + neighbor r2-eth187 activate + neighbor r2-eth188 activate + neighbor r2-eth189 activate + neighbor r2-eth190 activate + neighbor r2-eth191 activate + neighbor r2-eth192 activate + neighbor r2-eth193 activate + neighbor r2-eth194 activate + neighbor r2-eth195 activate + neighbor r2-eth196 activate + neighbor r2-eth197 activate + neighbor r2-eth198 activate + neighbor r2-eth199 activate + neighbor r2-eth200 activate +exit-address-family +exit diff --git a/tests/topotests/high_ecmp/test_high_ecmp_unnumbered.py b/tests/topotests/high_ecmp/test_high_ecmp_unnumbered.py index 0947272386..ed6257f72e 100644 --- a/tests/topotests/high_ecmp/test_high_ecmp_unnumbered.py +++ b/tests/topotests/high_ecmp/test_high_ecmp_unnumbered.py @@ -21,6 +21,12 @@ import re import sys import pytest import json +from time import sleep + +from lib.common_config import ( + kill_router_daemons, + start_router_daemons, +) pytestmark = [pytest.mark.bgpd] @@ -99,6 +105,171 @@ def teardown_module(_mod): tgen.stop_topology() +def test_bgp_route_cleanup(): + failures = 0 + net = get_topogen().net + expected_route_count = 2000 + + # First, extract IPv4 and IPv6 loopback addresses from r1 + lo_output = net["r1"].cmd("vtysh -c 'show interface lo'") + + # Extract IPv4 and IPv6 addresses from the output + ipv4_match = re.search(r"inet (\d+\.\d+\.\d+\.\d+)/\d+", lo_output) + ipv6_match = re.search(r"inet6 ([0-9a-f:]+)/\d+", lo_output) + + if not ipv4_match or not ipv6_match: + assert False, "Could not find IPv4 or IPv6 address on loopback interface" + + ipv4_nexthop = ipv4_match.group(1) + ipv6_nexthop = ipv6_match.group(1) + + print(f"\nUsing nexthops: IPv4={ipv4_nexthop}, IPv6={ipv6_nexthop}") + + # Install IPv4 routes + ipv4_cmd = f"vtysh -c 'sharp install routes 39.99.0.0 nexthop {ipv4_nexthop} {expected_route_count}'" + net["r1"].cmd(ipv4_cmd) + + # Install IPv6 routes + ipv6_cmd = f"vtysh -c 'sharp install routes 2100:cafe:: nexthop {ipv6_nexthop} {expected_route_count}'" + net["r1"].cmd(ipv6_cmd) + + # Initialize actual counts + ipv4_actual_count = 0 + ipv6_actual_count = 0 + max_attempts = 12 # 60 seconds max (12 * 5) + attempt = 0 + + # Wait until both IPv4 and IPv6 routes are installed + while ( + ipv4_actual_count != expected_route_count + or ipv6_actual_count != expected_route_count + ) and attempt < max_attempts: + sleep(5) + attempt += 1 + + # Get current IPv4 route count + ipv4_count_str = ( + net["r2"] + .cmd('vtysh -c "show bgp ipv4 unicast" | grep "39.99" | wc -l') + .rstrip() + ) + + # Get current IPv6 route count + ipv6_count_str = ( + net["r2"] + .cmd('vtysh -c "show bgp ipv6 unicast" | grep "cafe" | wc -l') + .rstrip() + ) + + try: + ipv4_actual_count = int(ipv4_count_str) + except ValueError: + ipv4_actual_count = 0 + + try: + ipv6_actual_count = int(ipv6_count_str) + except ValueError: + ipv6_actual_count = 0 + + print(f"Attempt {attempt}") + print(f"IPv4 Routes found: {ipv4_actual_count} / {expected_route_count}") + print(f"IPv6 Routes found: {ipv6_actual_count} / {expected_route_count}") + + # Verify we have the expected number of routes + if ipv4_actual_count != expected_route_count: + sys.stderr.write( + f"Failed to install expected IPv4 routes: got {ipv4_actual_count}, expected {expected_route_count}\n" + ) + failures += 1 + else: + print("IPv4 routes successfully installed") + + if ipv6_actual_count != expected_route_count: + sys.stderr.write( + f"Failed to install expected IPv6 routes: got {ipv6_actual_count}, expected {expected_route_count}\n" + ) + failures += 1 + else: + print("IPv6 routes successfully installed") + + # Stop bgpd in r1 to trigger deletion of routes in r2 + kill_router_daemons(get_topogen(), "r1", ["bgpd"]) + + # Initialize variables for post-removal check + # Start with the original count + ipv4_final_count = expected_route_count + ipv6_final_count = expected_route_count + expected_final_count = 0 + attempt = 0 + max_removal_attempts = 12 + + # Wait until both IPv4 and IPv6 routes are fully removed + while ( + ipv4_final_count != expected_final_count + or ipv6_final_count != expected_final_count + ) and attempt < max_removal_attempts: + sleep(5) + attempt += 1 + + # Get current IPv4 route count + ipv4_count_str = ( + net["r2"] + .cmd('vtysh -c "show bgp ipv4 unicast" | grep "39.99" | wc -l') + .rstrip() + ) + + # Get current IPv6 route count + ipv6_count_str = ( + net["r2"] + .cmd('vtysh -c "show bgp ipv6 unicast" | grep "cafe" | wc -l') + .rstrip() + ) + + try: + ipv4_final_count = int(ipv4_count_str) + except ValueError: + ipv4_final_count = 0 + + try: + ipv6_final_count = int(ipv6_count_str) + except ValueError: + ipv6_final_count = 0 + + print(f"Route Removal Attempt {attempt}") + print(f"IPv4 Routes remaining: {ipv4_final_count} / {expected_final_count}") + print(f"IPv6 Routes remaining: {ipv6_final_count} / {expected_final_count}") + + # If both are already at expected count, break early + if ( + ipv4_final_count == expected_final_count + and ipv6_final_count == expected_final_count + ): + print("All routes successfully removed") + break + + # Final verification + if ipv4_final_count != expected_final_count: + sys.stderr.write( + f"Failed to remove IPv4 routes after {max_removal_attempts} attempts: " + f"{ipv4_final_count} routes still present\n" + ) + failures += 1 + else: + print("IPv4 routes successfully removed") + + if ipv6_final_count != expected_final_count: + sys.stderr.write( + f"Failed to remove IPv6 routes after {max_removal_attempts} attempts: " + f"{ipv6_final_count} routes still present\n" + ) + failures += 1 + else: + print("IPv6 routes successfully removed") + + start_router_daemons(get_topogen(), "r1", ["bgpd"]) + assert failures == 0, f"Test failed with {failures} failures" + + def test_nothing(): "Do Nothing" tgen = get_topogen()