diff options
-rw-r--r-- | lib/if.h | 7 | ||||
-rw-r--r-- | zebra/connected.c | 9 | ||||
-rw-r--r-- | zebra/interface.c | 19 |
3 files changed, 29 insertions, 6 deletions
@@ -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. */ diff --git a/zebra/connected.c b/zebra/connected.c index 38ab37d5..d474560c 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -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 (); diff --git a/zebra/interface.c b/zebra/interface.c index cd78ebbc..470df0cd 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -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); |