From patchwork Tue Apr 24 13:08:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajkumar Manoharan X-Patchwork-Id: 154674 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]) by ozlabs.org (Postfix) with ESMTP id AF68DB6FBB for ; Tue, 24 Apr 2012 23:08:25 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 8A0E99D24A; Tue, 24 Apr 2012 09:08:21 -0400 (EDT) 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 g+x8o0gc6ORc; Tue, 24 Apr 2012 09:08:21 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id DD0D49D256; Tue, 24 Apr 2012 09:08:04 -0400 (EDT) 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 9551E9D261 for ; Tue, 24 Apr 2012 09:08:03 -0400 (EDT) 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 t3HQOOE5oRez for ; Tue, 24 Apr 2012 09:07:58 -0400 (EDT) Received: from wolverine01.qualcomm.com (wolverine01.qualcomm.com [199.106.114.254]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "wolverine01.qualcomm.com", Issuer "VeriSign Class 3 Secure Server CA" (not verified)) by maxx.maxx.shmoo.com (Postfix) with ESMTPS id 96D309C1BA for ; Tue, 24 Apr 2012 09:07:53 -0400 (EDT) X-IronPort-AV: E=McAfee;i="5400,1158,6690"; a="184418314" Received: from ironmsg03-r.qualcomm.com ([172.30.46.17]) by wolverine01.qualcomm.com with ESMTP; 24 Apr 2012 06:07:52 -0700 X-IronPort-AV: E=Sophos;i="4.75,470,1330934400"; d="scan'208";a="240265304" Received: from nasanexhc05.na.qualcomm.com ([172.30.48.2]) by Ironmsg03-R.qualcomm.com with ESMTP/TLS/AES128-SHA; 24 Apr 2012 06:07:52 -0700 Received: from qcmail1.qualcomm.com (172.30.48.1) by qcmail1.qualcomm.com (172.30.48.2) with Microsoft SMTP Server (TLS) id 14.2.283.3; Tue, 24 Apr 2012 06:07:50 -0700 Received: by qcmail1.qualcomm.com (sSMTP sendmail emulation); Tue, 24 Apr 2012 18:38:45 +0530 From: Rajkumar Manoharan To: Subject: [PATCH 2/3] wpa_supplicant: Add 2040 BSS intolerance support in station mode Date: Tue, 24 Apr 2012 18:38:36 +0530 Message-ID: <1335272917-7503-2-git-send-email-rmanohar@qca.qualcomm.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1335272917-7503-1-git-send-email-rmanohar@qca.qualcomm.com> References: <1335272917-7503-1-git-send-email-rmanohar@qca.qualcomm.com> MIME-Version: 1.0 X-Originating-IP: [172.30.48.1] Cc: hostap@lists.shmoo.com X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com Add support for HT STA to report 40MHz intolerance to the associated AP. A HT station generates a report (2040 BSS coexistence) of channel list if it finds a non-HT capable AP or a HT AP which prohibits 40MHz transmission (i.e 40MHz intolerant bit is set in HT capabilities IE) from the scan results. Signed-off-by: Rajkumar Manoharan --- wpa_supplicant/events.c | 6 ++ wpa_supplicant/sme.c | 151 +++++++++++++++++++++++++++++++++++++ wpa_supplicant/sme.h | 6 ++ wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 164 insertions(+) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 8fdc544..a0bd903 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1096,6 +1096,12 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid); + /* + * TODO: This should be done at the completion of OBSS scan operations + * which may or may not be identical to other scans.. + */ + sme_proc_40mhz_intolerant(wpa_s); + if (selected) { int skip; skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid, diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index b366847..07f5d3e 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -609,6 +609,157 @@ void sme_deinit(struct wpa_supplicant *wpa_s) } +static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s, + const u8 *chan_list, u8 num_channels, + u8 num_intol) +{ + struct ieee80211_2040_bss_coex_ie *bc_ie; + struct ieee80211_2040_intol_chan_report *ic_report; + struct wpabuf *buf; + + wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR, + MAC2STR(wpa_s->bssid)); + + buf = wpabuf_alloc(2 + /* action.category + action_code */ + sizeof(struct ieee80211_2040_bss_coex_ie) + + sizeof(struct ieee80211_2040_intol_chan_report) + + num_channels); + if (buf == NULL) + return; + + wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); + wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX); + + bc_ie = wpabuf_put(buf, sizeof(*bc_ie)); + bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE; + bc_ie->length = 1; + if (num_intol) + bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ; + + ic_report = wpabuf_put(buf, sizeof(*ic_report)); + ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT; + ic_report->length = num_channels + 1; + ic_report->op_class = 0; + + os_memcpy(wpabuf_put(buf, num_channels), chan_list, num_channels); + + if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "SME: Failed to send 20/40 BSS Coexistence frame"); + } + + wpabuf_free(buf); +} + +/** + * enum wpas_band - Frequency band + * @WPAS_BAND_2GHZ: 2.4 GHz ISM band + * @WPAS_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + */ +enum wpas_band { + WPAS_BAND_2GHZ, + WPAS_BAND_5GHZ, + WPAS_BAND_INVALID +}; + +/** + * freq_to_channel - Convert frequency into channel info + * @channel: Buffer for returning channel number + * Returns: Band (2 or 5 GHz) + */ +static enum wpas_band freq_to_channel(int freq, u8 *channel) +{ + enum wpas_band band = (freq <= 2484) ? WPAS_BAND_2GHZ : WPAS_BAND_5GHZ; + u8 chan = 0; + + if (freq >= 2412 && freq <= 2472) + chan = (freq - 2407) / 5; + else if (freq == 2484) + chan = 14; + else if (freq >= 5180 && freq <= 5805) + chan = (freq - 5000) / 5; + + *channel = chan; + return band; +} + +void sme_proc_40mhz_intolerant(struct wpa_supplicant *wpa_s) +{ + struct wpa_bss *bss; + enum wpas_band assoc_band; + const u8 *ie; + u16 ht_cap; + u8 chan_list[P2P_MAX_CHANNELS], channel; + u8 num_channels = 0, num_intol = 0, i; + + if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED) + return; + + /* Check whether local driver supports HT40 */ + if (!wpa_s->hw.modes || + !(wpa_s->hw.modes->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) + return; + + /* Check whether AP supports HT40 */ + ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION); + if (!ie || ie[1] < 2 || + !(ie[3] & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH)) + return; + + /* + * Check whether AP uses regulatory triplet or channel triplet in + * country info. Right now the operating class of the BSS channel + * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12), + * based on the assumption that operating class triplet is not used in + * beacon frame. If the First Channel Number/Operating Extension + * Identifier octet has a positive integer value of 201 or greater, + * then its operating class triplet. + * + * TODO: If Supported Operating Classes element is present in beacon + * frame, have to lookup operating class in Annex E and fill them in + * 2040 coex frame. + */ + ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY); + if (ie && (ie[1] >= 6) && (ie[5] >= 201)) + return; + + assoc_band = freq_to_channel(wpa_s->current_bss->freq, &channel); + if (assoc_band != WPAS_BAND_2GHZ) + return; + + os_memset(chan_list, 0, sizeof(chan_list)); + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + /* Skip other band bss */ + if (freq_to_channel(bss->freq, &channel) != assoc_band) + continue; + + ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP); + ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0; + + if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) { + /* Check whether the channel is already considered */ + for (i = 0; i < num_channels; i++) { + if (channel == chan_list[i]) + break; + } + if (i != num_channels) + continue; + + if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT) + num_intol++; + + chan_list[num_channels++] = channel; + } + } + + if (num_channels) + sme_send_2040_bss_coex(wpa_s, chan_list, + num_channels, num_intol); +} + #ifdef CONFIG_IEEE80211W static const unsigned int sa_query_max_timeout = 1000; diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h index 33530bb..f735832 100644 --- a/wpa_supplicant/sme.h +++ b/wpa_supplicant/sme.h @@ -35,6 +35,8 @@ void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, const u8 *prev_pending_bssid); void sme_deinit(struct wpa_supplicant *wpa_s); +void sme_proc_40mhz_intolerant(struct wpa_supplicant *wpa_s); + #else /* CONFIG_SME */ static inline void sme_authenticate(struct wpa_supplicant *wpa_s, @@ -95,6 +97,10 @@ static inline void sme_deinit(struct wpa_supplicant *wpa_s) { } +static inline void sme_proc_40mhz_intolerant(struct wpa_supplicant *wpa_s) +{ +} + #endif /* CONFIG_SME */ #endif /* SME_H */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index b25116e..f3fb01f 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -628,6 +628,7 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s); void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s); void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s); +void wpa_supplicant_proc_40mhz_intolerant(struct wpa_supplicant *wpa_s); /* events.c */ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s);