]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
mac80211: limit bandwidth in HE capabilities
authorJohannes Berg <johannes.berg@intel.com>
Wed, 2 Feb 2022 08:49:34 +0000 (10:49 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Fri, 20 May 2022 12:38:48 +0000 (14:38 +0200)
BugLink: https://bugs.launchpad.net/bugs/1969110
[ Upstream commit 1f2c104448477512fcf7296df54bfbc3a6f9a765 ]

If we're limiting bandwidth for some reason such as regulatory
restrictions, then advertise that limitation just like we do
for VHT today, so the AP is aware we cannot use the higher BW
it might be using.

Fixes: 41cbb0f5a295 ("mac80211: add support for HE")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20220202104617.70c8e3e7ee76.If317630de69ff1146bec7d47f5b83038695eb71d@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
(cherry picked from commit 0aec294f2d2fb94f29aa6d206f5f1a71e7becde2)
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
net/mac80211/ieee80211_i.h
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/util.c

index 6a88195e5abef1f1fb5dc41fe3c97cd226cf8cb9..d30bd21697a3b191f491cc4ced4d32d5febe2d97 100644 (file)
@@ -2379,7 +2379,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
 u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
                                const struct cfg80211_chan_def *chandef);
 u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype);
-u8 *ieee80211_ie_build_he_cap(u8 *pos,
+u8 *ieee80211_ie_build_he_cap(u32 disable_flags, u8 *pos,
                              const struct ieee80211_sta_he_cap *he_cap,
                              u8 *end);
 void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
index 5dcfd53a4ab6c52ed9f5405373ef069de0e8512d..42bd81a30310190fc6ad8d4523c916df30dbac48 100644 (file)
@@ -580,7 +580,7 @@ int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata,
                return -ENOMEM;
 
        pos = skb_put(skb, ie_len);
-       ieee80211_ie_build_he_cap(pos, he_cap, pos + ie_len);
+       ieee80211_ie_build_he_cap(0, pos, he_cap, pos + ie_len);
 
        return 0;
 }
index 8d9fe27658360ad68dde68373d997d73ccdf254f..c8332452c11824078f98a23ee16121fafaa3b5bb 100644 (file)
@@ -630,7 +630,7 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
                                struct sk_buff *skb,
                                struct ieee80211_supported_band *sband)
 {
-       u8 *pos;
+       u8 *pos, *pre_he_pos;
        const struct ieee80211_sta_he_cap *he_cap = NULL;
        struct ieee80211_chanctx_conf *chanctx_conf;
        u8 he_cap_size;
@@ -647,16 +647,21 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
 
        he_cap = ieee80211_get_he_iftype_cap(sband,
                                             ieee80211_vif_type_p2p(&sdata->vif));
-       if (!he_cap || !reg_cap)
+       if (!he_cap || !chanctx_conf || !reg_cap)
                return;
 
+       /* get a max size estimate */
        he_cap_size =
                2 + 1 + sizeof(he_cap->he_cap_elem) +
                ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem) +
                ieee80211_he_ppe_size(he_cap->ppe_thres[0],
                                      he_cap->he_cap_elem.phy_cap_info);
        pos = skb_put(skb, he_cap_size);
-       ieee80211_ie_build_he_cap(pos, he_cap, pos + he_cap_size);
+       pre_he_pos = pos;
+       pos = ieee80211_ie_build_he_cap(sdata->u.mgd.flags,
+                                       pos, he_cap, pos + he_cap_size);
+       /* trim excess if any */
+       skb_trim(skb, skb->len - (pre_he_pos + he_cap_size - pos));
 
        ieee80211_ie_build_he_6ghz_cap(sdata, skb);
 }
index 2fe71ed9137b0f7402b2b2348241ad8c12b41e8f..be1911d8089fa4759d87f156b3c97737333d6794 100644 (file)
@@ -1959,7 +1959,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
        if (he_cap &&
            cfg80211_any_usable_channels(local->hw.wiphy, BIT(sband->band),
                                         IEEE80211_CHAN_NO_HE)) {
-               pos = ieee80211_ie_build_he_cap(pos, he_cap, end);
+               pos = ieee80211_ie_build_he_cap(0, pos, he_cap, end);
                if (!pos)
                        goto out_err;
        }
@@ -2903,10 +2903,11 @@ u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
                                     he_cap->he_cap_elem.phy_cap_info);
 }
 
-u8 *ieee80211_ie_build_he_cap(u8 *pos,
+u8 *ieee80211_ie_build_he_cap(u32 disable_flags, u8 *pos,
                              const struct ieee80211_sta_he_cap *he_cap,
                              u8 *end)
 {
+       struct ieee80211_he_cap_elem elem;
        u8 n;
        u8 ie_len;
        u8 *orig_pos = pos;
@@ -2919,7 +2920,23 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
        if (!he_cap)
                return orig_pos;
 
-       n = ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem);
+       /* modify on stack first to calculate 'n' and 'ie_len' correctly */
+       elem = he_cap->he_cap_elem;
+
+       if (disable_flags & IEEE80211_STA_DISABLE_40MHZ)
+               elem.phy_cap_info[0] &=
+                       ~(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
+                         IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G);
+
+       if (disable_flags & IEEE80211_STA_DISABLE_160MHZ)
+               elem.phy_cap_info[0] &=
+                       ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+
+       if (disable_flags & IEEE80211_STA_DISABLE_80P80MHZ)
+               elem.phy_cap_info[0] &=
+                       ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
+
+       n = ieee80211_he_mcs_nss_size(&elem);
        ie_len = 2 + 1 +
                 sizeof(he_cap->he_cap_elem) + n +
                 ieee80211_he_ppe_size(he_cap->ppe_thres[0],
@@ -2933,8 +2950,8 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
        *pos++ = WLAN_EID_EXT_HE_CAPABILITY;
 
        /* Fixed data */
-       memcpy(pos, &he_cap->he_cap_elem, sizeof(he_cap->he_cap_elem));
-       pos += sizeof(he_cap->he_cap_elem);
+       memcpy(pos, &elem, sizeof(elem));
+       pos += sizeof(elem);
 
        memcpy(pos, &he_cap->he_mcs_nss_supp, n);
        pos += n;