Commit c270b07757 for frr

commit c270b0775734ca82f7cde6150c5cae8baec6c771
Author: Kyrylo Yatsenko <hedrok@gmail.com>
Date:   Fri Nov 6 16:43:32 2026 +0200

    tests: Add test for deferred BGP route leak

    Add test that checks configurations like

    ```
    router bgp 65500 vrf NONNA
     address-family ipv4 unicast
      redistribute connected
      rd vpn export 65500:100
      rt vpn export 65500:110
      export vpn

    router bgp 65500
    ```

    where leak was deferred while there was no default BGP instance

    Signed-off-by: Kyrylo Yatsenko <hedrok@gmail.com>

diff --git a/tests/topotests/bgp_vrf_deferred_leak/__init__.py b/tests/topotests/bgp_vrf_deferred_leak/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/topotests/bgp_vrf_deferred_leak/r1/frr.conf b/tests/topotests/bgp_vrf_deferred_leak/r1/frr.conf
new file mode 100644
index 0000000000..4a82bbbc8c
--- /dev/null
+++ b/tests/topotests/bgp_vrf_deferred_leak/r1/frr.conf
@@ -0,0 +1,18 @@
+hostname r1
+
+interface dummy5
+ ip address 10.0.5.1/24
+ no shut
+!
+interface NONNA
+ no shut
+!
+
+router bgp 65500 vrf NONNA
+ address-family ipv4 unicast
+  redistribute connected
+  rd vpn export 65500:100
+  rt vpn export 65500:110
+  export vpn
+ !
+!
diff --git a/tests/topotests/bgp_vrf_deferred_leak/setup_vrfs b/tests/topotests/bgp_vrf_deferred_leak/setup_vrfs
new file mode 100644
index 0000000000..37d3cce414
--- /dev/null
+++ b/tests/topotests/bgp_vrf_deferred_leak/setup_vrfs
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+ip link add NONNA type vrf table 1004
+ip link add dummy5 type dummy
+ip link set dummy5 master NONNA
diff --git a/tests/topotests/bgp_vrf_deferred_leak/test_bgp-vrf-deferred-leak.py b/tests/topotests/bgp_vrf_deferred_leak/test_bgp-vrf-deferred-leak.py
new file mode 100644
index 0000000000..a8fa9d19d0
--- /dev/null
+++ b/tests/topotests/bgp_vrf_deferred_leak/test_bgp-vrf-deferred-leak.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# test_bgp-vrf-deferred-leak.py
+#
+# Copyright (c) 2026 VyOS, Inc; Kyrylo Yatsenko
+#
+
+"""
+test_bgp-vrf-deferred-leak.py: Test vrf route leaking for deferred routes
+"""
+
+import os
+import sys
+from functools import partial
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+    "Build function"
+    tgen.add_router("r1")
+
+
+def setup_module(mod):
+    tgen = Topogen(build_topo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+
+    for router in router_list.values():
+        router.run("/bin/bash {}/setup_vrfs".format(CWD))
+        router.load_frr_config()
+
+    tgen.start_router()
+
+
+def teardown_module(mod):
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+# Check deferred leaks after default bgp instance is created,
+# see comment to vpn_leak_postchange_all
+def test_vrf_deferred_route_leak():
+    logger.info(
+        "Ensure that deferred route leaks are processed properly (the ones exported before default bgp router is created)"
+    )
+    tgen = get_topogen()
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    r1 = tgen.gears["r1"]
+
+    # Wait for all preconditions:
+    # * Wait for route to be known to bgp vrf instance
+    # * Wait for all known conditions that can call `vpn_leak_postchange_all`
+    #   asynchronously after default bgp instance creation so that we really
+    #   check that deferred leaks are processed properly
+    # * Recheck that default bgp instance is not created yet
+    wait_data = [
+        # route in NONNA is known to bgp
+        {
+            "cmd": "show bgp vrf NONNA ipv4 unicast json",
+            "expect": {"routes": {"10.0.5.0/24": [{"valid": True}]}},
+            "msg": "Initial route in BGP VRF didn't appear",
+        },
+        # call in `bgp_zebra_label_manager_connect`
+        {
+            "cmd": "show bgp labelpool summary json",
+            "expect": {"reconnects": 1},
+            "msg": "Wait for label manager connect failed",
+        },
+        # call in `bgp_ifp_up`
+        {
+            "cmd": "show interface NONNA json",
+            "expect": {"NONNA": {"operationalStatus": "up"}},
+            "msg": "Wait for NONNA vrf interface to come up failed",
+        },
+        # Ensure currently there is no default bgp instance
+        {
+            "cmd": "show bgp vrfs json",
+            "expect": {"vrfs": {"default": None}},
+            "msg": "bgp default instance is unexpectedly present before the test",
+        },
+    ]
+
+    for data in wait_data:
+        cmd = data["cmd"]
+        expect = data["expect"]
+        msg = data["msg"]
+
+        test_func = partial(
+            topotest.router_json_cmp, r1, cmd, expect
+        )
+        result, diff = topotest.run_and_expect(test_func, None, count=15, wait=1)
+        assert result, f"{msg}:\n{diff}"
+
+    # Now enable bgp router in default VRF
+    r1.vtysh_cmd("configure terminal\nrouter bgp 65500")
+
+    # Verify deferred route leak was processed properly
+    expect = {
+        "routes": {
+            "routeDistinguishers": {
+                "65500:100": {
+                    "10.0.5.0/24": [{"valid": True}],
+                },
+            },
+        }
+    }
+    test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
+    result, diff = topotest.run_and_expect(test_func, None, count=15, wait=1)
+    assert result, "BGP VRF deferred route leak check failed:\n{}".format(diff)
+
+
+def test_memory_leak():
+    "Run the memory leak test and report results."
+    tgen = get_topogen()
+    if not tgen.is_memleak_enabled():
+        pytest.skip("Memory leak test/report is disabled")
+
+    tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))