[PATCH 2/9] mac80211: limit the A-MSDU Tx based on peer's capabilities

2015-12-08 Thread Emmanuel Grumbach
In VHT, the specification allows to limit the number of
MSDUs in an A-MSDU in the Extended Capabilities IE. There
is also a limitation on the byte size in the VHT IE.
In HT, the only limitation is on the byte size.
Parse the capabilities from the peer and make them
available to the driver.

In HT, there is another limitation when a BA agreement
is active: the byte size can't be greater than 4095.
This is not enforced here.

Signed-off-by: Emmanuel Grumbach 
---
 include/linux/ieee80211.h | 19 +++
 include/net/mac80211.h| 14 ++
 net/mac80211/cfg.c| 29 +
 net/mac80211/ht.c |  5 +
 net/mac80211/vht.c| 18 ++
 5 files changed, 85 insertions(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index d9ddb89..3b1f6ce 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -163,6 +163,14 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
 /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
 #define IEEE80211_MAX_FRAME_LEN2352
 
+/* Maximal size of an A-MSDU */
+#define IEEE80211_MAX_MPDU_LEN_HT_3839 3839
+#define IEEE80211_MAX_MPDU_LEN_HT_7935 7935
+
+#define IEEE80211_MAX_MPDU_LEN_VHT_38953895
+#define IEEE80211_MAX_MPDU_LEN_VHT_79917991
+#define IEEE80211_MAX_MPDU_LEN_VHT_11454   11454
+
 #define IEEE80211_MAX_SSID_LEN 32
 
 #define IEEE80211_MAX_MESH_ID_LEN  32
@@ -1505,6 +1513,7 @@ struct ieee80211_vht_operation {
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x0001
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
0x0002
+#define IEEE80211_VHT_CAP_MAX_MPDU_MASK
0x0003
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ   0x0004
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ  0x0008
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK 0x000C
@@ -2086,6 +2095,16 @@ enum ieee80211_tdls_actioncode {
 #define WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLEDBIT(5)
 #define WLAN_EXT_CAPA8_OPMODE_NOTIFBIT(6)
 
+/* Defines the maximal number of MSDUs in an A-MSDU. */
+#define WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB   BIT(7)
+#define WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB   BIT(0)
+
+/*
+ * Fine Timing Measurement Initiator - bit 71 of @WLAN_EID_EXT_CAPABILITY
+ * information element
+ */
+#define WLAN_EXT_CAPA9_FTM_INITIATOR   BIT(7)
+
 /* TDLS specific payload type in the LLC/SNAP header */
 #define WLAN_TDLS_SNAP_RFTYPE  0x2
 
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 8da483b..71be30d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1701,6 +1701,18 @@ struct ieee80211_sta_rates {
  * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only
  * valid if the STA is a TDLS peer in the first place.
  * @mfp: indicates whether the STA uses management frame protection or not.
+ * @max_amsdu_subframes: indicates the maximal number of MSDUs in a single
+ * A-MSDU. Taken from the Extended Capabilities element. 0 means
+ * unlimited.
+ * @max_amsdu_len: indicates the maximal length of an A-MSDU in bytes. This
+ * field is always valid for packets with a VHT preamble. For packets
+ * with a HT preamble, additional limits apply:
+ * + If the skb is transmitted as part of a BA agreement, the
+ *   A-MSDU maximal size is min(max_amsdu_len, 4065) bytes.
+ * + If the skb is not part of a BA aggreement, the A-MSDU maximal
+ *   size is min(max_amsdu_len, 7935) bytes.
+ * Both additional HT limits must be enforced by the low level driver.
+ * This is defined by the spec (IEEE 802.11-2012 section 8.3.2.2 NOTE 2).
  * @txq: per-TID data TX queues (if driver uses the TXQ abstraction)
  */
 struct ieee80211_sta {
@@ -1719,6 +1731,8 @@ struct ieee80211_sta {
bool tdls;
bool tdls_initiator;
bool mfp;
+   u8 max_amsdu_subframes;
+   u16 max_amsdu_len;
 
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
 
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 2d1c4c3..b9e2c2f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1131,6 +1131,34 @@ 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] &
+   

Re: [PATCH 2/9] mac80211: limit the A-MSDU Tx based on peer's capabilities

2015-12-08 Thread Krishna Chaitanya
On Tue, Dec 8, 2015 at 7:34 PM, Emmanuel Grumbach
 wrote:
> index 7a76ce6..f4a5287 100644
> --- a/net/mac80211/ht.c
> +++ b/net/mac80211/ht.c
> @@ -230,6 +230,11 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct 
> ieee80211_sub_if_data *sdata,
> /* set Rx highest rate */
> ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
>
> +   if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_7935;
> +   else
> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839;
> +
>   apply:
> changed = memcmp(>sta.ht_cap, _cap, sizeof(ht_cap));
>
> diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
> index 92c9843..d2f2ff6 100644
> --- a/net/mac80211/vht.c
> +++ b/net/mac80211/vht.c
> @@ -281,6 +281,24 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct 
> ieee80211_sub_if_data *sdata,
> }
>
> sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
> +
> +   /* If HT IE reported 3839 bytes only, stay with that size. */
> +   if (sta->sta.max_amsdu_len == IEEE80211_MAX_MPDU_LEN_HT_3839)
> +   return;
> +
> +   switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
> +   break;
> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
> +   break;
> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
> +   default:
> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
> +   break;
> +   }
Ideally speaking shouldn't we use different variables for HT and VHT
and depending on
rate HT/VHT we should aggregate accordingly? of course that will be
tricky as we dont
have the rate control info at the time of aggregation. Standard is
clear about usage of
independent lengths depending on whether its an VHT/HT PPDU.

If we use the same variable to arrive at max_amsdu_len for both VHT
and HT, we might
end up sending 11454 sized MSDU in a HT rate.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/9] mac80211: limit the A-MSDU Tx based on peer's capabilities

2015-12-08 Thread Grumbach, Emmanuel


On 12/08/2015 06:03 PM, Krishna Chaitanya wrote:
> On Tue, Dec 8, 2015 at 7:34 PM, Emmanuel Grumbach
>  wrote:
>> index 7a76ce6..f4a5287 100644
>> --- a/net/mac80211/ht.c
>> +++ b/net/mac80211/ht.c
>> @@ -230,6 +230,11 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct 
>> ieee80211_sub_if_data *sdata,
>> /* set Rx highest rate */
>> ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
>>
>> +   if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
>> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_7935;
>> +   else
>> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839;
>> +
>>   apply:
>> changed = memcmp(>sta.ht_cap, _cap, sizeof(ht_cap));
>>
>> diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
>> index 92c9843..d2f2ff6 100644
>> --- a/net/mac80211/vht.c
>> +++ b/net/mac80211/vht.c
>> @@ -281,6 +281,24 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct 
>> ieee80211_sub_if_data *sdata,
>> }
>>
>> sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
>> +
>> +   /* If HT IE reported 3839 bytes only, stay with that size. */
>> +   if (sta->sta.max_amsdu_len == IEEE80211_MAX_MPDU_LEN_HT_3839)
>> +   return;
>> +
>> +   switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
>> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
>> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
>> +   break;
>> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
>> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
>> +   break;
>> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
>> +   default:
>> +   sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
>> +   break;
>> +   }
> Ideally speaking shouldn't we use different variables for HT and VHT
> and depending on
> rate HT/VHT we should aggregate accordingly? of course that will be
> tricky as we dont
> have the rate control info at the time of aggregation. Standard is
> clear about usage of
> independent lengths depending on whether its an VHT/HT PPDU.

Yes - but since it is tricky, I preferred to be on the safe side and
limit VHT amsdus for the very peculiar AP that would decide to have
large A-MSDUs in VHT and small ones in HT (?!).

> If we use the same variable to arrive at max_amsdu_len for both VHT
> and HT, we might
> end up sending 11454 sized MSDU in a HT rate.
>
And since that can't be handled at the time of the A-MSDU building,
leave that to another entity :)
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/9] mac80211: limit the A-MSDU Tx based on peer's capabilities

2015-12-08 Thread Grumbach, Emmanuel


On 12/08/2015 06:35 PM, Krishna Chaitanya wrote:
>
>
> On Dec 8, 2015 10:01 PM, "Grumbach, Emmanuel"
> > wrote:
> >
> >
> >
> > On 12/08/2015 06:03 PM, Krishna Chaitanya wrote:
> > > On Tue, Dec 8, 2015 at 7:34 PM, Emmanuel Grumbach
> > > >
> wrote:
> > >> index 7a76ce6..f4a5287 100644
> > >> --- a/net/mac80211/ht.c
> > >> +++ b/net/mac80211/ht.c
> > >> @@ -230,6 +230,11 @@ bool
> ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
> > >> /* set Rx highest rate */
> > >> ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
> > >>
> > >> +   if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
> > >> +   sta->sta.max_amsdu_len =
> IEEE80211_MAX_MPDU_LEN_HT_7935;
> > >> +   else
> > >> +   sta->sta.max_amsdu_len =
> IEEE80211_MAX_MPDU_LEN_HT_3839;
> > >> +
> > >>   apply:
> > >> changed = memcmp(>sta.ht_cap, _cap, sizeof(ht_cap));
> > >>
> > >> diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
> > >> index 92c9843..d2f2ff6 100644
> > >> --- a/net/mac80211/vht.c
> > >> +++ b/net/mac80211/vht.c
> > >> @@ -281,6 +281,24 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct
> ieee80211_sub_if_data *sdata,
> > >> }
> > >>
> > >> sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
> > >> +
> > >> +   /* If HT IE reported 3839 bytes only, stay with that size. */
> > >> +   if (sta->sta.max_amsdu_len == IEEE80211_MAX_MPDU_LEN_HT_3839)
> > >> +   return;
> > >> +
> > >> +   switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
> > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
> > >> +   sta->sta.max_amsdu_len =
> IEEE80211_MAX_MPDU_LEN_VHT_11454;
> > >> +   break;
> > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
> > >> +   sta->sta.max_amsdu_len =
> IEEE80211_MAX_MPDU_LEN_VHT_7991;
> > >> +   break;
> > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
> > >> +   default:
> > >> +   sta->sta.max_amsdu_len =
> IEEE80211_MAX_MPDU_LEN_VHT_3895;
> > >> +   break;
> > >> +   }
> > > Ideally speaking shouldn't we use different variables for HT and VHT
> > > and depending on
> > > rate HT/VHT we should aggregate accordingly? of course that will be
> > > tricky as we dont
> > > have the rate control info at the time of aggregation. Standard is
> > > clear about usage of
> > > independent lengths depending on whether its an VHT/HT PPDU.
> >
> > Yes - but since it is tricky, I preferred to be on the safe side and
> > limit VHT amsdus for the very peculiar AP that would decide to have
> > large A-MSDUs in VHT and small ones in HT (?!).
> Yes but wouldn't it be safer to just use min(ht , vht)? For a good AP
> it shouldn't matter and bad AP it will still work.
>
This is the de-facto what this code does I think.
If the HT limit is 4K, then don't even take the VHT limit into account
and the VHT limit can't be smaller than the HT one in that case.
If the HT limit is 8K, then we can limit it further to 4K in case VHT
has a limit of 4K (which is another weird case), but we can also make it
larger for VHT frames?

So I don't really see the bug here, am I missing something?

> > > If we use the same variable to arrive at max_amsdu_len for both VHT
> > > and HT, we might
> > > end up sending 11454 sized MSDU in a HT rate.
> > >
> > And since that can't be handled at the time of the A-MSDU building,
> > leave that to another entity :)
>

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/9] mac80211: limit the A-MSDU Tx based on peer's capabilities

2015-12-08 Thread Grumbach, Emmanuel


On 12/08/2015 09:11 PM, Krishna Chaitanya wrote:
>
>
> On Dec 9, 2015 12:37 AM, "Grumbach, Emmanuel"
> > wrote:
> >
> >
> >
> > On 12/08/2015 07:49 PM, Krishna Chaitanya wrote:
> > >
> > >
> > > On Dec 8, 2015 10:13 PM, "Grumbach, Emmanuel"
> > > 
>  >> wrote:
> > > >
> > > >
> > > >
> > > > On 12/08/2015 06:35 PM, Krishna Chaitanya wrote:
> > > > >
> > > > >
> > > > > On Dec 8, 2015 10:01 PM, "Grumbach, Emmanuel"
> > > > >  
> >
> > >  
> > >   > > > > >
> > > > > >
> > > > > >
> > > > > > On 12/08/2015 06:03 PM, Krishna Chaitanya wrote:
> > > > > > > On Tue, Dec 8, 2015 at 7:34 PM, Emmanuel Grumbach
> > > > > > >  
> > >  >
> > >  
>   > > > > wrote:
> > > > > > >> index 7a76ce6..f4a5287 100644
> > > > > > >> --- a/net/mac80211/ht.c
> > > > > > >> +++ b/net/mac80211/ht.c
> > > > > > >> @@ -230,6 +230,11 @@ bool
> > > > > ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data
> *sdata,
> > > > > > >> /* set Rx highest rate */
> > > > > > >> ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
> > > > > > >>
> > > > > > >> +   if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
> > > > > > >> +   sta->sta.max_amsdu_len =
> > > > > IEEE80211_MAX_MPDU_LEN_HT_7935;
> > > > > > >> +   else
> > > > > > >> +   sta->sta.max_amsdu_len =
> > > > > IEEE80211_MAX_MPDU_LEN_HT_3839;
> > > > > > >> +
> > > > > > >>   apply:
> > > > > > >> changed = memcmp(>sta.ht_cap, _cap,
> > > sizeof(ht_cap));
> > > > > > >>
> > > > > > >> diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
> > > > > > >> index 92c9843..d2f2ff6 100644
> > > > > > >> --- a/net/mac80211/vht.c
> > > > > > >> +++ b/net/mac80211/vht.c
> > > > > > >> @@ -281,6 +281,24 @@
> ieee80211_vht_cap_ie_to_sta_vht_cap(struct
> > > > > ieee80211_sub_if_data *sdata,
> > > > > > >> }
> > > > > > >>
> > > > > > >> sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
> > > > > > >> +
> > > > > > >> +   /* If HT IE reported 3839 bytes only, stay with that
> > > size. */
> > > > > > >> +   if (sta->sta.max_amsdu_len ==
> > > IEEE80211_MAX_MPDU_LEN_HT_3839)
> > > > > > >> +   return;
> > > > > > >> +
> > > > > > >> +   switch (vht_cap->cap &
> IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
> > > > > > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
> > > > > > >> +   sta->sta.max_amsdu_len =
> > > > > IEEE80211_MAX_MPDU_LEN_VHT_11454;
> > > > > > >> +   break;
> > > > > > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
> > > > > > >> +   sta->sta.max_amsdu_len =
> > > > > IEEE80211_MAX_MPDU_LEN_VHT_7991;
> > > > > > >> +   break;
> > > > > > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
> > > > > > >> +   default:
> > > > > > >> +   sta->sta.max_amsdu_len =
> > > > > IEEE80211_MAX_MPDU_LEN_VHT_3895;
> > > > > > >> +   break;
> > > > > > >> +   }
> > > > > > > Ideally speaking shouldn't we use different variables for HT
> > > and VHT
> > > > > > > and depending on
> > > > > > > rate HT/VHT we should aggregate accordingly? of course that
> > > will be
> > > > > > > tricky as we dont
> > > > > > > have the rate control info at the time of aggregation.
> Standard is
> > > > > > > clear about usage of
> > > > > > > independent lengths depending on whether its an VHT/HT PPDU.
> > > > > >
> > > > > > Yes - but since it is tricky, I preferred to be on the safe
> side and
> > > > > > limit VHT amsdus for the very peculiar AP that would decide
> to have
> > > > > > large A-MSDUs in VHT and small ones in HT (?!).
> > > > > Yes but wouldn't it be safer to just use min(ht , vht)? For a
> good AP
> > > > > it shouldn't matter and bad AP it will still work.
> > > > >
> > > > This is the de-facto what this code does I think.
> > > > If the HT limit is 4K, then don't even take the VHT limit into
> account
> > > > and the VHT limit can't be smaller than the HT one in that case.
> > > > If the HT limit is 8K, then we can limit it further to 4K in
> case VHT
> > > > has a limit of 4K (which is another weird case), but we can also
> make it
> > > > larger for VHT frames?
> > > >
> > > > So I don't really see the bug here, am I 

