linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH] mac80211: FIF_PSPOLL filter flag
@ 2009-07-30 13:53 Igor Perminov
  2009-07-30 14:18 ` Johannes Berg
  0 siblings, 1 reply; 4+ messages in thread
From: Igor Perminov @ 2009-07-30 13:53 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

When an interface is configured in the AP mode, the mac80211
implementation doesn't inform the driver to receive PS Poll frames.
It leads to inability to communicate with power-saving stations
reliably.
The FIF_CONTROL flag isn't passed by mac80211 to
ieee80211_ops.configure_filter when an interface is in the AP mode.
And it's ok, because we don't want to receive ACK frames and other
control ones, but only PS Poll ones.

This patch introduces the FIF_PSPOLL filter flag in addition to
FIF_CONTROL, which means for the driver "pass PS Poll frames".

This flag is passed to the driver:
A) When an interface is configured in the AP mode.
B) In all cases, when the FIF_CONTROL flag was passed earlier (in
addition to it).

Signed-off-by: Igor Perminov <igor.perminov@inbox.ru>
---
 include/net/mac80211.h     |    8 ++++++--
 net/mac80211/ieee80211_i.h |    2 +-
 net/mac80211/iface.c       |   23 +++++++++++++++++++++--
 net/mac80211/main.c        |    3 +++
 4 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d4e09a0..5113bba 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1236,10 +1236,13 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  *	mac80211 needs to do and the amount of CPU wakeups, so you should
  *	honour this flag if possible.
  *
- * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then
- *	only those addressed to this station
+ * @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS
+ *  is not set then only those addressed to this station.
  *
  * @FIF_OTHER_BSS: pass frames destined to other BSSes
+ *
+ * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS  is not set then only
+ *  those addressed to this station.
  */
 enum ieee80211_filter_flags {
 	FIF_PROMISC_IN_BSS	= 1<<0,
@@ -1249,6 +1252,7 @@ enum ieee80211_filter_flags {
 	FIF_BCN_PRBRESP_PROMISC	= 1<<4,
 	FIF_CONTROL		= 1<<5,
 	FIF_OTHER_BSS		= 1<<6,
+	FIF_PSPOLL		= 1<<7,
 };
 
 /**
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index aec6853..ab6003d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -621,7 +621,7 @@ struct ieee80211_local {
 	int open_count;
 	int monitors, cooked_mntrs;
 	/* number of interfaces with corresponding FIF_ flags */
-	int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss;
+	int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll;
 	unsigned int filter_flags; /* FIF_* */
 	struct iw_statistics wstats;
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a83087f..bbf32da 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -220,8 +220,10 @@ static int ieee80211_open(struct net_device *dev)
 			local->fif_fcsfail++;
 		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
 			local->fif_plcpfail++;
-		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
+		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++;
 
@@ -245,6 +247,14 @@ static int ieee80211_open(struct net_device *dev)
 
 			ieee80211_start_mesh(sdata);
 		}
+		else if (sdata->vif.type == NL80211_IFTYPE_AP) {
+			local->fif_pspoll++;
+
+			spin_lock_bh(&local->filter_lock);
+			ieee80211_configure_filter(local);
+			spin_unlock_bh(&local->filter_lock);
+		}
+
 		changed |= ieee80211_reset_erp_info(sdata);
 		ieee80211_bss_info_change_notify(sdata, changed);
 		ieee80211_enable_keys(sdata);
@@ -439,8 +449,10 @@ static int ieee80211_stop(struct net_device *dev)
 			local->fif_fcsfail--;
 		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
 			local->fif_plcpfail--;
-		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
+		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--;
 
@@ -497,6 +509,13 @@ static int ieee80211_stop(struct net_device *dev)
 		}
 		/* fall through */
 	default:
+		if (sdata->vif.type == NL80211_IFTYPE_AP) {
+			local->fif_pspoll--;
+
+			spin_lock_bh(&local->filter_lock);
+			ieee80211_configure_filter(local);
+			spin_unlock_bh(&local->filter_lock);
+		}
 		if (local->scan_sdata == sdata) {
 			if (!local->ops->hw_scan)
 				cancel_delayed_work_sync(&local->scan_work);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5e76dd1..c330235 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -77,6 +77,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
 	if (local->fif_other_bss)
 		new_flags |= FIF_OTHER_BSS;
 
+	if (local->fif_pspoll)
+		new_flags |= FIF_PSPOLL;
+
 	changed_flags = local->filter_flags ^ new_flags;
 
 	/* be a bit nasty */



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] mac80211: FIF_PSPOLL filter flag
  2009-07-30 13:53 [RFC PATCH] mac80211: FIF_PSPOLL filter flag Igor Perminov
@ 2009-07-30 14:18 ` Johannes Berg
  2009-07-30 15:05   ` Igor Perminov
  0 siblings, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2009-07-30 14:18 UTC (permalink / raw)
  To: Igor Perminov; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 835 bytes --]

On Thu, 2009-07-30 at 17:53 +0400, Igor Perminov wrote:

> @@ -245,6 +247,14 @@ static int ieee80211_open(struct net_device *dev)
>  
>  			ieee80211_start_mesh(sdata);
>  		}
> +		else if (sdata->vif.type == NL80211_IFTYPE_AP) {

Put 'else if' on the same line as '}' please

> +		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
> +			local->fif_pspoll--;
>  			local->fif_control--;
> +		}

Yeah, that's exactly what I was thinking of :)

> @@ -497,6 +509,13 @@ static int ieee80211_stop(struct net_device *dev)
>  		}
>  		/* fall through */
>  	default:
> +		if (sdata->vif.type == NL80211_IFTYPE_AP) {

I'd probably put this after a
	case NL80211_IFTYPE_AP:
label but you need the if () anyway ... hmm I guess we really should
clean up this code and split it into two switch statements...

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] mac80211: FIF_PSPOLL filter flag
  2009-07-30 14:18 ` Johannes Berg
