From patchwork Thu Nov 21 12:21:55 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Kwaczynski X-Patchwork-Id: 293103 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 B26E02C008C for ; Thu, 21 Nov 2013 23:22:21 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 977639D1E6; Thu, 21 Nov 2013 07:22:19 -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 gv6XBezaMum7; Thu, 21 Nov 2013 07:22:19 -0500 (EST) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 9016A9D22E; Thu, 21 Nov 2013 07:22:14 -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 DCB959D22E for ; Thu, 21 Nov 2013 07:22:13 -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 vRwdmpWKvLNe for ; Thu, 21 Nov 2013 07:22:08 -0500 (EST) Received: from mail-ee0-f46.google.com (mail-ee0-f46.google.com [74.125.83.46]) (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 9789D9D1E6 for ; Thu, 21 Nov 2013 07:22:08 -0500 (EST) Received: by mail-ee0-f46.google.com with SMTP id c4so4686063eek.33 for ; Thu, 21 Nov 2013 04:22:07 -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=jf53Xqf8P6qhTOvxx0NDx8uSlrstcIaDzHkWziiI0jo=; b=hNEmtUh7Q1FKWgGOOoQ785RaAXu/Tt+ryqWIg9WUJuxD/6TtYdyEKI/Ks7IuvSH6kw agLQq0YJ9AzjV/75q4cswacX21FzxD2QIFg/5UhLivwXub0io56+OYPnqjT+EK2PNrl4 Ejh/sxnTA4geZfoVHBOdILIfv4UVBpp1z90P8= 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=jf53Xqf8P6qhTOvxx0NDx8uSlrstcIaDzHkWziiI0jo=; b=EJvImfsEuxO+ZCr/a+Y/pPYryDXjmTUvgc27uM7HHunUuBoqLfrIEfPcjDhgiTB0uB 4hRP+ikq6mfr4/hNxmBgii4sFQUox7RXN4o882+eKA+VCWUZkbVneR0qJniRpNJS4wof 2VSofPdD/nzgzx57VHTFKyCOkG/VzYaptnfL+4zZr9kAIRYbaKmIFD3jsx9V1o54ry/b ZKB9hq7B8lk93irtB81ajvu7bpz8VOd2Z9kSkX6hYpzOLQ9vsGwMG91PKFNY/G9af6Xk 00MXu909nHZNFRP8TBLQ0B7C1ubZa6hRbzC4O+yOyJynsKyKANUMuuF37Zr1p2XARRp2 8Wag== X-Gm-Message-State: ALoCoQkwEKWr8SInrWK65+Wc+/vo8QpEA19/FSqRT1TvgUrbJEJbg8WVFhJujsL6bUdey3gbTSVulb2h74iOkbjWOFMjA7OnfxS27N8fraALs9wbadp9C3s= X-Received: by 10.14.101.4 with SMTP id a4mr8546637eeg.28.1385036527315; Thu, 21 Nov 2013 04:22:07 -0800 (PST) Received: from localhost.localdomain ([91.198.246.8]) by mx.google.com with ESMTPSA id 44sm69655748eek.5.2013.11.21.04.22.05 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 21 Nov 2013 04:22:06 -0800 (PST) From: Marek Kwaczynski To: hostap@lists.shmoo.com Subject: [PATCH] hostapd: Add Operating Mode Notification support Date: Thu, 21 Nov 2013 13:21:55 +0100 Message-Id: <1385036515-11234-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-off-by: Marek Kwaczynski --- 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 ++++++ src/drivers/nl80211_copy.h | 5 +++++ 12 files changed, 66 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 38590a3..230d821 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 2a80419..1211e5b 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 9b2f81e..b05cc79 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -6948,6 +6948,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); diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index f752e98..16f16c8 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -1508,6 +1508,9 @@ enum nl80211_commands { * to react to radar events, e.g. initiate a channel switch or leave the * IBSS network. * + * @NL80211_ATTR_VHT_OPMODE: VHT Operating mode information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1824,6 +1827,8 @@ enum nl80211_attrs { NL80211_ATTR_HANDLE_DFS, + NL80211_ATTR_VHT_OPMODE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST,