diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-11-15 20:54:53 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-11-20 16:20:31 -0500 |
commit | c1428b3f45d152a300e4f18638ebf30ceafda6c3 (patch) | |
tree | b20a916281f23052a0001771c95d49d3364960a9 /net | |
parent | b52f2198ac889561d341c6990d669a671f93f450 (diff) |
mac80211: fix allmulti/promisc behaviour
When an interface with promisc/allmulti bit is taken down,
the mac80211 state can become confused. This fixes it by
making mac80211 keep track of all *active* interfaces that
have the promisc/allmulti bit set in the sdata, we sync
the interface bit into sdata at set_multicast_list() time
so this works.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index c38e2cd4f7a7..59350b8727ec 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -267,6 +267,17 @@ static int ieee80211_open(struct net_device *dev) | |||
267 | tasklet_enable(&local->tasklet); | 267 | tasklet_enable(&local->tasklet); |
268 | } | 268 | } |
269 | 269 | ||
270 | /* | ||
271 | * set_multicast_list will be invoked by the networking core | ||
272 | * which will check whether any increments here were done in | ||
273 | * error and sync them down to the hardware as filter flags. | ||
274 | */ | ||
275 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
276 | atomic_inc(&local->iff_allmultis); | ||
277 | |||
278 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
279 | atomic_inc(&local->iff_promiscs); | ||
280 | |||
270 | local->open_count++; | 281 | local->open_count++; |
271 | 282 | ||
272 | netif_start_queue(dev); | 283 | netif_start_queue(dev); |
@@ -284,6 +295,18 @@ static int ieee80211_stop(struct net_device *dev) | |||
284 | 295 | ||
285 | netif_stop_queue(dev); | 296 | netif_stop_queue(dev); |
286 | 297 | ||
298 | /* | ||
299 | * Don't count this interface for promisc/allmulti while it | ||
300 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
301 | * on the master interface which will sync these down to the | ||
302 | * hardware as filter flags. | ||
303 | */ | ||
304 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
305 | atomic_dec(&local->iff_allmultis); | ||
306 | |||
307 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
308 | atomic_dec(&local->iff_promiscs); | ||
309 | |||
287 | dev_mc_unsync(local->mdev, dev); | 310 | dev_mc_unsync(local->mdev, dev); |
288 | 311 | ||
289 | /* down all dependent devices, that is VLANs */ | 312 | /* down all dependent devices, that is VLANs */ |