From patchwork Tue Oct 15 02:08:31 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Yeow Yeoh X-Patchwork-Id: 3041461 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 9795BBF924 for ; Tue, 15 Oct 2013 02:09:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 96C36201FD for ; Tue, 15 Oct 2013 02:09:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 822E220213 for ; Tue, 15 Oct 2013 02:09:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756676Ab3JOCJJ (ORCPT ); Mon, 14 Oct 2013 22:09:09 -0400 Received: from mail-pd0-f177.google.com ([209.85.192.177]:59555 "EHLO mail-pd0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756223Ab3JOCI6 (ORCPT ); Mon, 14 Oct 2013 22:08:58 -0400 Received: by mail-pd0-f177.google.com with SMTP id y10so8160970pdj.36 for ; Mon, 14 Oct 2013 19:08:58 -0700 (PDT) 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=GHl+CR9ou4wEpqq6LxvTDGn6CWLs5Kch40n5DEb8zCE=; b=AQOLPUbqEdQNTI2pqKrv8GBKXWpJ76Z4+G3jIT2RJPg85CgFrS5ID1SIwqN7D58wfv X+gr67ClQ3NMbGWGDYKiJuLmEhh9SdOhLlfma7zcJKzMJxUaDUO6x+3kU4Q1z/RgIE7p Y7J2Um4j/j0RW5XdiYDmSey24PvGCugINFm3IU9RL03Hq9bvS9fz+hwWz4IWp/y9vi6x im0EbhdmUIcijpGuM4kUKWFWPBhCq45zYM8OtMnMFsaaSQEHUuAIMGtbieFQKeRfBqUt 4tFc8E/h2287rXCAuftovX1tj8TRRc21Ki3zQAnb7WcqnVodly39wcVnHUmcPeTVpkI5 FJjw== X-Gm-Message-State: ALoCoQkdrHAib7kgzK+ZgR7lIZ/sB3KZ+iSMtkKGHiI+W/vcCzTi/Fn9hzvK8NAxeldmrm9JWbiS X-Received: by 10.68.129.99 with SMTP id nv3mr39598271pbb.40.1381802938339; Mon, 14 Oct 2013 19:08:58 -0700 (PDT) Received: from localhost.localdomain (70-35-43-50.static.wiline.com. [70.35.43.50]) by mx.google.com with ESMTPSA id py4sm80909986pbb.33.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 14 Oct 2013 19:08:57 -0700 (PDT) From: Chun-Yeow Yeoh To: linux-wireless@vger.kernel.org Cc: johannes@sipsolutions.net, linville@tuxdriver.com, devel@lists.open80211s.org, distro11s@cozybit.com, Chun-Yeow Yeoh Subject: [PATCH v5 5/5] mac80211: process mesh channel switching using beacon Date: Mon, 14 Oct 2013 19:08:31 -0700 Message-Id: <1381802911-3921-6-git-send-email-yeohchunyeow@cozybit.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1381802911-3921-1-git-send-email-yeohchunyeow@cozybit.com> References: <1381802911-3921-1-git-send-email-yeohchunyeow@cozybit.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Trigger the mesh channel switching procedure if the mesh STA happens to miss the CSA action frame but able to receive the beacon containing the CSA and MCSP elements from its peer mesh STAs. Signed-off-by: Chun-Yeow Yeoh --- v2: fix return value (Johannes Berg) net/mac80211/mesh.c | 132 +++++++++++++++++++++++++++++++++++++++++++--- net/mac80211/spectmgmt.c | 6 +++ 2 files changed, 130 insertions(+), 8 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 50b1863..35c4147 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -850,6 +850,124 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) ieee80211_configure_filter(local); } +static bool +ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, + struct ieee802_11_elems *elems, bool beacon) +{ + struct cfg80211_csa_settings params; + struct ieee80211_csa_ie csa_ie; + struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_chanctx *chanctx; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + int err, num_chanctx; + u32 sta_flags; + + if (sdata->vif.csa_active) + return true; + + if (!ifmsh->mesh_id) + return false; + + sta_flags = IEEE80211_STA_DISABLE_VHT; + switch (sdata->vif.bss_conf.chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + sta_flags |= IEEE80211_STA_DISABLE_HT; + case NL80211_CHAN_WIDTH_20: + sta_flags |= IEEE80211_STA_DISABLE_40MHZ; + break; + default: + break; + } + + memset(¶ms, 0, sizeof(params)); + memset(&csa_ie, 0, sizeof(csa_ie)); + err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band, + sta_flags, sdata->vif.addr, + &csa_ie); + if (err < 0) + return false; + if (err) + return false; + + params.chandef = csa_ie.chandef; + params.count = csa_ie.count; + + if (sdata->vif.bss_conf.chandef.chan->band != + params.chandef.chan->band) + return false; + + if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, + IEEE80211_CHAN_DISABLED)) { + sdata_info(sdata, + "mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n", + sdata->vif.addr, + params.chandef.chan->center_freq, + params.chandef.width, + params.chandef.center_freq1, + params.chandef.center_freq2); + return false; + } + + err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, + ¶ms.chandef); + if (err < 0) + return false; + if (err) { + params.radar_required = true; + /* TODO: DFS not (yet) supported */ + return false; + } + + rcu_read_lock(); + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); + if (!chanctx_conf) + goto failed_chswitch; + + /* don't handle for multi-VIF cases */ + chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); + if (chanctx->refcount > 1) + goto failed_chswitch; + + num_chanctx = 0; + list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) + num_chanctx++; + + if (num_chanctx > 1) + goto failed_chswitch; + + rcu_read_unlock(); + + mcsa_dbg(sdata, + "received channel switch announcement to go to channel %d MHz\n", + params.chandef.chan->center_freq); + + params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT; + if (beacon) + ifmsh->chsw_ttl = csa_ie.ttl - 1; + + if (ifmsh->chsw_ttl > 0) + ieee80211_mesh_csa_beacon(sdata, ¶ms, false); + + sdata->csa_radar_required = params.radar_required; + + if (params.block_tx) + ieee80211_stop_queues_by_reason(&sdata->local->hw, + IEEE80211_MAX_QUEUE_MAP, + IEEE80211_QUEUE_STOP_REASON_CSA); + + sdata->local->csa_chandef = params.chandef; + sdata->vif.csa_active = true; + + ieee80211_bss_info_change_notify(sdata, err); + drv_channel_switch_beacon(sdata, ¶ms.chandef); + + return true; +failed_chswitch: + rcu_read_unlock(); + return false; +} + static void ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) @@ -956,6 +1074,9 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, if (ifmsh->sync_ops) ifmsh->sync_ops->rx_bcn_presp(sdata, stype, mgmt, &elems, rx_status); + + if (!ifmsh->chsw_init) + ieee80211_mesh_process_chnswitch(sdata, &elems, true); } int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) @@ -1051,7 +1172,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee802_11_elems elems; u16 pre_value; - bool block_tx, fwd_csa = true; + bool fwd_csa = true; size_t baselen; u8 *pos, ttl; @@ -1080,13 +1201,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, mcsa_dbg(sdata, "Failed to forward the CSA frame"); } - /* block the Tx only after forwarding the CSA frame if required */ - block_tx = elems.mesh_chansw_params_ie->mesh_flags & - WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT; - if (block_tx) - ieee80211_stop_queues_by_reason(&sdata->local->hw, - IEEE80211_MAX_QUEUE_MAP, - IEEE80211_QUEUE_STOP_REASON_CSA); + if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) + mcsa_dbg(sdata, "Failed to process CSA action frame"); } static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index a298e12..a40da20 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -74,6 +74,12 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, return 1; } + /* Mesh Channel Switch Parameters Element */ + if (elems->mesh_chansw_params_ie) { + csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl; + csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags; + } + new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) {