mac80211: mesh: separate plid and aid concepts
authorBob Copeland <me@bobcopeland.com>
Tue, 14 Jul 2015 12:31:58 +0000 (08:31 -0400)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 17 Jul 2015 13:47:11 +0000 (15:47 +0200)
According to 802.11-2012 13.3.1, a mesh STA should assign an AID
upon receipt of a mesh peering open frame rather than using the link
id of the peer.  Using the peer link id has two potential issues:
it may not be unique among the peers, and by its nature it is random,
so the TIM may not compress well.

In preparation for allocating it properly, use sta->sta.aid, but keep
the existing behavior of using the plid in the aid we send.

Signed-off-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mesh_plink.c
net/mac80211/mesh_ps.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h

index a5aa0345dd7e17dbf6f8dbd3efb60be717d80988..3323413acb77b082bb26a4d6e297bc729cd0092c 100644 (file)
@@ -13,6 +13,7 @@
 #include "rate.h"
 #include "mesh.h"
 
+#define PLINK_CNF_AID(mgmt) ((mgmt)->u.action.u.self_prot.variable + 2)
 #define PLINK_GET_LLID(p) (p + 2)
 #define PLINK_GET_PLID(p) (p + 4)
 
@@ -200,6 +201,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
 }
 
 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
+                              struct sta_info *sta,
                               enum ieee80211_self_protected_actioncode action,
                               u8 *da, u16 llid, u16 plid, u16 reason)
 {
@@ -249,7 +251,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
                        /* AID */
                        pos = skb_put(skb, 2);
-                       put_unaligned_le16(plid, pos);
+                       put_unaligned_le16(sta->sta.aid, pos);
                }
                if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
                    ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
@@ -362,7 +364,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta)
        spin_lock_bh(&sta->mesh->plink_lock);
        changed = __mesh_plink_deactivate(sta);
        sta->mesh->reason = WLAN_REASON_MESH_PEER_CANCELED;
-       mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
+       mesh_plink_frame_tx(sdata, sta, WLAN_SP_MESH_PEERING_CLOSE,
                            sta->sta.addr, sta->mesh->llid, sta->mesh->plid,
                            sta->mesh->reason);
        spin_unlock_bh(&sta->mesh->plink_lock);
@@ -619,7 +621,7 @@ static void mesh_plink_timer(unsigned long data)
        }
        spin_unlock_bh(&sta->mesh->plink_lock);
        if (action)
-               mesh_plink_frame_tx(sdata, action, sta->sta.addr,
+               mesh_plink_frame_tx(sdata, sta, action, sta->sta.addr,
                                    sta->mesh->llid, sta->mesh->plid, reason);
 }
 
@@ -689,7 +691,7 @@ u32 mesh_plink_open(struct sta_info *sta)
        /* set the non-peer mode to active during peering */
        changed = ieee80211_mps_local_status_update(sdata);
 
-       mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
+       mesh_plink_frame_tx(sdata, sta, WLAN_SP_MESH_PEERING_OPEN,
                            sta->sta.addr, sta->mesh->llid, 0, 0);
        return changed;
 }
@@ -871,13 +873,13 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata,
        }
        spin_unlock_bh(&sta->mesh->plink_lock);
        if (action) {
-               mesh_plink_frame_tx(sdata, action, sta->sta.addr,
+               mesh_plink_frame_tx(sdata, sta, action, sta->sta.addr,
                                    sta->mesh->llid, sta->mesh->plid,
                                    sta->mesh->reason);
 
                /* also send confirm in open case */
                if (action == WLAN_SP_MESH_PEERING_OPEN) {
-                       mesh_plink_frame_tx(sdata,
+                       mesh_plink_frame_tx(sdata, sta,
                                            WLAN_SP_MESH_PEERING_CONFIRM,
                                            sta->sta.addr, sta->mesh->llid,
                                            sta->mesh->plid, 0);
@@ -1067,8 +1069,9 @@ 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, WLAN_SP_MESH_PEERING_CLOSE,
+               mesh_plink_frame_tx(sdata, NULL, WLAN_SP_MESH_PEERING_CLOSE,
                                    mgmt->sa, 0, plid,
                                    WLAN_REASON_MESH_CONFIG);
                goto unlock_rcu;
@@ -1077,9 +1080,15 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
                goto unlock_rcu;
        }
 
-       /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */
-       if (!sta->mesh->plid && event == CNF_ACPT)
-               sta->mesh->plid = plid;
+       if (event == CNF_ACPT) {
+               /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */
+               if (!sta->mesh->plid) {
+                       sta->mesh->plid = plid;
+                       sta->sta.aid = sta->mesh->plid;
+               }
+
+               sta->mesh->aid = get_unaligned_le16(PLINK_CNF_AID(mgmt));
+       }
 
        changed |= mesh_plink_fsm(sdata, sta, event);
 
index 29747f92b9b02a34648b300edd3750d03052ee13..90a268abea171aebc5d5907929db0804a2b0f7b0 100644 (file)
@@ -579,7 +579,7 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
 
        if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
                has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len,
-                                                  sta->mesh->llid);
+                                                  sta->mesh->aid);
 
        if (has_buffered)
                mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
index 9da7d2bc271ac7586e5dcb8656bde7cd244229ae..70cd9fa57424579d16514725c95f6c55d0f7b8aa 100644 (file)
@@ -635,7 +635,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
        bool indicate_tim = false;
        u8 ignore_for_tim = sta->sta.uapsd_queues;
        int ac;
-       u16 id;
+       u16 id = sta->sta.aid;
 
        if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
            sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
@@ -643,12 +643,9 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
                        return;
 
                ps = &sta->sdata->bss->ps;
-               id = sta->sta.aid;
 #ifdef CONFIG_MAC80211_MESH
        } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) {
                ps = &sta->sdata->u.mesh.ps;
-               /* TIM map only for 1 <= PLID <= IEEE80211_MAX_AID */
-               id = sta->mesh->plid % (IEEE80211_MAX_AID + 1);
 #endif
        } else {
                return;
index 6dcb33484eac4901f6b71d85c4ff09f70084e03f..1d2805c598c055effac3698d324d095afa43d056 100644 (file)
@@ -277,6 +277,7 @@ struct ieee80211_fast_tx {
  * @plink_lock: serialize access to plink fields
  * @llid: Local link ID
  * @plid: Peer link ID
+ * @aid: local aid supplied by peer
  * @reason: Cancel reason on PLINK_HOLDING state
  * @plink_retries: Retries in establishment
  * @plink_state: peer link state
@@ -301,6 +302,7 @@ struct mesh_sta {
        spinlock_t plink_lock;
        u16 llid;
        u16 plid;
+       u16 aid;
        u16 reason;
        u8 plink_retries;