From 85f9da7f786a8f8d922e254b3a6159068f50b9f6 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 10 Feb 2016 09:53:21 -0800 Subject: [PATCH] zebra: fix interface lookup for vrf configuration Ticket:CM-9073 Reviewed By: sharpd Testing Done:Manual, see ticket Changed logic when "interface swpxx " 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. --- lib/if.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- lib/if.h | 2 +- lib/zclient.c | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/lib/if.c b/lib/if.c index 6a54d242a0..6a8a5242e1 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; diff --git a/lib/if.h b/lib/if.h index b0f620352b..a411e709f2 100644 --- a/lib/if.h +++ b/lib/if.h @@ -300,7 +300,7 @@ extern struct interface *if_get_by_name_len(const char *ifname,size_t namelen); extern struct interface *if_lookup_by_name_len_vrf(const char *ifname, size_t namelen, vrf_id_t vrf_id); extern struct interface *if_get_by_name_len_vrf(const char *ifname, - size_t namelen, vrf_id_t vrf_id); + size_t namelen, vrf_id_t vrf_id, int vty); /* Delete the interface, but do not free the structure, and leave it in the diff --git a/lib/zclient.c b/lib/zclient.c index 42a9659393..21d9253067 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -902,7 +902,7 @@ zebra_interface_add_read (struct stream *s, vrf_id_t vrf_id) /* Lookup/create interface by name. */ ifp = if_get_by_name_len_vrf (ifname_tmp, strnlen (ifname_tmp, INTERFACE_NAMSIZ), - vrf_id); + vrf_id, 0); zebra_interface_if_set_value (s, ifp); -- 2.39.5