summaryrefslogtreecommitdiff
path: root/lib/if.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/if.c')
-rw-r--r--lib/if.c75
1 files changed, 69 insertions, 6 deletions
diff --git a/lib/if.c b/lib/if.c
index f7a167f251..9ee2f02e62 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -132,18 +132,26 @@ static int if_cmp_index_func(const struct interface *ifp1,
}
/* Create new interface structure. */
-struct interface *if_create(const char *name, vrf_id_t vrf_id)
+static struct interface *if_create_backend(const char *name, ifindex_t ifindex,
+ vrf_id_t vrf_id)
{
struct vrf *vrf = vrf_get(vrf_id, NULL);
struct interface *ifp;
ifp = XCALLOC(MTYPE_IF, sizeof(struct interface));
- ifp->ifindex = IFINDEX_INTERNAL;
-
- assert(name);
- strlcpy(ifp->name, name, sizeof(ifp->name));
ifp->vrf_id = vrf_id;
- IFNAME_RB_INSERT(vrf, ifp);
+
+ if (name) {
+ strlcpy(ifp->name, name, sizeof(ifp->name));
+ IFNAME_RB_INSERT(vrf, ifp);
+ } else
+ ifp->name[0] = '\0';
+
+ if (ifindex != IFINDEX_INTERNAL)
+ if_set_index(ifp, ifindex);
+ else
+ ifp->ifindex = ifindex; /* doesn't add it to the list */
+
ifp->connected = list_new();
ifp->connected->del = (void (*)(void *))connected_free;
@@ -158,6 +166,16 @@ struct interface *if_create(const char *name, vrf_id_t vrf_id)
return ifp;
}
+struct interface *if_create(const char *name, vrf_id_t vrf_id)
+{
+ return if_create_backend(name, IFINDEX_INTERNAL, vrf_id);
+}
+
+struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id)
+{
+ return if_create_backend(NULL, ifindex, vrf_id);
+}
+
/* Create new interface structure. */
void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
{
@@ -302,6 +320,23 @@ struct interface *if_lookup_by_name_all_vrf(const char *name)
return NULL;
}
+struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)
+{
+ struct vrf *vrf;
+ struct interface *ifp;
+
+ if (ifindex == IFINDEX_INTERNAL)
+ return NULL;
+
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+ ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
+ if (ifp)
+ return ifp;
+ }
+
+ return NULL;
+}
+
/* Lookup interface by IPv4 address. */
struct interface *if_lookup_exact_address(void *src, int family,
vrf_id_t vrf_id)
@@ -447,6 +482,34 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id)
return NULL;
}
+struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id)
+{
+ struct interface *ifp;
+
+ switch (vrf_get_backend()) {
+ case VRF_BACKEND_UNKNOWN:
+ case VRF_BACKEND_NETNS:
+ ifp = if_lookup_by_index(ifindex, vrf_id);
+ if (ifp)
+ return ifp;
+ return if_create_ifindex(ifindex, vrf_id);
+ case VRF_BACKEND_VRF_LITE:
+ ifp = if_lookup_by_index_all_vrf(ifindex);
+ if (ifp) {
+ if (ifp->vrf_id == vrf_id)
+ return ifp;
+ /* If it came from the kernel or by way of zclient,
+ * believe it and update the ifp accordingly.
+ */
+ if_update_to_new_vrf(ifp, vrf_id);
+ return ifp;
+ }
+ return if_create_ifindex(ifindex, vrf_id);
+ }
+
+ return NULL;
+}
+
void if_set_index(struct interface *ifp, ifindex_t ifindex)
{
struct vrf *vrf;