From patchwork Mon Nov 25 11:31:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Kwaczynski X-Patchwork-Id: 293891 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "maxx.shmoo.com", Issuer "CA Cert Signing Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 9825F2C00E3 for ; Mon, 25 Nov 2013 22:32:29 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 927E59C12D; Mon, 25 Nov 2013 06:32:08 -0500 (EST) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fMhHdAkIynop; Mon, 25 Nov 2013 06:32:08 -0500 (EST) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 293589C12E; Mon, 25 Nov 2013 06:32:03 -0500 (EST) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 62DEE9C12E for ; Mon, 25 Nov 2013 06:32:00 -0500 (EST) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id E0FbaPjH30p0 for ; Mon, 25 Nov 2013 06:31:54 -0500 (EST) Received: from mail-ea0-f178.google.com (mail-ea0-f178.google.com [209.85.215.178]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (not verified)) by maxx.maxx.shmoo.com (Postfix) with ESMTPS id 1A83E9C12D for ; Mon, 25 Nov 2013 06:31:53 -0500 (EST) Received: by mail-ea0-f178.google.com with SMTP id d10so2343530eaj.9 for ; Mon, 25 Nov 2013 03:31:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id; bh=UhM1HuqjfUZ2MeGvmI9A0rfsxqjLBR8VpIM6aoe6Zhs=; b=nLgSzVjjUNUAXJl5xbil5eFgD9aFfBRIitFWuKkWIgRes7ScLKrLcl3SQV+1NR7Qlf MHiOO1wMpmxz+hmb7MI0jFdRYI3g/qqGWbb3nwD2jzt8yWS9ZJ4xJpY0qB1ugdFMPrXg 0wxo5yJ9dFac7BGVyEVkI43lIhzQDti9CUOv4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=UhM1HuqjfUZ2MeGvmI9A0rfsxqjLBR8VpIM6aoe6Zhs=; b=Xf53t+DvYANtfFaHZ3UHexUvyWsH6gGKA3s7t5qjEp76cFFEjEWOBKqzwUl9Fh078E hkbLGM1jRw5QSYGZIGHm+kEyycWaQkyJBlr8ta4z68LUec9dmmqMg5wlN94sozsI3xFO J9fHsZ4zWS3zI/EdAWmmINS0xO1bykDGBojNnSPH2cZ4lzVEma/vWaGFgYZA/RjUUbQl t64QgQhMSl41sTsMC6mcL/2F9z6Dc7p7GkEut+oRVKFO7bTHvEMfRCm1gsgibLtTVENH +UVUV63BmzcT57T+uJTHBz7Gxfl1mhDOqeofbVLpOMPE4fV8F/CIBfaRzb0AakMrqWaI hcmg== X-Gm-Message-State: ALoCoQnyQ37c+DcrFHf6djYlGXrXA1iGHNBD7vUuv+s/xxOT03OSDn1n5OR8dDcHOMJB669Y3LmzbVB/Zp1shKv1MrTHT5qdmHrcBIsHZ5YL8iuvxABE+/M= X-Received: by 10.15.82.8 with SMTP id z8mr13051590eey.25.1385379111795; Mon, 25 Nov 2013 03:31:51 -0800 (PST) Received: from localhost.localdomain ([91.198.246.8]) by mx.google.com with ESMTPSA id z1sm93756659eeo.14.2013.11.25.03.31.50 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 25 Nov 2013 03:31:51 -0800 (PST) From: Marek Kwaczynski To: hostap@lists.shmoo.com Subject: [PATCH] hostapd: Add Operating Mode Notification support Date: Mon, 25 Nov 2013 12:31:10 +0100 Message-Id: <1385379070-4425-1-git-send-email-marek.kwaczynski@tieto.com> X-Mailer: git-send-email 1.7.9.5 X-DomainID: tieto.com Cc: j@w1.fi X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com Handling Operating Mode Notification received in Assoc Request. Signed-hostap: Marek Kwaczynski --- Dependencies: [PATCH 1/2] nl80211/cfg80211: Set VHT Operating mode [PATCH 2/2] mac80211: Update opmode during adding new station Patches were sent to linux-wireless@vger.kernel.org. Review is ongoing. src/ap/ap_drv_ops.c | 4 +++- src/ap/ap_drv_ops.h | 2 +- src/ap/ieee802_11.c | 8 +++++++- src/ap/ieee802_11.h | 2 ++ src/ap/ieee802_11_vht.c | 25 +++++++++++++++++++++++++ src/ap/sta_info.h | 3 ++- src/common/ieee802_11_common.c | 4 ++++ src/common/ieee802_11_common.h | 2 ++ src/common/ieee802_11_defs.h | 7 +++++++ src/drivers/driver.h | 2 ++ src/drivers/driver_nl80211.c | 6 ++++++ 11 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 0dc0600..3541b82 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -347,7 +347,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, u16 listen_interval, const struct ieee80211_ht_capabilities *ht_capab, const struct ieee80211_vht_capabilities *vht_capab, - u32 flags, u8 qosinfo) + u32 flags, u8 qosinfo, u8 vht_opmode) { struct hostapd_sta_add_params params; @@ -365,6 +365,8 @@ int hostapd_sta_add(struct hostapd_data *hapd, params.listen_interval = listen_interval; params.ht_capabilities = ht_capab; params.vht_capabilities = vht_capab; + params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); + params.vht_opmode = vht_opmode; params.flags = hostapd_sta_flags_to_drv(flags); params.qosinfo = qosinfo; return hapd->driver->sta_add(hapd->drv_priv, ¶ms); diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 1eab939..8fa1fb4 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -39,7 +39,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, u16 listen_interval, const struct ieee80211_ht_capabilities *ht_capab, const struct ieee80211_vht_capabilities *vht_capab, - u32 flags, u8 qosinfo); + u32 flags, u8 qosinfo, u8 vht_opmode); int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, size_t elem_len); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index d553caa..bd5ee8e 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -921,6 +921,12 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, elems.vht_capabilities_len); if (resp != WLAN_STATUS_SUCCESS) return resp; + + resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif, + elems.vht_opmode_notif_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && !(sta->flags & WLAN_STA_VHT)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, @@ -1958,7 +1964,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd, sta->listen_interval, sta->flags & WLAN_STA_HT ? &ht_cap : NULL, sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, - sta->flags, sta->qosinfo)) { + sta->flags, sta->qosinfo, sta->vht_opmode)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, "Could not add STA to kernel driver"); diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 61f1316..0c8cf8b 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -62,6 +62,8 @@ u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta); u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta, const u8 *vht_capab, size_t vht_capab_len); +u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_opmode, size_t vht_opmode_len); void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, const u8 *buf, size_t len, int ack); void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index 60e6b57..96dfd45 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -109,6 +109,31 @@ u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_SUCCESS; } +u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_oper_notif, size_t vht_oper_notif_len) +{ + u8 channel_width; + + if (!vht_oper_notif || vht_oper_notif_len != VHT_OPMODE_LEN) { + sta->flags &= ~WLAN_STA_VHT_OPMODE_ENABLED; + return WLAN_STATUS_SUCCESS; + } + channel_width = *vht_oper_notif & VHT_OPMODE_CHANNEL_WIDTH_MASK; + + if (channel_width != VHT_CHANWIDTH_USE_HT && + channel_width != VHT_CHANWIDTH_80MHZ && + channel_width != VHT_CHANWIDTH_160MHZ && + channel_width != VHT_CHANWIDTH_80P80MHZ && + (*vht_oper_notif & VHT_OPMODE_CHANNEL_RxNSS_MASK) > VHT_RX_NSS_MAX_STREAMS - 1) { + sta->flags &= ~WLAN_STA_VHT_OPMODE_ENABLED; + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + sta->flags |= WLAN_STA_VHT_OPMODE_ENABLED; + sta->vht_opmode = *vht_oper_notif; + + return WLAN_STATUS_SUCCESS; +} + void hostapd_get_vht_capab(struct hostapd_data *hapd, struct ieee80211_vht_capabilities *vht_cap, struct ieee80211_vht_capabilities *neg_vht_cap) diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index dc74219..11339f5 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -29,6 +29,7 @@ #define WLAN_STA_WPS2 BIT(16) #define WLAN_STA_GAS BIT(17) #define WLAN_STA_VHT BIT(18) +#define WLAN_STA_VHT_OPMODE_ENABLED BIT(19) #define WLAN_STA_PENDING_DISASSOC_CB BIT(29) #define WLAN_STA_PENDING_DEAUTH_CB BIT(30) #define WLAN_STA_NONERP BIT(31) @@ -105,7 +106,7 @@ struct sta_info { struct ieee80211_ht_capabilities *ht_capabilities; struct ieee80211_vht_capabilities *vht_capabilities; - + u8 vht_opmode; #ifdef CONFIG_IEEE80211W int sa_query_count; /* number of pending SA Query requests; * 0 = no SA Query in progress */ diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 304dfc6..50e692e 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -267,6 +267,10 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->vht_operation = pos; elems->vht_operation_len = elen; break; + case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION: + elems->vht_opmode_notif = pos; + elems->vht_opmode_notif_len = elen; + break; case WLAN_EID_LINK_ID: if (elen < 18) break; diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index c4618b2..19176af 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -35,6 +35,7 @@ struct ieee802_11_elems { const u8 *ht_operation; const u8 *vht_capabilities; const u8 *vht_operation; + const u8 *vht_opmode_notif; const u8 *vendor_ht_cap; const u8 *p2p; const u8 *wfd; @@ -70,6 +71,7 @@ struct ieee802_11_elems { u8 ht_operation_len; u8 vht_capabilities_len; u8 vht_operation_len; + u8 vht_opmode_notif_len; u8 vendor_ht_cap_len; u8 p2p_len; u8 wfd_len; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 9b2d54f..6e939b6 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -748,6 +748,13 @@ struct ieee80211_vht_operation { #define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28)) #define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29)) +#define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(6) | BIT(7)) +#define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(1) | BIT(2) | BIT(3)) +#define VHT_OPMODE_NOTIF_RX_NSS_SHIFT 4 +#define VHT_OPMODE_LEN 1 + +#define VHT_RX_NSS_MAX_STREAMS 8 + /* VHT channel widths */ #define VHT_CHANWIDTH_USE_HT 0 #define VHT_CHANWIDTH_80MHZ 1 diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 3502eb8..63836a9 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -983,6 +983,8 @@ struct hostapd_sta_add_params { u16 listen_interval; const struct ieee80211_ht_capabilities *ht_capabilities; const struct ieee80211_vht_capabilities *vht_capabilities; + int vht_opmode_enabled; + u8 vht_opmode; u32 flags; /* bitmask of WPA_STA_* flags */ int set; /* Set STA parameters instead of add */ u8 qosinfo; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 64ab29a..4bdb516 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -6958,6 +6958,12 @@ static int wpa_driver_nl80211_sta_add(void *priv, params->vht_capabilities); } + if (params->vht_opmode_enabled) { + wpa_printf(MSG_DEBUG, " * opmode=%u", params->vht_opmode); + NLA_PUT_U8(msg, NL80211_ATTR_VHT_OPMODE, + params->vht_opmode); + } + wpa_printf(MSG_DEBUG, " * capability=0x%x", params->capability); NLA_PUT_U16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability);