mac80211: TX legacy rate control for Beacon frames

Use the Beacon frame specific legacy rate configuration, if specified
for AP or mesh, instead of the generic rate mask when selecting the TX
rate for Beacon frames.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Link: https://lore.kernel.org/r/20200425155713.25687-4-jouni@codeaurora.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Jouni Malinen 2020-04-25 18:57:12 +03:00 committed by Johannes Berg
parent bedd7904e8
commit 08fad438be
4 changed files with 34 additions and 2 deletions

View file

@ -994,7 +994,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
BSS_CHANGED_TWT |
BSS_CHANGED_HE_OBSS_PD |
BSS_CHANGED_HE_BSS_COLOR;
int err;
int i, err;
int prev_beacon_int;
old = sdata_dereference(sdata->u.ap.beacon, sdata);
@ -1085,6 +1085,17 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
IEEE80211_P2P_OPPPS_ENABLE_BIT;
sdata->beacon_rate_set = false;
if (wiphy_ext_feature_isset(local->hw.wiphy,
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) {
for (i = 0; i < NUM_NL80211_BANDS; i++) {
sdata->beacon_rateidx_mask[i] =
params->beacon_rate.control[i].legacy;
if (sdata->beacon_rateidx_mask[i])
sdata->beacon_rate_set = true;
}
}
err = ieee80211_assign_beacon(sdata, &params->beacon, NULL);
if (err < 0) {
ieee80211_vif_release_channel(sdata);
@ -1189,6 +1200,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
ieee80211_free_keys(sdata, true);
sdata->vif.bss_conf.enable_beacon = false;
sdata->beacon_rate_set = false;
sdata->vif.bss_conf.ssid_len = 0;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
@ -1949,6 +1961,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
const u8 *old_ie;
struct ieee80211_sub_if_data *sdata = container_of(ifmsh,
struct ieee80211_sub_if_data, u.mesh);
int i;
/* allocate information elements */
new_ie = NULL;
@ -1987,6 +2000,17 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
sdata->vif.bss_conf.dtim_period = setup->dtim_period;
sdata->beacon_rate_set = false;
if (wiphy_ext_feature_isset(sdata->local->hw.wiphy,
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) {
for (i = 0; i < NUM_NL80211_BANDS; i++) {
sdata->beacon_rateidx_mask[i] =
setup->beacon_rate.control[i].legacy;
if (sdata->beacon_rateidx_mask[i])
sdata->beacon_rate_set = true;
}
}
return 0;
}

View file

@ -962,6 +962,10 @@ struct ieee80211_sub_if_data {
bool rc_has_vht_mcs_mask[NUM_NL80211_BANDS];
u16 rc_rateidx_vht_mcs_mask[NUM_NL80211_BANDS][NL80211_VHT_NSS_MAX];
/* Beacon frame (non-MCS) rate (as a bitmap) */
u32 beacon_rateidx_mask[NUM_NL80211_BANDS];
bool beacon_rate_set;
union {
struct ieee80211_if_ap ap;
struct ieee80211_if_wds wds;

View file

@ -994,6 +994,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
/* stop the beacon */
ifmsh->mesh_id_len = 0;
sdata->vif.bss_conf.enable_beacon = false;
sdata->beacon_rate_set = false;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);

View file

@ -4883,7 +4883,10 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
txrc.bss_conf = &sdata->vif.bss_conf;
txrc.skb = skb;
txrc.reported_rate.idx = -1;
txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
else
txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
txrc.bss = true;
rate_control_get_rate(sdata, NULL, &txrc);