[zebra] Fix forgetfulness wrt configured address on FreeBSD

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.
This commit is contained in:
Paul Jakma 2006-06-15 18:10:47 +00:00
parent 630c97ce0f
commit 74ecdc9e74
3 changed files with 74 additions and 21 deletions

View 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>

View 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);
}

View 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))