From patchwork Fri Oct 1 21:53:20 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Lamparter X-Patchwork-Id: 225902 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o91LrRNK030859 for ; Fri, 1 Oct 2010 21:53:27 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756971Ab0JAVx0 (ORCPT ); Fri, 1 Oct 2010 17:53:26 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:62208 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756895Ab0JAVxZ (ORCPT ); Fri, 1 Oct 2010 17:53:25 -0400 Received: by fxm14 with SMTP id 14so923215fxm.19 for ; Fri, 01 Oct 2010 14:53:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:received:from:to:subject:date :user-agent:cc:references:in-reply-to:mime-version:content-type :content-transfer-encoding:message-id; bh=f9yTPqaAvQhcIGTE1hTiW8jzEleO25U97pBwGHlWhCE=; b=Kpp3iEa4CaEsheNGUgpCkmilp/yJESmoHbVRqt6SqvQUo+VvGsiyW/n28pwZWhU2cx YfAn54CFYSuClga3Zqnm7jKJqj2DjJw0mT9kudeJizcam1pQMpWfp7vIdtbIB/+4EpMT cL2kEkLFgh4a1bXaHTnuYaJeQyKgFU7TCnL4c= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=from:to:subject:date:user-agent:cc:references:in-reply-to :mime-version:content-type:content-transfer-encoding:message-id; b=Un0nG20PByBdoFUWr+VEmaZR8t4HKrCefVTMkS/DF3D5ZZoFWVjSpAt7tT/4dv4Z23 x2sdE4Tsaagyp0uInrsAqeWz6+LFLCpMNagVkAnfArwZVd69L8rCBHyOAkxvZspxmABv S4sBZWQChrO8MmY9zXoioQlxEA47vqHAavguA= Received: by 10.223.123.19 with SMTP id n19mr5956721far.75.1285970003799; Fri, 01 Oct 2010 14:53:23 -0700 (PDT) Received: from debian64.daheim (p549CB68E.dip.t-dialin.net [84.156.182.142]) by mx.google.com with ESMTPS id h12sm881186faa.37.2010.10.01.14.53.22 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 01 Oct 2010 14:53:22 -0700 (PDT) Received: from debian64.daheim ([192.168.0.4] helo=debian64.localnet ident=chuck) by debian64.daheim with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1P1nXd-000146-GS; Fri, 01 Oct 2010 23:53:21 +0200 From: Christian Lamparter To: linux-wireless@vger.kernel.org Subject: [PATCH] mac80211: fix rx monitor filter refcounters Date: Fri, 1 Oct 2010 23:53:20 +0200 User-Agent: KMail/1.13.5 (Linux/2.6.36-rc6-wl+; KDE/4.4.5; x86_64; ; ) Cc: "John W. Linville" , Johannes Berg References: <201009281836.24529.chunkeey@googlemail.com> <201009292157.04141.chunkeey@googlemail.com> <1285790439.3756.35.camel@jlt3.sipsolutions.net> In-Reply-To: <1285790439.3756.35.camel@jlt3.sipsolutions.net> MIME-Version: 1.0 Message-Id: <201010012353.21053.chunkeey@googlemail.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 01 Oct 2010 21:53:28 +0000 (UTC) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c981604..554166b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -68,8 +68,36 @@ static int ieee80211_change_iface(struct wiphy *wiphy, params && params->use_4addr >= 0) sdata->u.mgd.use_4addr = params->use_4addr; - if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) - sdata->u.mntr_flags = *flags; + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) { + struct ieee80211_local *local = sdata->local; + + if (test_bit(SDATA_STATE_RUNNING, &sdata->state)) { + /* + * Prohibit MONITOR_FLAG_COOK_FRAMES to be + * changed while the interface is up. + * Else we would need to add a lot of cruft + * to update everything: + * cooked_mntrs, monitor and all fif_* counters + * reconfigure hardware + */ + if ((*flags & MONITOR_FLAG_COOK_FRAMES) != + (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) + return -ENOSYS; + + ieee80211_adjust_monitor_flags(sdata, -1); + sdata->u.mntr_flags = *flags; + ieee80211_adjust_monitor_flags(sdata, 1); + + ieee80211_configure_filter(local); + } else { + /* + * Because the interface is down, ieee80211_do_stop + * and ieee80211_do_open take care of "everything" + * mentioned in the comment above. + */ + sdata->u.mntr_flags = *flags; + } + } return 0; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 945fbf2..f6a6d78 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1132,6 +1132,8 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); void ieee80211_remove_interfaces(struct ieee80211_local *local); u32 __ieee80211_recalc_idle(struct ieee80211_local *local); void ieee80211_recalc_idle(struct ieee80211_local *local); +void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, + const int offset); static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) { diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6678573..1300e88 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -148,6 +148,26 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, return 0; } +void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, + const int offset) +{ + struct ieee80211_local *local = sdata->local; + u32 flags = sdata->u.mntr_flags; + +#define ADJUST(_f, _s) do { \ + if (flags & MONITOR_FLAG_##_f) \ + local->fif_##_s += offset; \ + } while (0) + + ADJUST(FCSFAIL, fcsfail); + ADJUST(PLCPFAIL, plcpfail); + ADJUST(CONTROL, control); + ADJUST(CONTROL, pspoll); + ADJUST(OTHER_BSS, other_bss); + +#undef ADJUST +} + /* * NOTE: Be very careful when changing this function, it must NOT return * an error on interface type changes that have been pre-checked, so most @@ -240,17 +260,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; } - if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) - local->fif_fcsfail++; - if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) - local->fif_plcpfail++; - if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { - local->fif_control++; - local->fif_pspoll++; - } - if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) - local->fif_other_bss++; - + ieee80211_adjust_monitor_flags(sdata, 1); ieee80211_configure_filter(local); netif_carrier_on(dev); @@ -477,17 +487,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; } - if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) - local->fif_fcsfail--; - if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) - local->fif_plcpfail--; - if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { - local->fif_pspoll--; - local->fif_control--; - } - if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) - local->fif_other_bss--; - + ieee80211_adjust_monitor_flags(sdata, -1); ieee80211_configure_filter(local); break; case NL80211_IFTYPE_MESH_POINT: