]> git.puffer.fish Git - mirror/frr.git/commitdiff
[zebra] Fix forgetfulness wrt configured address on FreeBSD
authorPaul Jakma <paul.jakma@sun.com>
Thu, 15 Jun 2006 18:10:47 +0000 (18:10 +0000)
committerPaul Jakma <paul.jakma@sun.com>
Thu, 15 Jun 2006 18:10:47 +0000 (18:10 +0000)
2006-06-15 Paul Jakma <paul.jakma@sun.com>

* (general) The key fixes are actually Andrew Schorr's.
* interface.c: (ip_address_uninstall) Unset the configured flag.
* connected.c: (connected_same) new helper, check whether
  two connected are same.
  (connected_implicit_withdraw) new helper, consolidation of
  existing code in connected_add_ipv{4,6}.
  Try filter out unneeded Zserv address delete/adds when
  address is exact same.
  Where old address is implicitely removed, be sure to preserve
  the IFC_CONFIGURED flag if set, fixes bug where configured
  addresses were being lost on FreeBSD.

zebra/ChangeLog
zebra/connected.c
zebra/interface.c

index c31e350404e8d2b79a36acfa8b3e873a9dbd9bc4..69bb1e8eb93c55e39cdeaf6bb2a9ea0921e324a9 100644 (file)
@@ -2,6 +2,16 @@
 
        * interface.c: (if_flag_dump_vty) redundant code, remove.
          (if_dump_vty) use libzebra if_flag_dump.
+         (ip_address_uninstall) Unset the configured flag.
+       * connected.c: (connected_same) new helper, check whether
+         two connected are same.
+         (connected_implicit_withdraw) new helper, consolidation of
+         existing code in connected_add_ipv{4,6}.
+         Try filter out unneeded Zserv address delete/adds when
+         address is exact same.
+         Where old address is implicitely removed, be sure to preserve
+         the IFC_CONFIGURED flag if set, fixes bug where configured
+         addresses were being lost on FreeBSD (Andrew Schorr).   
 
 2006-05-21 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
 
index 37aa456af8baedc2bf29abf1171dac2356042932..736b40b00da6798425225575ca1260bd69a54e1a 100644 (file)
@@ -111,6 +111,63 @@ connected_check (struct interface *ifp, struct prefix *p)
   return NULL;
 }
 
+/* Check if two ifc's describe the same address */
+static int
+connected_same (struct connected *ifc1, struct connected *ifc2)
+{
+  if (ifc1->ifp != ifc2->ifp)
+    return 0;
+  
+  if (ifc1->destination)
+    if (!ifc2->destination)
+      return 0;
+  if (ifc2->destination)
+    if (!ifc1->destination)
+      return 0;
+  
+  if (ifc1->destination && ifc2->destination)
+    if (!prefix_same (ifc1->destination, ifc2->destination))
+      return 0;
+
+  if (ifc1->flags != ifc2->flags)
+    return 0;
+  
+  return 1;
+}
+
+/* Handle implicit withdrawals of addresses, where a system ADDs an address
+ * to an interface which already has the same address configured.
+ *
+ * Returns the struct connected which must be announced to clients,
+ * or NULL if nothing to do.
+ */
+static struct connected *
+connected_implicit_withdraw (struct interface *ifp, struct connected *ifc)
+{
+  struct connected *current;
+  
+  /* Check same connected route. */
+  if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
+    {
+      if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
+        SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
+       
+      /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
+       * back an address we have already added.
+       */
+      if (connected_same (current, ifc))
+        {
+          /* nothing to do */
+          connected_free (ifc);
+          return NULL;
+        }
+      
+      UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
+      connected_withdraw (current); /* implicit withdraw - freebsd does this */
+    }
+  return ifc;
+}
+
 /* Called from if_up(). */
 void
 connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
@@ -157,7 +214,6 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
 {
   struct prefix_ipv4 *p;
   struct connected *ifc;
-  struct connected *current;
 
   /* Make connected structure. */
   ifc = connected_new ();
@@ -226,16 +282,9 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
   if (label)
     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
 
-  /* Check same connected route. */
-  if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
-    {
-      if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
-       {
-         SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
-         UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
-       }
-      connected_withdraw (current); /* implicit withdraw - freebsd does this */
-    }
+  /* nothing to do? */
+  if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
+    return;
   
   connected_announce (ifp, ifc);
 }
@@ -347,7 +396,6 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
 {
   struct prefix_ipv6 *p;
   struct connected *ifc;
-  struct connected *current;
 
   /* Make connected structure. */
   ifc = connected_new ();
@@ -373,15 +421,8 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
   if (label)
     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
   
-  if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
-    {
-      if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
-       {
-         SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
-         UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
-       }
-      connected_withdraw (current); /* implicit update of existing address */
-    }
+  if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
+    return;
   
   connected_announce (ifp, ifc);
 }
index e386047fbe47ffee35dfb8544a9b5c3064387fd8..69124b3de8996b9f28c7a1b740c8208df155156f 100644 (file)
@@ -1273,6 +1273,8 @@ ip_address_uninstall (struct vty *vty, struct interface *ifp,
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
     return CMD_WARNING;
 
+  UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
+  
   /* This is not real address or interface is not active. */
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
       || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))