wifi: cfg80211: handle UHB AP and STA power type
authorMukesh Sisodiya <mukesh.sisodiya@intel.com>
Wed, 20 Dec 2023 11:41:38 +0000 (13:41 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 21 Dec 2023 19:35:14 +0000 (20:35 +0100)
UHB AP send supported power type(LPI, SP, VLP)
in beacon and probe response IE and STA should
connect to these AP only if their regulatory support
the AP power type.

Beacon/Probe response are reported to userspace
with reason "STA regulatory not supporting to connect to AP
based on transmitted power type" and it should
not connect to AP.

Signed-off-by: Mukesh Sisodiya <mukesh.sisodiya@intel.com>
Reviewed-by: Gregory Greenman <gregory.greenman@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20231220133549.cbfbef9170a9.I432f78438de18aa9f5c9006be12e41dc34cc47c5@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/linux/ieee80211.h
include/net/cfg80211.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/scan.c

index 8ad008591e3209edc3ab28ae27f34ea54e688bbc..2f555448204774a2ecb5585e7a304438ee6aadf1 100644 (file)
@@ -2720,6 +2720,7 @@ static inline bool ieee80211_he_capa_size_ok(const u8 *data, u8 len)
 
 #define IEEE80211_6GHZ_CTRL_REG_LPI_AP 0
 #define IEEE80211_6GHZ_CTRL_REG_SP_AP  1
+#define IEEE80211_6GHZ_CTRL_REG_VLP_AP 2
 
 /**
  * struct ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
index 745974d45ea463fd5a5026d9b4c5881ba0a6ff85..cf79656ce09ca1f05b733bfce2393f4a044d9454 100644 (file)
@@ -118,6 +118,10 @@ struct wiphy;
  *     restrictions.
  * @IEEE80211_CHAN_NO_EHT: EHT operation is not permitted on this channel.
  * @IEEE80211_CHAN_DFS_CONCURRENT: See %NL80211_RRF_DFS_CONCURRENT
+ * @IEEE80211_CHAN_NO_UHB_VLP_CLIENT: Client connection with VLP AP
+ *     not permitted using this channel
+ * @IEEE80211_CHAN_NO_UHB_AFC_CLIENT: Client connection with AFC AP
+ *     not permitted using this channel
  */
 enum ieee80211_channel_flags {
        IEEE80211_CHAN_DISABLED         = 1<<0,
@@ -142,6 +146,8 @@ enum ieee80211_channel_flags {
        IEEE80211_CHAN_NO_320MHZ        = 1<<19,
        IEEE80211_CHAN_NO_EHT           = 1<<20,
        IEEE80211_CHAN_DFS_CONCURRENT   = 1<<21,
+       IEEE80211_CHAN_NO_UHB_VLP_CLIENT= 1<<22,
+       IEEE80211_CHAN_NO_UHB_AFC_CLIENT= 1<<23,
 };
 
 #define IEEE80211_CHAN_NO_HT40 \
index 466da830e65f7c0b8920ba5749886293466be49b..1ccdcae24372227b2f811765128fa409e58e66ee 100644 (file)
@@ -4260,6 +4260,10 @@ enum nl80211_wmm_rule {
  *     allowed for peer-to-peer or adhoc communication under the control
  *     of a DFS master which operates on the same channel (FCC-594280 D01
  *     Section B.3). Should be used together with %NL80211_RRF_DFS only.
+ * @NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT: Client connection to VLP AP
+ *     not allowed using this channel
+ * @NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT: Client connection to AFC AP
+ *     not allowed using this channel
  * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
  *     currently defined
  * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -4300,6 +4304,8 @@ enum nl80211_frequency_attr {
        NL80211_FREQUENCY_ATTR_NO_EHT,
        NL80211_FREQUENCY_ATTR_PSD,
        NL80211_FREQUENCY_ATTR_DFS_CONCURRENT,
+       NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT,
+       NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT,
 
        /* keep last */
        __NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -4509,6 +4515,8 @@ enum nl80211_sched_scan_match_attr {
        peer-to-peer or adhoc communication under the control of a DFS master
        which operates on the same channel (FCC-594280 D01 Section B.3).
        Should be used together with %NL80211_RRF_DFS only.
+ * @NL80211_RRF_NO_UHB_VLP_CLIENT: Client connection to VLP AP not allowed
+ * @NL80211_RRF_NO_UHB_AFC_CLIENT: Client connection to AFC AP not allowed
  */
 enum nl80211_reg_rule_flags {
        NL80211_RRF_NO_OFDM             = 1<<0,
@@ -4531,6 +4539,8 @@ enum nl80211_reg_rule_flags {
        NL80211_RRF_NO_EHT              = 1<<19,
        NL80211_RRF_PSD                 = 1<<20,
        NL80211_RRF_DFS_CONCURRENT      = 1<<21,
+       NL80211_RRF_NO_UHB_VLP_CLIENT   = 1<<22,
+       NL80211_RRF_NO_UHB_AFC_CLIENT   = 1<<23,
 };
 
 #define NL80211_RRF_PASSIVE_SCAN       NL80211_RRF_NO_IR
@@ -5086,9 +5096,12 @@ enum nl80211_bss_use_for {
  *     BSS isn't possible
  * @NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY: NSTR nonprimary links aren't
  *     supported by the device, and this BSS entry represents one.
+ * @NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH: STA is not supporting
+ *     the AP power type (SP, VLP, AP) that the AP uses.
  */
 enum nl80211_bss_cannot_use_reasons {
        NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY  = 1 << 0,
+       NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 1 << 1,
 };
 
 /**
index 534ef3fe0696a46868b5521066d9aab88723dc14..60877b532993219c6607c28d6b4e0fb6ae2506ad 100644 (file)
@@ -1204,6 +1204,12 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
                if ((chan->flags & IEEE80211_CHAN_DFS_CONCURRENT) &&
                    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DFS_CONCURRENT))
                        goto nla_put_failure;
+               if ((chan->flags & IEEE80211_CHAN_NO_UHB_VLP_CLIENT) &&
+                   nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT))
+                       goto nla_put_failure;
+               if ((chan->flags & IEEE80211_CHAN_NO_UHB_AFC_CLIENT) &&
+                   nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT))
+                       goto nla_put_failure;
        }
 
        if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
index 44684df6473435db87d1a110bfada54749417dd8..2741b626919af0b3635ea0c06edf07f5f2afe4b6 100644 (file)
@@ -1595,6 +1595,10 @@ static u32 map_regdom_flags(u32 rd_flags)
                channel_flags |= IEEE80211_CHAN_NO_EHT;
        if (rd_flags & NL80211_RRF_DFS_CONCURRENT)
                channel_flags |= IEEE80211_CHAN_DFS_CONCURRENT;
+       if (rd_flags & NL80211_RRF_NO_UHB_VLP_CLIENT)
+               channel_flags |= IEEE80211_CHAN_NO_UHB_VLP_CLIENT;
+       if (rd_flags & NL80211_RRF_NO_UHB_AFC_CLIENT)
+               channel_flags |= IEEE80211_CHAN_NO_UHB_AFC_CLIENT;
        if (rd_flags & NL80211_RRF_PSD)
                channel_flags |= IEEE80211_CHAN_PSD;
        return channel_flags;
index 3d260c99c348028f38de90d8306a51f16b2a5aa8..a601f1c7f8351c25672387683f2ce26ab3745b63 100644 (file)
@@ -2848,6 +2848,36 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
 }
 EXPORT_SYMBOL(cfg80211_inform_bss_data);
 
+static bool cfg80211_uhb_power_type_valid(const u8 *ie,
+                                         size_t ielen,
+                                         const u32 flags)
+{
+       const struct element *tmp;
+       struct ieee80211_he_operation *he_oper;
+
+       tmp = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ie, ielen);
+       if (tmp && tmp->datalen >= sizeof(*he_oper) + 1) {
+               const struct ieee80211_he_6ghz_oper *he_6ghz_oper;
+
+               he_oper = (void *)&tmp->data[1];
+               he_6ghz_oper = ieee80211_he_6ghz_oper(he_oper);
+
+               if (!he_6ghz_oper)
+                       return false;
+
+               switch (u8_get_bits(he_6ghz_oper->control,
+                                   IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) {
+               case IEEE80211_6GHZ_CTRL_REG_LPI_AP:
+                       return true;
+               case IEEE80211_6GHZ_CTRL_REG_SP_AP:
+                       return !(flags & IEEE80211_CHAN_NO_UHB_AFC_CLIENT);
+               case IEEE80211_6GHZ_CTRL_REG_VLP_AP:
+                       return !(flags & IEEE80211_CHAN_NO_UHB_VLP_CLIENT);
+               }
+       }
+       return false;
+}
+
 /* cfg80211_inform_bss_width_frame helper */
 static struct cfg80211_bss *
 cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
@@ -2906,6 +2936,14 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
        if (!channel)
                return NULL;
 
+       if (channel->band == NL80211_BAND_6GHZ &&
+           !cfg80211_uhb_power_type_valid(variable, ielen, channel->flags)) {
+               data->restrict_use = 1;
+               data->use_for = 0;
+               data->cannot_use_reasons =
+                       NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH;
+       }
+
        if (ext) {
                const struct ieee80211_s1g_bcn_compat_ie *compat;
                const struct element *elem;