mac80211: mesh: support sending wide bandwidth CSA

To support HT and VHT CSA, beacons and action frames must include the
corresponding IEs.

Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
[make ieee80211_ie_build_wide_bw_cs() return void]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Simon Wunderlich 2017-05-23 17:00:42 +02:00 committed by Johannes Berg
parent 3b23782f7d
commit 75d627d53e
3 changed files with 82 additions and 2 deletions

View file

@ -690,6 +690,9 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
2 + sizeof(struct ieee80211_channel_sw_ie) +
/* Mesh Channel Switch Parameters */
2 + sizeof(struct ieee80211_mesh_chansw_params_ie) +
/* Channel Switch Wrapper + Wide Bandwidth CSA IE */
2 + 2 + sizeof(struct ieee80211_wide_bw_chansw_ie) +
2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
2 + 8 + /* supported rates */
2 + 3; /* DS params */
tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
@ -736,8 +739,13 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
rcu_read_lock();
csa = rcu_dereference(ifmsh->csa);
if (csa) {
pos = skb_put(skb, 13);
memset(pos, 0, 13);
enum nl80211_channel_type ct;
struct cfg80211_chan_def *chandef;
int ie_len = 2 + sizeof(struct ieee80211_channel_sw_ie) +
2 + sizeof(struct ieee80211_mesh_chansw_params_ie);
pos = skb_put(skb, ie_len);
memset(pos, 0, ie_len);
*pos++ = WLAN_EID_CHANNEL_SWITCH;
*pos++ = 3;
*pos++ = 0x0;
@ -760,6 +768,39 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
pos += 2;
put_unaligned_le16(ifmsh->pre_value, pos);
pos += 2;
switch (csa->settings.chandef.width) {
case NL80211_CHAN_WIDTH_40:
ie_len = 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
pos = skb_put(skb, ie_len);
memset(pos, 0, ie_len);
*pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
*pos++ = 1; /* len */
ct = cfg80211_get_chandef_type(&csa->settings.chandef);
if (ct == NL80211_CHAN_HT40PLUS)
*pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
else
*pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
break;
case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160:
/* Channel Switch Wrapper + Wide Bandwidth CSA IE */
ie_len = 2 + 2 +
sizeof(struct ieee80211_wide_bw_chansw_ie);
pos = skb_put(skb, ie_len);
memset(pos, 0, ie_len);
*pos++ = WLAN_EID_CHANNEL_SWITCH_WRAPPER; /* EID */
*pos++ = 5; /* len */
/* put sub IE */
chandef = &csa->settings.chandef;
ieee80211_ie_build_wide_bw_cs(pos, chandef);
break;
default:
break;
}
}
rcu_read_unlock();