summaryrefslogtreecommitdiff
path: root/lib/if.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2019-06-22 13:35:45 -0400
committerGitHub <noreply@github.com>2019-06-22 13:35:45 -0400
commita12bb225a6681b7e7eb0aac105cbc8b745675131 (patch)
treeadb8d7935dcb1da93d6cf4082f903e412e292640 /lib/if.c
parentefe42c51c48da8bc89df4891235fb3be0e502cf8 (diff)
parenta41c4e1b1f577443ad26222704a69649c280cd9e (diff)
Merge pull request #3775 from pguibert6WIND/ospf_missing_interface_handling_2
Ospf missing interface handling 2
Diffstat (limited to 'lib/if.c')
-rw-r--r--lib/if.c107
1 files changed, 60 insertions, 47 deletions
diff --git a/lib/if.c b/lib/if.c
index f7a167f251..8885fb11a3 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -132,9 +132,8 @@ 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)
+struct interface *if_create(const char *name, struct vrf *vrf)
{
- struct vrf *vrf = vrf_get(vrf_id, NULL);
struct interface *ifp;
ifp = XCALLOC(MTYPE_IF, sizeof(struct interface));
@@ -142,7 +141,7 @@ struct interface *if_create(const char *name, vrf_id_t vrf_id)
assert(name);
strlcpy(ifp->name, name, sizeof(ifp->name));
- ifp->vrf_id = vrf_id;
+ ifp->vrf = vrf;
IFNAME_RB_INSERT(vrf, ifp);
ifp->connected = list_new();
ifp->connected->del = (void (*)(void *))connected_free;
@@ -158,26 +157,34 @@ struct interface *if_create(const char *name, vrf_id_t vrf_id)
return ifp;
}
-/* Create new interface structure. */
-void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
+/* Create new interface structure.
+ * vrf must be created outside of this routing
+ */
+void if_update_to_new_vrf(struct interface *ifp, struct vrf *vrf)
{
- struct vrf *old_vrf, *vrf;
+ struct vrf *old_vrf;
+ if (!vrf) {
+ flog_err(EC_LIB_INTERFACE, "interface %s. Unknown VRF",
+ ifp->name);
+ return;
+ }
/* remove interface from old master vrf list */
- old_vrf = vrf_lookup_by_id(ifp->vrf_id);
+ old_vrf = ifp->vrf;
if (old_vrf) {
IFNAME_RB_REMOVE(old_vrf, ifp);
if (ifp->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(old_vrf, ifp);
}
- ifp->vrf_id = vrf_id;
- vrf = vrf_get(ifp->vrf_id, NULL);
+ ifp->vrf = vrf;
IFNAME_RB_INSERT(vrf, ifp);
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
@@ -218,9 +225,8 @@ void if_delete_retain(struct interface *ifp)
/* Delete and free interface structure. */
void if_delete(struct interface *ifp)
{
- struct vrf *vrf;
+ struct vrf *vrf = ifp->vrf;
- vrf = vrf_lookup_by_id(ifp->vrf_id);
assert(vrf);
IFNAME_RB_REMOVE(vrf, ifp);
@@ -265,16 +271,16 @@ const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id)
ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id)
{
struct interface *ifp;
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
- return ((ifp = if_lookup_by_name(name, vrf_id)) != NULL)
+ return ((ifp = if_lookup_by_name(name, vrf)) != NULL)
? ifp->ifindex
: IFINDEX_INTERNAL;
}
/* Interface existance check by interface name. */
-struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id)
+struct interface *if_lookup_by_name(const char *name, struct vrf *vrf)
{
- struct vrf *vrf = vrf_lookup_by_id(vrf_id);
struct interface if_tmp;
if (!vrf || !name
@@ -294,7 +300,7 @@ struct interface *if_lookup_by_name_all_vrf(const char *name)
return NULL;
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- ifp = if_lookup_by_name(name, vrf->vrf_id);
+ ifp = if_lookup_by_name(name, vrf);
if (ifp)
return ifp;
}
@@ -419,29 +425,29 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz,
/* Get interface by name if given name interface doesn't exist create
one. */
-struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id)
+struct interface *if_get_by_name(const char *name, struct vrf *vrf)
{
struct interface *ifp;
switch (vrf_get_backend()) {
case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
- ifp = if_lookup_by_name(name, vrf_id);
+ ifp = if_lookup_by_name(name, vrf);
if (ifp)
return ifp;
- return if_create(name, vrf_id);
+ return if_create(name, vrf);
case VRF_BACKEND_VRF_LITE:
ifp = if_lookup_by_name_all_vrf(name);
if (ifp) {
- if (ifp->vrf_id == vrf_id)
+ if (ifp->vrf == vrf)
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);
+ if_update_to_new_vrf(ifp, vrf);
return ifp;
}
- return if_create(name, vrf_id);
+ return if_create(name, vrf);
}
return NULL;
@@ -451,7 +457,7 @@ void if_set_index(struct interface *ifp, ifindex_t ifindex)
{
struct vrf *vrf;
- vrf = vrf_lookup_by_id(ifp->vrf_id);
+ vrf = ifp->vrf;
assert(vrf);
if (ifp->ifindex == ifindex)
@@ -595,7 +601,8 @@ static void if_dump(const struct interface *ifp)
zlog_info(
"Interface %s vrf %u index %d metric %d mtu %d "
"mtu6 %d %s",
- ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric,
+ ifp->name, vrf_to_id(ifp->vrf),
+ ifp->ifindex, ifp->metric,
ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags));
}
@@ -631,12 +638,12 @@ void if_dump_all(void)
* if not:
* - no idea, just get the name in its entirety.
*/
-static struct interface *if_sunwzebra_get(const char *name, vrf_id_t vrf_id)
+static struct interface *if_sunwzebra_get(const char *name, struct vrf *vrf)
{
struct interface *ifp;
char *cp;
- if ((ifp = if_lookup_by_name(name, vrf_id)) != NULL)
+ if ((ifp = if_lookup_by_name(name, vrf)) != NULL)
return ifp;
/* hunt the primary interface name... */
@@ -644,7 +651,7 @@ static struct interface *if_sunwzebra_get(const char *name, vrf_id_t vrf_id)
if (cp)
*cp = '\0';
- return if_get_by_name(name, vrf_id);
+ return if_get_by_name(name, vrf);
}
#endif /* SUNOS_5 */
@@ -777,7 +784,8 @@ connected_log(struct connected *connected, char *str)
p = connected->address;
snprintf(logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ", str,
- ifp->name, ifp->vrf_id, prefix_family_str(p),
+ ifp->name, vrf_to_id(ifp->vrf),
+ prefix_family_str(p),
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
p = connected->destination;
@@ -1126,9 +1134,9 @@ DEFPY_NOSH (interface,
VRF_CMD_HELP_STR)
{
char xpath_list[XPATH_MAXLEN];
- vrf_id_t vrf_id;
- struct interface *ifp;
+ struct interface *ifp = NULL;
int ret;
+ struct vrf *vrf;
if (!vrfname)
vrfname = VRF_DEFAULT_NAME;
@@ -1140,16 +1148,24 @@ DEFPY_NOSH (interface,
* interface is found, then a new one should be created on the default
* VRF.
*/
- VRF_GET_ID(vrf_id, vrfname, false);
- ifp = if_lookup_by_name_all_vrf(ifname);
- if (ifp && ifp->vrf_id != vrf_id) {
- struct vrf *vrf;
-
+ VRF_GET_INSTANCE(vrf, vrfname, false, true);
+ /*
+ * within vrf context, vrf_id may be unknown
+ * this happens on daemons relying on zebra
+ * on this specific case, interface creation may
+ * be forced
+ */
+ if (vrf && (vrf->vrf_id == VRF_UNKNOWN ||
+ vrf_get_backend() == VRF_BACKEND_UNKNOWN))
+ ifp = if_lookup_by_name(ifname, vrf);
+ else
+ ifp = if_lookup_by_name_all_vrf(ifname);
+ if (ifp && ifp->vrf != vrf) {
/*
* Special case 1: a VRF name was specified, but the found
* interface is associated to different VRF. Reject the command.
*/
- if (vrf_id != VRF_DEFAULT) {
+ if (vrf->vrf_id != VRF_DEFAULT) {
vty_out(vty, "%% interface %s not in %s vrf\n", ifname,
vrfname);
return CMD_WARNING_CONFIG_FAILED;
@@ -1160,9 +1176,8 @@ DEFPY_NOSH (interface,
* interface is associated to a VRF other than the default one.
* Update vrf_id and vrfname to account for that.
*/
- vrf = vrf_lookup_by_id(ifp->vrf_id);
+ vrf = ifp->vrf;
assert(vrf);
- vrf_id = ifp->vrf_id;
vrfname = vrf->name;
}
@@ -1181,7 +1196,7 @@ DEFPY_NOSH (interface,
* all interface-level commands are converted to the new
* northbound model.
*/
- ifp = if_lookup_by_name(ifname, vrf_id);
+ ifp = if_lookup_by_name(ifname, vrf);
if (ifp)
VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp);
}
@@ -1303,7 +1318,7 @@ static int lib_interface_create(enum nb_event event,
const char *ifname;
const char *vrfname;
struct vrf *vrf;
- struct interface *ifp;
+ struct interface *ifp = NULL;
ifname = yang_dnode_get_string(dnode, "./name");
vrfname = yang_dnode_get_string(dnode, "./vrf");
@@ -1316,11 +1331,9 @@ static int lib_interface_create(enum nb_event event,
vrfname);
return NB_ERR_VALIDATION;
}
- if (vrf->vrf_id == VRF_UNKNOWN) {
- zlog_warn("%s: VRF %s is not active", __func__,
- vrf->name);
- return NB_ERR_VALIDATION;
- }
+ if (vrf->vrf_id == VRF_UNKNOWN)
+ zlog_warn("%s: VRF %s is not active. Using interface however.",
+ __func__, vrf->name);
/* if VRF is netns or not yet known - init for instance
* then assumption is that passed config is exact
@@ -1328,7 +1341,7 @@ static int lib_interface_create(enum nb_event event,
*/
if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
ifp = if_lookup_by_name_all_vrf(ifname);
- if (ifp && ifp->vrf_id != vrf->vrf_id) {
+ if (ifp && ifp->vrf != vrf) {
zlog_warn(
"%s: interface %s already exists in another VRF",
__func__, ifp->name);
@@ -1343,9 +1356,9 @@ static int lib_interface_create(enum nb_event event,
vrf = vrf_lookup_by_name(vrfname);
assert(vrf);
#ifdef SUNOS_5
- ifp = if_sunwzebra_get(ifname, vrf->vrf_id);
+ ifp = if_sunwzebra_get(ifname, vrf);
#else
- ifp = if_get_by_name(ifname, vrf->vrf_id);
+ ifp = if_get_by_name(ifname, vrf);
#endif /* SUNOS_5 */
nb_running_set_entry(dnode, ifp);
break;