summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/if.c2
-rw-r--r--lib/vrf.c18
-rw-r--r--zebra/if_netlink.c4
3 files changed, 22 insertions, 2 deletions
diff --git a/lib/if.c b/lib/if.c
index 0cfd591160..a803754375 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -177,6 +177,8 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
if (ifp->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_INSERT(vrf, ifp);
+ if (!old_vrf->name)
+ return;
/*
* HACK: Change the interface VRF in the running configuration directly,
* bypassing the northbound layer. This is necessary to avoid deleting
diff --git a/lib/vrf.c b/lib/vrf.c
index 229f19f29a..862a3da067 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -176,6 +176,24 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
name, vrf_id, vrf->vrf_id);
return NULL;
}
+ /* look for duplicates. case is followine one:
+ * - a vrf is configured per name -> vrfA
+ * - netlink discovery creates a vrf with vrf_id ->vrfB
+ * - then, netlink discovers vrf, and associated vrf_id and name
+ * -> so vrfA and vrfB must be merged
+ */
+ if (vrf && vrf_id != VRF_UNKNOWN
+ && vrf->vrf_id == VRF_UNKNOWN) {
+ struct vrf *vrf2 = vrf_lookup_by_id(vrf_id);
+ struct interface *ifp;
+
+ if (vrf2 && !vrf2->name && vrf2 != vrf) {
+ /* move vrf2 context to vrf */
+ FOR_ALL_INTERFACES (vrf2, ifp)
+ if_update_to_new_vrf(ifp, vrf);
+ vrf_delete(vrf2);
+ }
+ }
/* Try to find VRF both by ID and name */
if (!vrf && vrf_id != VRF_UNKNOWN)
vrf = vrf_lookup_by_id(vrf_id);
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 4b998bcdc4..2c94dd52b5 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -665,6 +665,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
&& !vrf_is_backend_netns()) {
zif_slave_type = ZEBRA_IF_SLAVE_VRF;
vrf_id = *(uint32_t *)RTA_DATA(tb[IFLA_MASTER]);
+ /* vrf can be needed before vrf netlink discovery */
+ vrf_get(vrf_id, NULL);
} else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) {
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex =
@@ -677,9 +679,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
}
if (vrf_is_backend_netns())
vrf_id = (vrf_id_t)ns_id;
-
vrf = vrf_lookup_by_id(vrf_id);
-
/* If linking to another interface, note it. */
if (tb[IFLA_LINK])
link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);