@@ -1255,13 +1255,16 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
}
static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+ struct ieee80211_mgmt *mgmt, size_t len,
+ struct ieee802_11_elems *elems)
{
struct ieee80211_mgmt *mgmt_fwd;
struct sk_buff *skb;
struct ieee80211_local *local = sdata->local;
u8 *pos = mgmt->u.action.u.chan_switch.variable;
size_t offset_ttl;
+ /* mgmt hdr 24 + csa action 15 without sec offset and wide bw */
+ unsigned int basic_hdrlen = 39;
skb = dev_alloc_skb(local->tx_headroom + len);
if (!skb)
@@ -1269,11 +1272,17 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
skb_reserve(skb, local->tx_headroom);
mgmt_fwd = skb_put(skb, len);
+ if (ieee80211_has_order(mgmt->frame_control))
+ basic_hdrlen += 4;
+
+ if (elems->wide_bw_chansw_ie)
+ basic_hdrlen += 5;
+
/* offset_ttl is based on whether the secondary channel
* offset is available or not. Subtract 1 from the mesh TTL
* and disable the initiator flag before forwarding.
*/
- offset_ttl = (len < 42) ? 7 : 10;
+ offset_ttl = (len < basic_hdrlen) ? 7 : 10;
*(pos + offset_ttl) -= 1;
*(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
@@ -1323,7 +1332,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
/* forward or re-broadcast the CSA frame */
if (fwd_csa) {
- if (mesh_fwd_csa_frame(sdata, mgmt, len) < 0)
+ if (mesh_fwd_csa_frame(sdata, mgmt, len, &elems) < 0)
mcsa_dbg(sdata, "Failed to forward the CSA frame");
}
}