From patchwork Thu Jul 17 14:14:26 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arik Nemtsov X-Patchwork-Id: 4575801 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 CDDECC0514 for ; Thu, 17 Jul 2014 14:15:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 008CA2011E for ; Thu, 17 Jul 2014 14:15:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C849E201BF for ; Thu, 17 Jul 2014 14:15:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933823AbaGQOOc (ORCPT ); Thu, 17 Jul 2014 10:14:32 -0400 Received: from mail-wg0-f47.google.com ([74.125.82.47]:43247 "EHLO mail-wg0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933822AbaGQOOT (ORCPT ); Thu, 17 Jul 2014 10:14:19 -0400 Received: by mail-wg0-f47.google.com with SMTP id b13so2029499wgh.18 for ; Thu, 17 Jul 2014 07:14:17 -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=phIYUUQ9YI0q8d+WhmJP8oJalcW9rDHwYyzaUvMw5h4=; b=L+9JsOMv6aFcps5RJttra+9UFplFUzCZsD5YGUtfZoI+vMGz1DDJWVH4NawrZlwyho ciwTctTmSItSfa8BBs2JTZsIbYSKJVY0SsSit1EysZ+yiZbdzAywWMIbB5FQHvMWapBh idHxxrVVGH7OUdoY3X9WalOk5IBM2PvT2lXkSzskHHfLKh/hLJ/mF5ghVZvUXvGUhe19 UoTQ9u7kFKhMY3vYGzhQk1ZGHcgiW+Cy81SvShgF+0pyVSRbcXMMXJjb5iedz9xishMp QrY/lD81uiFFdBaK4S8DVUPbcBm4glvQAFZsCLjJz8Sd2AOO9xILaw0EbWAXHTSjIJxW 5l0A== X-Gm-Message-State: ALoCoQkuT8e+VAWeux1is/0g2tJBHL8ys7RED7e3phHNz8rMVXe4F4hRSN8N8Tv//SrhIXtDImjL X-Received: by 10.180.108.1 with SMTP id hg1mr23163686wib.25.1405606457885; Thu, 17 Jul 2014 07:14:17 -0700 (PDT) Received: from athena.amr.corp.intel.com (46-116-100-31.bb.netvision.net.il. [46.116.100.31]) by mx.google.com with ESMTPSA id ft6sm17691865wic.0.2014.07.17.07.14.16 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 17 Jul 2014 07:14:17 -0700 (PDT) From: Arik Nemtsov To: Cc: Johannes Berg , Arik Nemtsov Subject: [PATCH 10/15] mac80211: support HT for TDLS stations Date: Thu, 17 Jul 2014 17:14:26 +0300 Message-Id: <1405606471-30128-11-git-send-email-arik@wizery.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1405606471-30128-1-git-send-email-arik@wizery.com> References: <1405606471-30128-1-git-send-email-arik@wizery.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=-6.9 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 Add the HT capabilities and HT operation information elements to TDLS setup packets where appropriate. Signed-off-by: Arik Nemtsov Reviewed-by: Emmanuel Grumbach --- net/mac80211/ht.c | 7 ++--- net/mac80211/tdls.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 15702ff..568055c 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -150,13 +150,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, /* * If user has specified capability over-rides, take care - * of that if the station we're setting up is the AP that + * of that if the station we're setting up is the AP or TDLS peer that * we advertised a restricted capability set to. Override * our own capabilities and then use those below. */ - if ((sdata->vif.type == NL80211_IFTYPE_STATION || - sdata->vif.type == NL80211_IFTYPE_ADHOC) && - !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) ieee80211_apply_htcap_overrides(sdata, &own_cap); /* diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index c59b8f4..50d0e06 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -170,9 +170,23 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, { enum ieee80211_band band = ieee80211_get_sdata_band(sdata); struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + struct ieee80211_sta_ht_cap ht_cap; + struct sta_info *sta = NULL; size_t offset = 0, noffset; u8 *pos; + rcu_read_lock(); + + /* we should have the peer STA if we're already responding */ + if (action_code == WLAN_TDLS_SETUP_RESPONSE) { + sta = sta_info_get(sdata, peer); + if (WARN_ON_ONCE(!sta)) { + rcu_read_unlock(); + return; + } + } + ieee80211_add_srates_ie(sdata, skb, false, band); ieee80211_add_ext_srates_ie(sdata, skb, false, band); @@ -224,6 +238,38 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, offset = noffset; } + /* + * with TDLS we can switch channels, and HT-caps are not necessarily + * the same on all bands. The specification limits the setup to a + * single HT-cap, so use the current band for now. + */ + sband = local->hw.wiphy->bands[band]; + memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); + if ((action_code == WLAN_TDLS_SETUP_REQUEST || + action_code == WLAN_TDLS_SETUP_RESPONSE) && + ht_cap.ht_supported && (!sta || sta->sta.ht_cap.ht_supported)) { + if (action_code == WLAN_TDLS_SETUP_REQUEST) { + ieee80211_apply_htcap_overrides(sdata, &ht_cap); + + /* disable SMPS in TDLS initiator */ + ht_cap.cap |= (WLAN_HT_CAP_SM_PS_DISABLED + << IEEE80211_HT_CAP_SM_PS_SHIFT); + } else { + /* disable SMPS in TDLS responder */ + sta->sta.ht_cap.cap |= + (WLAN_HT_CAP_SM_PS_DISABLED + << IEEE80211_HT_CAP_SM_PS_SHIFT); + + /* the peer caps are already intersected with our own */ + memcpy(&ht_cap, &sta->sta.ht_cap, sizeof(ht_cap)); + } + + pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); + ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap); + } + + rcu_read_unlock(); + /* add any remaining IEs */ if (extra_ies_len) { noffset = extra_ies_len; @@ -241,14 +287,16 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, size_t extra_ies_len) { struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; size_t offset = 0, noffset; - struct sta_info *sta; + struct sta_info *sta, *ap_sta; u8 *pos; rcu_read_lock(); sta = sta_info_get(sdata, peer); - if (WARN_ON_ONCE(!sta)) { + ap_sta = sta_info_get(sdata, ifmgd->bssid); + if (WARN_ON_ONCE(!sta || !ap_sta)) { rcu_read_unlock(); return; } @@ -272,6 +320,38 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, test_sta_flag(sta, WLAN_STA_WME)) ieee80211_tdls_add_wmm_param_ie(sdata, skb); + /* add any custom IEs that go before HT operation */ + if (extra_ies_len) { + static const u8 before_ht_op[] = { + WLAN_EID_RSN, + WLAN_EID_QOS_CAPA, + WLAN_EID_FAST_BSS_TRANSITION, + WLAN_EID_TIMEOUT_INTERVAL, + }; + noffset = ieee80211_ie_split(extra_ies, extra_ies_len, + before_ht_op, + ARRAY_SIZE(before_ht_op), + offset); + pos = skb_put(skb, noffset - offset); + memcpy(pos, extra_ies + offset, noffset - offset); + offset = noffset; + } + + /* if HT support is only added in TDLS, we need an HT-operation IE */ + if (!ap_sta->sta.ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) { + struct ieee80211_chanctx_conf *chanctx_conf = + rcu_dereference(sdata->vif.chanctx_conf); + if (!WARN_ON(!chanctx_conf)) { + pos = skb_put(skb, 2 + + sizeof(struct ieee80211_ht_operation)); + /* send an empty HT operation IE */ + ieee80211_ie_build_ht_oper(pos, &sta->sta.ht_cap, + &chanctx_conf->def, 0); + } + } + + rcu_read_unlock(); + /* add any remaining IEs */ if (extra_ies_len) { noffset = extra_ies_len; @@ -280,8 +360,6 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, } ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); - - rcu_read_unlock(); } static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata, @@ -441,6 +519,8 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, 50 + /* supported rates */ 7 + /* ext capab */ 26 + /* max(WMM-info, WMM-param) */ + 2 + max(sizeof(struct ieee80211_ht_cap), + sizeof(struct ieee80211_ht_operation)) + extra_ies_len + sizeof(struct ieee80211_tdls_lnkie)); if (!skb)