diff options
Diffstat (limited to 'net/mac80211/mesh_plink.c')
| -rw-r--r-- | net/mac80211/mesh_plink.c | 134 |
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 | ||
| 40 | static 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 | |||
| 50 | static 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 | |||
| 40 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 62 | static 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 | } |
| 161 | out: | ||
| 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 | ||
| 233 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 247 | static 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 | ||
| 669 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, | 678 | void 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) { |
