From patchwork Wed Apr 18 13:44:09 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajkumar Manoharan X-Patchwork-Id: 153513 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 7A35CB7021 for ; Wed, 18 Apr 2012 23:44:36 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 7D2E39D225; Wed, 18 Apr 2012 09:44:34 -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 rcjqahRgs3aQ; Wed, 18 Apr 2012 09:44:34 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id DB0489D21D; Wed, 18 Apr 2012 09:43:53 -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 A85E49D21B for ; Wed, 18 Apr 2012 09:43:52 -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 eP9rr3KHNlEw for ; Wed, 18 Apr 2012 09:43:41 -0400 (EDT) Received: from wolverine02.qualcomm.com (wolverine02.qualcomm.com [199.106.114.251]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "wolverine02.qualcomm.com", Issuer "VeriSign Class 3 Secure Server CA" (not verified)) by maxx.maxx.shmoo.com (Postfix) with ESMTPS id 0893E9D1F0 for ; Wed, 18 Apr 2012 09:43:31 -0400 (EDT) X-IronPort-AV: E=McAfee;i="5400,1158,6684"; a="180454279" Received: from ironmsg02-l.qualcomm.com ([172.30.48.16]) by wolverine02.qualcomm.com with ESMTP; 18 Apr 2012 06:43:31 -0700 X-IronPort-AV: E=Sophos;i="4.75,441,1330934400"; d="scan'208";a="120459715" Received: from nasanexhc07.na.qualcomm.com ([172.30.39.190]) by ironmsg02-L.qualcomm.com with ESMTP/TLS/AES128-SHA; 18 Apr 2012 06:43:31 -0700 Received: from qcmail1.qualcomm.com (172.30.39.5) by qcmail1.qualcomm.com (172.30.39.190) with Microsoft SMTP Server (TLS) id 14.2.283.3; Wed, 18 Apr 2012 06:43:29 -0700 Received: by qcmail1.qualcomm.com (sSMTP sendmail emulation); Wed, 18 Apr 2012 19:14:21 +0530 From: Rajkumar Manoharan To: Subject: [RFC 2/3] wpa_supplicant: Add 2040 BSS intolerance support in station mode Date: Wed, 18 Apr 2012 19:14:09 +0530 Message-ID: <1334756650-10624-2-git-send-email-rmanohar@qca.qualcomm.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1334756650-10624-1-git-send-email-rmanohar@qca.qualcomm.com> References: <1334756650-10624-1-git-send-email-rmanohar@qca.qualcomm.com> MIME-Version: 1.0 X-Originating-IP: [172.30.39.5] 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 | 4 ++ wpa_supplicant/sme.c | 42 +++++++++++++++++ wpa_supplicant/sme.h | 8 ++++ wpa_supplicant/wpa_supplicant.c | 92 +++++++++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 1 + wpa_supplicant/wps_supplicant.h | 11 +++++ 6 files changed, 158 insertions(+) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 8fdc544..8018a69 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1096,6 +1096,10 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid); +#ifdef CONFIG_SME + wpa_supplicant_proc_40mhz_intolerant(wpa_s); +#endif /* CONFIG_SME */ + 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..8f5f628 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -609,6 +609,48 @@ void sme_deinit(struct wpa_supplicant *wpa_s) } +void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s, + const u8 *chan_list, u8 num_channels) +{ + 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; + 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; + + 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); +} + + #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..8bdb638 100644 --- a/wpa_supplicant/sme.h +++ b/wpa_supplicant/sme.h @@ -35,6 +35,9 @@ 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_send_2040_bss_coex(struct wpa_supplicant *wpa_s, + const u8 *chan_list, u8 n_channels); + #else /* CONFIG_SME */ static inline void sme_authenticate(struct wpa_supplicant *wpa_s, @@ -95,6 +98,11 @@ static inline void sme_deinit(struct wpa_supplicant *wpa_s) { } +static inline void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s, + const u8 *chan_list, u8 n_channels) +{ +} + #endif /* CONFIG_SME */ #endif /* SME_H */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index c5a7115..5d4de3c 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3216,3 +3216,95 @@ int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s) return wpa_s->conf->ap_scan == 2 || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION); } + + +#ifdef CONFIG_SME +/** + * 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 wpa_supplicant_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, 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" (IEEE802.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); + 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; + + chan_list[num_channels++] = channel; + } + } + + if (num_channels) + sme_send_2040_bss_coex(wpa_s, chan_list, num_channels); +} +#endif /* CONFIG_SME */ 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); diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h index a5472a0..31f0274 100644 --- a/wpa_supplicant/wps_supplicant.h +++ b/wpa_supplicant/wps_supplicant.h @@ -25,6 +25,17 @@ struct wps_new_ap_settings { const char *key_hex; }; +/** + * 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 +}; + int wpas_wps_init(struct wpa_supplicant *wpa_s); void wpas_wps_deinit(struct wpa_supplicant *wpa_s); int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s);