From patchwork Wed Nov 7 20:17:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christopher Wiley X-Patchwork-Id: 197727 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 4127C2C00D6 for ; Thu, 8 Nov 2012 07:17:37 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id B34ED9C153; Wed, 7 Nov 2012 15:17:34 -0500 (EST) 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 O118B1Kv85A2; Wed, 7 Nov 2012 15:17:34 -0500 (EST) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 5CE179C14E; Wed, 7 Nov 2012 15:17:30 -0500 (EST) 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 8EEEA9C14E for ; Wed, 7 Nov 2012 15:17:28 -0500 (EST) 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 BEb4HpDlWFsE for ; Wed, 7 Nov 2012 15:17:24 -0500 (EST) Received: from mail-yh0-f74.google.com (mail-yh0-f74.google.com [209.85.213.74]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (not verified)) by maxx.maxx.shmoo.com (Postfix) with ESMTPS id CDDEE9C14C for ; Wed, 7 Nov 2012 15:17:24 -0500 (EST) Received: by mail-yh0-f74.google.com with SMTP id 10so231759yhl.5 for ; Wed, 07 Nov 2012 12:17:23 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:x-gm-message-state; bh=v9295lbuHcuKcY6TF2I9kSJCALrVEmVWCqzspU1ytio=; b=T29IJjHHWwecZjfo0tDploCXYdwM7n8fuYr7G7lnG2x1X/9IYZ9XzA3hGmK9/lFpPK GKBLy3i5o+HUDTMvVjQWkGvQddInOfqEoPtKapYEh4WYKQ4AU0Bmsq75Sc5tgKy0txvZ tDtTo7gdvyA8kOdXqE9trTEhKRc4/dfoKP3hqlWMFJGrvvAUBvQa/cmzaIumTy1l/Imz Bv+QYw97dotTi/9wP4Jk+KQifoiuegmTSd4Dl8SM9QI0gMohylIQkddgtztEilgNfi/f ty9tlDU8GHSljrk3WfJZ3f5kpX+VFfmbsFh5n5PlJCg2QjkznDK+XejFgn6ErAf92xoQ 2EHA== Received: by 10.101.176.10 with SMTP id d10mr922048anp.12.1352319443377; Wed, 07 Nov 2012 12:17:23 -0800 (PST) Received: from wpzn3.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id i63si1546111yhk.5.2012.11.07.12.17.23 (version=TLSv1/SSLv3 cipher=AES128-SHA); Wed, 07 Nov 2012 12:17:23 -0800 (PST) Received: from mintyfresh.mtv.corp.google.com (mintyfresh.mtv.corp.google.com [172.22.73.124]) by wpzn3.hot.corp.google.com (Postfix) with ESMTP id 26C13100047; Wed, 7 Nov 2012 12:17:23 -0800 (PST) Received: by mintyfresh.mtv.corp.google.com (Postfix, from userid 55395) id C4E14100B86; Wed, 7 Nov 2012 12:17:22 -0800 (PST) From: Christopher Wiley To: hostap@lists.shmoo.com Subject: [PATCH] Roam correctly through cfg80211 without SME Date: Wed, 7 Nov 2012 12:17:16 -0800 Message-Id: <1352319436-29633-1-git-send-email-wiley@chromium.org> X-Mailer: git-send-email 1.7.7.3 X-Gm-Message-State: ALoCoQnqUajD0ljwcUwy0VIFjpl/fr8txecL8ySDHL+kxKRT1vNMeHLUeG0jJs2DKBROYyA3BVZhszdPnqAxIpBT309yp792eGy5elTnrr/bXMScLCXUUbWc/UOk0z0qKai13x0cnN4wrj9MUjKlcRmMwxYV2rU0hFNmoNX3qf1F7rXQvXQBwXIvqfsQOhhpYtHOqFaMUu+f 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: , MIME-Version: 1.0 Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com Change the nl80211 driver in wpa_supplicant to correctly handle connecting to a new AP through cfg80211 without SME capability. As before, the driver will disconnect from the previously associated AP, but now we attempt to immediately connect to our intended AP. This prevents us from blacklisting the AP we were trying to connect to because of a semantic mismatch between cfg80211 and wpa_supplicant. The disconnect/connect patch generates a local disconnect nl80211 event which we discard because we're already correctly tracking the pending association request. In detail: cfg80211 does not support connecting to a new BSS while already connected to another BSS, if the underlying driver doesn't support separate authenticate and associate commands. wpa_supplicant is written to expect that this is a supported operation, except for a little error handling that disconnects from the current BSS when roaming fails and relies on autoconnect logic to reconnect later. However, this failure to connect is incorrectly attributed to the new AP we attempted to associate with, rather than a local condition in cfg80211. The combined effect of these two conditions is that full-mac drivers accessible through cfg80211 but without SME capability take a long time to roam across BSS's because wpa_supplicant will: 1) Fail to associate for local reasons 2) Disconnect and return that the association request failed 3) Blacklist the association target (incorrectly) 4) Do a scan 5) Pick a less desirable AP to associate with Signed-hostap: Christoper Wiley --- src/drivers/driver_nl80211.c | 51 +++++++++++++++++++++++++++++++++-------- 1 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index b73373a..7f0dd46 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -250,6 +250,7 @@ struct wpa_driver_nl80211_data { unsigned int scan_for_auth:1; unsigned int retry_auth:1; unsigned int use_monitor:1; + unsigned int ignore_next_local_disconnect:1; u64 remain_on_chan_cookie; u64 send_action_cookie; @@ -1191,6 +1192,7 @@ static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv, struct nlattr *by_ap) { union wpa_event_data data; + unsigned int locally_generated = by_ap == NULL; if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { /* @@ -1201,6 +1203,18 @@ static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv, "event when using userspace SME"); return; } + if (drv->ignore_next_local_disconnect) { + drv->ignore_next_local_disconnect = 0; + if (locally_generated) { + wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect " + "event triggered during reassociation"); + return; + } + wpa_printf(MSG_WARNING, "nl80211: Was expecting local " + "disconnect but got another disconnect " + "event first"); + } + wpa_printf(MSG_DEBUG, "nl80211: Disconnect event"); drv->associated = 0; @@ -4509,6 +4523,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, { wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code); drv->associated = 0; + drv->ignore_next_local_disconnect = 0; /* Disconnect command doesn't need BSSID - it uses cached value */ return wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT, reason_code, 0); @@ -6663,7 +6678,7 @@ nla_put_failure: } -static int wpa_driver_nl80211_connect( +static int wpa_driver_nl80211_try_connect( struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { @@ -6843,15 +6858,6 @@ skip_auth_type: if (ret) { wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " "(%s)", ret, strerror(-ret)); - /* - * cfg80211 does not currently accept new connection if we are - * already connected. As a workaround, force disconnection and - * try again once the driver indicates it completed - * disconnection. - */ - if (ret == -EALREADY) - wpa_driver_nl80211_disconnect( - drv, WLAN_REASON_PREV_AUTH_NOT_VALID); goto nla_put_failure; } ret = 0; @@ -6864,6 +6870,31 @@ nla_put_failure: } +static int wpa_driver_nl80211_connect( + struct wpa_driver_nl80211_data *drv, + struct wpa_driver_associate_params *params) +{ + int ret = wpa_driver_nl80211_try_connect(drv, params); + if (ret == -EALREADY) { + /* + * cfg80211 does not currently accept new connections if + * we are already connected. As a workaround, force + * disconnection and try again. + */ + wpa_printf(MSG_DEBUG, "nl80211: Explicitly " + "disconnecting before reassociation " + "attempt"); + if (wpa_driver_nl80211_disconnect( + drv, WLAN_REASON_PREV_AUTH_NOT_VALID)) + return -1; + /* Ignore the next local disconnect message. */ + drv->ignore_next_local_disconnect = 1; + ret = wpa_driver_nl80211_try_connect(drv, params); + } + return ret; +} + + static int wpa_driver_nl80211_associate( void *priv, struct wpa_driver_associate_params *params) {