mac80211: TX legacy rate control for Beacon frames
authorJouni Malinen <jouni@codeaurora.org>
Sat, 25 Apr 2020 15:57:12 +0000 (18:57 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 29 Apr 2020 14:16:47 +0000 (16:16 +0200)
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>
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mesh.c
net/mac80211/tx.c

index ae3e063..548a384 100644 (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;
 }
 
index 9407cf4..8cbae66 100644 (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;
index 36978a0..5930d07 100644 (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);
 
index 3dc1990..6dad67e 100644 (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);