While flushing the multicast filter of an interface, do not zero the relevant

ifmultiaddr structures' reference to the parent interface, unless the parent
interface is really detaching. While here, program only link layer multicast
filters to a wlan's hardware parent interface.

PR:		kern/142391, kern/142392
Reviewed by:	sam, rpaolo, bms
MFC after:	1 week
This commit is contained in:
Shteryana Shopova 2010-01-24 16:17:58 +00:00
parent 780b61c45b
commit 93ec7edca7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=202935
3 changed files with 25 additions and 5 deletions

View File

@ -740,9 +740,10 @@ if_purgeaddrs(struct ifnet *ifp)
}
/*
* Remove any multicast network addresses from an interface.
* Remove any multicast network addresses from an interface when an ifnet
* is going away.
*/
void
static void
if_purgemaddrs(struct ifnet *ifp)
{
struct ifmultiaddr *ifma;
@ -2939,6 +2940,22 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
return (0);
}
/*
* Delete all multicast group membership for an interface.
* Should be used to quickly flush all multicast filters.
*/
void
if_delallmulti(struct ifnet *ifp)
{
struct ifmultiaddr *ifma;
struct ifmultiaddr *next;
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
if_delmulti_locked(ifp, ifma, 0);
IF_ADDR_UNLOCK(ifp);
}
/*
* Delete a multicast group membership by group membership pointer.
* Network-layer protocol domains must use this routine.

View File

@ -833,7 +833,7 @@ void if_delmulti_ifma(struct ifmultiaddr *);
void if_detach(struct ifnet *);
void if_vmove(struct ifnet *, struct vnet *);
void if_purgeaddrs(struct ifnet *);
void if_purgemaddrs(struct ifnet *);
void if_delallmulti(struct ifnet *);
void if_down(struct ifnet *);
struct ifmultiaddr *
if_findmulti(struct ifnet *, struct sockaddr *);

View File

@ -3199,15 +3199,18 @@ ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
void *ioctl;
IEEE80211_LOCK(ic);
if_purgemaddrs(parent);
if_delallmulti(parent);
ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
parent->if_ioctl = NULL;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
struct ifnet *ifp = vap->iv_ifp;
struct ifmultiaddr *ifma;
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
(void) if_addmulti(parent, ifma->ifma_addr, NULL);
}
}
parent->if_ioctl = ioctl;
ieee80211_runtask(ic, &ic->ic_mcast_task);