diff options
author | glebius <glebius@FreeBSD.org> | 2007-02-02 09:39:09 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2007-02-02 09:39:09 +0000 |
commit | 325d4d7fdaa90f6cd1f3135dea61dec9ece00f8f (patch) | |
tree | ef09959160540fe421ba0859b005e6599ff7ff4e /sys | |
parent | 60c94b272a52e5b62fb932bcac75dc529dbd909d (diff) | |
download | FreeBSD-src-325d4d7fdaa90f6cd1f3135dea61dec9ece00f8f.zip FreeBSD-src-325d4d7fdaa90f6cd1f3135dea61dec9ece00f8f.tar.gz |
Since rev. 1.94 of netinet/in.c, the netinet layer frees all its
multicast memberships, when interface is detached. Thus, when
an underlying interface is detached, we do not need to free
our multicast memberships.
Reviewed by: bms
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_carp.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 87bb1c9..bff8d29 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -219,6 +219,7 @@ static void carp_sc_state_locked(struct carp_softc *); static void carp_send_na(struct carp_softc *); static int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); +static void carp_multicast6_cleanup(struct carp_softc *); #endif static LIST_HEAD(, carp_softc) carpif_list; @@ -423,6 +424,16 @@ carp_clone_destroy(struct ifnet *ifp) free(sc, M_CARP); } +/* + * This function can be called on CARP interface destroy path, + * and in case of the removal of the underlying interface as + * well. We differentiate these two cases. In the latter case + * we do not cleanup our multicast memberships, since they + * are already freed. Also, in the latter case we do not + * release the lock on return, because the function will be + * called once more, for another CARP instance on the same + * interface. + */ static void carpdetach(struct carp_softc *sc, int unlock) { @@ -443,7 +454,11 @@ carpdetach(struct carp_softc *sc, int unlock) carp_set_state(sc, INIT); SC2IFP(sc)->if_flags &= ~IFF_UP; carp_setrun(sc, 0); - carp_multicast_cleanup(sc); + if (unlock) + carp_multicast_cleanup(sc); +#ifdef INET6 + carp_multicast6_cleanup(sc); +#endif if (sc->sc_carpdev != NULL) { cif = (struct carp_if *)sc->sc_carpdev->if_carp; @@ -1369,13 +1384,10 @@ carp_setrun(struct carp_softc *sc, sa_family_t af) } } -void +static void carp_multicast_cleanup(struct carp_softc *sc) { struct ip_moptions *imo = &sc->sc_imo; -#ifdef INET6 - struct ip6_moptions *im6o = &sc->sc_im6o; -#endif u_int16_t n = imo->imo_num_memberships; /* Clean up our own multicast memberships */ @@ -1387,8 +1399,14 @@ carp_multicast_cleanup(struct carp_softc *sc) } imo->imo_num_memberships = 0; imo->imo_multicast_ifp = NULL; +} #ifdef INET6 +static void +carp_multicast6_cleanup(struct carp_softc *sc) +{ + struct ip6_moptions *im6o = &sc->sc_im6o; + while (!LIST_EMPTY(&im6o->im6o_memberships)) { struct in6_multi_mship *imm = LIST_FIRST(&im6o->im6o_memberships); @@ -1397,8 +1415,8 @@ carp_multicast_cleanup(struct carp_softc *sc) in6_leavegroup(imm); } im6o->im6o_multicast_ifp = NULL; -#endif } +#endif static int carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) |