summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 896fe3bd599e..5b919cab1de0 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -259,6 +259,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
*pos++ = WLAN_EID_MESH_CONFIG;
*pos++ = meshconf_len;
+ /* save a pointer for quick updates in pre-tbtt */
+ ifmsh->meshconf_offset = pos - skb->data;
+
/* Active path selection protocol ID */
*pos++ = ifmsh->mesh_pp_id;
/* Active path selection metric ID */
@@ -674,8 +677,6 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
rcu_read_lock();
csa = rcu_dereference(ifmsh->csa);
if (csa) {
- __le16 pre_value;
-
pos = skb_put(skb, 13);
memset(pos, 0, 13);
*pos++ = WLAN_EID_CHANNEL_SWITCH;
@@ -697,8 +698,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos);
pos += 2;
- pre_value = cpu_to_le16(ifmsh->pre_value);
- memcpy(pos, &pre_value, 2);
+ put_unaligned_le16(ifmsh->pre_value, pos);
pos += 2;
}
rcu_read_unlock();
@@ -726,6 +726,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
bcn->tail_len = skb->len;
memcpy(bcn->tail, skb->data, bcn->tail_len);
+ bcn->meshconf = (struct ieee80211_meshconf_ie *)
+ (bcn->tail + ifmsh->meshconf_offset);
dev_kfree_skb(skb);
rcu_assign_pointer(ifmsh->beacon, bcn);
@@ -805,6 +807,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
return -ENOMEM;
}
+ ieee80211_recalc_dtim(local, sdata);
ieee80211_bss_info_change_notify(sdata, changed);
netif_carrier_on(sdata->dev);
@@ -943,14 +946,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, &params, false) < 0)
return false;
+ } else {
+ return false;
+ }
sdata->csa_radar_required = params.radar_required;
@@ -959,7 +967,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->local->csa_chandef = params.chandef;
+ sdata->csa_chandef = params.chandef;
sdata->vif.csa_active = true;
ieee80211_bss_info_change_notify(sdata, err);
@@ -1163,7 +1171,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 +1189,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 +1200,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);