From patchwork Tue Jan 21 06:57:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 312796 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]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FF142C00A6 for ; Tue, 21 Jan 2014 18:04:48 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id A367E9C1A6; Tue, 21 Jan 2014 02:04:22 -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 2QwPhkBDR1Zp; Tue, 21 Jan 2014 02:04:22 -0500 (EST) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 3260B9C1BE; Tue, 21 Jan 2014 02:03:20 -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 E0A4B9C1BB for ; Tue, 21 Jan 2014 02:03:18 -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 at9R3Dl3+msF for ; Tue, 21 Jan 2014 02:03:13 -0500 (EST) Received: from mail-ea0-f180.google.com (mail-ea0-f180.google.com [209.85.215.180]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (not verified)) by maxx.maxx.shmoo.com (Postfix) with ESMTPS id C0CFF9C18D for ; Tue, 21 Jan 2014 02:03:03 -0500 (EST) Received: by mail-ea0-f180.google.com with SMTP id f15so3497966eak.25 for ; Mon, 20 Jan 2014 23:03:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6meqQFfyuAYlKcxTYWf4vE6SBhkADDAs6p4xHsLz48E=; b=l5CRHdGFlfkKJFaaGy2HXtTCOSvKombu0um618a+htjEJbDHkJ5elcBMD6XCYlz0KJ NrML/hh1kLgKd9B4qP45NXTGJHG6QyhQ0D1v6DvS6zBJygSB9vAyFAdgNH0l7FwZgN8u RGVhF7FVGoEjHRiWOAb/9DsKPMiVVQDxnb4eE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6meqQFfyuAYlKcxTYWf4vE6SBhkADDAs6p4xHsLz48E=; b=lJFrqMImWs/ThizBywATXrpHlSDpkbQK0JEcwuo2HzPJuC62MZUvsp08q/1YIC5KLv b9DPtMNBV+6+Qcupv9dBP+9LQlv4fDTVLQe0nBUuCW9F9Xan/jOkE7t2W+NRWC+BFaLy 7+HxNxz1/4spb8+zqSExpzk1P/1i16QYJLBj3z8XS72MletUG4WVKEN/zcTwYrzxL5ui we8jel8w6y4+oWnFdMGR69dODaGklj9DhoHXN1PiQ4XIs6y5E/LEAJspuUmIzQ/OHL65 tNr1SgM1pkV9r0h3vFZJrqSSyMya7yNsXs0qUKY/lQVAy6ON/TBXJplCpUA6+n+MgvEZ SHPw== X-Gm-Message-State: ALoCoQlYyPaMhy00xNnQCNX48umSHB6qrpN5dwx5RjXWD8CshCHEwBfKwlAzUw4s8Flzl0pS30bX+CPL/7cqTnlLJHIt7GbccdXmOvRW36UM1OW8gY7FHnY= X-Received: by 10.14.2.73 with SMTP id 49mr21903157eee.15.1390287782818; Mon, 20 Jan 2014 23:03:02 -0800 (PST) Received: from localhost.localdomain ([91.198.246.8]) by mx.google.com with ESMTPSA id z46sm11330367een.1.2014.01.20.23.03.01 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Jan 2014 23:03:02 -0800 (PST) From: Michal Kazior To: j@w1.fi Subject: [RFC 6/6] nl80211: implement multi-interface CSA Date: Tue, 21 Jan 2014 07:57:28 +0100 Message-Id: <1390287448-7718-7-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 1.8.4.rc3 In-Reply-To: <1390287448-7718-1-git-send-email-michal.kazior@tieto.com> References: <1390287448-7718-1-git-send-email-michal.kazior@tieto.com> X-DomainID: tieto.com Cc: hostap@lists.shmoo.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 This implements extended channel switch command variant. The extension allows declaring an array of per interface CSA requests. CSA can be performed per-wiphy. For single-interface CSA old command variant is used so older kernels will still work with single-interface uses. Signed-hostap: Michal Kazior --- src/drivers/driver_nl80211.c | 152 ++++++++++++++++++++++++++++++------------- 1 file changed, 106 insertions(+), 46 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 94c2164..de7604d 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -11390,18 +11390,87 @@ nla_put_failure: } +static int set_csa_settings(struct nl_msg *msg, + struct csa_settings *settings) +{ + struct i802_bss *bss = settings->priv; + struct nlattr *beacon_csa; + int ret; + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, settings->cs_count); + ret = nl80211_put_freq_params(msg, &settings->freq_params); + if (ret) + return ret; + + if (settings->block_tx) + NLA_PUT_FLAG(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX); + + /* beacon_after params */ + ret = set_beacon_data(msg, &settings->beacon_after); + if (ret) + return ret; + + /* beacon_csa params */ + beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES); + if (!beacon_csa) + return -ENOBUFS; + + ret = set_beacon_data(msg, &settings->beacon_csa); + if (ret) + return ret; + + NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_BEACON, + settings->counter_offset_beacon); + + if (settings->beacon_csa.probe_resp) + NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_PRESP, + settings->counter_offset_presp); + + nla_nest_end(msg, beacon_csa); + + return 0; + +nla_put_failure: + return -ENOBUFS; +} + + +static int validate_csa_settings(struct csa_settings *settings, + int num_settings) +{ + int i; + + if (num_settings <= 0) + return -EINVAL; + + for (i = 0; i < num_settings; i++) { + if (!settings->beacon_csa.tail || + ((settings->beacon_csa.tail_len <= + settings->counter_offset_beacon) || + (settings->beacon_csa.tail[settings->counter_offset_beacon] != + settings->cs_count))) + return -EINVAL; + + if (settings->beacon_csa.probe_resp && + ((settings->beacon_csa.probe_resp_len <= + settings->counter_offset_presp) || + (settings->beacon_csa.probe_resp[settings->counter_offset_presp] != + settings->cs_count))) + return -EINVAL; + } + + return 0; +} + + static int nl80211_switch_channel(void *priv, struct csa_settings *settings, int num_settings) { struct nl_msg *msg; struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; - struct nlattr *beacon_csa; - int ret = -ENOBUFS; - - /* multi-BSS not implemented yet */ - if (num_settings != 1) - return -EOPNOTSUPP; + int i, ret = -ENOBUFS; wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)", settings->cs_count, settings->block_tx, @@ -11418,62 +11487,53 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings, (drv->nlmode != NL80211_IFTYPE_P2P_GO)) return -EOPNOTSUPP; - /* check settings validity */ - if (!settings->beacon_csa.tail || - ((settings->beacon_csa.tail_len <= - settings->counter_offset_beacon) || - (settings->beacon_csa.tail[settings->counter_offset_beacon] != - settings->cs_count))) - return -EINVAL; - - if (settings->beacon_csa.probe_resp && - ((settings->beacon_csa.probe_resp_len <= - settings->counter_offset_presp) || - (settings->beacon_csa.probe_resp[settings->counter_offset_presp] != - settings->cs_count))) - return -EINVAL; + ret = validate_csa_settings(settings, num_settings); + if (ret) + return ret; msg = nlmsg_alloc(); if (!msg) return -ENOMEM; nl80211_cmd(drv, msg, 0, NL80211_CMD_CHANNEL_SWITCH); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, settings->cs_count); - ret = nl80211_put_freq_params(msg, &settings->freq_params); - if (ret) - goto error; - - if (settings->block_tx) - NLA_PUT_FLAG(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, bss->wiphy_data->wiphy_idx); + + if (num_settings == 1) { + /* use old command format for single interface to talk with + * older kernels */ + ret = set_csa_settings(msg, &settings[0]); + if (ret) + goto error; + } + else { + struct nlattr *ifaces; + + /* newer kernel support multi-interface CSA with an extended + * command structure */ + ifaces = nla_nest_start(msg, NL80211_ATTR_CH_SWITCH_IFACES); + if (!ifaces) + goto nla_put_failure; - /* beacon_after params */ - ret = set_beacon_data(msg, &settings->beacon_after); - if (ret) - goto error; + for (i = 0; i < num_settings; i++) { + struct nlattr *iface; - /* beacon_csa params */ - beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES); - if (!beacon_csa) - goto nla_put_failure; + iface = nla_nest_start(msg, i + 1); + ret = set_csa_settings(msg, &settings[i]); + nla_nest_end(msg, iface); - ret = set_beacon_data(msg, &settings->beacon_csa); - if (ret) - goto error; - - NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_BEACON, - settings->counter_offset_beacon); + if (ret) + goto error; + } - if (settings->beacon_csa.probe_resp) - NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_PRESP, - settings->counter_offset_presp); + nla_nest_end(msg, ifaces); + } - nla_nest_end(msg, beacon_csa); ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)", ret, strerror(-ret)); } + return ret; nla_put_failure: