wifi: mac80211: limit A-MSDU subframes for client too

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: 506bcfa8ab ("mac80211: limit the A-MSDU Tx based on peer's capabilities")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2022-07-13 18:08:03 +02:00
Родитель 5d3a341c0d
Коммит 175ad2ec89
4 изменённых файлов: 32 добавлений и 27 удалений

Просмотреть файл

@ -1776,33 +1776,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
sta->sta.max_sp = params->max_sp; sta->sta.max_sp = params->max_sp;
} }
/* The sender might not have sent the last bit, consider it to be 0 */ ieee80211_sta_set_max_amsdu_subframes(sta, params->ext_capab,
if (params->ext_capab_len >= 8) { params->ext_capab_len);
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;
}
}
/* /*
* cfg80211 validates this (1-2007) and allows setting the AID * cfg80211 validates this (1-2007) and allows setting the AID

Просмотреть файл

@ -4488,6 +4488,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
sta->sta.mfp = false; 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) && sta->sta.wme = (elems->wmm_param || elems->s1g_capab) &&
local->hw.queues >= IEEE80211_NUM_ACS; local->hw.queues >= IEEE80211_NUM_ACS;

Просмотреть файл

@ -2761,3 +2761,26 @@ void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
sta_remove_link(sta, link_id, true); 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;
}

Просмотреть файл

@ -910,6 +910,10 @@ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
unsigned long ieee80211_sta_last_active(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 { enum sta_stats_type {
STA_STATS_RATE_TYPE_INVALID = 0, STA_STATS_RATE_TYPE_INVALID = 0,
STA_STATS_RATE_TYPE_LEGACY, STA_STATS_RATE_TYPE_LEGACY,