HE: Add MU EDCA Parameter Set element (AP)

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>
This commit is contained in:
Siva Mullati 2019-01-07 14:56:24 +05:30 committed by Jouni Malinen
parent cfb01f58a6
commit 11ce7a1bc3
7 changed files with 189 additions and 2 deletions

View 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);

View 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

View 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 */

View 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 */

View 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,

View 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;
}

View file

@ -467,6 +467,7 @@
#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