|
@@ -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();
|
|
|
|