summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_vty.c28
-rw-r--r--tests/topotests/bgp_vrf_different_asn/__init__.py0
-rw-r--r--tests/topotests/bgp_vrf_different_asn/r1/frr.conf18
-rw-r--r--tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py107
4 files changed, 151 insertions, 2 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 0ef1351835..bce8202377 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1701,6 +1701,10 @@ DEFUN (no_router_bgp,
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) {
if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
continue;
+
+ if (CHECK_FLAG(tmp_bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
if (CHECK_FLAG(
tmp_bgp->af_flags[AFI_IP]
[SAFI_UNICAST],
@@ -10567,12 +10571,20 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
vrf_bgp = bgp_lookup_by_name(import_name);
if (!vrf_bgp) {
- if (strcmp(import_name, VRF_DEFAULT_NAME) == 0)
+ if (strcmp(import_name, VRF_DEFAULT_NAME) == 0) {
vrf_bgp = bgp_default;
- else
+ } else {
/* Auto-create assuming the same AS */
ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type,
NULL, ASNOTATION_UNDEFINED);
+
+ /* Auto created VRF instances should be marked
+ * properly, otherwise we have a state after bgpd
+ * restart where VRF instance has default VRF's ASN.
+ */
+ SET_FLAG(vrf_bgp->vrf_flags, BGP_VRF_AUTO);
+ }
+
if (ret) {
vty_out(vty,
"VRF %s is not configured as a bgp instance\n",
@@ -12745,6 +12757,9 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
vty_out(vty, "{\n");
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!is_first)
@@ -16130,6 +16145,9 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
vty_out(vty, "{\n");
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!(json = json_object_new_object())) {
@@ -16689,6 +16707,9 @@ static int bgp_show_all_instance_route_leak_vty(struct vty *vty, afi_t afi,
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)
vrf_name = bgp->name;
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
if (use_json) {
json_vrf = json_object_new_object();
} else {
@@ -16779,6 +16800,9 @@ static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
struct bgp *bgp;
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
if (!uj)
vty_out(vty, "\nInstance %s:\n",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
diff --git a/tests/topotests/bgp_vrf_different_asn/__init__.py b/tests/topotests/bgp_vrf_different_asn/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_vrf_different_asn/__init__.py
diff --git a/tests/topotests/bgp_vrf_different_asn/r1/frr.conf b/tests/topotests/bgp_vrf_different_asn/r1/frr.conf
new file mode 100644
index 0000000000..b325dfb7f0
--- /dev/null
+++ b/tests/topotests/bgp_vrf_different_asn/r1/frr.conf
@@ -0,0 +1,18 @@
+!
+vrf vrf100
+ vni 10100
+exit-vrf
+!
+interface r1-eth0 vrf vrf100
+ ip address 192.168.1.1/24
+!
+router bgp 65000
+ address-family ipv4 unicast
+ import vrf vrf100
+ exit-address-family
+!
+router bgp 65100 vrf vrf100
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py b/tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py
new file mode 100644
index 0000000000..9a1a9ec766
--- /dev/null
+++ b/tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+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, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 2):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ r1 = tgen.gears["r1"]
+ r1.run("ip link add vrf100 type vrf table 1001")
+ r1.run("ip link set up dev vrf100")
+ r1.run("ip link set r1-eth0 master vrf100")
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_vrf_different_asn():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_check_instances():
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp vrf all json"))
+ expected = {
+ "default": {
+ "vrfName": "default",
+ "localAS": 65000,
+ },
+ "vrf100": {
+ "vrfName": "vrf100",
+ "localAS": 65100,
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_check_instances)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see vrf100 to be under 65100 ASN"
+
+ def _bgp_check_imported_route():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip route 192.168.1.0/24 json")
+ )
+ expected = {
+ "192.168.1.0/24": [
+ {
+ "installed": True,
+ "selected": True,
+ "nexthops": [
+ {
+ "interfaceName": "vrf100",
+ "vrf": "vrf100",
+ "active": True,
+ }
+ ],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_check_imported_route)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see 192.168.1.0/24 being imported into a default VRF"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))