diff options
Diffstat (limited to 'lib/if.c')
| -rw-r--r-- | lib/if.c | 99 |
1 files changed, 89 insertions, 10 deletions
@@ -45,6 +45,8 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected") DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label") DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters") +static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, + vrf_id_t vrf_id); static int if_cmp_func(const struct interface *, const struct interface *); static int if_cmp_index_func(const struct interface *ifp1, const struct interface *ifp2); @@ -132,18 +134,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 +168,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) { @@ -239,8 +259,9 @@ void if_delete(struct interface *ifp) XFREE(MTYPE_IF, ifp); } -/* Interface existance check by index. */ -struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) +/* Used only internally to check within VRF only */ +static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, + vrf_id_t vrf_id) { struct vrf *vrf; struct interface if_tmp; @@ -253,6 +274,19 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp); } +/* Interface existance check by index. */ +struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) +{ + switch (vrf_get_backend()) { + case VRF_BACKEND_UNKNOWN: + case VRF_BACKEND_NETNS: + return(if_lookup_by_ifindex(ifindex, vrf_id)); + case VRF_BACKEND_VRF_LITE: + return(if_lookup_by_index_all_vrf(ifindex)); + } + return NULL; +} + const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id) { struct interface *ifp; @@ -302,7 +336,24 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) return NULL; } -/* Lookup interface by IPv4 address. */ +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_ifindex(ifindex, vrf->vrf_id); + if (ifp) + return ifp; + } + + return NULL; +} + +/* Lookup interface by IP address. */ struct interface *if_lookup_exact_address(void *src, int family, vrf_id_t vrf_id) { @@ -334,7 +385,7 @@ struct interface *if_lookup_exact_address(void *src, int family, return NULL; } -/* Lookup interface by IPv4 address. */ +/* Lookup interface by IP address. */ struct connected *if_lookup_address(void *matchaddr, int family, vrf_id_t vrf_id) { @@ -447,6 +498,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_ifindex(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; |
