From a0413b17340a18ed905edc804ee2aab09b2c3186 Mon Sep 17 00:00:00 2001 From: Moshe Benji Date: Wed, 22 Oct 2014 08:03:54 -0400 Subject: [PATCH] WMM AC: Parse WMM IE on association Initialize WMM AC data structures upon successful association with an AP that publishes WMM support, and deinitialize the data structure when the association is no longer valid. Signed-off-by: Moshe Benji Signed-off-by: Eliad Peller --- src/common/ieee802_11_defs.h | 7 +- wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + wpa_supplicant/events.c | 9 +++ wpa_supplicant/wmm_ac.c | 128 ++++++++++++++++++++++++++++++ wpa_supplicant/wmm_ac.h | 51 ++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 + 7 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 wpa_supplicant/wmm_ac.c create mode 100644 wpa_supplicant/wmm_ac.h diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 8bcd109fe..14a0ddc94 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -884,6 +884,8 @@ struct wmm_information_element { } STRUCT_PACKED; +#define WMM_QOSINFO_AP_UAPSD 0x80 + #define WMM_QOSINFO_STA_AC_MASK 0x0f #define WMM_QOSINFO_STA_SP_MASK 0x03 #define WMM_QOSINFO_STA_SP_SHIFT 5 @@ -951,11 +953,12 @@ struct wmm_tspec_element { /* Access Categories / ACI to AC coding */ -enum { +enum wmm_ac { WMM_AC_BE = 0 /* Best Effort */, WMM_AC_BK = 1 /* Background */, WMM_AC_VI = 2 /* Video */, - WMM_AC_VO = 3 /* Voice */ + WMM_AC_VO = 3 /* Voice */, + WMM_AC_NUM = 4 }; diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 5e6a88f69..5ab299625 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -83,6 +83,7 @@ OBJS += eap_register.c OBJS += src/utils/common.c OBJS += src/utils/wpa_debug.c OBJS += src/utils/wpabuf.c +OBJS += wmm_ac.c OBJS_p = wpa_passphrase.c OBJS_p += src/utils/common.c OBJS_p += src/utils/wpa_debug.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 16c2830c3..470a85d1c 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -80,6 +80,7 @@ OBJS_p += ../src/utils/wpabuf.o OBJS_c = wpa_cli.o ../src/common/wpa_ctrl.o OBJS_c += ../src/utils/wpa_debug.o OBJS_c += ../src/utils/common.o +OBJS += wmm_ac.o ifndef CONFIG_OS ifdef CONFIG_NATIVE_WINDOWS diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index c1684bf45..e078c70cd 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -44,6 +44,7 @@ #include "interworking.h" #include "mesh.h" #include "mesh_mpm.h" +#include "wmm_ac.h" #ifndef CONFIG_NO_SCAN_PROCESSING @@ -2037,6 +2038,12 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IBSS_RSN */ wpas_wps_notify_assoc(wpa_s, bssid); + + if (data) { + wmm_ac_notify_assoc(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, + &data->assoc_info.wmm_params); + } } @@ -2124,6 +2131,8 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, return; } + wmm_ac_notify_disassoc(wpa_s); + if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) { wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - " "pre-shared key may be incorrect"); diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c new file mode 100644 index 000000000..13bf7a36c --- /dev/null +++ b/wpa_supplicant/wmm_ac.c @@ -0,0 +1,128 @@ +/* + * Wi-Fi Multimedia Admission Control (WMM-AC) + * Copyright(c) 2014, Intel Mobile Communication GmbH. + * Copyright(c) 2014, Intel Corporation. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_common.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "wmm_ac.h" + + +static struct wmm_ac_assoc_data * +wmm_ac_process_param_elem(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len) +{ + struct ieee802_11_elems elems; + struct wmm_parameter_element *wmm_params; + struct wmm_ac_assoc_data *assoc_data; + int i; + + /* Parsing WMM Parameter Element */ + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) != ParseOK) { + wpa_printf(MSG_DEBUG, "WMM AC: could not parse assoc ies"); + return NULL; + } + + if (!elems.wmm) { + wpa_printf(MSG_DEBUG, "WMM AC: No WMM IE"); + return NULL; + } + + if (elems.wmm_len != sizeof(*wmm_params)) { + wpa_printf(MSG_WARNING, "WMM AC: Invalid WMM ie length"); + return NULL; + } + + wmm_params = (struct wmm_parameter_element *)(elems.wmm); + + assoc_data = os_zalloc(sizeof(*assoc_data)); + if (!assoc_data) + return NULL; + + for (i = 0; i < WMM_AC_NUM; i++) + assoc_data->ac_params[i].acm = + !!(wmm_params->ac[i].aci_aifsn & WMM_AC_ACM); + + wpa_printf(MSG_DEBUG, + "WMM AC: AC mandatory: AC_BE=%u AC_BK=%u AC_VI=%u AC_VO=%u", + assoc_data->ac_params[WMM_AC_BE].acm, + assoc_data->ac_params[WMM_AC_BK].acm, + assoc_data->ac_params[WMM_AC_VI].acm, + assoc_data->ac_params[WMM_AC_VO].acm); + + return assoc_data; +} + + +static int wmm_ac_init(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len, const struct wmm_params *wmm_params) +{ + struct wmm_ac_assoc_data *assoc_data; + u8 ac; + + if (wpa_s->wmm_ac_assoc_info) { + wpa_printf(MSG_ERROR, "WMM AC: Already initialized"); + return -1; + } + + if (!ies) { + wpa_printf(MSG_ERROR, "WMM AC: Missing IEs"); + return -1; + } + + if (!(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) { + wpa_printf(MSG_DEBUG, "WMM AC: Missing U-APSD configuration"); + return -1; + } + + assoc_data = wmm_ac_process_param_elem(wpa_s, ies, ies_len); + if (!assoc_data) + return -1; + + wpa_printf(MSG_DEBUG, "WMM AC: U-APSD queues=0x%x", + wmm_params->uapsd_queues); + + for (ac = 0; ac < WMM_AC_NUM; ac++) { + assoc_data->ac_params[ac].uapsd = + !!(wmm_params->uapsd_queues & BIT(ac)); + } + + wpa_s->wmm_ac_assoc_info = assoc_data; + return 0; +} + + +static void wmm_ac_deinit(struct wpa_supplicant *wpa_s) +{ + os_free(wpa_s->wmm_ac_assoc_info); + wpa_s->wmm_ac_assoc_info = NULL; +} + + +void wmm_ac_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len, const struct wmm_params *wmm_params) +{ + if (wmm_ac_init(wpa_s, ies, ies_len, wmm_params)) + return; + + wpa_printf(MSG_DEBUG, + "WMM AC: Valid WMM association, WMM AC is enabled"); +} + + +void wmm_ac_notify_disassoc(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->wmm_ac_assoc_info) + return; + + wmm_ac_deinit(wpa_s); + wpa_printf(MSG_DEBUG, "WMM AC: WMM AC is disabled"); +} diff --git a/wpa_supplicant/wmm_ac.h b/wpa_supplicant/wmm_ac.h new file mode 100644 index 000000000..dd376170a --- /dev/null +++ b/wpa_supplicant/wmm_ac.h @@ -0,0 +1,51 @@ +/* + * Wi-Fi Multimedia Admission Control (WMM-AC) + * Copyright(c) 2014, Intel Mobile Communication GmbH. + * Copyright(c) 2014, Intel Corporation. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WMM_AC_H +#define WMM_AC_H + +#include "common/ieee802_11_defs.h" +#include "drivers/driver.h" + +struct wpa_supplicant; + +/** + * struct wmm_ac_assoc_data - WMM Admission Control Association Data + * + * This struct will store any relevant WMM association data needed by WMM AC. + * In case there is a valid WMM association, an instance of this struct will be + * created. In case there is no instance of this struct, the station is not + * associated to a valid WMM BSS and hence, WMM AC will not be used. + */ +struct wmm_ac_assoc_data { + struct { + /* + * acm - Admission Control Mandatory + * In case an access category is ACM, the traffic will have + * to be admitted by WMM-AC's admission mechanism before use. + */ + unsigned int acm:1; + + /* + * uapsd_queues - Unscheduled Automatic Power Save Delivery + * queues. + * Indicates whether ACs are configured for U-APSD (or legacy + * PS). Storing this value is necessary in order to set the + * Power Save Bit (PSB) in ADDTS request Action frames (if not + * given). + */ + unsigned int uapsd:1; + } ac_params[WMM_AC_NUM]; +}; + +void wmm_ac_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len, const struct wmm_params *wmm_params); +void wmm_ac_notify_disassoc(struct wpa_supplicant *wpa_s); + +#endif /* WMM_AC_H */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 73e26282f..334bf717f 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -15,6 +15,7 @@ #include "common/wpa_ctrl.h" #include "wps/wps_defs.h" #include "config_ssid.h" +#include "wmm_ac.h" extern const char *wpa_supplicant_version; extern const char *wpa_supplicant_license; @@ -888,6 +889,8 @@ struct wpa_supplicant { struct l2_packet_data *l2_test; unsigned int extra_roc_dur; #endif /* CONFIG_TESTING_OPTIONS */ + + struct wmm_ac_assoc_data *wmm_ac_assoc_info; };