mac80211: HE: add Spatial Reuse element parsing support
authorJohn Crispin <john@phrozen.org>
Tue, 18 Jun 2019 06:19:14 +0000 (08:19 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 26 Jul 2019 14:14:12 +0000 (16:14 +0200)
Add support to mac80211 for parsing SPR elements as per
P802.11ax_D4.0 section 9.4.2.241.

Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
Link: https://lore.kernel.org/r/20190618061915.7102-2-john@phrozen.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/linux/ieee80211.h
net/mac80211/ieee80211_i.h
net/mac80211/util.c

index f36144eda5d6992510d063a985f553b5aeb8fc47..a656f31262f127651af439b51bdf229afc02e57b 100644 (file)
@@ -1633,6 +1633,18 @@ struct ieee80211_he_operation {
        u8 optional[0];
 } __packed;
 
+/**
+ * struct ieee80211_he_spr - HE spatial reuse element
+ *
+ * This structure is the "HE spatial reuse element" element as
+ * described in P802.11ax_D4.0 section 9.4.2.241
+ */
+struct ieee80211_he_spr {
+       u8 he_sr_control;
+       /* Optional 0 to 19 bytes: depends on @he_sr_control */
+       u8 optional[0];
+} __packed;
+
 /**
  * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field
  *
@@ -2071,6 +2083,42 @@ ieee80211_he_oper_size(const u8 *he_oper_ie)
        return oper_len;
 }
 
+/* HE Spatial Reuse defines */
+#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT                        0x4
+#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT               0x8
+
+/*
+ * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size
+ * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the the byte
+ *     after the ext ID byte. It is assumed that he_spr_ie has at least
+ *     sizeof(struct ieee80211_he_spr) bytes, the caller must have validated
+ *     this
+ * @return the actual size of the IE data (not including header), or 0 on error
+ */
+static inline u8
+ieee80211_he_spr_size(const u8 *he_spr_ie)
+{
+       struct ieee80211_he_spr *he_spr = (void *)he_spr_ie;
+       u8 spr_len = sizeof(struct ieee80211_he_spr);
+       u32 he_spr_params;
+
+       /* Make sure the input is not NULL */
+       if (!he_spr_ie)
+               return 0;
+
+       /* Calc required length */
+       he_spr_params = le32_to_cpu(he_spr->he_sr_control);
+       if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
+               spr_len++;
+       if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)
+               spr_len += 18;
+
+       /* Add the first byte (extension ID) to the total length */
+       spr_len++;
+
+       return spr_len;
+}
+
 /* Authentication algorithms */
 #define WLAN_AUTH_OPEN 0
 #define WLAN_AUTH_SHARED_KEY 1
@@ -2493,6 +2541,7 @@ enum ieee80211_eid_ext {
        WLAN_EID_EXT_HE_OPERATION = 36,
        WLAN_EID_EXT_UORA = 37,
        WLAN_EID_EXT_HE_MU_EDCA = 38,
+       WLAN_EID_EXT_HE_SPR = 39,
        WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME = 52,
        WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,
        WLAN_EID_EXT_NON_INHERITANCE = 56,
index 4c80c0ed67a77e72043ee6686763e8864ebc2f86..472c5a40317d474ae2b95ed31a8ce49f1e53f7c5 100644 (file)
@@ -1480,6 +1480,7 @@ struct ieee802_11_elems {
        const struct ieee80211_meshconf_ie *mesh_config;
        const u8 *he_cap;
        const struct ieee80211_he_operation *he_operation;
+       const struct ieee80211_he_spr *he_spr;
        const struct ieee80211_mu_edca_param_set *mu_edca_param_set;
        const u8 *uora_element;
        const u8 *mesh_id;
index 3441558ef2d252b39b57f20b9fdffd9f29c84c76..3e2aeb1a75b4ad3d2fef7c1f20fb291821255421 100644 (file)
@@ -1240,6 +1240,10 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
                                   WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
                                   elen == 3) {
                                elems->mbssid_config_ie = (void *)&pos[1];
+                       } else if (pos[0] == WLAN_EID_EXT_HE_SPR &&
+                                  elen >= sizeof(*elems->he_spr) &&
+                                  elen >= ieee80211_he_spr_size(&pos[1])) {
+                               elems->he_spr = (void *)&pos[1];
                        }
                        break;
                default: