]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: fix interface lookup for vrf configuration
authorDon Slice <dslice@cumulusnetworks.com>
Wed, 10 Feb 2016 17:53:21 +0000 (09:53 -0800)
committerDon Slice <dslice@cumulusnetworks.com>
Wed, 10 Feb 2016 21:01:16 +0000 (13:01 -0800)
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.

lib/if.c
lib/if.h
lib/zclient.c

index 6a54d242a09e0a9e238d2331c33b7ac780627296..6a8a5242e1bd9cbf1873bd18c33c7a73f5b42dde 100644 (file)
--- 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;
 
index b0f620352b60f1546598e2a07bc5749ba32260fd..a411e709f29eaf9b7cd044fa4928e60ff558fab7 100644 (file)
--- 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
index 42a96593930ef47b32e7352ed617542b9bb64b37..21d92530670eed4af53b6d75fc3909bc5c94c173 100644 (file)
@@ -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);