summaryrefslogtreecommitdiffstats
path: root/lib/if.c
diff options
context:
space:
mode:
authorDon Slice <dslice@cumulusnetworks.com>2016-02-10 18:53:21 +0100
committerDon Slice <dslice@cumulusnetworks.com>2016-02-10 22:01:16 +0100
commit85f9da7f786a8f8d922e254b3a6159068f50b9f6 (patch)
tree0ef60c189f8c3b2e1f174ce9c88983f5c6b43d95 /lib/if.c
parentzebra: display_vrf_name_on_interface (diff)
downloadfrr-85f9da7f786a8f8d922e254b3a6159068f50b9f6.tar.xz
frr-85f9da7f786a8f8d922e254b3a6159068f50b9f6.zip
zebra: fix interface lookup for vrf configuration
Ticket:CM-9073 Reviewed By: sharpd Testing Done:Manual, see ticket Changed logic when "interface swpxx <vrf foo>" entered so that: 1. it matches when the command is entered without a vrf but the interface already exists in a vrf. 2. If the command is entered with a vrf name that is different than is defined by the kernel, the command is rejected. 3. If the call is made from other than the vty session, believe the new information and update the vrf accordingly.
Diffstat (limited to 'lib/if.c')
-rw-r--r--lib/if.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/lib/if.c b/lib/if.c
index 6a54d242a..6a8a5242e 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -454,18 +454,50 @@ if_get_by_name (const char *name)
}
struct interface *
-if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
+if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int vty)
{
struct interface *ifp;
+ struct listnode *node;
+ struct vrf *vrf = NULL;
+ vrf_iter_t iter;
+
+ ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id);
+ if (ifp)
+ return ifp;
- return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \
- ifp : if_create_vrf (name, namelen, vrf_id);
+ /* Didn't find the interface on that vrf. Defined on a different one? */
+ for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
+ {
+ vrf = vrf_iter2vrf(iter);
+ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf->vrf_id), node, ifp))
+ {
+ if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
+ {
+ /* Found a match. If the interface command was entered in vty without a
+ * VRF (passed as VRF_DEFAULT), accept the ifp we found. If a vrf was
+ * entered and there is a mismatch, reject it if from vty. If it came
+ * from the kernel by way of zclient, believe it and update
+ * the ifp accordingly.
+ */
+ if (vrf_id == VRF_DEFAULT)
+ return ifp;
+ if (vty)
+ return NULL;
+ else
+ {
+ if_update_vrf (ifp, name, namelen, vrf_id);
+ return ifp;
+ }
+ }
+ }
+ }
+ return (if_create_vrf (name, namelen, vrf_id));
}
struct interface *
if_get_by_name_len (const char *name, size_t namelen)
{
- return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT);
+ return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT, 0);
}
/* Does interface up ? */
@@ -683,9 +715,9 @@ if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
/* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
if (seppos < nlen)
- return if_get_by_name_len_vrf (name, seppos, vrf_id);
+ return if_get_by_name_len_vrf (name, seppos, vrf_id, 1);
else
- return if_get_by_name_len_vrf (name, nlen, vrf_id);
+ return if_get_by_name_len_vrf (name, nlen, vrf_id, 1);
}
#endif /* SUNOS_5 */
@@ -715,9 +747,14 @@ DEFUN (interface,
#ifdef SUNOS_5
ifp = if_sunwzebra_get (argv[0], sl, vrf_id);
#else
- ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id);
+ ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id, 1);
#endif /* SUNOS_5 */
+ if (!ifp)
+ {
+ vty_out (vty, "%% interface %s not in %s%s", argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
vty->index = ifp;
vty->node = INTERFACE_NODE;