All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/4] refactor station state management
@ 2011-12-13 20:07 Johannes Berg
  2011-12-13 20:07 ` [RFC 1/4] mac80211: use station mutex in configuration Johannes Berg
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Johannes Berg @ 2011-12-13 20:07 UTC (permalink / raw)
  To: linux-wireless

Here's a first step towards something I talked to some
of you about -- making drivers more aware of station
state.

Because experience tells me that drivers will be written
for the common case, and forget about uncommon sequences,
this first step enforces proper ordering of states, now
a station can move only between these states like this:
 NONE  <--> AUTHENTICATED <--> ASSOCIATED <--> AUTHORIZED

As a consequence, IBSS stations and WDS peers need to
go through ASSOCIATED state (and get ASSOC flag set),
but this doesn't seem to be an issue, in fact it makes
at least one place in the code simpler.

This patchset still has two issues:
 * secure mesh is broken right now I think, its state
   change possibilities are rather confusing
   (need help to fix this, at least explanations)
 * TLDS isn't handled (maybe not an issue?)


My further plan is the following:
 1) figure out the issues above
 2) notify drivers of these state changes
 3) refactor auth/assoc process as described before
  a) don't track multiple authentications
  b) don't try to keep an existing authentication/association
  c) set channel first etc.
 4) remove dummy station code
  a) add regular station entry before auth
  b) notify to AUTH state when auth succeeds
  c) notify to ASSOC state when assoc succeeds

This patchset is but the first step on this journey, at the
end of which we will hopefully find multi-channel support :-)

johannes

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

* [RFC 1/4] mac80211: use station mutex in configuration
  2011-12-13 20:07 [RFC 0/4] refactor station state management Johannes Berg
@ 2011-12-13 20:07 ` Johannes Berg
  2011-12-13 20:07 ` [RFC 2/4] mac80211: refactor station state transitions Johannes Berg
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2011-12-13 20:07 UTC (permalink / raw)
  To: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

There's no need to use RCU here, we can just lock
the station mutex instead. This allows the code
to sleep, which is necessary for later patches.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

--- a/net/mac80211/cfg.c	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/cfg.c	2011-12-13 21:01:28.000000000 +0100
@@ -960,11 +960,11 @@ static int ieee80211_change_station(stru
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *vlansdata;
 
-	rcu_read_lock();
+	mutex_lock(&local->sta_mtx);
 
 	sta = sta_info_get_bss(sdata, mac);
 	if (!sta) {
-		rcu_read_unlock();
+		mutex_unlock(&local->sta_mtx);
 		return -ENOENT;
 	}
 
@@ -972,7 +972,7 @@ static int ieee80211_change_station(stru
 	if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
 	    !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) !=
 	    !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
-		rcu_read_unlock();
+		mutex_unlock(&local->sta_mtx);
 		return -EINVAL;
 	}
 
@@ -981,13 +981,13 @@ static int ieee80211_change_station(stru
 
 		if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 		    vlansdata->vif.type != NL80211_IFTYPE_AP) {
-			rcu_read_unlock();
+			mutex_unlock(&local->sta_mtx);
 			return -EINVAL;
 		}
 
 		if (params->vlan->ieee80211_ptr->use_4addr) {
 			if (vlansdata->u.vlan.sta) {
-				rcu_read_unlock();
+				mutex_unlock(&local->sta_mtx);
 				return -EBUSY;
 			}
 
@@ -1003,7 +1003,7 @@ static int ieee80211_change_station(stru
 	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates)
 		rate_control_rate_init(sta);
 
-	rcu_read_unlock();
+	mutex_unlock(&local->sta_mtx);
 
 	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
 	    params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))



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

* [RFC 2/4] mac80211: refactor station state transitions
  2011-12-13 20:07 [RFC 0/4] refactor station state management Johannes Berg
  2011-12-13 20:07 ` [RFC 1/4] mac80211: use station mutex in configuration Johannes Berg
@ 2011-12-13 20:07 ` Johannes Berg
  2011-12-14  0:29   ` Thomas Pedersen
  2011-12-13 20:07 ` [RFC 3/4] mac80211: unwind station state on destroy Johannes Berg
  2011-12-13 20:07 ` [RFC 4/4] mac80211: count authorized stations per BSS Johannes Berg
  3 siblings, 1 reply; 7+ messages in thread
From: Johannes Berg @ 2011-12-13 20:07 UTC (permalink / raw)
  To: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

Station entries can have various states, the most
important ones being auth, assoc and authorized.
This patch prepares us for telling the driver about
these states, we don't want to confuse drivers with
strange transitions, so with this we enforce that
they move in the right order between them (back and
forth); some transitions might happen before the
driver even knows about the station, but at least
runtime transitions will be ordered correctly.

As a consequence, IBSS and MESH stations will now
have the ASSOC flag set (so they can transition to
AUTHORIZED), and we can get rid of a special case
in TX processing.

TBD: WLAN_STA_TDLS_PEER_AUTH?
TBD: secure mesh AUTH transitions?

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c        |   44 +++++++++++++++++++++-----------
 net/mac80211/ibss.c       |    5 ++-
 net/mac80211/iface.c      |    5 ++-
 net/mac80211/mesh_plink.c |    7 +++--
 net/mac80211/mlme.c       |    6 ++--
 net/mac80211/sta_info.c   |   62 +++++++++++++++++++++++++++++++++++++++++-----
 net/mac80211/sta_info.h   |   36 ++++++++++++++++++++++++++
 net/mac80211/tx.c         |    1 
 8 files changed, 136 insertions(+), 30 deletions(-)

