aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2015-07-14 08:31:59 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-07-17 09:47:58 -0400
commit0e0060fcfb3d0f5a53ef43e7b6a50227b934ab7c (patch)
treefbe2ed18adcd104851994f59e56c299b1935bf08
parenta69bd8e60b02946896c097439b94eb77c0c2c9e4 (diff)
mac80211: select an AID when creating new mesh STAs
Instead of using peer link id for AID, generate a new AID when creating mesh STAs in the kernel peering manager. This enables smaller TIM elements and more closely follows the standard, and it also enables mesh to work on drivers that require a valid AID when the STA is inserted (ath10k firmware has this requirement, for example). In the case of userspace-managed stations, we use the AID from NL80211_CMD_NEW_STATION. Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/mesh_plink.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 3323413acb77..e12be2e4e8df 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -422,20 +422,54 @@ out:
422 spin_unlock_bh(&sta->mesh->plink_lock); 422 spin_unlock_bh(&sta->mesh->plink_lock);
423} 423}
424 424
425static int mesh_allocate_aid(struct ieee80211_sub_if_data *sdata)
426{
427 struct sta_info *sta;
428 unsigned long *aid_map;
429 int aid;
430
431 aid_map = kcalloc(BITS_TO_LONGS(IEEE80211_MAX_AID + 1),
432 sizeof(*aid_map), GFP_KERNEL);
433 if (!aid_map)
434 return -ENOMEM;
435
436 /* reserve aid 0 for mcast indication */
437 __set_bit(0, aid_map);
438
439 rcu_read_lock();
440 list_for_each_entry_rcu(sta, &sdata->local->sta_list, list)
441 __set_bit(sta->sta.aid, aid_map);
442 rcu_read_unlock();
443
444 aid = find_first_zero_bit(aid_map, IEEE80211_MAX_AID + 1);
445 kfree(aid_map);
446
447 if (aid > IEEE80211_MAX_AID)
448 return -ENOBUFS;
449
450 return aid;
451}
452
425static struct sta_info * 453static struct sta_info *
426__mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) 454__mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
427{ 455{
428 struct sta_info *sta; 456 struct sta_info *sta;
457 int aid;
429 458
430 if (sdata->local->num_sta >= MESH_MAX_PLINKS) 459 if (sdata->local->num_sta >= MESH_MAX_PLINKS)
431 return NULL; 460 return NULL;
432 461
462 aid = mesh_allocate_aid(sdata);
463 if (aid < 0)
464 return NULL;
465
433 sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); 466 sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
434 if (!sta) 467 if (!sta)
435 return NULL; 468 return NULL;
436 469
437 sta->mesh->plink_state = NL80211_PLINK_LISTEN; 470 sta->mesh->plink_state = NL80211_PLINK_LISTEN;
438 sta->sta.wme = true; 471 sta->sta.wme = true;
472 sta->sta.aid = aid;
439 473
440 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); 474 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
441 sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); 475 sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
@@ -659,8 +693,6 @@ static u16 mesh_get_new_llid(struct ieee80211_sub_if_data *sdata)
659 693
660 do { 694 do {
661 get_random_bytes(&llid, sizeof(llid)); 695 get_random_bytes(&llid, sizeof(llid));
662 /* for mesh PS we still only have the AID range for TIM bits */
663 llid = (llid % IEEE80211_MAX_AID) + 1;
664 } while (llid_in_use(sdata, llid)); 696 } while (llid_in_use(sdata, llid));
665 697
666 return llid; 698 return llid;
@@ -1069,7 +1101,6 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
1069 goto unlock_rcu; 1101 goto unlock_rcu;
1070 } 1102 }
1071 sta->mesh->plid = plid; 1103 sta->mesh->plid = plid;
1072 sta->sta.aid = plid;
1073 } else if (!sta && event == OPN_RJCT) { 1104 } else if (!sta && event == OPN_RJCT) {
1074 mesh_plink_frame_tx(sdata, NULL, WLAN_SP_MESH_PEERING_CLOSE, 1105 mesh_plink_frame_tx(sdata, NULL, WLAN_SP_MESH_PEERING_CLOSE,
1075 mgmt->sa, 0, plid, 1106 mgmt->sa, 0, plid,
@@ -1082,10 +1113,8 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
1082 1113
1083 if (event == CNF_ACPT) { 1114 if (event == CNF_ACPT) {
1084 /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */ 1115 /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */
1085 if (!sta->mesh->plid) { 1116 if (!sta->mesh->plid)
1086 sta->mesh->plid = plid; 1117 sta->mesh->plid = plid;
1087 sta->sta.aid = sta->mesh->plid;
1088 }
1089 1118
1090 sta->mesh->aid = get_unaligned_le16(PLINK_CNF_AID(mgmt)); 1119 sta->mesh->aid = get_unaligned_le16(PLINK_CNF_AID(mgmt));
1091 } 1120 }