|
@@ -422,20 +422,54 @@ out:
|
|
|
spin_unlock_bh(&sta->mesh->plink_lock);
|
|
|
}
|
|
|
|
|
|
+static int mesh_allocate_aid(struct ieee80211_sub_if_data *sdata)
|
|
|
+{
|
|
|
+ struct sta_info *sta;
|
|
|
+ unsigned long *aid_map;
|
|
|
+ int aid;
|
|
|
+
|
|
|
+ aid_map = kcalloc(BITS_TO_LONGS(IEEE80211_MAX_AID + 1),
|
|
|
+ sizeof(*aid_map), GFP_KERNEL);
|
|
|
+ if (!aid_map)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ /* reserve aid 0 for mcast indication */
|
|
|
+ __set_bit(0, aid_map);
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ list_for_each_entry_rcu(sta, &sdata->local->sta_list, list)
|
|
|
+ __set_bit(sta->sta.aid, aid_map);
|
|
|
+ rcu_read_unlock();
|
|
|
+
|
|
|
+ aid = find_first_zero_bit(aid_map, IEEE80211_MAX_AID + 1);
|
|
|
+ kfree(aid_map);
|
|
|
+
|
|
|
+ if (aid > IEEE80211_MAX_AID)
|
|
|
+ return -ENOBUFS;
|
|
|
+
|
|
|
+ return aid;
|
|
|
+}
|
|
|
+
|
|
|
static struct sta_info *
|
|
|
__mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
|
|
|
{
|
|
|
struct sta_info *sta;
|
|
|
+ int aid;
|
|
|
|
|
|
if (sdata->local->num_sta >= MESH_MAX_PLINKS)
|
|
|
return NULL;
|
|
|
|
|
|
+ aid = mesh_allocate_aid(sdata);
|
|
|
+ if (aid < 0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
|
|
|
if (!sta)
|
|
|
return NULL;
|
|
|
|
|
|
sta->mesh->plink_state = NL80211_PLINK_LISTEN;
|
|
|
sta->sta.wme = true;
|
|
|
+ sta->sta.aid = aid;
|
|
|
|
|
|
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
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)
|
|
|
|
|
|
do {
|
|
|
get_random_bytes(&llid, sizeof(llid));
|
|
|
- /* for mesh PS we still only have the AID range for TIM bits */
|
|
|
- llid = (llid % IEEE80211_MAX_AID) + 1;
|
|
|
} while (llid_in_use(sdata, llid));
|
|
|
|
|
|
return llid;
|
|
@@ -1069,7 +1101,6 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
|
|
|
goto unlock_rcu;
|
|
|
}
|
|
|
sta->mesh->plid = plid;
|
|
|
- sta->sta.aid = plid;
|
|
|
} else if (!sta && event == OPN_RJCT) {
|
|
|
mesh_plink_frame_tx(sdata, NULL, WLAN_SP_MESH_PEERING_CLOSE,
|
|
|
mgmt->sa, 0, plid,
|
|
@@ -1082,10 +1113,8 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
if (event == CNF_ACPT) {
|
|
|
/* 802.11-2012 13.3.7.2 - update plid on CNF if not set */
|
|
|
- if (!sta->mesh->plid) {
|
|
|
+ if (!sta->mesh->plid)
|
|
|
sta->mesh->plid = plid;
|
|
|
- sta->sta.aid = sta->mesh->plid;
|
|
|
- }
|
|
|
|
|
|
sta->mesh->aid = get_unaligned_le16(PLINK_CNF_AID(mgmt));
|
|
|
}
|