aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_plink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r--net/mac80211/mesh_plink.c134
1 files changed, 67 insertions, 67 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index f7526e509aa8..07d396d57079 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -37,9 +37,31 @@ enum plink_event {
37 CLS_IGNR 37 CLS_IGNR
38}; 38};
39 39
40static const char * const mplstates[] = {
41 [NL80211_PLINK_LISTEN] = "LISTEN",
42 [NL80211_PLINK_OPN_SNT] = "OPN-SNT",
43 [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
44 [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD",
45 [NL80211_PLINK_ESTAB] = "ESTAB",
46 [NL80211_PLINK_HOLDING] = "HOLDING",
47 [NL80211_PLINK_BLOCKED] = "BLOCKED"
48};
49
50static const char * const mplevents[] = {
51 [PLINK_UNDEFINED] = "NONE",
52 [OPN_ACPT] = "OPN_ACPT",
53 [OPN_RJCT] = "OPN_RJCT",
54 [OPN_IGNR] = "OPN_IGNR",
55 [CNF_ACPT] = "CNF_ACPT",
56 [CNF_RJCT] = "CNF_RJCT",
57 [CNF_IGNR] = "CNF_IGNR",
58 [CLS_ACPT] = "CLS_ACPT",
59 [CLS_IGNR] = "CLS_IGNR"
60};
61
40static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 62static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
41 enum ieee80211_self_protected_actioncode action, 63 enum ieee80211_self_protected_actioncode action,
42 u8 *da, __le16 llid, __le16 plid, __le16 reason); 64 u8 *da, __le16 llid, __le16 plid, __le16 reason);
43 65
44/** 66/**
45 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine 67 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
@@ -129,7 +151,6 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
129{ 151{
130 struct ieee80211_local *local = sdata->local; 152 struct ieee80211_local *local = sdata->local;
131 struct sta_info *sta; 153 struct sta_info *sta;
132 u32 changed = 0;
133 u16 ht_opmode; 154 u16 ht_opmode;
134 bool non_ht_sta = false, ht20_sta = false; 155 bool non_ht_sta = false, ht20_sta = false;
135 156
@@ -142,23 +163,19 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
142 sta->plink_state != NL80211_PLINK_ESTAB) 163 sta->plink_state != NL80211_PLINK_ESTAB)
143 continue; 164 continue;
144 165
145 switch (sta->ch_width) { 166 if (sta->sta.bandwidth > IEEE80211_STA_RX_BW_20)
146 case NL80211_CHAN_WIDTH_20_NOHT: 167 continue;
147 mpl_dbg(sdata, 168
148 "mesh_plink %pM: nonHT sta (%pM) is present\n", 169 if (!sta->sta.ht_cap.ht_supported) {
149 sdata->vif.addr, sta->sta.addr); 170 mpl_dbg(sdata, "nonHT sta (%pM) is present\n",
171 sta->sta.addr);
150 non_ht_sta = true; 172 non_ht_sta = true;
151 goto out;
152 case NL80211_CHAN_WIDTH_20:
153 mpl_dbg(sdata,
154 "mesh_plink %pM: HT20 sta (%pM) is present\n",
155 sdata->vif.addr, sta->sta.addr);
156 ht20_sta = true;
157 default:
158 break; 173 break;
159 } 174 }
175
176 mpl_dbg(sdata, "HT20 sta (%pM) is present\n", sta->sta.addr);
177 ht20_sta = true;
160 } 178 }
161out:
162 rcu_read_unlock(); 179 rcu_read_unlock();
163 180
164 if (non_ht_sta) 181 if (non_ht_sta)
@@ -169,16 +186,13 @@ out:
169 else 186 else
170 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; 187 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
171 188
172 if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { 189 if (sdata->vif.bss_conf.ht_operation_mode == ht_opmode)
173 sdata->vif.bss_conf.ht_operation_mode = ht_opmode; 190 return 0;
174 sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
175 changed = BSS_CHANGED_HT;
176 mpl_dbg(sdata,
177 "mesh_plink %pM: protection mode changed to %d\n",
178 sdata->vif.addr, ht_opmode);
179 }
180 191
181 return changed; 192 sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
193 sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
194 mpl_dbg(sdata, "selected new HT protection mode %d\n", ht_opmode);
195 return BSS_CHANGED_HT;
182} 196}
183 197
184/** 198/**
@@ -231,8 +245,9 @@ u32 mesh_plink_deactivate(struct sta_info *sta)
231} 245}
232 246
233static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 247static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
234 enum ieee80211_self_protected_actioncode action, 248 enum ieee80211_self_protected_actioncode action,
235 u8 *da, __le16 llid, __le16 plid, __le16 reason) { 249 u8 *da, __le16 llid, __le16 plid, __le16 reason)
250{
236 struct ieee80211_local *local = sdata->local; 251 struct ieee80211_local *local = sdata->local;
237 struct sk_buff *skb; 252 struct sk_buff *skb;
238 struct ieee80211_tx_info *info; 253 struct ieee80211_tx_info *info;
@@ -283,13 +298,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
283 } 298 }
284 if (ieee80211_add_srates_ie(sdata, skb, true, band) || 299 if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
285 ieee80211_add_ext_srates_ie(sdata, skb, true, band) || 300 ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
286 mesh_add_rsn_ie(skb, sdata) || 301 mesh_add_rsn_ie(sdata, skb) ||
287 mesh_add_meshid_ie(skb, sdata) || 302 mesh_add_meshid_ie(sdata, skb) ||
288 mesh_add_meshconf_ie(skb, sdata)) 303 mesh_add_meshconf_ie(sdata, skb))
289 goto free; 304 goto free;
290 } else { /* WLAN_SP_MESH_PEERING_CLOSE */ 305 } else { /* WLAN_SP_MESH_PEERING_CLOSE */
291 info->flags |= IEEE80211_TX_CTL_NO_ACK; 306 info->flags |= IEEE80211_TX_CTL_NO_ACK;
292 if (mesh_add_meshid_ie(skb, sdata)) 307 if (mesh_add_meshid_ie(sdata, skb))
293 goto free; 308 goto free;
294 } 309 }
295 310
@@ -333,12 +348,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
333 } 348 }
334 349
335 if (action != WLAN_SP_MESH_PEERING_CLOSE) { 350 if (action != WLAN_SP_MESH_PEERING_CLOSE) {
336 if (mesh_add_ht_cap_ie(skb, sdata) || 351 if (mesh_add_ht_cap_ie(sdata, skb) ||
337 mesh_add_ht_oper_ie(skb, sdata)) 352 mesh_add_ht_oper_ie(sdata, skb))
338 goto free; 353 goto free;
339 } 354 }
340 355
341 if (mesh_add_vendor_ies(skb, sdata)) 356 if (mesh_add_vendor_ies(sdata, skb))
342 goto free; 357 goto free;
343 358
344 ieee80211_tx_skb(sdata, skb); 359 ieee80211_tx_skb(sdata, skb);
@@ -370,24 +385,18 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
370 if (sta->sta.supp_rates[band] != rates) 385 if (sta->sta.supp_rates[band] != rates)
371 changed |= IEEE80211_RC_SUPP_RATES_CHANGED; 386 changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
372 sta->sta.supp_rates[band] = rates; 387 sta->sta.supp_rates[band] = rates;
373 if (elems->ht_cap_elem &&
374 sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
375 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
376 elems->ht_cap_elem, sta);
377 else
378 memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
379 388
380 if (elems->ht_operation) { 389 if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
381 struct cfg80211_chan_def chandef; 390 elems->ht_cap_elem, sta))
391 changed |= IEEE80211_RC_BW_CHANGED;
382 392
383 if (!(elems->ht_operation->ht_param & 393 /* HT peer is operating 20MHz-only */
384 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) 394 if (elems->ht_operation &&
385 sta->sta.bandwidth = IEEE80211_STA_RX_BW_20; 395 !(elems->ht_operation->ht_param &
386 ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, 396 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
387 elems->ht_operation, &chandef); 397 if (sta->sta.bandwidth != IEEE80211_STA_RX_BW_20)
388 if (sta->ch_width != chandef.width)
389 changed |= IEEE80211_RC_BW_CHANGED; 398 changed |= IEEE80211_RC_BW_CHANGED;
390 sta->ch_width = chandef.width; 399 sta->sta.bandwidth = IEEE80211_STA_RX_BW_20;
391 } 400 }
392 401
393 if (insert) 402 if (insert)
@@ -666,8 +675,9 @@ u32 mesh_plink_block(struct sta_info *sta)
666} 675}
667 676
668 677
669void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, 678void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
670 size_t len, struct ieee80211_rx_status *rx_status) 679 struct ieee80211_mgmt *mgmt, size_t len,
680 struct ieee80211_rx_status *rx_status)
671{ 681{
672 struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; 682 struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
673 struct ieee802_11_elems elems; 683 struct ieee802_11_elems elems;
@@ -680,15 +690,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
680 u8 *baseaddr; 690 u8 *baseaddr;
681 u32 changed = 0; 691 u32 changed = 0;
682 __le16 plid, llid, reason; 692 __le16 plid, llid, reason;
683 static const char *mplstates[] = {
684 [NL80211_PLINK_LISTEN] = "LISTEN",
685 [NL80211_PLINK_OPN_SNT] = "OPN-SNT",
686 [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
687 [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD",
688 [NL80211_PLINK_ESTAB] = "ESTAB",
689 [NL80211_PLINK_HOLDING] = "HOLDING",
690 [NL80211_PLINK_BLOCKED] = "BLOCKED"
691 };
692 693
693 /* need action_code, aux */ 694 /* need action_code, aux */
694 if (len < IEEE80211_MIN_ACTION_SIZE + 3) 695 if (len < IEEE80211_MIN_ACTION_SIZE + 3)
@@ -708,13 +709,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
708 baselen += 4; 709 baselen += 4;
709 } 710 }
710 ieee802_11_parse_elems(baseaddr, len - baselen, &elems); 711 ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
712
711 if (!elems.peering) { 713 if (!elems.peering) {
712 mpl_dbg(sdata, 714 mpl_dbg(sdata,
713 "Mesh plink: missing necessary peer link ie\n"); 715 "Mesh plink: missing necessary peer link ie\n");
714 return; 716 return;
715 } 717 }
718
716 if (elems.rsn_len && 719 if (elems.rsn_len &&
717 sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { 720 sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
718 mpl_dbg(sdata, 721 mpl_dbg(sdata,
719 "Mesh plink: can't establish link with secure peer\n"); 722 "Mesh plink: can't establish link with secure peer\n");
720 return; 723 return;
@@ -733,7 +736,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
733 } 736 }
734 737
735 if (ftype != WLAN_SP_MESH_PEERING_CLOSE && 738 if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
736 (!elems.mesh_id || !elems.mesh_config)) { 739 (!elems.mesh_id || !elems.mesh_config)) {
737 mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); 740 mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
738 return; 741 return;
739 } 742 }
@@ -859,11 +862,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
859 } 862 }
860 } 863 }
861 864
862 mpl_dbg(sdata, 865 mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa,
863 "Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", 866 mplstates[sta->plink_state], mplevents[event]);
864 mgmt->sa, mplstates[sta->plink_state],
865 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
866 event);
867 reason = 0; 867 reason = 0;
868 spin_lock_bh(&sta->lock); 868 spin_lock_bh(&sta->lock);
869 switch (sta->plink_state) { 869 switch (sta->plink_state) {