Commit 3b144658 authored by Thomas Pedersen's avatar Thomas Pedersen Committed by Johannes Berg

mac80211: dynamic short slot time for MBSSs

The standard mandates mesh STAs to set the ERP Short Slot
Time capability info bit in beacons to 0. Even though this
is their way of disallowing short slot time for mesh STAs,
there should be no harm in enabling it if we determine all
STAs in the current MBSS support ERP rates.

Increases throughput about 20% for legacy rates when
enabled.
Signed-off-by: default avatarThomas Pedersen <thomas@cozybit.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 8dcf011a
...@@ -629,11 +629,6 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -629,11 +629,6 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
sdata->vif.bss_conf.basic_rates = sdata->vif.bss_conf.basic_rates =
ieee80211_mandatory_rates(local, band); ieee80211_mandatory_rates(local, band);
if (band == IEEE80211_BAND_5GHZ) {
sdata->vif.bss_conf.use_short_slot = true;
changed |= BSS_CHANGED_ERP_SLOT;
}
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
netif_carrier_on(sdata->dev); netif_carrier_on(sdata->dev);
......
...@@ -55,6 +55,66 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) ...@@ -55,6 +55,66 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta)
sta->plink_retries = 0; sta->plink_retries = 0;
} }
/*
* mesh_set_short_slot_time - enable / disable ERP short slot time.
*
* The standard indirectly mandates mesh STAs to turn off short slot time by
* disallowing advertising this (802.11-2012 8.4.1.4), but that doesn't mean we
* can't be sneaky about it. Enable short slot time if all mesh STAs in the
* MBSS support ERP rates.
*
* Returns BSS_CHANGED_ERP_SLOT or 0 for no change.
*/
static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
struct sta_info *sta;
u32 erp_rates = 0, changed = 0;
int i;
bool short_slot = false;
if (band == IEEE80211_BAND_5GHZ) {
/* (IEEE 802.11-2012 19.4.5) */
short_slot = true;
goto out;
} else if (band != IEEE80211_BAND_2GHZ ||
(band == IEEE80211_BAND_2GHZ &&
local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
goto out;
for (i = 0; i < sband->n_bitrates; i++)
if (sband->bitrates[i].flags & IEEE80211_RATE_ERP_G)
erp_rates |= BIT(i);
if (!erp_rates)
goto out;
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list) {
if (sdata != sta->sdata ||
sta->plink_state != NL80211_PLINK_ESTAB)
continue;
short_slot = false;
if (erp_rates & sta->sta.supp_rates[band])
short_slot = true;
else
break;
}
rcu_read_unlock();
out:
if (sdata->vif.bss_conf.use_short_slot != short_slot) {
sdata->vif.bss_conf.use_short_slot = short_slot;
changed = BSS_CHANGED_ERP_SLOT;
mpl_dbg(sdata, "mesh_plink %pM: ERP short slot time %d\n",
sdata->vif.addr, short_slot);
}
return changed;
}
/** /**
* mesh_set_ht_prot_mode - set correct HT protection mode * mesh_set_ht_prot_mode - set correct HT protection mode
* *
...@@ -896,6 +956,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -896,6 +956,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_plink_inc_estab_count(sdata);
changed |= mesh_set_ht_prot_mode(sdata); changed |= mesh_set_ht_prot_mode(sdata);
changed |= mesh_set_short_slot_time(sdata);
mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr); sta->sta.addr);
break; break;
...@@ -931,6 +992,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -931,6 +992,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_plink_inc_estab_count(sdata);
changed |= mesh_set_ht_prot_mode(sdata); changed |= mesh_set_ht_prot_mode(sdata);
changed |= mesh_set_short_slot_time(sdata);
mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr); sta->sta.addr);
mesh_plink_frame_tx(sdata, mesh_plink_frame_tx(sdata,
...@@ -954,6 +1016,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -954,6 +1016,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
changed |= mesh_set_ht_prot_mode(sdata); changed |= mesh_set_ht_prot_mode(sdata);
changed |= mesh_set_short_slot_time(sdata);
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
sta->sta.addr, llid, plid, reason); sta->sta.addr, llid, plid, reason);
break; break;
......
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