From patchwork Mon Feb 3 14:55:19 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Kwaczynski X-Patchwork-Id: 316171 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 ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 1A2622C0091 for ; Tue, 4 Feb 2014 01:56:32 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 86F479D260; Mon, 3 Feb 2014 09:56:30 -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 mI3rlXyb+H3l; Mon, 3 Feb 2014 09:56:30 -0500 (EST) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 7D9219C1A2; Mon, 3 Feb 2014 09:56:25 -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 AF4329C1A2 for ; Mon, 3 Feb 2014 09:56:23 -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 wgiNHOL7epvA for ; Mon, 3 Feb 2014 09:56:18 -0500 (EST) Received: from mail-ee0-f45.google.com (mail-ee0-f45.google.com [74.125.83.45]) (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 0CDE89C194 for ; Mon, 3 Feb 2014 09:56:17 -0500 (EST) Received: by mail-ee0-f45.google.com with SMTP id b15so3664847eek.32 for ; Mon, 03 Feb 2014 06:56:15 -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=rK1+9zFK2GMD3Jv1h51lj7Z0KVTY4puM+cwWTQfkYfo=; b=jE06iKnNaLoXoz3wnzzvf7I709UKHUZ75k+ENA0hHl99ri27JteVw5ctQw70xnw+1O 5F4NRlJJ6G4vlY5rlOkhslJ15Fk6m/ifTf4JX/QTZyotVnZ28dxLyL6mIAORClosRnRP HQ8cx1pc+kFFGya0xekGHkAKjMbB2tFmzsc9U= 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=rK1+9zFK2GMD3Jv1h51lj7Z0KVTY4puM+cwWTQfkYfo=; b=k1BD/cILfTiPoPt0Ac1v9oRQgKyIf9IaAvdIm+VijTVLScKmZjuLOXlFDYn4Cxv1Xj LLis6XW4qEBtj6P8Dk74ldP3xYhU4v8+/hdpnWcpjUWkxMGY8EzmL9YfAKrwtLGB4TA9 M3pjmlR8DRsIKRwx0FnxxRRyIQQEqJDVQ5Y5FLIVoYfR7zR6z52ZFhhCFIorIEMbuuvE 5/rSnFT6GwqVrhm/gMTJKfla+B59XnKzoY8xZaIigGY/BEE+KQjSXwcmXw/tMpWLIldb iSgu3IuIoyLuAlJU0XVmr/+l4HGH3FH4KF7plBbaHeXx4FXoJpxIlWBRJEmk/8MkFgLI ZYiA== X-Gm-Message-State: ALoCoQkPyC+YR0RsG1GlwjCOwjgMKysX6YJkMZ3wMoNv8geBQ2RZ0nnWFeorQc1mtKdGOSrNps6Q8zdk0WzyQ60UEt/jXj5fYYcJAn8P/uQYtW9c2vE9V7M= X-Received: by 10.15.35.194 with SMTP id g42mr43639771eev.20.1391439375517; Mon, 03 Feb 2014 06:56:15 -0800 (PST) Received: from localhost.localdomain ([91.198.246.8]) by mx.google.com with ESMTPSA id x2sm75824332eeo.8.2014.02.03.06.56.09 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 03 Feb 2014 06:56:12 -0800 (PST) From: Marek Kwaczynski To: hostap@lists.shmoo.com Subject: [PATCH V3] hostapd: Add Operating Mode Notification support Date: Mon, 3 Feb 2014 15:55:19 +0100 Message-Id: <1391439319-28071-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 --- Required patches in mac80211 were applied. 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 | 26 ++++++++++++++++++++++++++ src/ap/sta_info.h | 2 ++ 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, 62 insertions(+), 3 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 893e6d9..e998fc6 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -346,7 +346,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; @@ -364,6 +364,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 15a4b26..9edaf7d 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -40,7 +40,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 dee3c7a..d22b2a0 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -910,6 +910,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, @@ -1953,7 +1959,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 5edeb71..4966bcd 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 f2ab182..136a9dd 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -108,6 +108,32 @@ 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 9b77e06..1973af6 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -27,6 +27,7 @@ #define WLAN_STA_GAS BIT(17) #define WLAN_STA_VHT BIT(18) #define WLAN_STA_WNM_SLEEP_MODE BIT(19) +#define WLAN_STA_VHT_OPMODE_ENABLED BIT(20) #define WLAN_STA_PENDING_DISASSOC_CB BIT(29) #define WLAN_STA_PENDING_DEAUTH_CB BIT(30) #define WLAN_STA_NONERP BIT(31) @@ -104,6 +105,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 809089f..cc58ea2 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -252,6 +252,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 b84dd9e..178bdb6 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -30,6 +30,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; @@ -60,6 +61,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 6f7f777..a927ed3 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -764,6 +764,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 2f4536e..f4b4672 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1007,6 +1007,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 81f20b3..20642a1 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -7347,6 +7347,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_OPMODE_NOTIF, + params->vht_opmode); + } + wpa_printf(MSG_DEBUG, " * capability=0x%x", params->capability); NLA_PUT_U16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability);