]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: add ZEBRA_IFC_QUEUED to keep track of kernel state
authorChristian Franke <chris@opensourcerouting.org>
Thu, 24 Jan 2013 14:04:48 +0000 (14:04 +0000)
committerDavid Lamparter <equinox@opensourcerouting.org>
Thu, 19 Sep 2013 15:51:16 +0000 (17:51 +0200)
As there are timeframes when we don't get a notification from the kernel
about new addresses. (e.g. while Linux performs IPv6 DAD), we need to
have some information whether an address has been sent to the kernel or
not.

One case where this is relevant would be a user adding an IPv6 address,
but deleting it before DAD has been complete. With the next patch which
removes some (ill assuming) synchronous parts in address setup,
ipv6_address_uninstall would not know whether or not it has to actually
delete the prefix from the kernel. Resolving these windows where we lack
information is what the flag ZEBRA_IFC_QUEUED is intended for.

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
lib/if.h
zebra/connected.c
zebra/interface.c

index 2116e12ebe3ca727deb0a1c0a1c9243e93fe6d36..13cc254e262863f63837a2a629cc3dae7b241e25 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -151,11 +151,16 @@ struct connected
   u_char conf;
 #define ZEBRA_IFC_REAL         (1 << 0)
 #define ZEBRA_IFC_CONFIGURED   (1 << 1)
+#define ZEBRA_IFC_QUEUED       (1 << 2)
   /*
      The ZEBRA_IFC_REAL flag should be set if and only if this address
-     exists in the kernel.
+     exists in the kernel and is actually usable. (A case where it exists but
+     is not yet usable would be IPv6 with DAD)
      The ZEBRA_IFC_CONFIGURED flag should be set if and only if this address
      was configured by the user from inside quagga.
+     The ZEBRA_IFC_QUEUED flag should be set if and only if the address exists
+     in the kernel. It may and should be set although the address might not be
+     usable yet. (compare with ZEBRA_IFC_REAL)
    */
 
   /* Flags for connected address. */
index 38ab37d59e0c88724095212edad9af8d5a59ad04..d474560c86aa687fcc1011dbe40d65d06c8c75a6 100644 (file)
@@ -62,6 +62,9 @@ connected_withdraw (struct connected *ifc)
       UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
     }
 
+  /* The address is not in the kernel anymore, so clear the flag */
+  UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
+
   if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
     {
       listnode_delete (ifc->ifp->connected, ifc);
@@ -211,6 +214,9 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
   ifc = connected_new ();
   ifc->ifp = ifp;
   ifc->flags = flags;
+  /* If we get a notification from the kernel,
+   * we can safely assume the address is known to the kernel */
+  SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
 
   /* Allocate new connected address. */
   p = prefix_ipv4_new ();
@@ -363,6 +369,9 @@ connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
   ifc = connected_new ();
   ifc->ifp = ifp;
   ifc->flags = flags;
+  /* If we get a notification from the kernel,
+   * we can safely assume the address is known to the kernel */
+  SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
 
   /* Allocate new connected address. */
   p = prefix_ipv6_new ();
index cd78ebbcd48e2ee2f1779e81c55541b084b673c1..470df0cdd432fdb6c72e01a71b3b8453f95637d4 100644 (file)
@@ -289,7 +289,7 @@ if_addr_wakeup (struct interface *ifp)
       p = ifc->address;
        
       if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
-         && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
+         && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED))
        {
          /* Address check. */
          if (p->family == AF_INET)
@@ -321,6 +321,7 @@ if_addr_wakeup (struct interface *ifp)
              /* Add to subnet chain list. */
              if_subnet_add (ifp, ifc);
 
+             SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
              SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
 
              zebra_interface_address_add_update (ifp, ifc);
@@ -345,6 +346,7 @@ if_addr_wakeup (struct interface *ifp)
                             safe_strerror(errno));
                  continue;
                }
+             SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
              SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
 
              zebra_interface_address_add_update (ifp, ifc);
@@ -454,6 +456,7 @@ if_delete_update (struct interface *ifp)
                  zebra_interface_address_delete_update (ifp, ifc);
 
                  UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
+                 UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
 
                  /* Remove from subnet chain. */
                  list_delete_node (addr_list, anode);
@@ -482,6 +485,7 @@ if_delete_update (struct interface *ifp)
              zebra_interface_address_delete_update (ifp, ifc);
 
              UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
+             UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
 
              if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
                last = node;
@@ -1229,7 +1233,7 @@ ip_address_install (struct vty *vty, struct interface *ifp,
     SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
 
   /* In case of this route need to install kernel. */
-  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
+  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED)
       && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
     {
       /* Some system need to up the interface to set IP address. */
@@ -1251,6 +1255,7 @@ ip_address_install (struct vty *vty, struct interface *ifp,
       if_subnet_add (ifp, ifc);
 
       /* IP address propery set. */
+      SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
       SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
 
       /* Update interface address information to protocol daemon. */
@@ -1296,7 +1301,7 @@ ip_address_uninstall (struct vty *vty, struct interface *ifp,
   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)
+  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED)
       || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
     {
       listnode_delete (ifp->connected, ifc);
@@ -1321,6 +1326,7 @@ ip_address_uninstall (struct vty *vty, struct interface *ifp,
    * through the route socket, and we don't want to touch that behaviour
    * for now.  It should work without the #ifdef, but why take the risk...
    * -- equinox 2012-07-13 */
+  UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
 #ifdef HAVE_NETLINK
 
   /* Remove connected route. */
@@ -1437,7 +1443,7 @@ ipv6_address_install (struct vty *vty, struct interface *ifp,
     SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
 
   /* In case of this route need to install kernel. */
-  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
+  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED)
       && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
     {
       /* Some system need to up the interface to set IP address. */
@@ -1457,6 +1463,7 @@ ipv6_address_install (struct vty *vty, struct interface *ifp,
        }
 
       /* IP address propery set. */
+      SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
       SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
 
       /* Update interface address information to protocol daemon. */
@@ -1502,7 +1509,7 @@ ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
   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)
+  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED)
       || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
     {
       listnode_delete (ifp->connected, ifc);
@@ -1519,6 +1526,8 @@ ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
       return CMD_WARNING;
     }
 
+  UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
+
   /* Redistribute this information. */
   zebra_interface_address_delete_update (ifp, ifc);