aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c90
1 files changed, 54 insertions, 36 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index ff0296c7bab8..649ad513547f 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -76,7 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
76 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 76 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
77 struct ieee80211_local *local = sdata->local; 77 struct ieee80211_local *local = sdata->local;
78 u32 basic_rates = 0; 78 u32 basic_rates = 0;
79 enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT; 79 struct cfg80211_chan_def sta_chan_def;
80 80
81 /* 81 /*
82 * As support for each feature is added, check for matching 82 * As support for each feature is added, check for matching
@@ -97,23 +97,17 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
97 (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) 97 (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
98 goto mismatch; 98 goto mismatch;
99 99
100 ieee80211_sta_get_rates(local, ie, local->oper_channel->band, 100 ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata),
101 &basic_rates); 101 &basic_rates);
102 102
103 if (sdata->vif.bss_conf.basic_rates != basic_rates) 103 if (sdata->vif.bss_conf.basic_rates != basic_rates)
104 goto mismatch; 104 goto mismatch;
105 105
106 if (ie->ht_operation) 106 ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
107 sta_channel_type = 107 ie->ht_operation, &sta_chan_def);
108 ieee80211_ht_oper_to_channel_type(ie->ht_operation); 108
109 109 if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
110 /* Disallow HT40+/- mismatch */ 110 &sta_chan_def))
111 if (ie->ht_operation &&
112 (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS ||
113 sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) &&
114 (sta_channel_type == NL80211_CHAN_HT40MINUS ||
115 sta_channel_type == NL80211_CHAN_HT40PLUS) &&
116 sdata->vif.bss_conf.channel_type != sta_channel_type)
117 goto mismatch; 111 goto mismatch;
118 112
119 return true; 113 return true;
@@ -129,7 +123,7 @@ mismatch:
129bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) 123bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
130{ 124{
131 return (ie->mesh_config->meshconf_cap & 125 return (ie->mesh_config->meshconf_cap &
132 MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; 126 IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
133} 127}
134 128
135/** 129/**
@@ -169,7 +163,7 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
169 return -ENOMEM; 163 return -ENOMEM;
170 sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; 164 sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
171 for (i = 0; i < RMC_BUCKETS; i++) 165 for (i = 0; i < RMC_BUCKETS; i++)
172 INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); 166 INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]);
173 return 0; 167 return 0;
174} 168}
175 169
@@ -183,7 +177,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
183 return; 177 return;
184 178
185 for (i = 0; i < RMC_BUCKETS; i++) 179 for (i = 0; i < RMC_BUCKETS; i++)
186 list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { 180 list_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
187 list_del(&p->list); 181 list_del(&p->list);
188 kmem_cache_free(rm_cache, p); 182 kmem_cache_free(rm_cache, p);
189 } 183 }
@@ -216,7 +210,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
216 /* Don't care about endianness since only match matters */ 210 /* Don't care about endianness since only match matters */
217 memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); 211 memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
218 idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; 212 idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask;
219 list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { 213 list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
220 ++entries; 214 ++entries;
221 if (time_after(jiffies, p->exp_time) || 215 if (time_after(jiffies, p->exp_time) ||
222 (entries == RMC_QUEUE_MAX_LEN)) { 216 (entries == RMC_QUEUE_MAX_LEN)) {
@@ -235,7 +229,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
235 p->seqnum = seqnum; 229 p->seqnum = seqnum;
236 p->exp_time = jiffies + RMC_TIMEOUT; 230 p->exp_time = jiffies + RMC_TIMEOUT;
237 memcpy(p->sa, sa, ETH_ALEN); 231 memcpy(p->sa, sa, ETH_ALEN);
238 list_add(&p->list, &rmc->bucket[idx].list); 232 list_add(&p->list, &rmc->bucket[idx]);
239 return 0; 233 return 0;
240} 234}
241 235
@@ -264,16 +258,16 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
264 /* Authentication Protocol identifier */ 258 /* Authentication Protocol identifier */
265 *pos++ = ifmsh->mesh_auth_id; 259 *pos++ = ifmsh->mesh_auth_id;
266 /* Mesh Formation Info - number of neighbors */ 260 /* Mesh Formation Info - number of neighbors */
267 neighbors = atomic_read(&ifmsh->mshstats.estab_plinks); 261 neighbors = atomic_read(&ifmsh->estab_plinks);
268 /* Number of neighbor mesh STAs or 15 whichever is smaller */ 262 /* Number of neighbor mesh STAs or 15 whichever is smaller */
269 neighbors = (neighbors > 15) ? 15 : neighbors; 263 neighbors = (neighbors > 15) ? 15 : neighbors;
270 *pos++ = neighbors << 1; 264 *pos++ = neighbors << 1;
271 /* Mesh capability */ 265 /* Mesh capability */
272 *pos = MESHCONF_CAPAB_FORWARDING; 266 *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING;
273 *pos |= ifmsh->accepting_plinks ? 267 *pos |= ifmsh->accepting_plinks ?
274 MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; 268 IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
275 *pos++ |= ifmsh->adjusting_tbtt ? 269 *pos++ |= ifmsh->adjusting_tbtt ?
276 MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; 270 IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
277 *pos++ = 0x00; 271 *pos++ = 0x00;
278 272
279 return 0; 273 return 0;
@@ -355,12 +349,22 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
355{ 349{
356 struct ieee80211_local *local = sdata->local; 350 struct ieee80211_local *local = sdata->local;
357 struct ieee80211_supported_band *sband; 351 struct ieee80211_supported_band *sband;
358 struct ieee80211_channel *chan = local->oper_channel; 352 struct ieee80211_chanctx_conf *chanctx_conf;
353 struct ieee80211_channel *chan;
359 u8 *pos; 354 u8 *pos;
360 355
361 if (skb_tailroom(skb) < 3) 356 if (skb_tailroom(skb) < 3)
362 return -ENOMEM; 357 return -ENOMEM;
363 358
359 rcu_read_lock();
360 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
361 if (WARN_ON(!chanctx_conf)) {
362 rcu_read_unlock();
363 return -EINVAL;
364 }
365 chan = chanctx_conf->def.chan;
366 rcu_read_unlock();
367
364 sband = local->hw.wiphy->bands[chan->band]; 368 sband = local->hw.wiphy->bands[chan->band];
365 if (sband->band == IEEE80211_BAND_2GHZ) { 369 if (sband->band == IEEE80211_BAND_2GHZ) {
366 pos = skb_put(skb, 2 + 1); 370 pos = skb_put(skb, 2 + 1);
@@ -376,12 +380,13 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
376 struct ieee80211_sub_if_data *sdata) 380 struct ieee80211_sub_if_data *sdata)
377{ 381{
378 struct ieee80211_local *local = sdata->local; 382 struct ieee80211_local *local = sdata->local;
383 enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
379 struct ieee80211_supported_band *sband; 384 struct ieee80211_supported_band *sband;
380 u8 *pos; 385 u8 *pos;
381 386
382 sband = local->hw.wiphy->bands[local->oper_channel->band]; 387 sband = local->hw.wiphy->bands[band];
383 if (!sband->ht_cap.ht_supported || 388 if (!sband->ht_cap.ht_supported ||
384 sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) 389 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
385 return 0; 390 return 0;
386 391
387 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) 392 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
@@ -397,14 +402,26 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
397 struct ieee80211_sub_if_data *sdata) 402 struct ieee80211_sub_if_data *sdata)
398{ 403{
399 struct ieee80211_local *local = sdata->local; 404 struct ieee80211_local *local = sdata->local;
400 struct ieee80211_channel *channel = local->oper_channel; 405 struct ieee80211_chanctx_conf *chanctx_conf;
406 struct ieee80211_channel *channel;
401 enum nl80211_channel_type channel_type = 407 enum nl80211_channel_type channel_type =
402 sdata->vif.bss_conf.channel_type; 408 cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef);
403 struct ieee80211_supported_band *sband = 409 struct ieee80211_supported_band *sband;
404 local->hw.wiphy->bands[channel->band]; 410 struct ieee80211_sta_ht_cap *ht_cap;
405 struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
406 u8 *pos; 411 u8 *pos;
407 412
413 rcu_read_lock();
414 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
415 if (WARN_ON(!chanctx_conf)) {
416 rcu_read_unlock();
417 return -EINVAL;
418 }
419 channel = chanctx_conf->def.chan;
420 rcu_read_unlock();
421
422 sband = local->hw.wiphy->bands[channel->band];
423 ht_cap = &sband->ht_cap;
424
408 if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) 425 if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
409 return 0; 426 return 0;
410 427
@@ -412,7 +429,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
412 return -ENOMEM; 429 return -ENOMEM;
413 430
414 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); 431 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
415 ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type, 432 ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef,
416 sdata->vif.bss_conf.ht_operation_mode); 433 sdata->vif.bss_conf.ht_operation_mode);
417 434
418 return 0; 435 return 0;
@@ -610,7 +627,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
610 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; 627 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
611 sdata->vif.bss_conf.basic_rates = 628 sdata->vif.bss_conf.basic_rates =
612 ieee80211_mandatory_rates(sdata->local, 629 ieee80211_mandatory_rates(sdata->local,
613 sdata->local->oper_channel->band); 630 ieee80211_get_sdata_band(sdata));
614 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 631 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
615 BSS_CHANGED_BEACON_ENABLED | 632 BSS_CHANGED_BEACON_ENABLED |
616 BSS_CHANGED_HT | 633 BSS_CHANGED_HT |
@@ -680,8 +697,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
680 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, 697 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
681 &elems); 698 &elems);
682 699
683 /* ignore beacons from secure mesh peers if our security is off */ 700 /* ignore non-mesh or secure / unsecure mismatch */
684 if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) 701 if ((!elems.mesh_id || !elems.mesh_config) ||
702 (elems.rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
703 (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
685 return; 704 return;
686 705
687 if (elems.ds_params && elems.ds_params_len == 1) 706 if (elems.ds_params && elems.ds_params_len == 1)
@@ -694,8 +713,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
694 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) 713 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
695 return; 714 return;
696 715
697 if (elems.mesh_id && elems.mesh_config && 716 if (mesh_matches_local(sdata, &elems))
698 mesh_matches_local(sdata, &elems))
699 mesh_neighbour_update(sdata, mgmt->sa, &elems); 717 mesh_neighbour_update(sdata, mgmt->sa, &elems);
700 718
701 if (ifmsh->sync_ops) 719 if (ifmsh->sync_ops)