From patchwork Wed Oct 10 21:51:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christopher Wiley X-Patchwork-Id: 190762 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 96ABD2C0080 for ; Thu, 11 Oct 2012 08:51:42 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 3FF7A9D21E; Wed, 10 Oct 2012 17:51:31 -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 9N777to3XRl8; Wed, 10 Oct 2012 17:51:31 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 6D2DE9D216; Wed, 10 Oct 2012 17:51:20 -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 EC57C9D215 for ; Wed, 10 Oct 2012 17:51:18 -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 ZMRb+HMbiNE2 for ; Wed, 10 Oct 2012 17:51:13 -0400 (EDT) Received: from mail-qc0-f201.google.com (mail-qc0-f201.google.com [209.85.216.201]) (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 A3F099CEB9 for ; Wed, 10 Oct 2012 17:51:13 -0400 (EDT) Received: by mail-qc0-f201.google.com with SMTP id a6so128248qch.2 for ; Wed, 10 Oct 2012 14:51:13 -0700 (PDT) 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:in-reply-to:references :x-gm-message-state; bh=oNgonH31268qzWh7hT978bBmI6Eluo40oHfGpPIS5Gg=; b=OAiF3z8YObNP0gcvneriEmFRHM9O7fVSj0k3Vnwm9w+36+Pk2qeuj5X/W3r23zJepb rTCfa0EaWdzxIlVgAaPjUpi/R08rvBUQ9HhWvj9LweV1CN+2ABPLlJzKCePtWYJzba7M BuKteVZy6c+GipeQ65W6g/q8IGLYmkGDOXPJMVju3ltwJOB9Se8G8ORl1Tc8mXSUUQDP BaXQS5b/KS23FwDx1O1TF3kh9rFXmTRT2CDmesE688nWEhL5T9b7FPyHZ9WHTP8aZ/jA DF1r5g0/fCtrd7F15rainK9YhKf39yh5pq32K5kJlOziN+yZVc9h/rND3dJzFthTEG7e PuOQ== Received: by 10.236.82.202 with SMTP id o50mr17387126yhe.30.1349905873283; Wed, 10 Oct 2012 14:51:13 -0700 (PDT) Received: from wpzn4.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id h50si184192yhi.3.2012.10.10.14.51.13 (version=TLSv1/SSLv3 cipher=AES128-SHA); Wed, 10 Oct 2012 14:51:13 -0700 (PDT) Received: from mintyfresh.mtv.corp.google.com (mintyfresh.mtv.corp.google.com [172.22.73.124]) by wpzn4.hot.corp.google.com (Postfix) with ESMTP id 2123E1E0048; Wed, 10 Oct 2012 14:51:13 -0700 (PDT) Received: by mintyfresh.mtv.corp.google.com (Postfix, from userid 55395) id CA5DA1000EA; Wed, 10 Oct 2012 14:51:12 -0700 (PDT) From: Christopher Wiley To: hostap@shmoo.com Subject: [RFC] Roam correctly through cfg80211 without SME Date: Wed, 10 Oct 2012 14:51:04 -0700 Message-Id: <1349905864-25674-2-git-send-email-wiley@chromium.org> X-Mailer: git-send-email 1.7.7.3 In-Reply-To: <1349905864-25674-1-git-send-email-wiley@chromium.org> References: <1349905864-25674-1-git-send-email-wiley@chromium.org> X-Gm-Message-State: ALoCoQlpiL3Jvw/AJ5tBXzmfpVAXllazQta/AP7Ob0TBNQAZ+7rmtsPqezG7TrknHnzLXIh5phFgW5HYVpCAPooWtjSwZrb/pphLBxmc/sfLgQ31sUGyTr6EgwnEDtfegAdI4XUClcPWorw7Af2DuuFlBuS+rqiA4fO5NiVum1rPDiuN7nxK5oZ7xFxs4xm1kQc0s9V5F814 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 --- 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 58ede8e..129b0e0 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; @@ -1182,6 +1183,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) { /* @@ -1192,6 +1194,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"); + } + drv->associated = 0; os_memset(&data, 0, sizeof(data)); @@ -4480,6 +4494,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); @@ -6626,7 +6641,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) { @@ -6806,15 +6821,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; @@ -6827,6 +6833,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) {