wifi: mac80211: limit A-MSDU subframes for client too
authorJohannes Berg <johannes.berg@intel.com>
Wed, 13 Jul 2022 16:08:03 +0000 (18:08 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 15 Jul 2022 09:43:23 +0000 (11:43 +0200)
In AP/mesh where the stations are added by userspace, we
limit the number of A-MSDU subframes according to the
extended capabilities.

Refactor the code and extend that also to client-side.

Fixes: 506bcfa8abeb ("mac80211: limit the A-MSDU Tx based on peer's capabilities")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/mlme.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h

index bdc3d74eecc159487dcc10e69d1d67fc3c60040b..1545648e2031e40e7805999bb58fac361c1f7515 100644 (file)
@@ -1776,33 +1776,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                sta->sta.max_sp = params->max_sp;
        }
 
-       /* The sender might not have sent the last bit, consider it to be 0 */
-       if (params->ext_capab_len >= 8) {
-               u8 val = (params->ext_capab[7] &
-                         WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB) >> 7;
-
-               /* we did get all the bits, take the MSB as well */
-               if (params->ext_capab_len >= 9) {
-                       u8 val_msb = params->ext_capab[8] &
-                               WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB;
-                       val_msb <<= 1;
-                       val |= val_msb;
-               }
-
-               switch (val) {
-               case 1:
-                       sta->sta.max_amsdu_subframes = 32;
-                       break;
-               case 2:
-                       sta->sta.max_amsdu_subframes = 16;
-                       break;
-               case 3:
-                       sta->sta.max_amsdu_subframes = 8;
-                       break;
-               default:
-                       sta->sta.max_amsdu_subframes = 0;
-               }
-       }
+       ieee80211_sta_set_max_amsdu_subframes(sta, params->ext_capab,
+                                             params->ext_capab_len);
 
        /*
         * cfg80211 validates this (1-2007) and allows setting the AID
index 308a8fe50212528b9c89c6bac97e145463aad3be..3263bb18828416d94a9df5bd62abdb44b58a601b 100644 (file)
@@ -4488,6 +4488,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                sta->sta.mfp = false;
        }
 
+       ieee80211_sta_set_max_amsdu_subframes(sta, elems->ext_capab,
+                                             elems->ext_capab_len);
+
        sta->sta.wme = (elems->wmm_param || elems->s1g_capab) &&
                       local->hw.queues >= IEEE80211_NUM_ACS;
 
index f52a7fa6dde58f25d722920263a13b8cb9dd3254..eed88630594f7ddeb7d99edc08c7ad9d2d48e3b2 100644 (file)
@@ -2761,3 +2761,26 @@ void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
 
        sta_remove_link(sta, link_id, true);
 }
+
+void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
+                                          const u8 *ext_capab,
+                                          unsigned int ext_capab_len)
+{
+       u8 val;
+
+       sta->sta.max_amsdu_subframes = 0;
+
+       if (ext_capab_len < 8)
+               return;
+
+       /* The sender might not have sent the last bit, consider it to be 0 */
+       val = u8_get_bits(ext_capab[7], WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB);
+
+       /* we did get all the bits, take the MSB as well */
+       if (ext_capab_len >= 9)
+               val |= u8_get_bits(ext_capab[8],
+                                  WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB) << 1;
+
+       if (val)
+               sta->sta.max_amsdu_subframes = 4 << val;
+}
index ea0eeee808a5c4b176460f91ef9006fec5e291e9..6bc26a2c46073ea29d5eda4b2260348aa6a6547b 100644 (file)
@@ -910,6 +910,10 @@ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
 
 unsigned long ieee80211_sta_last_active(struct sta_info *sta);
 
+void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
+                                          const u8 *ext_capab,
+                                          unsigned int ext_capab_len);
+
 enum sta_stats_type {
        STA_STATS_RATE_TYPE_INVALID = 0,
        STA_STATS_RATE_TYPE_LEGACY,