]> git.puffer.fish Git - matthieu/frr.git/commitdiff
test: Test for bgp route delete
authorSoumya Roy <souroy@nvidia.com>
Mon, 7 Apr 2025 21:38:32 +0000 (21:38 +0000)
committerSoumya Roy <souroy@nvidia.com>
Wed, 9 Apr 2025 20:46:43 +0000 (20:46 +0000)
This fix add tests to verify routes/path are getting
deleted properly, when the advertising neighbor is shutdown

Signed-off-by: Soumya Roy <souroy@nvidia.com>
tests/topotests/high_ecmp/r1/frr_unnumbered_bgp.conf
tests/topotests/high_ecmp/r2/frr_unnumbered_bgp.conf
tests/topotests/high_ecmp/test_high_ecmp_unnumbered.py

index f48eb234059594b72543d16e5ad66b9111478406..7f83c6a25c5b63266ea2b0e53df73b47e18f962e 100644 (file)
@@ -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
index 0b12e83e1fa07805d935d59a1958ea86e0ac9036..9428af3440ed02ba9c0a4ba4e7d14b62e5d9492e 100644 (file)
@@ -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
index 0947272386af9206bdb99dd95833bdd66139ba8e..ed6257f72ece27422d9183791746442e76838a62 100644 (file)
@@ -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()