All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] mac80211: refactor mesh peer initialization
@ 2012-04-19  2:23 Thomas Pedersen
  2012-04-19  2:23 ` [PATCH 2/2] mac80211: refactor mesh peer rate handling Thomas Pedersen
  0 siblings, 1 reply; 2+ messages in thread
From: Thomas Pedersen @ 2012-04-19  2:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, Thomas Pedersen, johannes, linville

This patch unifies the previous two paths toward mesh peer creation a
bit. It also fixes a bug where a peer's changing rates or HT mode
wouldn't register on leaving and then returning to the mesh with a sta
entry still present.

Also clean up locking and clear possibly stale ht cap.

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
---
 net/mac80211/mesh_plink.c |  126 +++++++++++++++++++++++++-------------------
 1 files changed, 72 insertions(+), 54 deletions(-)

diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 9c836e7..c3a0b0a 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -82,20 +82,14 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta)
 }
 
 /*
- * NOTE: This is just an alias for sta_info_alloc(), see notes
- *       on it in the lifecycle management section!
+ * Allocate mesh sta entry and insert into station table
  */
 static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
-					 u8 *hw_addr, u32 rates,
-					 struct ieee802_11_elems *elems)
+					 u8 *hw_addr)
 {
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_supported_band *sband;
 	struct sta_info *sta;
 
-	sband = local->hw.wiphy->bands[local->oper_channel->band];
-
-	if (local->num_sta >= MESH_MAX_PLINKS)
+	if (sdata->local->num_sta >= MESH_MAX_PLINKS)
 		return NULL;
 
 	sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
@@ -108,12 +102,8 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
 
 	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,
-						  elems->ht_cap_elem,
-						  &sta->sta.ht_cap);
-	rate_control_rate_init(sta);
+	if (sta_info_insert(sta))
+		return NULL;
 
 	return sta;
 }
@@ -274,43 +264,76 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 	return 0;
 }
 
-void mesh_neighbour_update(u8 *hw_addr, u32 rates,
-		struct ieee80211_sub_if_data *sdata,
-		struct ieee802_11_elems *elems)
+/* mesh_peer_init - initialize new mesh peer and return resulting sta_info
+ *
+ * @sdata: local meshif
+ * @addr: peer's address
+ * @rates: station's supported rates
+ * @elems: IEs from beacon or mesh peering frame
+ *
+ * call under RCU
+ */
+static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
+				       u8 *addr, u32 rates,
+				       struct ieee802_11_elems *elems)
 {
 	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_supported_band *sband;
 	struct sta_info *sta;
 
-	rcu_read_lock();
+	sband = local->hw.wiphy->bands[local->oper_channel->band];
 
-	sta = sta_info_get(sdata, hw_addr);
+	sta = sta_info_get(sdata, addr);
 	if (!sta) {
-		rcu_read_unlock();
-		/* Userspace handles peer allocation when security is enabled
-		 * */
-		if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
-			cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
-					elems->ie_start, elems->total_len,
-					GFP_KERNEL);
-		else
-			sta = mesh_plink_alloc(sdata, hw_addr, rates, elems);
+		sta = mesh_plink_alloc(sdata, addr);
 		if (!sta)
-			return;
-		if (sta_info_insert_rcu(sta)) {
-			rcu_read_unlock();
-			return;
-		}
+			return NULL;
 	}
 
+	spin_lock_bh(&sta->lock);
 	sta->last_rx = jiffies;
 	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,
+						  elems->ht_cap_elem,
+						  &sta->sta.ht_cap);
+	else
+		memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
+
+	rate_control_rate_init(sta);
+	spin_unlock_bh(&sta->lock);
+
+	return sta;
+}
+
+void mesh_neighbour_update(u8 *hw_addr, u32 rates,
+			   struct ieee80211_sub_if_data *sdata,
+			   struct ieee802_11_elems *elems)
+{
+	struct sta_info *sta;
+
+	/* Userspace handles peer allocation when security is enabled */
+	if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) {
+		cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
+						   elems->ie_start,
+						   elems->total_len,
+						   GFP_KERNEL);
+		return;
+	}
+
+	rcu_read_lock();
+	sta = mesh_peer_init(sdata, hw_addr, rates, elems);
+	if (!sta)
+		goto out;
+
 	if (mesh_peer_accepts_plinks(elems) &&
-			sta->plink_state == NL80211_PLINK_LISTEN &&
-			sdata->u.mesh.accepting_plinks &&
-			sdata->u.mesh.mshcfg.auto_open_plinks &&
-			rssi_threshold_check(sta, sdata))
+	    sta->plink_state == NL80211_PLINK_LISTEN &&
+	    sdata->u.mesh.accepting_plinks &&
+	    sdata->u.mesh.mshcfg.auto_open_plinks &&
+	    rssi_threshold_check(sta, sdata))
 		mesh_plink_open(sta);
 
+out:
 	rcu_read_unlock();
 }
 
@@ -587,26 +610,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 		return;
 	} else if (!sta) {
 		/* ftype == WLAN_SP_MESH_PEERING_OPEN */
-
-		rcu_read_unlock();
-
 		if (!mesh_plink_free_count(sdata)) {
 			mpl_dbg("Mesh plink error: no more free plinks\n");
-			return;
-		}
-		sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems);
-		if (!sta) {
-			mpl_dbg("Mesh plink error: plink table full\n");
-			return;
-		}
-		if (sta_info_insert_rcu(sta)) {
 			rcu_read_unlock();
 			return;
 		}
 		event = OPN_ACPT;
-		spin_lock_bh(&sta->lock);
 	} else if (matches_local) {
-		spin_lock_bh(&sta->lock);
 		switch (ftype) {
 		case WLAN_SP_MESH_PEERING_OPEN:
 			if (!mesh_plink_free_count(sdata) ||
@@ -643,12 +653,19 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 			break;
 		default:
 			mpl_dbg("Mesh plink: unknown frame subtype\n");
-			spin_unlock_bh(&sta->lock);
 			rcu_read_unlock();
 			return;
 		}
-	} else {
-		spin_lock_bh(&sta->lock);
+	}
+
+	if (event == OPN_ACPT) {
+		/* allocate sta entry if necessary and update info */
+		sta = mesh_peer_init(sdata, mgmt->sa, rates, &elems);
+		if (!sta) {
+			mpl_dbg("Mesh plink: failed to init peer!\n");
+			rcu_read_unlock();
+			return;
+		}
 	}
 
 	mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
@@ -656,6 +673,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 		le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
 		event);
 	reason = 0;
+	spin_lock_bh(&sta->lock);
 	switch (sta->plink_state) {
 		/* spin_unlock as soon as state is updated at each case */
 	case NL80211_PLINK_LISTEN:
-- 
1.7.5.4


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

* [PATCH 2/2] mac80211: refactor mesh peer rate handling
  2012-04-19  2:23 [PATCH 1/2] mac80211: refactor mesh peer initialization Thomas Pedersen
@ 2012-04-19  2:23 ` Thomas Pedersen
  0 siblings, 0 replies; 2+ messages in thread
From: Thomas Pedersen @ 2012-04-19  2:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, Thomas Pedersen, johannes, linville

To avoid passing supp_rates and basic_rates around all the time, just
derive these when needed in mesh_matches_local() and mesh_peer_init().

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
---
 net/mac80211/mesh.c       |   19 +++++++++----------
 net/mac80211/mesh.h       |   10 +++++-----
 net/mac80211/mesh_plink.c |   25 +++++++++++--------------
 3 files changed, 25 insertions(+), 29 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 133c118..598a96a 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -64,18 +64,18 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
 /**
  * mesh_matches_local - check if the config of a mesh point matches ours
  *
- * @ie: information elements of a management frame from the mesh peer
  * @sdata: local mesh subif
- * @basic_rates: BSSBasicRateSet of the peer candidate
+ * @ie: information elements of a management frame from the mesh peer
  *
  * This function checks if the mesh configuration of a mesh point matches the
  * local mesh configuration, i.e. if both nodes belong to the same mesh network.
  */
-bool mesh_matches_local(struct ieee802_11_elems *ie,
-			struct ieee80211_sub_if_data *sdata, u32 basic_rates)
+bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
+			struct ieee802_11_elems *ie)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	struct ieee80211_local *local = sdata->local;
+	u32 basic_rates = 0;
 
 	/*
 	 * As support for each feature is added, check for matching
@@ -96,6 +96,9 @@ bool mesh_matches_local(struct ieee802_11_elems *ie,
 	     (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
 		goto mismatch;
 
+	ieee80211_sta_get_rates(local, ie, local->oper_channel->band,
+				&basic_rates);
+
 	if (sdata->vif.bss_conf.basic_rates != basic_rates)
 		goto mismatch;
 
@@ -630,7 +633,6 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	struct ieee802_11_elems elems;
 	struct ieee80211_channel *channel;
-	u32 supp_rates = 0, basic_rates = 0;
 	size_t baselen;
 	int freq;
 	enum ieee80211_band band = rx_status->band;
@@ -661,12 +663,9 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
 	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
 		return;
 
-	supp_rates = ieee80211_sta_get_rates(local, &elems,
-					     band, &basic_rates);
-
 	if (elems.mesh_id && elems.mesh_config &&
-	    mesh_matches_local(&elems, sdata, basic_rates))
-		mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems);
+	    mesh_matches_local(sdata, &elems))
+		mesh_neighbour_update(sdata, mgmt->sa, &elems);
 
 	if (ifmsh->sync_ops)
 		ifmsh->sync_ops->rx_bcn_presp(sdata,
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 4ad7389..345f0e7 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -222,8 +222,8 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
 		char *addr6);
 int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
 		struct ieee80211_sub_if_data *sdata);
-bool mesh_matches_local(struct ieee802_11_elems *ie,
-			struct ieee80211_sub_if_data *sdata, u32 basic_rates);
+bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
+			struct ieee802_11_elems *ie);
 void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
 void mesh_mgmt_ies_add(struct sk_buff *skb,
 		struct ieee80211_sub_if_data *sdata);
@@ -276,9 +276,9 @@ int mesh_path_add_gate(struct mesh_path *mpath);
 int mesh_path_send_to_gates(struct mesh_path *mpath);
 int mesh_gate_num(struct ieee80211_sub_if_data *sdata);
 /* Mesh plinks */