@ 2009-07-30 15:05   ` Igor Perminov
  2009-07-30 15:31     ` Johannes Berg
  0 siblings, 1 reply; 4+ messages in thread
From: Igor Perminov @ 2009-07-30 15:05 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

> > @@ -497,6 +509,13 @@ static int ieee80211_stop(struct net_device *dev)
> >  		}
> >  		/* fall through */
> >  	default:
> > +		if (sdata->vif.type == NL80211_IFTYPE_AP) {
> 
> I'd probably put this after a
> 	case NL80211_IFTYPE_AP:
> label but you need the if () anyway ... hmm I guess we really should
> clean up this code and split it into two switch statements...

And may be do it above?

	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
		atomic_dec(&local->iff_allmultis);

	if (sdata->flags & IEEE80211_SDATA_PROMISC)
		atomic_dec(&local->iff_promiscs);

+	if (sdata->vif.type == NL80211_IFTYPE_AP)
+		local->fif_pspoll--;
+
	netif_addr_lock_bh(dev);
	spin_lock_bh(&local->filter_lock);
	__dev_addr_unsync(&local->mc_list, &local->mc_count,
			  &dev->mc_list, &dev->mc_count);
	ieee80211_configure_filter(local);
	spin_unlock_bh(&local->filter_lock);
	netif_addr_unlock_bh(dev);

Igor



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] mac80211: FIF_PSPOLL filter flag
  2009-07-30 15:05   ` Igor Perminov
@ 2009-07-30 15:31     ` Johannes Berg
  0 siblings, 0 replies; 4+ messages in thread
From: Johannes Berg @ 2009-07-30 15:31 UTC (permalink / raw)
  To: Igor Perminov; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 833 bytes --]

On Thu, 2009-07-30 at 19:05 +0400, Igor Perminov wrote:
> > > @@ -497,6 +509,13 @@ static int ieee80211_stop(struct net_device *dev)
> > >  		}
> > >  		/* fall through */
> > >  	default:
> > > +		if (sdata->vif.type == NL80211_IFTYPE_AP) {
> > 
> > I'd probably put this after a
> > 	case NL80211_IFTYPE_AP:
> > label but you need the if () anyway ... hmm I guess we really should
> > clean up this code and split it into two switch statements...
> 
> And may be do it above?
> 
> 	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
> 		atomic_dec(&local->iff_allmultis);
> 
> 	if (sdata->flags & IEEE80211_SDATA_PROMISC)
> 		atomic_dec(&local->iff_promiscs);
> 
> +	if (sdata->vif.type == NL80211_IFTYPE_AP)
> +		local->fif_pspoll--;
> +

Looks good, yeah, also saves another configure_filter call.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-07-30 15:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-30 13:53 [RFC PATCH] mac80211: FIF_PSPOLL filter flag Igor Perminov
2009-07-30 14:18 ` Johannes Berg
2009-07-30 15:05   ` Igor Perminov
2009-07-30 15:31     ` Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).