Re: [PATCH 2/9] mac80211: limit the A-MSDU Tx based on peer's capabilities

2015-12-08 Thread Krishna Chaitanya
On Wed, Dec 9, 2015 at 12:52 AM, Grumbach, Emmanuel
 wrote:
>
>
> On 12/08/2015 09:11 PM, Krishna Chaitanya wrote:
>>
>>
>> On Dec 9, 2015 12:37 AM, "Grumbach, Emmanuel"
>> > wrote:
>> >
>> >
>> >
>> > On 12/08/2015 07:49 PM, Krishna Chaitanya wrote:
>> > >
>> > >
>> > > On Dec 8, 2015 10:13 PM, "Grumbach, Emmanuel"
>> > > 
>> > >> wrote:
>> > > >
>> > > >
>> > > >
>> > > > On 12/08/2015 06:35 PM, Krishna Chaitanya wrote:
>> > > > >
>> > > > >
>> > > > > On Dec 8, 2015 10:01 PM, "Grumbach, Emmanuel"
>> > > > > > 
>> >
>> > > > 
>> > > > > > > > > >
>> > > > > >
>> > > > > >
>> > > > > > On 12/08/2015 06:03 PM, Krishna Chaitanya wrote:
>> > > > > > > On Tue, Dec 8, 2015 at 7:34 PM, Emmanuel Grumbach
>> > > > > > > > 
>> > > > >
>> > > > 
>> > > > > > > wrote:
>> > > > > > >> index 7a76ce6..f4a5287 100644
>> > > > > > >> --- a/net/mac80211/ht.c
>> > > > > > >> +++ b/net/mac80211/ht.c
>> > > > > > >> @@ -230,6 +230,11 @@ bool
>> > > > > ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data
>> *sdata,
>> > > > > > >> /* set Rx highest rate */
>> > > > > > >> ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
>> > > > > > >>
>> > > > > > >> +   if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
>> > > > > > >> +   sta->sta.max_amsdu_len =
>> > > > > IEEE80211_MAX_MPDU_LEN_HT_7935;
>> > > > > > >> +   else
>> > > > > > >> +   sta->sta.max_amsdu_len =
>> > > > > IEEE80211_MAX_MPDU_LEN_HT_3839;
>> > > > > > >> +
>> > > > > > >>   apply:
>> > > > > > >> changed = memcmp(>sta.ht_cap, _cap,
>> > > sizeof(ht_cap));
>> > > > > > >>
>> > > > > > >> diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
>> > > > > > >> index 92c9843..d2f2ff6 100644
>> > > > > > >> --- a/net/mac80211/vht.c
>> > > > > > >> +++ b/net/mac80211/vht.c
>> > > > > > >> @@ -281,6 +281,24 @@
>> ieee80211_vht_cap_ie_to_sta_vht_cap(struct
>> > > > > ieee80211_sub_if_data *sdata,
>> > > > > > >> }
>> > > > > > >>
>> > > > > > >> sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
>> > > > > > >> +
>> > > > > > >> +   /* If HT IE reported 3839 bytes only, stay with that
>> > > size. */
>> > > > > > >> +   if (sta->sta.max_amsdu_len ==
>> > > IEEE80211_MAX_MPDU_LEN_HT_3839)
>> > > > > > >> +   return;
>> > > > > > >> +
>> > > > > > >> +   switch (vht_cap->cap &
>> IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
>> > > > > > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
>> > > > > > >> +   sta->sta.max_amsdu_len =
>> > > > > IEEE80211_MAX_MPDU_LEN_VHT_11454;
>> > > > > > >> +   break;
>> > > > > > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
>> > > > > > >> +   sta->sta.max_amsdu_len =
>> > > > > IEEE80211_MAX_MPDU_LEN_VHT_7991;
>> > > > > > >> +   break;
>> > > > > > >> +   case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
>> > > > > > >> +   default:
>> > > > > > >> +   sta->sta.max_amsdu_len =
>> > > > > IEEE80211_MAX_MPDU_LEN_VHT_3895;
>> > > > > > >> +   break;
>> > > > > > >> +   }
>> > > > > > > Ideally speaking shouldn't we use different variables for HT
>> > > and VHT
>> > > > > > > and depending on
>> > > > > > > rate HT/VHT we should aggregate accordingly? of course that
>> > > will be
>> > > > > > > tricky as we dont
>> > > > > > > have the rate control info at the time of aggregation.
>> Standard is
>> > > > > > > clear about usage of
>> > > > > > > independent lengths depending on whether its an VHT/HT PPDU.
>> > > > > >
>> > > > > > Yes - but since it is tricky, I preferred to be on the safe
>> side and
>> > > > > > limit VHT amsdus for the very peculiar AP that would decide
>> to have
>> > > > > > large A-MSDUs in VHT and small ones in HT (?!).
>> > > > > Yes but wouldn't it be safer to just use min(ht , vht)? For a
>> good AP
>> > > > > it shouldn't matter and bad AP it will still work.
>> > > > >
>> > > > This is the de-facto what this code does I think.
>> > > > If the HT limit is 4K, then don't even take the VHT limit into
>> account
>> > > > and the VHT limit can't be smaller than the HT one in that case.
>> > > > If the HT limit is 8K, then we can