Commit 3f718fd8 authored by Chun-Yeow Yeoh's avatar Chun-Yeow Yeoh Committed by Johannes Berg

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: default avatarChun-Yeow Yeoh <yeohchunyeow@gmail.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 051a41fa
...@@ -3119,9 +3119,17 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, ...@@ -3119,9 +3119,17 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
params->chandef.chan->band) params->chandef.chan->band)
return -EINVAL; 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); err = ieee80211_mesh_csa_beacon(sdata, params, true);
if (err < 0) if (err < 0) {
ifmsh->chsw_init = false;
return err; return err;
}
break; break;
#endif #endif
default: default:
......
...@@ -1228,6 +1228,7 @@ struct ieee80211_csa_ie { ...@@ -1228,6 +1228,7 @@ struct ieee80211_csa_ie {
u8 mode; u8 mode;
u8 count; u8 count;
u8 ttl; u8 ttl;
u16 pre_value;
}; };
/* Parsed Information Elements */ /* Parsed Information Elements */
......
...@@ -943,14 +943,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, ...@@ -943,14 +943,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
params.chandef.chan->center_freq); params.chandef.chan->center_freq);
params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT; params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
if (beacon) if (beacon) {
ifmsh->chsw_ttl = csa_ie.ttl - 1; ifmsh->chsw_ttl = csa_ie.ttl - 1;
else if (ifmsh->pre_value >= csa_ie.pre_value)
ifmsh->chsw_ttl = 0; 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, &params, false) < 0) if (ieee80211_mesh_csa_beacon(sdata, &params, false) < 0)
return false; return false;
} else {
return false;
}
sdata->csa_radar_required = params.radar_required; sdata->csa_radar_required = params.radar_required;
...@@ -1163,7 +1168,6 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, ...@@ -1163,7 +1168,6 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
offset_ttl = (len < 42) ? 7 : 10; offset_ttl = (len < 42) ? 7 : 10;
*(pos + offset_ttl) -= 1; *(pos + offset_ttl) -= 1;
*(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
memcpy(mgmt_fwd, mgmt, len); memcpy(mgmt_fwd, mgmt, len);
eth_broadcast_addr(mgmt_fwd->da); eth_broadcast_addr(mgmt_fwd->da);
...@@ -1182,7 +1186,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, ...@@ -1182,7 +1186,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
u16 pre_value; u16 pre_value;
bool fwd_csa = true; bool fwd_csa = true;
size_t baselen; size_t baselen;
u8 *pos, ttl; u8 *pos;
if (mgmt->u.action.u.measurement.action_code != if (mgmt->u.action.u.measurement.action_code !=
WLAN_ACTION_SPCT_CHL_SWITCH) WLAN_ACTION_SPCT_CHL_SWITCH)
...@@ -1193,8 +1197,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, ...@@ -1193,8 +1197,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
u.action.u.chan_switch.variable); u.action.u.chan_switch.variable);
ieee802_11_parse_elems(pos, len - baselen, false, &elems); ieee802_11_parse_elems(pos, len - baselen, false, &elems);
ttl = elems.mesh_chansw_params_ie->mesh_ttl; ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
if (!--ttl) if (!--ifmsh->chsw_ttl)
fwd_csa = false; fwd_csa = false;
pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value); 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, ...@@ -78,6 +78,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
if (elems->mesh_chansw_params_ie) { if (elems->mesh_chansw_params_ie) {
csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl; csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags; 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); 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, ...@@ -2457,14 +2457,9 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00; WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */ put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
pos += 2; pos += 2;
if (!ifmsh->pre_value)
ifmsh->pre_value = 1;
else
ifmsh->pre_value++;
pre_value = cpu_to_le16(ifmsh->pre_value); pre_value = cpu_to_le16(ifmsh->pre_value);
memcpy(pos, &pre_value, 2); /* Precedence Value */ memcpy(pos, &pre_value, 2); /* Precedence Value */
pos += 2; pos += 2;
ifmsh->chsw_init = true;
} }
ieee80211_tx_skb(sdata, skb); ieee80211_tx_skb(sdata, skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment