]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
HE: Add MU EDCA Parameter Set element (AP)
authorSiva Mullati <siva.mullati@intel.com>
Mon, 7 Jan 2019 09:26:24 +0000 (14:56 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 8 Jan 2019 15:22:43 +0000 (17:22 +0200)
Add support for configuring parameters for the MU EDCA Parameter Set
element per IEEE P802.11ax/D3.0.

Signed-off-by: Siva Mullati <siva.mullati@intel.com>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.h
src/ap/beacon.c
src/ap/ieee802_11.h
src/ap/ieee802_11_he.c
src/common/ieee802_11_defs.h

index 10a52fda2a5bee180596c45d1105a18a01a832ae..daaa484f22c2b21a113c4652f9e167f7514d554c 100644 (file)
@@ -1379,6 +1379,14 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
 #endif /* CONFIG_IEEE80211AC */
 
 
+#ifdef CONFIG_IEEE80211AX
+static u8 set_he_cap(int val, u8 mask)
+{
+       return (u8) (mask & (val << ffs(mask)));
+}
+#endif /* CONFIG_IEEE80211AX */
+
+
 #ifdef CONFIG_INTERWORKING
 static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
                                    int line)
@@ -3397,6 +3405,90 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                conf->he_op.he_twt_required = atoi(pos);
        } else if (os_strcmp(buf, "he_rts_threshold") == 0) {
                conf->he_op.he_rts_threshold = atoi(pos);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_param_count") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_EDCA_PARAM_SET_COUNT);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_q_ack") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_Q_ACK);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_queue_request") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_QUEUE_REQUEST);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_txop_request") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_TXOP_REQUEST);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
 #endif /* CONFIG_IEEE80211AX */
        } else if (os_strcmp(buf, "max_listen_interval") == 0) {
                bss->max_listen_interval = atoi(pos);
index 26f9d3467cfbede1ea689877c8164f823cb7d87e..739d367728a9f21f5b07e9caff243f0a84feb460 100644 (file)
@@ -801,6 +801,30 @@ wmm_ac_vo_acm=0
 # unsigned integer = duration in units of 16 us
 #he_rts_threshold=0
 
+#he_mu_edca_qos_info_param_count
+#he_mu_edca_qos_info_q_ack
+#he_mu_edca_qos_info_queue_request=1
+#he_mu_edca_qos_info_txop_request
+#he_mu_edca_ac_be_aifsn=0
+#he_mu_edca_ac_be_ecwmin=15
+#he_mu_edca_ac_be_ecwmax=15
+#he_mu_edca_ac_be_timer=255
+#he_mu_edca_ac_bk_aifsn=0
+#he_mu_edca_ac_bk_aci=1
+#he_mu_edca_ac_bk_ecwmin=15
+#he_mu_edca_ac_bk_ecwmax=15
+#he_mu_edca_ac_bk_timer=255
+#he_mu_edca_ac_vi_ecwmin=15
+#he_mu_edca_ac_vi_ecwmax=15
+#he_mu_edca_ac_vi_aifsn=0
+#he_mu_edca_ac_vi_aci=2
+#he_mu_edca_ac_vi_timer=255
+#he_mu_edca_ac_vo_aifsn=0
+#he_mu_edca_ac_vo_aci=3
+#he_mu_edca_ac_vo_ecwmin=15
+#he_mu_edca_ac_vo_ecwmax=15
+#he_mu_edca_ac_vo_timer=255
+
 ##### IEEE 802.1X-2004 related configuration ##################################
 
 # Require IEEE 802.1X authorization
index c49e2c1c41f8c9bf79767d10c1e396b84fd414fd..990d0d1b536a00ed85d414b2f0eee277b6641c9b 100644 (file)
@@ -843,6 +843,7 @@ struct hostapd_config {
 #ifdef CONFIG_IEEE80211AX
        struct he_phy_capabilities_info he_phy_capab;
        struct he_operation he_op;
+       struct ieee80211_he_mu_edca_parameter_set he_mu_edca;
 #endif /* CONFIG_IEEE80211AX */
 
        /* VHT enable/disable config from CHAN_SWITCH */
index 19d0bcd2a7677a491e945dcbafa1de6fa7806cc5..3e62991d07affd5eed7e969c1b05e4cbd572007c 100644 (file)
@@ -397,7 +397,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 #ifdef CONFIG_IEEE80211AX
        if (hapd->iconf->ieee80211ax) {
                buflen += 3 + sizeof(struct ieee80211_he_capabilities) +
-                       3 + sizeof(struct ieee80211_he_operation);
+                       3 + sizeof(struct ieee80211_he_operation) +
+                       3 + sizeof(struct ieee80211_he_mu_edca_parameter_set);
        }
 #endif /* CONFIG_IEEE80211AX */
 
@@ -510,6 +511,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
        if (hapd->iconf->ieee80211ax) {
                pos = hostapd_eid_he_capab(hapd, pos);
                pos = hostapd_eid_he_operation(hapd, pos);
+               pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
        }
 #endif /* CONFIG_IEEE80211AX */
 
@@ -1085,7 +1087,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 #ifdef CONFIG_IEEE80211AX
        if (hapd->iconf->ieee80211ax) {
                tail_len += 3 + sizeof(struct ieee80211_he_capabilities) +
-                       3 + sizeof(struct ieee80211_he_operation);
+                       3 + sizeof(struct ieee80211_he_operation) +
+                       3 + sizeof(struct ieee80211_he_mu_edca_parameter_set);
        }
 #endif /* CONFIG_IEEE80211AX */
 
@@ -1222,6 +1225,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
        if (hapd->iconf->ieee80211ax) {
                tailpos = hostapd_eid_he_capab(hapd, tailpos);
                tailpos = hostapd_eid_he_operation(hapd, tailpos);
+               tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
        }
 #endif /* CONFIG_IEEE80211AX */
 
index 11747e135cc8a1d6c1490f17a8b7a09a5c353cab..50822267394ff8606a552c4dc5001184591ff7ad 100644 (file)
@@ -59,6 +59,7 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid);
 
 int hostapd_ht_operation_update(struct hostapd_iface *iface);
 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
index 1a8d4697298566ed4ee10444a832c14c13483c2c..072135863682eade3b625ae72bdd96b9715ce3fe 100644 (file)
@@ -86,3 +86,34 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
 
        return pos;
 }
