[ospfd] Fix multicast membership drop bug
2006-06-15 Paul Jakma <paul.jakma@sun.com>
* Reported by Milan Koci
* ospf_interface.h: (struct ospf_if_info) Add reference counts
for multicast group memberships. Add various macros to help
manipulate/check membership state.
* ospf_interface.c: (ospf_if_set_multicast) Maintain the
ospf_if_info reference counts, and only actually drop
memberships if it hits 0, to avoid losing membership when
OSPF is disabled on an interface with multiple active OSPF
interfaces.
* ospf_packet.c: (ospf_{hello,read}) Use the new macros to
check/set
multicast membership.
* ospf_vty.c: (show_ip_ospf_interface_sub) ditto.
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index b94cfa3..2c2c074 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -748,22 +748,25 @@
(OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_ACTIVE))
{
/* The interface should belong to the OSPF-all-routers group. */
- if (!CHECK_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS) &&
+ if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) &&
(ospf_if_add_allspfrouters(oi->ospf, oi->address,
oi->ifp->ifindex) >= 0))
- /* Set the flag only if the system call to join succeeded. */
- SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
+ /* Set the flag only if the system call to join succeeded. */
+ OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
}
else
{
/* The interface should NOT belong to the OSPF-all-routers group. */
- if (CHECK_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS))
+ if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS))
{
- ospf_if_drop_allspfrouters (oi->ospf, oi->address, oi->ifp->ifindex);
+ /* Only actually drop if this is the last reference */
+ if (OI_MEMBER_COUNT(oi, MEMBER_ALLROUTERS) == 1)
+ ospf_if_drop_allspfrouters (oi->ospf, oi->address,
+ oi->ifp->ifindex);
/* Unset the flag regardless of whether the system call to leave
the group succeeded, since it's much safer to assume that
we are not a member. */
- UNSET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
+ OI_MEMBER_LEFT(oi,MEMBER_ALLROUTERS);
}
}
@@ -773,22 +776,25 @@
(OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_ACTIVE))
{
/* The interface should belong to the OSPF-designated-routers group. */
- if (!CHECK_FLAG(oi->multicast_memberships, MEMBER_DROUTERS) &&
+ if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS) &&
(ospf_if_add_alldrouters(oi->ospf, oi->address,
oi->ifp->ifindex) >= 0))
/* Set the flag only if the system call to join succeeded. */
- SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
+ OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
}
else
{
/* The interface should NOT belong to the OSPF-designated-routers group */
- if (CHECK_FLAG(oi->multicast_memberships, MEMBER_DROUTERS))
+ if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS))
{
- ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex);
+ /* drop only if last reference */
+ if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1)
+ ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex);
+
/* Unset the flag regardless of whether the system call to leave
the group succeeded, since it's much safer to assume that
we are not a member. */
- UNSET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
+ OI_MEMBER_LEFT(oi, MEMBER_DROUTERS);
}
}
}