Patchwork hostapd: 11ac (VHT) Association

login
register
mail settings
Submitter Mahesh Palivela
Date Aug. 7, 2012, 9:46 a.m.
Message ID <5020E3F8.7000705@posedge.com>
Download mbox | patch
Permalink /patch/175556/
State Not Applicable
Headers show

Comments

Mahesh Palivela - Aug. 7, 2012, 9:46 a.m.
11ac (VHT) Association related change. To Parse VHT IEs in Assoc 
request, save VHT data and send assoc resp with VHT IEs.
Includes config changes for VHT

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(-)

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;