summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;