forked from Minki/linux
mac80211: fix the mesh channel switch support
Mesh STA receiving the mesh CSA action frame is not able to trigger the mesh channel switch due to the incorrect handling and comparison of mesh channel switch parameters element (MCSP)'s TTL. Make sure the MCSP's TTL is updated accordingly before calling the ieee80211_mesh_process_chnswitch. Also, we update the beacon before forwarding the CSA action frame, so MCSP's precedence value and initiator flag need to be updated prior to this. Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
051a41fa4e
commit
3f718fd840
@ -3119,9 +3119,17 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
params->chandef.chan->band)
|
||||
return -EINVAL;
|
||||
|
||||
ifmsh->chsw_init = true;
|
||||
if (!ifmsh->pre_value)
|
||||
ifmsh->pre_value = 1;
|
||||
else
|
||||
ifmsh->pre_value++;
|
||||
|
||||
err = ieee80211_mesh_csa_beacon(sdata, params, true);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
ifmsh->chsw_init = false;
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -1228,6 +1228,7 @@ struct ieee80211_csa_ie {
|
||||
u8 mode;
|
||||
u8 count;
|
||||
u8 ttl;
|
||||
u16 pre_value;
|
||||
};
|
||||
|
||||
/* Parsed Information Elements */
|
||||
|
@ -943,14 +943,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
|
||||
params.chandef.chan->center_freq);
|
||||
|
||||
params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
|
||||
if (beacon)
|
||||
if (beacon) {
|
||||
ifmsh->chsw_ttl = csa_ie.ttl - 1;
|
||||
else
|
||||
ifmsh->chsw_ttl = 0;
|
||||
if (ifmsh->pre_value >= csa_ie.pre_value)
|
||||
return false;
|
||||
ifmsh->pre_value = csa_ie.pre_value;
|
||||
}
|
||||
|
||||
if (ifmsh->chsw_ttl > 0)
|
||||
if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
|
||||
if (ieee80211_mesh_csa_beacon(sdata, ¶ms, false) < 0)
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
sdata->csa_radar_required = params.radar_required;
|
||||
|
||||
@ -1163,7 +1168,6 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
|
||||
offset_ttl = (len < 42) ? 7 : 10;
|
||||
*(pos + offset_ttl) -= 1;
|
||||
*(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
|
||||
sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
|
||||
|
||||
memcpy(mgmt_fwd, mgmt, len);
|
||||
eth_broadcast_addr(mgmt_fwd->da);
|
||||
@ -1182,7 +1186,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
|
||||
u16 pre_value;
|
||||
bool fwd_csa = true;
|
||||
size_t baselen;
|
||||
u8 *pos, ttl;
|
||||
u8 *pos;
|
||||
|
||||
if (mgmt->u.action.u.measurement.action_code !=
|
||||
WLAN_ACTION_SPCT_CHL_SWITCH)
|
||||
@ -1193,8 +1197,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
|
||||
u.action.u.chan_switch.variable);
|
||||
ieee802_11_parse_elems(pos, len - baselen, false, &elems);
|
||||
|
||||
ttl = elems.mesh_chansw_params_ie->mesh_ttl;
|
||||
if (!--ttl)
|
||||
ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
|
||||
if (!--ifmsh->chsw_ttl)
|
||||
fwd_csa = false;
|
||||
|
||||
pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
|
||||
|
@ -78,6 +78,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
|
||||
if (elems->mesh_chansw_params_ie) {
|
||||
csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
|
||||
csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
|
||||
csa_ie->pre_value = le16_to_cpu(
|
||||
elems->mesh_chansw_params_ie->mesh_pre_value);
|
||||
}
|
||||
|
||||
new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
|
||||
|
@ -2457,14 +2457,9 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
||||
WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
|
||||
put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
|
||||
pos += 2;
|
||||
if (!ifmsh->pre_value)
|
||||
ifmsh->pre_value = 1;
|
||||
else
|
||||
ifmsh->pre_value++;
|
||||
pre_value = cpu_to_le16(ifmsh->pre_value);
|
||||
memcpy(pos, &pre_value, 2); /* Precedence Value */
|
||||
pos += 2;
|
||||
ifmsh->chsw_init = true;
|
||||
}
|
||||
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
|
Loading…
Reference in New Issue
Block a user