aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2013-11-05 14:17:05 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 14:50:29 -0500
commit204d130426206071b08c0aa74002fbdb67960eed (patch)
treec1f4a7788bba2b3afe9c5df2254995231daefc9c /net/mac80211
parentc99a89edb1066e4c1f79b3ca4e91a676d1b25ce1 (diff)
mac80211: clean up mesh local link ID generation
802.11-2012 13.3.1 implicitly limits the mesh local link ID range to that of AID, since for mesh PS the local link ID must be indicated in the TIM IE, which only holds IEEE80211_MAX_AID bits. Also the code was allowing a local link ID of 0, but this is not correct since that TIM bit is used for indicating buffered mcast frames. Generate a random, unique, link ID from 1 - 2007, and drop a modulo conversion for the local link ID, but keep it for the peer link ID in case he chose something > MAX_AID. Signed-off-by: Thomas Pedersen <thomas@cozybit.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/mesh_plink.c40
-rw-r--r--net/mac80211/mesh_ps.c3
-rw-r--r--net/mac80211/sta_info.c4
3 files changed, 38 insertions, 9 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index ee2a97f31732..fadc3e189131 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -615,9 +615,40 @@ static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
615 add_timer(&sta->plink_timer); 615 add_timer(&sta->plink_timer);
616} 616}
617 617
618static bool llid_in_use(struct ieee80211_sub_if_data *sdata,
619 __le16 llid)
620{
621 struct ieee80211_local *local = sdata->local;
622 bool in_use = false;
623 struct sta_info *sta;
624
625 rcu_read_lock();
626 list_for_each_entry_rcu(sta, &local->sta_list, list) {
627 if (!memcmp(&sta->llid, &llid, sizeof(llid))) {
628 in_use = true;
629 break;
630 }
631 }
632 rcu_read_unlock();
633
634 return in_use;
635}
636
637static __le16 mesh_get_new_llid(struct ieee80211_sub_if_data *sdata)
638{
639 u16 llid;
640
641 do {
642 get_random_bytes(&llid, sizeof(llid));
643 /* for mesh PS we still only have the AID range for TIM bits */
644 llid = (llid % IEEE80211_MAX_AID) + 1;
645 } while (llid_in_use(sdata, cpu_to_le16(llid)));
646
647 return cpu_to_le16(llid);
648}
649
618u32 mesh_plink_open(struct sta_info *sta) 650u32 mesh_plink_open(struct sta_info *sta)
619{ 651{
620 __le16 llid;
621 struct ieee80211_sub_if_data *sdata = sta->sdata; 652 struct ieee80211_sub_if_data *sdata = sta->sdata;
622 u32 changed; 653 u32 changed;
623 654
@@ -625,8 +656,7 @@ u32 mesh_plink_open(struct sta_info *sta)
625 return 0; 656 return 0;
626 657
627 spin_lock_bh(&sta->lock); 658 spin_lock_bh(&sta->lock);
628 get_random_bytes(&llid, 2); 659 sta->llid = mesh_get_new_llid(sdata);
629 sta->llid = llid;
630 if (sta->plink_state != NL80211_PLINK_LISTEN && 660 if (sta->plink_state != NL80211_PLINK_LISTEN &&
631 sta->plink_state != NL80211_PLINK_BLOCKED) { 661 sta->plink_state != NL80211_PLINK_BLOCKED) {
632 spin_unlock_bh(&sta->lock); 662 spin_unlock_bh(&sta->lock);
@@ -643,7 +673,7 @@ u32 mesh_plink_open(struct sta_info *sta)
643 changed = ieee80211_mps_local_status_update(sdata); 673 changed = ieee80211_mps_local_status_update(sdata);
644 674
645 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, 675 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
646 sta->sta.addr, llid, 0, 0); 676 sta->sta.addr, sta->llid, 0, 0);
647 return changed; 677 return changed;
648} 678}
649 679
@@ -719,7 +749,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata,
719 break; 749 break;
720 case OPN_ACPT: 750 case OPN_ACPT:
721 sta->plink_state = NL80211_PLINK_OPN_RCVD; 751 sta->plink_state = NL80211_PLINK_OPN_RCVD;
722 get_random_bytes(&sta->llid, 2); 752 sta->llid = mesh_get_new_llid(sdata);
723 mesh_plink_timer_set(sta, 753 mesh_plink_timer_set(sta,
724 mshcfg->dot11MeshRetryTimeout); 754 mshcfg->dot11MeshRetryTimeout);
725 755
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c
index 0f79b78b5e86..9493868ef6c3 100644
--- a/net/mac80211/mesh_ps.c
+++ b/net/mac80211/mesh_ps.c
@@ -576,10 +576,9 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
576 int ac, buffer_local = 0; 576 int ac, buffer_local = 0;
577 bool has_buffered = false; 577 bool has_buffered = false;
578 578
579 /* TIM map only for LLID <= IEEE80211_MAX_AID */
580 if (sta->plink_state == NL80211_PLINK_ESTAB) 579 if (sta->plink_state == NL80211_PLINK_ESTAB)
581 has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len, 580 has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len,
582 le16_to_cpu(sta->llid) % IEEE80211_MAX_AID); 581 le16_to_cpu(sta->llid));
583 582
584 if (has_buffered) 583 if (has_buffered)
585 mps_dbg(sta->sdata, "%pM indicates buffered frames\n", 584 mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 1eb66e26e49d..7a9151590cce 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -630,8 +630,8 @@ void sta_info_recalc_tim(struct sta_info *sta)
630#ifdef CONFIG_MAC80211_MESH 630#ifdef CONFIG_MAC80211_MESH
631 } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { 631 } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) {
632 ps = &sta->sdata->u.mesh.ps; 632 ps = &sta->sdata->u.mesh.ps;
633 /* TIM map only for PLID <= IEEE80211_MAX_AID */ 633 /* TIM map only for 1 <= PLID <= IEEE80211_MAX_AID */
634 id = le16_to_cpu(sta->plid) % IEEE80211_MAX_AID; 634 id = le16_to_cpu(sta->plid) % (IEEE80211_MAX_AID + 1);
635#endif 635#endif
636 } else { 636 } else {
637 return; 637 return;