From patchwork Mon Jul 27 19:24:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilan Peer X-Patchwork-Id: 500616 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 CDD8B1401F6 for ; Tue, 28 Jul 2015 05:29:16 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id B77B017C181; Mon, 27 Jul 2015 15:29:06 -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 3B-3gUHIMnFO; Mon, 27 Jul 2015 15:29:06 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id E0C0C17C2B7; Mon, 27 Jul 2015 15:25:55 -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 4BB5717C395 for ; Mon, 27 Jul 2015 15:25:54 -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 t+7mfoQDJJiK for ; Mon, 27 Jul 2015 15:25:49 -0400 (EDT) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 3E4B917C2B6 for ; Mon, 27 Jul 2015 15:25:12 -0400 (EDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 27 Jul 2015 12:25:12 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,556,1432623600"; d="scan'208";a="770883285" Received: from unknown (HELO ipeer-dev-3.jer.intel.com) ([10.12.217.137]) by fmsmga002.fm.intel.com with ESMTP; 27 Jul 2015 12:25:11 -0700 From: Ilan Peer To: hostap@lists.shmoo.com Subject: [PATCH 11/17] P2P: Allow additional operating channels for P2P GO and client Date: Mon, 27 Jul 2015 22:24:28 +0300 Message-Id: <1438025074-23392-12-git-send-email-ilan.peer@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1438025074-23392-1-git-send-email-ilan.peer@intel.com> References: <1438025074-23392-1-git-send-email-ilan.peer@intel.com> 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 Enable using additional frequencies for P2P GO and P2P Client. 1. Allow using indoor channels iff allowed. 2. If indoor channels are not allowed, do not allow them even for P2P client usage. 3. Allow using a channel for P2P GO iff there is an additional station interface associated on that channel. 4. On relevant wpa_supplicant interface state change, update the P2P device with the new allowed frequency configuration. Signed-off-by: Ilan Peer --- src/ap/hw_features.c | 11 ++- wpa_supplicant/p2p_supplicant.c | 175 +++++++++++++++++++++++++++++++++------- wpa_supplicant/p2p_supplicant.h | 1 + 3 files changed, 154 insertions(+), 33 deletions(-) diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 7cb7e88..8b8787f 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -118,11 +118,16 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) } else if (((feature->channels[j].flag & HOSTAPD_CHAN_RADAR) && !(iface->drv_flags & - WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || - (feature->channels[j].flag & - HOSTAPD_CHAN_NO_IR)) { + WPA_DRIVER_FLAGS_DFS_OFFLOAD))) { feature->channels[j].flag |= HOSTAPD_CHAN_DISABLED; + } else if ((feature->channels[j].flag & + HOSTAPD_CHAN_NO_IR) && + !(feature->channels[j].flag & + (HOSTAPD_CHAN_INDOOR_ONLY | + HOSTAPD_CHAN_GO_CONCURRENT))) { + feature->channels[j].flag |= + HOSTAPD_CHAN_DISABLED; } if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index b52580a..af5b916 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3157,34 +3157,97 @@ static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, enum chan_allowed { - NOT_ALLOWED, NO_IR, ALLOWED + NOT_ALLOWED, NO_IR, INDOOR_ONLY, ALLOWED }; +static int wpas_p2p_get_unii(int freq) +{ + /* UNII-1 */ + if (freq >= 5150 && freq <= 5250) + return 0; + + /* UNII-2A */ + if (freq > 5250 && freq <= 5350) + return 1; + + /* UNII-2B */ + if (freq > 5350 && freq <= 5470) + return 2; + + /* UNII-2C */ + if (freq > 5470 && freq <= 5725) + return 3; + + /* UNII-3 */ + if (freq > 5725 && freq <= 5825) + return 4; + + return -1; +} + + +static unsigned int wpas_p2p_same_unii(int freq1, int freq2) +{ + int r1 = wpas_p2p_get_unii(freq1); + int r2 = wpas_p2p_get_unii(freq2); + + return (r1 != -1 && r1 == r2) ? 1 : 0; +} + + static int has_channel(struct wpa_global *global, - struct hostapd_hw_modes *mode, u8 chan, int *flags) + struct hostapd_hw_modes *mode, + u8 chan, int *flags, + struct wpa_used_freq_data *freqs, + unsigned int num) { - int i; - unsigned int freq; + int i, freq; + unsigned int j, is_shared_freq; freq = (mode->mode == HOSTAPD_MODE_IEEE80211A ? 5000 : 2407) + chan * 5; if (wpas_p2p_disallowed_freq(global, freq)) return NOT_ALLOWED; + /* Consider a frequency as usable for the GO_CONCURRENT relaxation iff + * the frequency is used by a BSS in 2.4 or is in the same UNII band as + * as a freq used by the BSS + */ + for (j = 0, is_shared_freq = 0; freqs && j < num; j++) { + if ((freqs[j].freq == freq || + wpas_p2p_same_unii(freqs[j].freq, freq)) && + freqs[j].flags & WPA_FREQ_USED_BY_INFRA_STATION) { + is_shared_freq = 1; + break; + } + } + for (i = 0; i < mode->num_channels; i++) { - if (mode->channels[i].chan == chan) { - if (flags) - *flags = mode->channels[i].flag; - if (mode->channels[i].flag & - (HOSTAPD_CHAN_DISABLED | - HOSTAPD_CHAN_RADAR)) - return NOT_ALLOWED; - if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR) + if (mode->channels[i].chan != chan) + continue; + + if (flags) + *flags = mode->channels[i].flag; + if (mode->channels[i].flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) + return NOT_ALLOWED; + + if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR) { + if (is_shared_freq && (mode->channels[i].flag & + HOSTAPD_CHAN_GO_CONCURRENT)) + return ALLOWED; + else if (mode->channels[i].flag & + HOSTAPD_CHAN_INDOOR_ONLY) + return INDOOR_ONLY; + else return NO_IR; - return ALLOWED; } - } + if (mode->channels[i].flag & HOSTAPD_CHAN_INDOOR_ONLY) + return INDOOR_ONLY; + + return ALLOWED; + } return NOT_ALLOWED; } @@ -3251,7 +3314,9 @@ static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s, static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s, struct hostapd_hw_modes *mode, - u8 channel, u8 bw) + u8 channel, u8 bw, + struct wpa_used_freq_data *freqs, + unsigned int num) { u8 center_chan; int i, flags; @@ -3267,9 +3332,12 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s, for (i = 0; i < 4; i++) { int adj_chan = center_chan - 6 + i * 4; - res = has_channel(wpa_s->global, mode, adj_chan, &flags); + res = has_channel(wpa_s->global, mode, adj_chan, &flags, freqs, + num); if (res == NOT_ALLOWED) return NOT_ALLOWED; + if (res == INDOOR_ONLY) + return INDOOR_ONLY; if (res == NO_IR) ret = NO_IR; @@ -3289,26 +3357,36 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s, static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s, struct hostapd_hw_modes *mode, - u8 channel, u8 bw) + u8 channel, u8 bw, + struct wpa_used_freq_data *freqs, + unsigned int num) { int flag = 0; enum chan_allowed res, res2; - res2 = res = has_channel(wpa_s->global, mode, channel, &flag); + res2 = res = has_channel(wpa_s->global, mode, channel, &flag, freqs, + num); if (bw == BW40MINUS) { if (!(flag & HOSTAPD_CHAN_HT40MINUS)) return NOT_ALLOWED; - res2 = has_channel(wpa_s->global, mode, channel - 4, NULL); + res2 = has_channel(wpa_s->global, mode, channel - 4, NULL, + freqs, num); } else if (bw == BW40PLUS) { if (!(flag & HOSTAPD_CHAN_HT40PLUS)) return NOT_ALLOWED; - res2 = has_channel(wpa_s->global, mode, channel + 4, NULL); + res2 = has_channel(wpa_s->global, mode, channel + 4, NULL, + freqs, num); } else if (bw == BW80) { - res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw); + res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw, freqs, + num); } if (res == NOT_ALLOWED || res2 == NOT_ALLOWED) return NOT_ALLOWED; + + if (res == INDOOR_ONLY || res2 == INDOOR_ONLY) + return NOT_ALLOWED; + if (res == NO_IR || res2 == NO_IR) return NO_IR; return res; @@ -3343,7 +3421,8 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, wpa_s->global->p2p_24ghz_social_channels = 1; for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { enum chan_allowed res; - res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw); + res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw, + freqs, num); if (res == ALLOWED) { if (reg == NULL) { wpa_printf(MSG_DEBUG, "P2P: Add operating class %u", @@ -3388,8 +3467,15 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s, struct hostapd_hw_modes *mode, u8 channel) { int op; - enum chan_allowed ret; + enum chan_allowed res; + struct wpa_used_freq_data *freqs; + unsigned int num = wpa_s->num_multichan_concurrent; + int ret; + freqs = os_calloc(num, sizeof(struct wpa_used_freq_data)); + num = get_shared_radio_freqs_data(wpa_s, freqs, num); + + ret = 0; for (op = 0; op_class[op].op_class; op++) { const struct p2p_oper_class_map *o = &op_class[op]; u8 ch; @@ -3399,19 +3485,33 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s, (o->bw != BW40PLUS && o->bw != BW40MINUS) || ch != channel) continue; - ret = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw); - if (ret == ALLOWED) - return (o->bw == BW40MINUS) ? -1 : 1; + res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw, + freqs, num); + if (res == ALLOWED) { + ret = (o->bw == BW40MINUS) ? -1 : 1; + break; + } } } - return 0; + os_free(freqs); + return ret; } int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s, struct hostapd_hw_modes *mode, u8 channel) { - if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW80)) + struct wpa_used_freq_data *freqs; + unsigned int num = wpa_s->num_multichan_concurrent; + int ret; + + freqs = os_calloc(num, sizeof(struct wpa_used_freq_data)); + num = get_shared_radio_freqs_data(wpa_s, freqs, num); + + ret = wpas_p2p_verify_channel(wpa_s, mode, channel, BW80, freqs, num); + os_free(freqs); + + if (!ret) return 0; return wpas_p2p_get_center_80mhz(wpa_s, mode, channel); @@ -8541,7 +8641,8 @@ static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s, * to move it */ if (wpa_s == ifs && - (trig == WPAS_P2P_CHANNEL_UPDATE_CS)) { + (trig == WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE || + trig == WPAS_P2P_CHANNEL_UPDATE_CS)) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO move - schedule re-consideration"); eloop_register_timeout(P2P_RECONSIDER_GO_MOVE_DELAY, 0, @@ -8560,7 +8661,21 @@ void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s) if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return; - wpas_p2p_update_channel_list(wpa_s); + /* Skip states that do not impact used frequencies */ + switch (wpa_s->wpa_state) { + case WPA_SCANNING: + case WPA_AUTHENTICATING: + case WPA_ASSOCIATING: + case WPA_ASSOCIATED: + case WPA_4WAY_HANDSHAKE: + case WPA_GROUP_HANDSHAKE: + return; + default: + break; + } + + wpas_p2p_update_channel_list(wpa_s, + WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE); } diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index feaf2ca..687c748 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -165,6 +165,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, enum wpas_p2p_channel_update_trig { WPAS_P2P_CHANNEL_UPDATE_ANY = 0, WPAS_P2P_CHANNEL_UPDATE_DRIVER, + WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE, WPAS_P2P_CHANNEL_UPDATE_AVOID, WPAS_P2P_CHANNEL_UPDATE_DISALLOW, WPAS_P2P_CHANNEL_UPDATE_CS,