Interworking: Add support for QoS Mapping functionality for the STA

Indicate support for QoS Mapping and configure driver to update the QoS
Map if QoS Map Set elements is received from the AP either in
(Re)Association Response or QoS Map Configure frame.

This commit adds support for receiving the frames with nl80211 drivers,
but the actual QoS Map configuration command is still missing.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-07-24 13:17:56 +03:00 committed by Jouni Malinen
parent 850e1c2579
commit 56f5af489c
6 changed files with 79 additions and 0 deletions

View file

@ -276,6 +276,12 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->interworking = pos; elems->interworking = pos;
elems->interworking_len = elen; elems->interworking_len = elen;
break; break;
case WLAN_EID_QOS_MAP_SET:
if (elen < 16)
break;
elems->qos_map_set = pos;
elems->qos_map_set_len = elen;
break;
case WLAN_EID_EXT_CAPAB: case WLAN_EID_EXT_CAPAB:
elems->ext_capab = pos; elems->ext_capab = pos;
elems->ext_capab_len = elen; elems->ext_capab_len = elen;

View file

@ -40,6 +40,7 @@ struct ieee802_11_elems {
const u8 *wfd; const u8 *wfd;
const u8 *link_id; const u8 *link_id;
const u8 *interworking; const u8 *interworking;
const u8 *qos_map_set;
const u8 *hs20; const u8 *hs20;
const u8 *ext_capab; const u8 *ext_capab;
const u8 *bss_max_idle_period; const u8 *bss_max_idle_period;
@ -73,6 +74,7 @@ struct ieee802_11_elems {
u8 p2p_len; u8 p2p_len;
u8 wfd_len; u8 wfd_len;
u8 interworking_len; u8 interworking_len;
u8 qos_map_set_len;
u8 hs20_len; u8 hs20_len;
u8 ext_capab_len; u8 ext_capab_len;
u8 ssid_list_len; u8 ssid_list_len;

View file

@ -3805,6 +3805,11 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP " wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
"handle %p", bss->nl_mgmt); "handle %p", bss->nl_mgmt);
#ifdef CONFIG_INTERWORKING
/* QoS Map Configure */
if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
return -1;
#endif /* CONFIG_INTERWORKING */
#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING) #if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
/* GAS Initial Request */ /* GAS Initial Request */
if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0) if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)

View file

@ -708,4 +708,13 @@ static inline int wpa_drv_status(struct wpa_supplicant *wpa_s,
return wpa_s->driver->status(wpa_s->drv_priv, buf, buflen); return wpa_s->driver->status(wpa_s->drv_priv, buf, buflen);
} }
static inline int wpa_drv_set_qos_map(struct wpa_supplicant *wpa_s,
const u8 *qos_map_set, u8 qos_map_set_len)
{
if (!wpa_s->driver->set_qos_map)
return -1;
return wpa_s->driver->set_qos_map(wpa_s->drv_priv, qos_map_set,
qos_map_set_len);
}
#endif /* DRIVER_I_H */ #endif /* DRIVER_I_H */

View file

@ -1503,6 +1503,43 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s)
} }
#ifdef CONFIG_INTERWORKING
static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
size_t len)
{
int res;
wpa_hexdump(MSG_DEBUG, "Interworking: QoS Map Set", qos_map, len);
res = wpa_drv_set_qos_map(wpa_s, qos_map, len);
if (res) {
wpa_printf(MSG_DEBUG, "Interworking: Failed to configure QoS Map Set to the driver");
}
return res;
}
static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len)
{
struct ieee802_11_elems elems;
if (ies == NULL)
return;
if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
return;
if (elems.qos_map_set) {
wpas_qos_map_set(wpa_s, elems.qos_map_set,
elems.qos_map_set_len);
}
}
#endif /* CONFIG_INTERWORKING */
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
union wpa_event_data *data) union wpa_event_data *data)
{ {
@ -1527,6 +1564,10 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len); data->assoc_info.resp_ies_len);
#endif /* CONFIG_WNM */ #endif /* CONFIG_WNM */
#ifdef CONFIG_INTERWORKING
interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#endif /* CONFIG_INTERWORKING */
} }
if (data->assoc_info.beacon_ies) if (data->assoc_info.beacon_ies)
wpa_hexdump(MSG_DEBUG, "beacon_ies", wpa_hexdump(MSG_DEBUG, "beacon_ies",
@ -2906,6 +2947,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break; break;
} }
#endif /* CONFIG_TDLS */ #endif /* CONFIG_TDLS */
#ifdef CONFIG_INTERWORKING
if (data->rx_action.category == WLAN_ACTION_QOS &&
data->rx_action.len >= 1 &&
data->rx_action.data[0] == QOS_QOS_MAP_CONFIG) {
wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
MACSTR, MAC2STR(data->rx_action.sa));
if (os_memcmp(data->rx_action.sa, wpa_s->bssid, ETH_ALEN)
== 0)
wpas_qos_map_set(wpa_s, data->rx_action.data + 1,
data->rx_action.len - 1);
break;
}
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
wpas_p2p_rx_action(wpa_s, data->rx_action.da, wpas_p2p_rx_action(wpa_s, data->rx_action.da,
data->rx_action.sa, data->rx_action.sa,

View file

@ -1219,6 +1219,9 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
#endif /* CONFIG_INTERWORKING */ #endif /* CONFIG_INTERWORKING */
break; break;
case 4: /* Bits 32-39 */ case 4: /* Bits 32-39 */
#ifdef CONFIG_INTERWORKING
*pos |= 0x01; /* Bit 32 - QoS Map */
#endif /* CONFIG_INTERWORKING */
break; break;
case 5: /* Bits 40-47 */ case 5: /* Bits 40-47 */
break; break;