+
+
+u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid)
+{
+       struct ieee80211_he_mu_edca_parameter_set *edca;
+       u8 *pos;
+       size_t i;
+
+       pos = (u8 *) &hapd->iface->conf->he_mu_edca;
+       for (i = 0; i < sizeof(*edca); i++) {
+               if (pos[i])
+                       break;
+       }
+       if (i == sizeof(*edca))
+               return eid; /* no MU EDCA Parameters configured */
+
+       pos = eid;
+       *pos++ = WLAN_EID_EXTENSION;
+       *pos++ = 1 + sizeof(*edca);
+       *pos++ = WLAN_EID_EXT_HE_MU_EDCA_PARAMS;
+
+       edca = (struct ieee80211_he_mu_edca_parameter_set *) pos;
+       os_memcpy(edca, &hapd->iface->conf->he_mu_edca, sizeof(*edca));
+
+       wpa_hexdump(MSG_DEBUG, "HE: MU EDCA Parameter Set element",
+                   pos, sizeof(*edca));
+
+       pos += sizeof(*edca);
+
+       return pos;
+}
index 178cab04181dcbb428ead3bd7295bc1b481209d1..cc512c6c95c207d89fb9a5c7e99afba38d01636d 100644 (file)
 #define WLAN_EID_EXT_PASSWORD_IDENTIFIER 33
 #define WLAN_EID_EXT_HE_CAPABILITIES 35
 #define WLAN_EID_EXT_HE_OPERATION 36
+#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
 #define WLAN_EID_EXT_OCV_OCI 54
 
 /* Extended Capabilities field */
@@ -2147,6 +2148,39 @@ struct ieee80211_he_operation {
                                                BIT(20) | BIT(21)))
 #define HE_OPERATION_RTS_THRESHOLD_OFFSET      12
 
+struct ieee80211_he_mu_edca_parameter_set {
+       u8 he_qos_info;
+       u8 he_mu_ac_be_param[3];
+       u8 he_mu_ac_bk_param[3];
+       u8 he_mu_ac_vi_param[3];
+       u8 he_mu_ac_vo_param[3];
+} STRUCT_PACKED;
+
+/* HE MU AC parameter record field format */
+/* ACI/AIFSN */
+#define HE_MU_AC_PARAM_ACI_IDX 0
+#define HE_MU_AC_PARAM_AIFSN ((u8) (BIT(0) | BIT(1) | BIT(2) | BIT(3)))
+#define HE_MU_AC_PARAM_ACM ((u8) BIT(4))
+#define HE_MU_AC_PARAM_ACI ((u8) (BIT(5) | BIT(6)))
+/* B7: Reserved */
+
+/* ECWmin/ECWmax */
+#define HE_MU_AC_PARAM_ECW_IDX 1
+#define HE_MU_AC_PARAM_ECWMIN ((u8) (BIT(0) | BIT(1) | BIT(2) | BIT(3)))
+#define HE_MU_AC_PARAM_ECWMAX ((u8) (BIT(4) | BIT(5) | BIT(6) | BIT(7)))
+
+/* MU EDCA Timer */
+#define HE_MU_AC_PARAM_TIMER_IDX 2
+
+/* HE QoS Info field */
+#define HE_QOS_INFO_EDCA_PARAM_SET_COUNT ((u8) (BIT(0) | BIT(1) | \
+                                               BIT(2) | BIT(3)))
+#define HE_QOS_INFO_Q_ACK ((u8) (BIT(4)))
+#define HE_QOS_INFO_QUEUE_REQUEST ((u8) (BIT(5)))
+#define HE_QOS_INFO_TXOP_REQUEST ((u8) (BIT(6)))
+/* B7: Reserved if sent by an AP; More Data Ack if sent by a non-AP STA */
+#define HE_QOS_INFO_MORE_DATA_ACK ((u8) (BIT(7)))
+
 /* DPP Public Action frame identifiers - OUI_WFA */
 #define DPP_OUI_TYPE 0x1A