--- a/net/mac80211/sta_info.c	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/sta_info.c	2011-12-13 21:03:19.000000000 +0100
@@ -204,16 +204,17 @@ struct sta_info *sta_info_get_by_idx(str
 }
 
 /**
- * __sta_info_free - internal STA free helper
+ * sta_info_free - free STA
  *
  * @local: pointer to the global information
  * @sta: STA info to free
  *
  * This function must undo everything done by sta_info_alloc()
- * that may happen before sta_info_insert().
+ * that may happen before sta_info_insert(). It may only be
+ * called when sta_info_insert() has not been attempted (and
+ * if that fails, the station is freed anyway.)
  */
-static void __sta_info_free(struct ieee80211_local *local,
-			    struct sta_info *sta)
+void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
 {
 	if (sta->rate_ctrl) {
 		rate_control_free_sta(sta);
@@ -598,7 +599,7 @@ int sta_info_insert_rcu(struct sta_info
 	return 0;
  out_free:
 	BUG_ON(!err);
-	__sta_info_free(local, sta);
+	sta_info_free(local, sta);
 	return err;
 }
 
@@ -949,7 +950,7 @@ static int __must_check __sta_info_destr
 	}
 #endif
 
-	__sta_info_free(local, sta);
+	sta_info_free(local, sta);
 
 	return 0;
 }
@@ -1513,3 +1514,52 @@ void ieee80211_sta_set_buffered(struct i
 	sta_info_recalc_tim(sta);
 }
 EXPORT_SYMBOL(ieee80211_sta_set_buffered);
+
+int sta_info_move_state_checked(struct sta_info *sta,
+				enum ieee80211_sta_state new_state)
+{
+	might_sleep(); /* for driver notify later */
+
+	if (sta->sta_state == new_state)
+		return 0;
+
+	switch (new_state) {
+	case IEEE80211_STA_NONE:
+		if (sta->sta_state == IEEE80211_STA_AUTH)
+			clear_bit(WLAN_STA_AUTH, &sta->_flags);
+		else
+			return -EINVAL;
+		break;
+	case IEEE80211_STA_AUTH:
+		if (sta->sta_state == IEEE80211_STA_NONE)
+			set_bit(WLAN_STA_AUTH, &sta->_flags);
+		else if (sta->sta_state == IEEE80211_STA_ASSOC)
+			clear_bit(WLAN_STA_ASSOC, &sta->_flags);
+		else
+			return -EINVAL;
+		break;
+	case IEEE80211_STA_ASSOC:
+		if (sta->sta_state == IEEE80211_STA_AUTH)
+			set_bit(WLAN_STA_ASSOC, &sta->_flags);
+		else if (sta->sta_state == IEEE80211_STA_AUTHORIZED)
+			clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
+		else
+			return -EINVAL;
+		break;
+	case IEEE80211_STA_AUTHORIZED:
+		if (sta->sta_state == IEEE80211_STA_ASSOC)
+			set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
+		else
+			return -EINVAL;
+		break;
+	default:
+		WARN(1, "invalid state %d", new_state);
+		return -EINVAL;
+	}
+
+	printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
+		sta->sdata->name, sta->sta.addr, new_state);
+	sta->sta_state = new_state;
+
+	return 0;
+}
--- a/net/mac80211/sta_info.h	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/sta_info.h	2011-12-13 21:03:10.000000000 +0100
@@ -73,6 +73,13 @@ enum ieee80211_sta_info_flags {
 	WLAN_STA_4ADDR_EVENT,
 };
 
+enum ieee80211_sta_state {
+	IEEE80211_STA_NONE,
+	IEEE80211_STA_AUTH,
+	IEEE80211_STA_ASSOC,
+	IEEE80211_STA_AUTHORIZED,
+};
+
 #define STA_TID_NUM 16
 #define ADDBA_RESP_INTERVAL HZ
 #define HT_AGG_MAX_RETRIES		0x3
@@ -262,6 +269,7 @@ struct sta_ampdu_mlme {
  * @dummy: indicate a dummy station created for receiving
  *	EAP frames before association
  * @sta: station information we share with the driver
+ * @sta_state: duplicates information about station state (for debug)
  */
 struct sta_info {
 	/* General information, mostly static */
@@ -283,6 +291,8 @@ struct sta_info {
 
 	bool uploaded;
 
+	enum ieee80211_sta_state sta_state;
+
 	/* use the accessors defined below */
 	unsigned long _flags;
 
@@ -371,12 +381,18 @@ static inline enum nl80211_plink_state s
 static inline void set_sta_flag(struct sta_info *sta,
 				enum ieee80211_sta_info_flags flag)
 {
+	WARN_ON(flag == WLAN_STA_AUTH ||
+		flag == WLAN_STA_ASSOC ||
+		flag == WLAN_STA_AUTHORIZED);
 	set_bit(flag, &sta->_flags);
 }
 
 static inline void clear_sta_flag(struct sta_info *sta,
 				  enum ieee80211_sta_info_flags flag)
 {
+	WARN_ON(flag == WLAN_STA_AUTH ||
+		flag == WLAN_STA_ASSOC ||
+		flag == WLAN_STA_AUTHORIZED);
 	clear_bit(flag, &sta->_flags);
 }
 
@@ -389,15 +405,32 @@ static inline int test_sta_flag(struct s
 static inline int test_and_clear_sta_flag(struct sta_info *sta,
 					  enum ieee80211_sta_info_flags flag)
 {
+	WARN_ON(flag == WLAN_STA_AUTH ||
+		flag == WLAN_STA_ASSOC ||
+		flag == WLAN_STA_AUTHORIZED);
 	return test_and_clear_bit(flag, &sta->_flags);
 }
 
 static inline int test_and_set_sta_flag(struct sta_info *sta,
 					enum ieee80211_sta_info_flags flag)
 {
+	WARN_ON(flag == WLAN_STA_AUTH ||
+		flag == WLAN_STA_ASSOC ||
+		flag == WLAN_STA_AUTHORIZED);
 	return test_and_set_bit(flag, &sta->_flags);
 }
 
+int sta_info_move_state_checked(struct sta_info *sta,
+				enum ieee80211_sta_state new_state);
+
+static inline void sta_info_move_state(struct sta_info *sta,
+				       enum ieee80211_sta_state new_state)
+{
+	int ret = sta_info_move_state_checked(sta, new_state);
+	WARN_ON_ONCE(ret);
+}
+
+
 void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
 			     struct tid_ampdu_tx *tid_tx);
 
@@ -489,6 +522,9 @@ struct sta_info *sta_info_get_by_idx(str
  */
 struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 				u8 *addr, gfp_t gfp);
+
+void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
+
 /*
  * Insert STA info into hash table/list, returns zero or a
  * -EEXIST if (if the same MAC address is already present).
--- a/net/mac80211/cfg.c	2011-12-13 21:01:28.000000000 +0100
+++ b/net/mac80211/cfg.c	2011-12-13 21:03:10.000000000 +0100
@@ -746,10 +746,11 @@ static void ieee80211_send_layer2_update
 	netif_rx_ni(skb);
 }
 
-static void sta_apply_parameters(struct ieee80211_local *local,
-				 struct sta_info *sta,
-				 struct station_parameters *params)
+static int sta_apply_parameters(struct ieee80211_local *local,
+				struct sta_info *sta,
+				struct station_parameters *params)
 {
+	int ret = 0;
 	u32 rates;
 	int i, j;
 	struct ieee80211_supported_band *sband;
@@ -763,11 +764,25 @@ static void sta_apply_parameters(struct
 
 	if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
 		if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
-			set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+			ret = sta_info_move_state_checked(sta,
+					IEEE80211_STA_AUTHORIZED);
 		else
-			clear_sta_flag(sta, WLAN_STA_AUTHORIZED);
+			ret = sta_info_move_state_checked(sta,
+					IEEE80211_STA_ASSOC);
 	}
 
+	if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
+		if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
+			ret = sta_info_move_state_checked(sta,
+					IEEE80211_STA_AUTH);
+		else
+			ret = sta_info_move_state_checked(sta,
+					IEEE80211_STA_NONE);
+	}
+
+	if (ret)
+		return ret;
+
 	if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
 		if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
 			set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
@@ -792,13 +807,6 @@ static void sta_apply_parameters(struct
 			clear_sta_flag(sta, WLAN_STA_MFP);
 	}
 
-	if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
-		if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
-			set_sta_flag(sta, WLAN_STA_AUTH);
-		else
-			clear_sta_flag(sta, WLAN_STA_AUTH);
-	}
-
 	if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
 		if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
 			set_sta_flag(sta, WLAN_STA_TDLS_PEER);
@@ -870,6 +878,8 @@ static void sta_apply_parameters(struct
 			}
 #endif
 	}
+
+	return 0;
 }
 
 static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
@@ -906,10 +916,14 @@ static int ieee80211_add_station(struct
 	if (!sta)
 		return -ENOMEM;
 
-	set_sta_flag(sta, WLAN_STA_AUTH);
-	set_sta_flag(sta, WLAN_STA_ASSOC);
+	sta_info_move_state(sta, IEEE80211_STA_AUTH);
+	sta_info_move_state(sta, IEEE80211_STA_ASSOC);
 
-	sta_apply_parameters(local, sta, params);
+	err = sta_apply_parameters(local, sta, params);
+	if (err) {
+		sta_info_free(local, sta);
+		return err;
+	}
 
 	/*
 	 * for TDLS, rate control should be initialized only when supported
--- a/net/mac80211/ibss.c	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/ibss.c	2011-12-13 21:03:10.000000000 +0100
@@ -512,7 +512,10 @@ struct sta_info *ieee80211_ibss_add_sta(
 		return NULL;
 
 	sta->last_rx = jiffies;
-	set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+
+	sta_info_move_state(sta, IEEE80211_STA_AUTH);
+	sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+	sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
 
 	/* make sure mandatory rates are always added */
 	sta->sta.supp_rates[band] = supp_rates |
--- a/net/mac80211/iface.c	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/iface.c	2011-12-13 21:03:10.000000000 +0100
@@ -318,8 +318,9 @@ static int ieee80211_do_open(struct net_
 			goto err_del_interface;
 		}
 
-		/* no atomic bitop required since STA is not live yet */
-		set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+		sta_info_move_state(sta, IEEE80211_STA_AUTH);
+		sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+		sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
 
 		res = sta_info_insert(sta);
 		if (res) {
--- a/net/mac80211/mesh_plink.c	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/mesh_plink.c	2011-12-13 21:03:10.000000000 +0100
@@ -96,9 +96,12 @@ static struct sta_info *mesh_plink_alloc
 	if (!sta)
 		return NULL;
 
-	set_sta_flag(sta, WLAN_STA_AUTH);
-	set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+	sta_info_move_state(sta, IEEE80211_STA_AUTH);
+	sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+	sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
+
 	set_sta_flag(sta, WLAN_STA_WME);
+
 	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
 	if (elems->ht_cap_elem)
 		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
--- a/net/mac80211/mlme.c	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/mlme.c	2011-12-13 21:03:10.000000000 +0100
@@ -1577,10 +1577,10 @@ static bool ieee80211_assoc_success(stru
 		return false;
 	}
 
-	set_sta_flag(sta, WLAN_STA_AUTH);
-	set_sta_flag(sta, WLAN_STA_ASSOC);
+	sta_info_move_state(sta, IEEE80211_STA_AUTH);
+	sta_info_move_state(sta, IEEE80211_STA_ASSOC);
 	if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
-		set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+		sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
 
 	rates = 0;
 	basic_rates = 0;
--- a/net/mac80211/tx.c	2011-12-13 21:01:26.000000000 +0100
+++ b/net/mac80211/tx.c	2011-12-13 21:03:10.000000000 +0100
@@ -295,7 +295,6 @@ ieee80211_tx_h_check_assoc(struct ieee80
 
 	if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
 		if (unlikely(!assoc &&
-			     tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
 			     ieee80211_is_data(hdr->frame_control))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 			printk(KERN_DEBUG "%s: dropped data frame to not "



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

* [RFC 3/4] mac80211: unwind station state on destroy
  2011-12-13 20:07 [RFC 0/4] refactor station state management Johannes Berg
  2011-12-13 20:07 ` [RFC 1/4] mac80211: use station mutex in configuration Johannes Berg
  2011-12-13 20:07 ` [RFC 2/4] mac80211: refactor station state transitions Johannes Berg
@ 2011-12-13 20:07 ` Johannes Berg
  2011-12-13 20:07 ` [RFC 4/4] mac80211: count authorized stations per BSS Johannes Berg
  3 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2011-12-13 20:07 UTC (permalink / raw)
  To: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

Before destroying a station entry, unwind its
state so drivers and other code can rely on
state transitions happening.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/sta_info.c |    3 +++
 net/mac80211/sta_info.h |    1 +
 2 files changed, 4 insertions(+)

--- a/net/mac80211/sta_info.h	2011-12-13 19:58:01.000000000 +0100
+++ b/net/mac80211/sta_info.h	2011-12-13 20:15:32.000000000 +0100
@@ -74,6 +74,7 @@ enum ieee80211_sta_info_flags {
 };
 
 enum ieee80211_sta_state {
+	/* NOTE: These need to be ordered correctly! */
 	IEEE80211_STA_NONE,
 	IEEE80211_STA_AUTH,
 	IEEE80211_STA_ASSOC,
--- a/net/mac80211/sta_info.c	2011-12-13 19:59:57.000000000 +0100
+++ b/net/mac80211/sta_info.c	2011-12-13 20:17:25.000000000 +0100
@@ -905,6 +905,9 @@ static int __must_check __sta_info_destr
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
 
+	while (sta->sta_state > IEEE80211_STA_NONE)
+		sta_info_move_state(sta, sta->sta_state - 1);
+
 	if (sta->uploaded) {
 		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 			sdata = container_of(sdata->bss,



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

* [RFC 4/4] mac80211: count authorized stations per BSS
  2011-12-13 20:07 [RFC 0/4] refactor station state management Johannes Berg
                   ` (2 preceding siblings ...)
  2011-12-13 20:07 ` [RFC 3/4] mac80211: unwind station state on destroy Johannes Berg
@ 2011-12-13 20:07 ` Johannes Berg
  3 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2011-12-13 20:07 UTC (permalink / raw)
  To: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

Currently, each AP interface will send multicast
traffic if any interface has a station entry even
if that station entry is allocated only. With the
new station state management we can easily fix it
by adding a counter that counts each authorized
station only and send multicast traffic only when
the correct interface has at least one authorized
station.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/debugfs_netdev.c |    2 ++
 net/mac80211/ieee80211_i.h    |    1 +
 net/mac80211/sta_info.c       |   14 +++++++++-----
 net/mac80211/tx.c             |   19 ++++++++-----------
 4 files changed, 20 insertions(+), 16 deletions(-)

--- a/net/mac80211/debugfs_netdev.c	2011-12-13 20:30:53.000000000 +0100
+++ b/net/mac80211/debugfs_netdev.c	2011-12-13 20:31:16.000000000 +0100
@@ -321,6 +321,7 @@ static ssize_t ieee80211_if_parse_tkip_m
 __IEEE80211_IF_FILE_W(tkip_mic_test);
 
 /* AP attributes */
+IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC);
 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
 
@@ -458,6 +459,7 @@ static void add_ap_files(struct ieee8021
 	DEBUGFS_ADD(rc_rateidx_mask_2ghz);
 	DEBUGFS_ADD(rc_rateidx_mask_5ghz);
 
+	DEBUGFS_ADD(num_sta_authorized);
 	DEBUGFS_ADD(num_sta_ps);
 	DEBUGFS_ADD(dtim_count);
 	DEBUGFS_ADD(num_buffered_multicast);
--- a/net/mac80211/ieee80211_i.h	2011-12-13 20:30:53.000000000 +0100
+++ b/net/mac80211/ieee80211_i.h	2011-12-13 20:31:16.000000000 +0100
@@ -243,6 +243,7 @@ struct ieee80211_if_ap {
 	u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
 	struct sk_buff_head ps_bc_buf;
 	atomic_t num_sta_ps; /* number of stations in PS mode */
+	atomic_t num_sta_authorized; /* number of authorized stations */
 	int dtim_count;
 	bool dtim_bc_mc;
 };
--- a/net/mac80211/sta_info.c	2011-12-13 20:31:16.000000000 +0100
+++ b/net/mac80211/sta_info.c	2011-12-13 20:31:16.000000000 +0100
@@ -1542,17 +1542,21 @@ int sta_info_move_state_checked(struct s
 			return -EINVAL;
 		break;
 	case IEEE80211_STA_ASSOC:
-		if (sta->sta_state == IEEE80211_STA_AUTH)
+		if (sta->sta_state == IEEE80211_STA_AUTH) {
 			set_bit(WLAN_STA_ASSOC, &sta->_flags);
-		else if (sta->sta_state == IEEE80211_STA_AUTHORIZED)
+		} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
+			if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
+				atomic_dec(&sta->sdata->u.ap.num_sta_authorized);
 			clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
-		else
+		} else
 			return -EINVAL;
 		break;
 	case IEEE80211_STA_AUTHORIZED:
-		if (sta->sta_state == IEEE80211_STA_ASSOC)
+		if (sta->sta_state == IEEE80211_STA_ASSOC) {
+			if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
+				atomic_inc(&sta->sdata->u.ap.num_sta_authorized);
 			set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
-		else
+		} else
 			return -EINVAL;
 		break;
 	default:
--- a/net/mac80211/tx.c	2011-12-13 20:30:53.000000000 +0100
+++ b/net/mac80211/tx.c	2011-12-13 20:31:16.000000000 +0100
@@ -304,17 +304,14 @@ ieee80211_tx_h_check_assoc(struct ieee80
 			I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
 			return TX_DROP;
 		}
-	} else {
-		if (unlikely(ieee80211_is_data(hdr->frame_control) &&
-			     tx->local->num_sta == 0 &&
-			     tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) {
-			/*
-			 * No associated STAs - no need to send multicast
-			 * frames.
-			 */
-			return TX_DROP;
-		}
-		return TX_CONTINUE;
+	} else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP &&
+			    ieee80211_is_data(hdr->frame_control) &&
+			    !atomic_read(&tx->sdata->u.ap.num_sta_authorized))) {
+		/*
+		 * No associated STAs - no need to send multicast
+		 * frames.
+		 */
+		return TX_DROP;
 	}
 
 	return TX_CONTINUE;



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

* Re: [RFC 2/4] mac80211: refactor station state transitions
  2011-12-13 20:07 ` [RFC 2/4] mac80211: refactor station state transitions Johannes Berg
@ 2011-12-14  0:29   ` Thomas Pedersen
  2011-12-14  8:22     ` Johannes Berg
  0 siblings, 1 reply; 7+ messages in thread
From: Thomas Pedersen @ 2011-12-14  0:29 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Javier Cardona

On Tue, Dec 13, 2011 at 12:07 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Station entries can have various states, the most
> important ones being auth, assoc and authorized.
> This patch prepares us for telling the driver about
> these states, we don't want to confuse drivers with
> strange transitions, so with this we enforce that
> they move in the right order between them (back and
> forth); some transitions might happen before the
> driver even knows about the station, but at least
> runtime transitions will be ordered correctly.
>
> As a consequence, IBSS and MESH stations will now
> have the ASSOC flag set (so they can transition to
> AUTHORIZED), and we can get rid of a special case
> in TX processing.
>
> TBD: WLAN_STA_TDLS_PEER_AUTH?
> TBD: secure mesh AUTH transitions?

This patch makes it impossible to add a new unauthenticated station,
AFAICT. Maybe this is not even desirable from mac80211's POV? The
reason the secure mesh daemon adds a new unauthenticated peer is to
stop NL80211_NEW_PEER_CANDIDATE notifications while userspace is
handling the authentication process, and we need a station entry for
ieee80211_mgmt_tx().

Some other mechanism could be implemented to halt new peer
notifications, or just allow userspace to add a station in state NONE
(ieee80211_tx_h_check_assoc() doesn't even check association flag for
mesh interfaces).

Thomas

>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>  net/mac80211/cfg.c        |   44 +++++++++++++++++++++-----------
>  net/mac80211/ibss.c       |    5 ++-
>  net/mac80211/iface.c      |    5 ++-
>  net/mac80211/mesh_plink.c |    7 +++--
>  net/mac80211/mlme.c       |    6 ++--
>  net/mac80211/sta_info.c   |   62 +++++++++++++++++++++++++++++++++++++++++-----
>  net/mac80211/sta_info.h   |   36 ++++++++++++++++++++++++++
>  net/mac80211/tx.c         |    1
>  8 files changed, 136 insertions(+), 30 deletions(-)
>
> --- a/net/mac80211/sta_info.c   2011-12-13 21:01:26.000000000 +0100
> +++ b/net/mac80211/sta_info.c   2011-12-13 21:03:19.000000000 +0100
> @@ -204,16 +204,17 @@ struct sta_info *sta_info_get_by_idx(str
>  }
>
>  /**
> - * __sta_info_free - internal STA free helper
> + * sta_info_free - free STA
>  *
>  * @local: pointer to the global information
>  * @sta: STA info to free
>  *
>  * This function must undo everything done by sta_info_alloc()
> - * that may happen before sta_info_insert().
> + * that may happen before sta_info_insert(). It may only be
> + * called when sta_info_insert() has not been attempted (and
> + * if that fails, the station is freed anyway.)
>  */
> -static void __sta_info_free(struct ieee80211_local *local,
> -                           struct sta_info *sta)
> +void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
>  {
>        if (sta->rate_ctrl) {
>                rate_control_free_sta(sta);
> @@ -598,7 +599,7 @@ int sta_info_insert_rcu(struct sta_info
>        return 0;
>  out_free:
>        BUG_ON(!err);
> -       __sta_info_free(local, sta);
> +       sta_info_free(local, sta);
>        return err;
>  }
>
> @@ -949,7 +950,7 @@ static int __must_check __sta_info_destr
>        }
>  #endif
>
> -       __sta_info_free(local, sta);
> +       sta_info_free(local, sta);
>
>        return 0;
>  }
> @@ -1513,3 +1514,52 @@ void ieee80211_sta_set_buffered(struct i
>        sta_info_recalc_tim(sta);
>  }
>  EXPORT_SYMBOL(ieee80211_sta_set_buffered);
> +
> +int sta_info_move_state_checked(struct sta_info *sta,
> +                               enum ieee80211_sta_state new_state)
> +{
> +       might_sleep(); /* for driver notify later */
> +
> +       if (sta->sta_state == new_state)
> +               return 0;
> +
> +       switch (new_state) {
> +       case IEEE80211_STA_NONE:
> +               if (sta->sta_state == IEEE80211_STA_AUTH)
> +                       clear_bit(WLAN_STA_AUTH, &sta->_flags);
> +               else
> +                       return -EINVAL;
> +               break;
> +       case IEEE80211_STA_AUTH:
> +               if (sta->sta_state == IEEE80211_STA_NONE)
> +                       set_bit(WLAN_STA_AUTH, &sta->_flags);
> +               else if (sta->sta_state == IEEE80211_STA_ASSOC)
> +                       clear_bit(WLAN_STA_ASSOC, &sta->_flags);
> +               else
> +                       return -EINVAL;
> +               break;
> +       case IEEE80211_STA_ASSOC:
> +               if (sta->sta_state == IEEE80211_STA_AUTH)
> +                       set_bit(WLAN_STA_ASSOC, &sta->_flags);
> +               else if (sta->sta_state == IEEE80211_STA_AUTHORIZED)
> +                       clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
> +               else
> +                       return -EINVAL;
> +               break;
> +       case IEEE80211_STA_AUTHORIZED:
> +               if (sta->sta_state == IEEE80211_STA_ASSOC)
> +                       set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
> +               else
> +                       return -EINVAL;
> +               break;
> +       default:
> +               WARN(1, "invalid state %d", new_state);
> +               return -EINVAL;
> +       }
> +
> +       printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
> +               sta->sdata->name, sta->sta.addr, new_state);
> +       sta->sta_state = new_state;
> +
> +       return 0;
> +}
> --- a/net/mac80211/sta_info.h   2011-12-13 21:01:26.000000000 +0100
> +++ b/net/mac80211/sta_info.h   2011-12-13 21:03:10.000000000 +0100
> @@ -73,6 +73,13 @@ enum ieee80211_sta_info_flags {
>        WLAN_STA_4ADDR_EVENT,
>  };
>
> +enum ieee80211_sta_state {
> +       IEEE80211_STA_NONE,
> +       IEEE80211_STA_AUTH,
> +       IEEE80211_STA_ASSOC,
> +       IEEE80211_STA_AUTHORIZED,
> +};
> +
>  #define STA_TID_NUM 16
>  #define ADDBA_RESP_INTERVAL HZ
>  #define HT_AGG_MAX_RETRIES             0x3
> @@ -262,6 +269,7 @@ struct sta_ampdu_mlme {
>  * @dummy: indicate a dummy station created for receiving
>  *     EAP frames before association
>  * @sta: station information we share with the driver
> + * @sta_state: duplicates information about station state (for debug)
>  */
>  struct sta_info {
>        /* General information, mostly static */
> @@ -283,6 +291,8 @@ struct sta_info {
>
>        bool uploaded;
>
> +       enum ieee80211_sta_state sta_state;
> +
>        /* use the accessors defined below */
>        unsigned long _flags;
>
> @@ -371,12 +381,18 @@ static inline enum nl80211_plink_state s
>  static inline void set_sta_flag(struct sta_info *sta,
>                                enum ieee80211_sta_info_flags flag)
>  {
> +       WARN_ON(flag == WLAN_STA_AUTH ||
> +               flag == WLAN_STA_ASSOC ||
> +               flag == WLAN_STA_AUTHORIZED);
>        set_bit(flag, &sta->_flags);
>  }
>
>  static inline void clear_sta_flag(struct sta_info *sta,
>                                  enum ieee80211_sta_info_flags flag)
>  {
> +       WARN_ON(flag == WLAN_STA_AUTH ||
> +               flag == WLAN_STA_ASSOC ||
> +               flag == WLAN_STA_AUTHORIZED);
>        clear_bit(flag, &sta->_flags);
>  }
>
> @@ -389,15 +405,32 @@ static inline int test_sta_flag(struct s
>  static inline int test_and_clear_sta_flag(struct sta_info *sta,
>                                          enum ieee80211_sta_info_flags flag)
>  {
> +       WARN_ON(flag == WLAN_STA_AUTH ||
> +               flag == WLAN_STA_ASSOC ||
> +               flag == WLAN_STA_AUTHORIZED);
>        return test_and_clear_bit(flag, &sta->_flags);
>  }
>
>  static inline int test_and_set_sta_flag(struct sta_info *sta,
>                                        enum ieee80211_sta_info_flags flag)
>  {
> +       WARN_ON(flag == WLAN_STA_AUTH ||
> +               flag == WLAN_STA_ASSOC ||
> +               flag == WLAN_STA_AUTHORIZED);
>        return test_and_set_bit(flag, &sta->_flags);
>  }
>
> +int sta_info_move_state_checked(struct sta_info *sta,
> +                               enum ieee80211_sta_state new_state);
> +
> +static inline void sta_info_move_state(struct sta_info *sta,
> +                                      enum ieee80211_sta_state new_state)
> +{
> +       int ret = sta_info_move_state_checked(sta, new_state);
> +       WARN_ON_ONCE(ret);
> +}
> +
> +
>  void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
>                             struct tid_ampdu_tx *tid_tx);
>
> @@ -489,6 +522,9 @@ struct sta_info *sta_info_get_by_idx(str
>  */
>  struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
>                                u8 *addr, gfp_t gfp);
> +
> +void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
> +
>  /*
>  * Insert STA info into hash table/list, returns zero or a
>  * -EEXIST if (if the same MAC address is already present).
> --- a/net/mac80211/cfg.c        2011-12-13 21:01:28.000000000 +0100
> +++ b/net/mac80211/cfg.c        2011-12-13 21:03:10.000000000 +0100
> @@ -746,10 +746,11 @@ static void ieee80211_send_layer2_update
>        netif_rx_ni(skb);
>  }
>
> -static void sta_apply_parameters(struct ieee80211_local *local,
> -                                struct sta_info *sta,
> -                                struct station_parameters *params)
> +static int sta_apply_parameters(struct ieee80211_local *local,
> +                               struct sta_info *sta,
> +                               struct station_parameters *params)
>  {
> +       int ret = 0;
>        u32 rates;
>        int i, j;
>        struct ieee80211_supported_band *sband;
> @@ -763,11 +764,25 @@ static void sta_apply_parameters(struct
>
>        if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
>                if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
> -                       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
> +                       ret = sta_info_move_state_checked(sta,
> +                                       IEEE80211_STA_AUTHORIZED);
>                else
> -                       clear_sta_flag(sta, WLAN_STA_AUTHORIZED);
> +                       ret = sta_info_move_state_checked(sta,
> +                                       IEEE80211_STA_ASSOC);
>        }
>
> +       if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
> +               if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
> +                       ret = sta_info_move_state_checked(sta,
> +                                       IEEE80211_STA_AUTH);
> +               else
> +                       ret = sta_info_move_state_checked(sta,
> +                                       IEEE80211_STA_NONE);
> +       }
> +
> +       if (ret)
> +               return ret;
> +
>        if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
>                if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
>                        set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
> @@ -792,13 +807,6 @@ static void sta_apply_parameters(struct
>                        clear_sta_flag(sta, WLAN_STA_MFP);
>        }
>
> -       if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
> -               if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
> -                       set_sta_flag(sta, WLAN_STA_AUTH);
> -               else
> -                       clear_sta_flag(sta, WLAN_STA_AUTH);
> -       }
> -
>        if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
>                if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
>                        set_sta_flag(sta, WLAN_STA_TDLS_PEER);
> @@ -870,6 +878,8 @@ static void sta_apply_parameters(struct
>                        }
>  #endif
>        }
> +
> +       return 0;
>  }
>
>  static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
> @@ -906,10 +916,14 @@ static int ieee80211_add_station(struct
>        if (!sta)
>                return -ENOMEM;
>
> -       set_sta_flag(sta, WLAN_STA_AUTH);
> -       set_sta_flag(sta, WLAN_STA_ASSOC);
> +       sta_info_move_state(sta, IEEE80211_STA_AUTH);
> +       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
>
> -       sta_apply_parameters(local, sta, params);
> +       err = sta_apply_parameters(local, sta, params);
> +       if (err) {
> +               sta_info_free(local, sta);
> +               return err;
> +       }
>
>        /*
>         * for TDLS, rate control should be initialized only when supported
> --- a/net/mac80211/ibss.c       2011-12-13 21:01:26.000000000 +0100
> +++ b/net/mac80211/ibss.c       2011-12-13 21:03:10.000000000 +0100
> @@ -512,7 +512,10 @@ struct sta_info *ieee80211_ibss_add_sta(
>                return NULL;
>
>        sta->last_rx = jiffies;
> -       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
> +
> +       sta_info_move_state(sta, IEEE80211_STA_AUTH);
> +       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
> +       sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
>
>        /* make sure mandatory rates are always added */
>        sta->sta.supp_rates[band] = supp_rates |
> --- a/net/mac80211/iface.c      2011-12-13 21:01:26.000000000 +0100
> +++ b/net/mac80211/iface.c      2011-12-13 21:03:10.000000000 +0100
> @@ -318,8 +318,9 @@ static int ieee80211_do_open(struct net_
>                        goto err_del_interface;
>                }
>
> -               /* no atomic bitop required since STA is not live yet */
> -               set_sta_flag(sta, WLAN_STA_AUTHORIZED);
> +               sta_info_move_state(sta, IEEE80211_STA_AUTH);
> +               sta_info_move_state(sta, IEEE80211_STA_ASSOC);
> +               sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
>
>                res = sta_info_insert(sta);
>                if (res) {
> --- a/net/mac80211/mesh_plink.c 2011-12-13 21:01:26.000000000 +0100
> +++ b/net/mac80211/mesh_plink.c 2011-12-13 21:03:10.000000000 +0100
> @@ -96,9 +96,12 @@ static struct sta_info *mesh_plink_alloc
>        if (!sta)
>                return NULL;
>
> -       set_sta_flag(sta, WLAN_STA_AUTH);
> -       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
> +       sta_info_move_state(sta, IEEE80211_STA_AUTH);
> +       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
> +       sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
> +
>        set_sta_flag(sta, WLAN_STA_WME);
> +
>        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
>        if (elems->ht_cap_elem)
>                ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
> --- a/net/mac80211/mlme.c       2011-12-13 21:01:26.000000000 +0100
> +++ b/net/mac80211/mlme.c       2011-12-13 21:03:10.000000000 +0100
> @@ -1577,10 +1577,10 @@ static bool ieee80211_assoc_success(stru
>                return false;
>        }
>
> -       set_sta_flag(sta, WLAN_STA_AUTH);
> -       set_sta_flag(sta, WLAN_STA_ASSOC);
> +       sta_info_move_state(sta, IEEE80211_STA_AUTH);
> +       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
>        if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
> -               set_sta_flag(sta, WLAN_STA_AUTHORIZED);
> +               sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
>
>        rates = 0;
>        basic_rates = 0;
> --- a/net/mac80211/tx.c 2011-12-13 21:01:26.000000000 +0100
> +++ b/net/mac80211/tx.c 2011-12-13 21:03:10.000000000 +0100
> @@ -295,7 +295,6 @@ ieee80211_tx_h_check_assoc(struct ieee80
>
>        if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
>                if (unlikely(!assoc &&
> -                            tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
>                             ieee80211_is_data(hdr->frame_control))) {
>  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
>                        printk(KERN_DEBUG "%s: dropped data frame to not "
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC 2/4] mac80211: refactor station state transitions
  2011-12-14  0:29   ` Thomas Pedersen
@ 2011-12-14  8:22     ` Johannes Berg
  0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2011-12-14  8:22 UTC (permalink / raw)
  To: Thomas Pedersen; +Cc: linux-wireless, Javier Cardona

On Tue, 2011-12-13 at 16:29 -0800, Thomas Pedersen wrote:
> On Tue, Dec 13, 2011 at 12:07 PM, Johannes Berg
> <johannes@sipsolutions.net> wrote:
> > From: Johannes Berg <johannes.berg@intel.com>
> >
> > Station entries can have various states, the most
> > important ones being auth, assoc and authorized.
> > This patch prepares us for telling the driver about
> > these states, we don't want to confuse drivers with
> > strange transitions, so with this we enforce that
> > they move in the right order between them (back and
> > forth); some transitions might happen before the
> > driver even knows about the station, but at least
> > runtime transitions will be ordered correctly.
> >
> > As a consequence, IBSS and MESH stations will now
> > have the ASSOC flag set (so they can transition to
> > AUTHORIZED), and we can get rid of a special case
> > in TX processing.
> >
> > TBD: WLAN_STA_TDLS_PEER_AUTH?
> > TBD: secure mesh AUTH transitions?
> 
> This patch makes it impossible to add a new unauthenticated station,
> AFAICT. Maybe this is not even desirable from mac80211's POV? The
> reason the secure mesh daemon adds a new unauthenticated peer is to
> stop NL80211_NEW_PEER_CANDIDATE notifications while userspace is
> handling the authentication process, and we need a station entry for
> ieee80211_mgmt_tx().

Ah, yes. I had to sleep over this -- now I understand why I was
confused. I'll amend the patch series to properly manage more of this in
cfg80211. I have a feeling we should also allow userspace to manage the
ASSOC state, but can we require it from the secure mesh userspace
daemon? It would break backward compatibility if we do ... I'll try to
find a workaround :)

johannes


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

end of thread, other threads:[~2011-12-14  8:22 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-13 20:07 [RFC 0/4] refactor station state management Johannes Berg
2011-12-13 20:07 ` [RFC 1/4] mac80211: use station mutex in configuration Johannes Berg
2011-12-13 20:07 ` [RFC 2/4] mac80211: refactor station state transitions Johannes Berg
2011-12-14  0:29   ` Thomas Pedersen
2011-12-14  8:22     ` Johannes Berg
2011-12-13 20:07 ` [RFC 3/4] mac80211: unwind station state on destroy Johannes Berg
2011-12-13 20:07 ` [RFC 4/4] mac80211: count authorized stations per BSS Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.