wifi: nl80211: validate and configure puncturing bitmap
authorAloka Dixit <quic_alokad@quicinc.com>
Tue, 31 Jan 2023 00:12:25 +0000 (16:12 -0800)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 14 Feb 2023 11:13:24 +0000 (12:13 +0100)
- New feature flag, NL80211_EXT_FEATURE_PUNCT, to advertise
  driver support for preamble puncturing in AP mode.
- New attribute, NL80211_ATTR_PUNCT_BITMAP, to receive a puncturing
  bitmap from the userspace during AP bring up (NL80211_CMD_START_AP)
  and channel switch (NL80211_CMD_CHANNEL_SWITCH) operations. Each bit
  corresponds to a 20 MHz channel in the operating bandwidth, lowest
  bit for the lowest channel. Bit set to 1 indicates that the channel
  is punctured. Higher 16 bits are reserved.
- New members added to structures cfg80211_ap_settings and
  cfg80211_csa_settings to propagate the bitmap to the driver after
  validation.

Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Link: https://lore.kernel.org/r/20230131001227.25014-3-quic_alokad@quicinc.com
[move validation against 0xffff into policy]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c

index 191603f32b370042c38557451ef6e54f7b64815e..fb8b79e6ac3675d97398adae358f1183ce1fcf12 100644 (file)
@@ -1316,6 +1316,9 @@ struct cfg80211_unsol_bcast_probe_resp {
  * @fils_discovery: FILS discovery transmission parameters
  * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
  * @mbssid_config: AP settings for multiple bssid
+ * @punct_bitmap: Preamble puncturing bitmap. Each bit represents
+ *     a 20 MHz channel, lowest bit corresponding to the lowest channel.
+ *     Bit set to 1 indicates that the channel is punctured.
  */
 struct cfg80211_ap_settings {
        struct cfg80211_chan_def chandef;
@@ -1350,6 +1353,7 @@ struct cfg80211_ap_settings {
        struct cfg80211_fils_discovery fils_discovery;
        struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
        struct cfg80211_mbssid_config mbssid_config;
+       u16 punct_bitmap;
 };
 
 /**
@@ -1367,6 +1371,9 @@ struct cfg80211_ap_settings {
  * @radar_required: whether radar detection is required on the new channel
  * @block_tx: whether transmissions should be blocked while changing
  * @count: number of beacons until switch
+ * @punct_bitmap: Preamble puncturing bitmap. Each bit represents
+ *     a 20 MHz channel, lowest bit corresponding to the lowest channel.
+ *     Bit set to 1 indicates that the channel is punctured.
  */
 struct cfg80211_csa_settings {
        struct cfg80211_chan_def chandef;
@@ -1379,6 +1386,7 @@ struct cfg80211_csa_settings {
        bool radar_required;
        bool block_tx;
        u8 count;
+       u16 punct_bitmap;
 };
 
 /**
index a984c6c4cf02ff7e77344d4d27b28ca8db23c72d..831660956ab28923c2513c7198139bae935ae9c6 100644 (file)
@@ -2769,6 +2769,12 @@ enum nl80211_commands {
  *     the incoming frame RX timestamp.
  * @NL80211_ATTR_TD_BITMAP: Transition Disable bitmap, for subsequent
  *     (re)associations.
+ *
+ * @NL80211_ATTR_PUNCT_BITMAP: (u32) Preamble puncturing bitmap, lowest
+ *     bit corresponds to the lowest 20 MHz channel. Each bit set to 1
+ *     indicates that the sub-channel is punctured. Higher 16 bits are
+ *     reserved.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3298,6 +3304,8 @@ enum nl80211_attrs {
        NL80211_ATTR_RX_HW_TIMESTAMP,
        NL80211_ATTR_TD_BITMAP,
 
+       NL80211_ATTR_PUNCT_BITMAP,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -6313,6 +6321,8 @@ enum nl80211_feature_flags {
  *     might apply, e.g. no scans in progress, no offchannel operations
  *     in progress, and no active connections.
  *
+ * @NL80211_EXT_FEATURE_PUNCT: Driver supports preamble puncturing in AP mode.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -6381,6 +6391,7 @@ enum nl80211_ext_feature_index {
        NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
        NL80211_EXT_FEATURE_RADAR_BACKGROUND,
        NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE,
+       NL80211_EXT_FEATURE_PUNCT,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
index c82c66c32faa8bf34f296ceabcc8be001d6393f1..683adeb3c9e3d9bbbbdfe0346f5605d17dfac700 100644 (file)
@@ -805,6 +805,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
        [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
        [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
+       [NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff),
 };
 
 /* policy for the key attributes */
@@ -3173,6 +3174,21 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
                wdev->iftype == NL80211_IFTYPE_P2P_GO;
 }
 
+static int nl80211_parse_punct_bitmap(struct cfg80211_registered_device *rdev,
+                                     struct genl_info *info,
+                                     const struct cfg80211_chan_def *chandef,
+                                     u16 *punct_bitmap)
+{
+       if (!wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_PUNCT))
+               return -EINVAL;
+
+       *punct_bitmap = nla_get_u32(info->attrs[NL80211_ATTR_PUNCT_BITMAP]);
+       if (!cfg80211_valid_disable_subchannel_bitmap(punct_bitmap, chandef))
+               return -EINVAL;
+
+       return 0;
+}
+
 int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
                          struct genl_info *info,
                          struct cfg80211_chan_def *chandef)
@@ -5957,6 +5973,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
+               err = nl80211_parse_punct_bitmap(rdev, info,
+                                                &params->chandef,
+                                                &params->punct_bitmap);
+               if (err)
+                       goto out;
+       }
+
        if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
                                           wdev->iftype)) {
                err = -EINVAL;
@@ -10114,6 +10138,14 @@ skip_beacons:
        if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
                params.block_tx = true;
 
+       if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
+               err = nl80211_parse_punct_bitmap(rdev, info,
+                                                &params.chandef,
+                                                &params.punct_bitmap);
+               if (err)
+                       goto free;
+       }
+
        wdev_lock(wdev);
        err = rdev_channel_switch(rdev, dev, &params);
        wdev_unlock(wdev);