-void mesh_neighbour_update(u8 *hw_addr, u32 rates,
-		struct ieee80211_sub_if_data *sdata,
-		struct ieee802_11_elems *ie);
+void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
+			   u8 *hw_addr,
+			   struct ieee802_11_elems *ie);
 bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
 void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
 void mesh_plink_broken(struct sta_info *sta);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index c3a0b0a..c2af7b3 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -268,20 +268,22 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
  *
  * @sdata: local meshif
  * @addr: peer's address
- * @rates: station's supported rates
  * @elems: IEs from beacon or mesh peering frame
  *
  * call under RCU
  */
 static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
-				       u8 *addr, u32 rates,
+				       u8 *addr,
 				       struct ieee802_11_elems *elems)
 {
 	struct ieee80211_local *local = sdata->local;
+	enum ieee80211_band band = local->oper_channel->band;
 	struct ieee80211_supported_band *sband;
+	u32 rates, basic_rates = 0;
 	struct sta_info *sta;
 
-	sband = local->hw.wiphy->bands[local->oper_channel->band];
+	sband = local->hw.wiphy->bands[band];
+	rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
 
 	sta = sta_info_get(sdata, addr);
 	if (!sta) {
@@ -292,7 +294,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
 
 	spin_lock_bh(&sta->lock);
 	sta->last_rx = jiffies;
-	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
+	sta->sta.supp_rates[band] = rates;
 	if (elems->ht_cap_elem)
 		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 						  elems->ht_cap_elem,
@@ -306,8 +308,8 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
 	return sta;
 }
 
-void mesh_neighbour_update(u8 *hw_addr, u32 rates,
-			   struct ieee80211_sub_if_data *sdata,
+void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
+			   u8 *hw_addr,
 			   struct ieee802_11_elems *elems)
 {
 	struct sta_info *sta;
@@ -322,7 +324,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
 	}
 
 	rcu_read_lock();
-	sta = mesh_peer_init(sdata, hw_addr, rates, elems);
+	sta = mesh_peer_init(sdata, hw_addr, elems);
 	if (!sta)
 		goto out;
 
@@ -479,7 +481,6 @@ void mesh_plink_block(struct sta_info *sta)
 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
 			 size_t len, struct ieee80211_rx_status *rx_status)
 {
-	struct ieee80211_local *local = sdata->local;
 	struct ieee802_11_elems elems;
 	struct sta_info *sta;
 	enum plink_event event;
@@ -488,7 +489,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 	bool deactivated, matches_local = true;
 	u8 ie_len;
 	u8 *baseaddr;
-	u32 rates, basic_rates = 0;
 	__le16 plid, llid, reason;
 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
 	static const char *mplstates[] = {
@@ -583,11 +583,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 
 	/* Now we will figure out the appropriate event... */
 	event = PLINK_UNDEFINED;
-	rates = ieee80211_sta_get_rates(local, &elems,
-					rx_status->band, &basic_rates);
-
 	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
-	    (!mesh_matches_local(&elems, sdata, basic_rates))) {
+	    !mesh_matches_local(sdata, &elems)) {
 		matches_local = false;
 		switch (ftype) {
 		case WLAN_SP_MESH_PEERING_OPEN:
@@ -660,7 +657,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 
 	if (event == OPN_ACPT) {
 		/* allocate sta entry if necessary and update info */
-		sta = mesh_peer_init(sdata, mgmt->sa, rates, &elems);
+		sta = mesh_peer_init(sdata, mgmt->sa, &elems);
 		if (!sta) {
 			mpl_dbg("Mesh plink: failed to init peer!\n");
 			rcu_read_unlock();
-- 
1.7.5.4


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

end of thread, other threads:[~2012-04-19  2:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-19  2:23 [PATCH 1/2] mac80211: refactor mesh peer initialization Thomas Pedersen
2012-04-19  2:23 ` [PATCH 2/2] mac80211: refactor mesh peer rate handling Thomas Pedersen

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.