Patchwork hostapd: 11ac Association

login
register
mail settings
Submitter Mahesh Palivela
Date July 23, 2012, 9:24 a.m.
Message ID <952C5D5D0470AE4FB7D8A75C6ADC71CA0FCC5E4A@mbx022-e1-nj-10.exch022.domain.local>
Download mbox | patch
Permalink /patch/172597/
State Accepted
Headers show

Comments

Mahesh Palivela - July 23, 2012, 9:24 a.m.
11ac Association related change. To Parse VHT IEs in Assoc request, save VHT data and send assoc resp with VHT IEs.

Signed-hostap: Mahesh Palivela <maheshp@posedge.com>
---
 hostapd/config_file.c          |    4 ++++
 hostapd/hostapd.conf           |   14 ++++++++++++++
 src/ap/ap_config.h             |    2 ++
 src/ap/ieee802_11.c            |   21 ++++++++++++++++++++-
 src/ap/ieee802_11.h            |    2 ++
 src/ap/ieee802_11_vht.c        |   36 ++++++++++++++++++++++++++++++++++++
 src/ap/sta_info.h              |    2 ++
 src/common/ieee802_11_common.c |    8 ++++++++
 src/common/ieee802_11_common.h |    4 ++++
 9 files changed, 92 insertions(+), 1 deletions(-)
Jouni Malinen - Aug. 10, 2012, 4:57 p.m.
On Mon, Jul 23, 2012 at 09:24:27AM +0000, Mahesh Palivela wrote:
> 11ac Association related change. To Parse VHT IEs in Assoc request, save VHT data and send assoc resp with VHT IEs.

Thanks, applied.

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index eebbaa6..c6e1215 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2200,8 +2200,12 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 					   "vht_capab", line);
 				errors++;
 			}
+		} else if (os_strcmp(buf, "require_vht") == 0) {
+		    conf->require_vht = atoi(pos);
 		} else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
 		    conf->vht_oper_chwidth = atoi(pos);
+		} else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
+		    conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
 #endif /* CONFIG_IEEE80211AC */
 		} else if (os_strcmp(buf, "max_listen_interval") == 0) {
 			bss->max_listen_interval = atoi(pos);
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 494f7ca..5d05ca8 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -545,7 +545,21 @@  wmm_ac_vo_acm=0
 # 0 = Tx antenna pattern might change during the lifetime of an association
 # 1 = Tx antenna pattern does not change during the lifetime of an association
 #vht_capab=[SHORT-GI-80][HTC-VHT]
+#
+# Require stations to support VHT PHY (reject association if they do not)
+#require_vht=1
+
+# 0 = 20 or 40 MHz operating Channel width
+# 1 = 80 MHz channel width
+# 2 = 160 MHz channel width
+# 3 = 80+80 MHz channel width
 #vht_oper_chwidth=1
+#
+# center freq = 5GHz + (5 * index)
+# So index 42 gives center freq 5.210 GHz
+# which is channel 42 in 5G band
+#
+#vht_oper_centr_freq_seg0_idx=42
 
 ##### IEEE 802.1X-2004 related configuration ##################################
 
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index ca4fe58..3e3d634 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -455,7 +455,9 @@  struct hostapd_config {
 	int require_ht;
 	u32 vht_capab;
 	int ieee80211ac;
+	int require_vht;
 	u8 vht_oper_chwidth;
+	u8 vht_oper_centr_freq_seg0_idx;
 };
 
 
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 3996c90..c9e77e4 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -648,6 +648,20 @@  static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
 	}
 #endif /* CONFIG_IEEE80211N */
 
+#ifdef CONFIG_IEEE80211AC
+	resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities,
+				 elems.vht_capabilities_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,
+			       HOSTAPD_LEVEL_INFO, "Station does not support "
+			       "mandatory VHT PHY - reject association");
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+#endif /* CONFIG_IEEE80211AC */
+
 	if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
 		wpa_ie = elems.rsn_ie;
 		wpa_ie_len = elems.rsn_ie_len;
@@ -771,7 +785,7 @@  static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
 #endif /* CONFIG_IEEE80211R */
 
 #ifdef CONFIG_IEEE80211N
