WMM AC: Parse WMM IE on association
[mech_eap.git] / wpa_supplicant / wmm_ac.c
1 /*
2  * Wi-Fi Multimedia Admission Control (WMM-AC)
3  * Copyright(c) 2014, Intel Mobile Communication GmbH.
4  * Copyright(c) 2014, Intel Corporation. All rights reserved.
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9
10 #include "includes.h"
11
12 #include "utils/common.h"
13 #include "common/ieee802_11_common.h"
14 #include "wpa_supplicant_i.h"
15 #include "driver_i.h"
16 #include "wmm_ac.h"
17
18
19 static struct wmm_ac_assoc_data *
20 wmm_ac_process_param_elem(struct wpa_supplicant *wpa_s, const u8 *ies,
21                           size_t ies_len)
22 {
23         struct ieee802_11_elems elems;
24         struct wmm_parameter_element *wmm_params;
25         struct wmm_ac_assoc_data *assoc_data;
26         int i;
27
28         /* Parsing WMM Parameter Element */
29         if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) != ParseOK) {
30                 wpa_printf(MSG_DEBUG, "WMM AC: could not parse assoc ies");
31                 return NULL;
32         }
33
34         if (!elems.wmm) {
35                 wpa_printf(MSG_DEBUG, "WMM AC: No WMM IE");
36                 return NULL;
37         }
38
39         if (elems.wmm_len != sizeof(*wmm_params)) {
40                 wpa_printf(MSG_WARNING, "WMM AC: Invalid WMM ie length");
41                 return NULL;
42         }
43
44         wmm_params = (struct wmm_parameter_element *)(elems.wmm);
45
46         assoc_data = os_zalloc(sizeof(*assoc_data));
47         if (!assoc_data)
48                 return NULL;
49
50         for (i = 0; i < WMM_AC_NUM; i++)
51                 assoc_data->ac_params[i].acm =
52                         !!(wmm_params->ac[i].aci_aifsn & WMM_AC_ACM);
53
54         wpa_printf(MSG_DEBUG,
55                    "WMM AC: AC mandatory: AC_BE=%u AC_BK=%u AC_VI=%u AC_VO=%u",
56                    assoc_data->ac_params[WMM_AC_BE].acm,
57                    assoc_data->ac_params[WMM_AC_BK].acm,
58                    assoc_data->ac_params[WMM_AC_VI].acm,
59                    assoc_data->ac_params[WMM_AC_VO].acm);
60
61         return assoc_data;
62 }
63
64
65 static int wmm_ac_init(struct wpa_supplicant *wpa_s, const u8 *ies,
66                        size_t ies_len, const struct wmm_params *wmm_params)
67 {
68         struct wmm_ac_assoc_data *assoc_data;
69         u8 ac;
70
71         if (wpa_s->wmm_ac_assoc_info) {
72                 wpa_printf(MSG_ERROR, "WMM AC: Already initialized");
73                 return -1;
74         }
75
76         if (!ies) {
77                 wpa_printf(MSG_ERROR, "WMM AC: Missing IEs");
78                 return -1;
79         }
80
81         if (!(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) {
82                 wpa_printf(MSG_DEBUG, "WMM AC: Missing U-APSD configuration");
83                 return -1;
84         }
85
86         assoc_data = wmm_ac_process_param_elem(wpa_s, ies, ies_len);
87         if (!assoc_data)
88                 return -1;
89
90         wpa_printf(MSG_DEBUG, "WMM AC: U-APSD queues=0x%x",
91                    wmm_params->uapsd_queues);
92
93         for (ac = 0; ac < WMM_AC_NUM; ac++) {
94                 assoc_data->ac_params[ac].uapsd =
95                         !!(wmm_params->uapsd_queues & BIT(ac));
96         }
97
98         wpa_s->wmm_ac_assoc_info = assoc_data;
99         return 0;
100 }
101
102
103 static void wmm_ac_deinit(struct wpa_supplicant *wpa_s)
104 {
105         os_free(wpa_s->wmm_ac_assoc_info);
106         wpa_s->wmm_ac_assoc_info = NULL;
107 }
108
109
110 void wmm_ac_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *ies,
111                          size_t ies_len, const struct wmm_params *wmm_params)
112 {
113         if (wmm_ac_init(wpa_s, ies, ies_len, wmm_params))
114                 return;
115
116         wpa_printf(MSG_DEBUG,
117                    "WMM AC: Valid WMM association, WMM AC is enabled");
118 }
119
120
121 void wmm_ac_notify_disassoc(struct wpa_supplicant *wpa_s)
122 {
123         if (!wpa_s->wmm_ac_assoc_info)
124                 return;
125
126         wmm_ac_deinit(wpa_s);
127         wpa_printf(MSG_DEBUG, "WMM AC: WMM AC is disabled");
128 }