-		if ((sta->flags & WLAN_STA_HT) &&
+		if (((sta->flags & WLAN_STA_HT) || (sta->flags & WLAN_STA_VHT)) &&
 		    wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
 			hostapd_logger(hapd, sta->addr,
 				       HOSTAPD_MODULE_IEEE80211,
@@ -875,6 +889,11 @@  static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 	p = hostapd_eid_ht_operation(hapd, p);
 #endif /* CONFIG_IEEE80211N */
 
+#ifdef CONFIG_IEEE80211AC
+	p = hostapd_eid_vht_capabilities(hapd, p);
+	p = hostapd_eid_vht_operation(hapd, p);
+#endif /* CONFIG_IEEE80211AC */
+
 	p = hostapd_eid_ext_capab(hapd, p);
 	p = hostapd_eid_bss_max_idle_period(hapd, p);
 
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 9993bee..7a631b4 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -56,6 +56,8 @@  void hostapd_get_ht_capab(struct hostapd_data *hapd,
 u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
 		      const u8 *ht_capab, size_t ht_capab_len);
 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);
 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 3ad33c8..7e3ed56 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -61,6 +61,14 @@  u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
 	oper = (struct ieee80211_vht_operation *) pos;
 	os_memset(oper, 0, sizeof(*oper));
 
+	/*
+	 * center freq = 5GHz + (5 * index)
+	 * So index 42 gives center freq 5.210 GHz
+	 * which is channel 42 in 5G band
+	 */
+	oper->vht_op_info_chan_center_freq_seg0_idx = 
+		hapd->iconf->vht_oper_centr_freq_seg0_idx;
+
 	oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth;
 
 	/* VHT Basic MCS set comes from hw */
@@ -70,3 +78,31 @@  u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
 
 	return pos;
 }
+
+u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+		      const u8 *vht_capab, size_t vht_capab_len)
+{
+	/* Disable VHT caps for STAs associated to no-VHT BSSes. */
+	if (!vht_capab ||
+	    vht_capab_len < sizeof(struct ieee80211_vht_capabilities) ||
+	    hapd->conf->disable_11ac) {
+		sta->flags &= ~WLAN_STA_VHT;
+		os_free(sta->vht_capabilities);
+		sta->vht_capabilities = NULL;
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	if (sta->vht_capabilities == NULL) {
+		sta->vht_capabilities =
+			os_zalloc(sizeof(struct ieee80211_vht_capabilities));
+		if (sta->vht_capabilities == NULL)
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+
+	sta->flags |= WLAN_STA_VHT;
+	os_memcpy(sta->vht_capabilities, vht_capab,
+		  sizeof(struct ieee80211_vht_capabilities));
+
+	return WLAN_STATUS_SUCCESS;
+}
+
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index cef428d..b5d0f11 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -28,6 +28,7 @@ 
 #define WLAN_STA_ASSOC_REQ_OK BIT(15)
 #define WLAN_STA_WPS2 BIT(16)
 #define WLAN_STA_GAS BIT(17)
+#define WLAN_STA_VHT BIT(18)
 #define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
 #define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
 #define WLAN_STA_NONERP BIT(31)
@@ -97,6 +98,7 @@  struct sta_info {
 	u8 *psk; /* PSK from RADIUS authentication server */
 
 	struct ieee80211_ht_capabilities *ht_capabilities;
+	struct ieee80211_vht_capabilities *vht_capabilities;
 
 #ifdef CONFIG_IEEE80211W
 	int sa_query_count; /* number of pending SA Query requests;
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index d65675c..72dff2f 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -253,6 +253,14 @@  ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
 			elems->ht_operation = pos;
 			elems->ht_operation_len = elen;
 			break;
+		case WLAN_EID_VHT_CAP:
+			elems->vht_capabilities = pos;
+			elems->vht_capabilities_len = elen;
+			break;
+		case WLAN_EID_VHT_OPERATION:
+			elems->vht_operation = pos;
+			elems->vht_operation_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 d9b2b6c..5ff7429 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -33,6 +33,8 @@  struct ieee802_11_elems {
 	const u8 *timeout_int;
 	const u8 *ht_capabilities;
 	const u8 *ht_operation;
+	const u8 *vht_capabilities;
+	const u8 *vht_operation;
 	const u8 *vendor_ht_cap;
 	const u8 *p2p;
 	const u8 *link_id;
@@ -63,6 +65,8 @@  struct ieee802_11_elems {
 	u8 timeout_int_len;
 	u8 ht_capabilities_len;
 	u8 ht_operation_len;
+	u8 vht_capabilities_len;
+	u8 vht_operation_len;
 	u8 vendor_ht_cap_len;
 	u8 p2p_len;
 	u8 interworking_len;