From patchwork Wed Jul 13 15:34:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590789 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13DF5C433EF for ; Wed, 13 Jul 2022 15:34:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236944AbiGMPen (ORCPT ); Wed, 13 Jul 2022 11:34:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231841AbiGMPel (ORCPT ); Wed, 13 Jul 2022 11:34:41 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D2EA30F46 for ; Wed, 13 Jul 2022 08:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=dowT5/fbHMQCPQq7DYbtU6a7iyOiKETaI20mzGTRkqk=; t=1657726480; x=1658936080; b=G8lVgFIvIE143HJ4RDOo68DLO41VSvbIjXVqaU+OGH7WcG2 IrtdbqCfBSeqq6MrFGybdm0bDIp/Hem7yXGZqAyGZlLFv3jIJFAhB4YdV4j9HCvNp1vBHJhhkJFnr yNb1HwWFWwsVrDeCcevKU5JbXn0HBLXqAkSXp5XxgOG3ZhA7dbrvskF0DCoMhnzgM8ReMRAj9qyvg 4Vby4Y0k5azDEuVCJhBW402RrqKx/y//gtQDj4zjFvrSZUhOtEPUTAhOsEt1h2ngB6Q2OmWCYMXbH r965z3OfrCn+CpjTGemgpAfzwQI/hSraz/Z+T6ddrCJQ8011xod11zI2qSYeK/Cg==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNp-00EnaA-Hr; Wed, 13 Jul 2022 17:34:37 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 01/21] wifi: nl80211: reject link specific elements on assoc link Date: Wed, 13 Jul 2022 17:34:13 +0200 Message-Id: <20220713173301.0c5d0302c561.I01b2db7b91d0f03790751b6bee9c7001ce323317@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg When we associate, we'll include all the elements for the link we're sending the association request on in the frame and the specific ones for other links in the multi-link element container. Prohibit adding link-specific elements for the association link. Fixes: d648c23024bd ("wifi: nl80211: support MLO in auth/assoc") Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ead9bd111280..be969f64b5c3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -10813,6 +10813,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) goto free; } + if (req.links[req.link_id].elems_len) { + GENL_SET_ERR_MSG(info, + "cannot have per-link elems on assoc link"); + err = -EINVAL; + goto free; + } + kfree(attrs); attrs = NULL; } else { From patchwork Wed Jul 13 15:34:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590319 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 613F5CCA481 for ; Wed, 13 Jul 2022 15:34:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236958AbiGMPes (ORCPT ); Wed, 13 Jul 2022 11:34:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40502 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236875AbiGMPem (ORCPT ); Wed, 13 Jul 2022 11:34:42 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 786C52FFE0 for ; Wed, 13 Jul 2022 08:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=5lXq3+gwn+yp3ypbdM7NnRAzFBA6eb94pXrPSZX9Wso=; t=1657726481; x=1658936081; b=cr8upjGLmDPNBaTNTooKVz56G2Ea8jA6+Ll+/8gJrw8poZq kMEJ73rSIYxcU/5g7wPdo9qxz+M4GZS1bmBo+w/tL4GaChSIKNckRiI80dk3QaK2jSKOQIPWBTwSi urHb2hQxuyQtZK3ZJoMhtzQasURbgQhhbYZJKTR7jU56gUklFvkYe7KkzxmjoLeygFGM0UEBHfE1I PCA2wZy5ZFCyai8SE0FovMKjVhqydVNv2h2Lo7dHLzcLLX8ly3+WwEaaGd5yUFQCDmMAUxhdJS2jW D4gV+bB5UxGIAwv+GMyH7CkRlok59VMsxEhD23BcmLBe1/qZKDipzYnlBDoVesgQ==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNp-00EnaA-QC; Wed, 13 Jul 2022 17:34:37 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 02/21] wifi: nl80211: reject fragmented and non-inheritance elements Date: Wed, 13 Jul 2022 17:34:14 +0200 Message-Id: <20220713173301.b71b1a24e37c.Iae35742381f6a5495768fca57e01b4a1fab918d6@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg The underlying mac80211 code cannot deal with fragmented elements for purposes of sorting the elements into the association frame, so reject those inside the link. We might want to reject them inside the assoc frame, but they're used today for FILS, so cannot do that. The non-inheritance element inside the links similarly cannot be handled by mac80211, and outside the links it makes no sense. Reject both since using them could lead to an incorrect implementation. Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index be969f64b5c3..e2d1efe0174e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -10661,6 +10661,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_IE]) { req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + + if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, + req.ie, req.ie_len)) { + GENL_SET_ERR_MSG(info, + "non-inheritance makes no sense"); + return -EINVAL; + } } if (info->attrs[NL80211_ATTR_USE_MFP]) { @@ -10805,6 +10812,24 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) nla_data(attrs[NL80211_ATTR_IE]); req.links[link_id].elems_len = nla_len(attrs[NL80211_ATTR_IE]); + + if (cfg80211_find_elem(WLAN_EID_FRAGMENT, + req.links[link_id].elems, + req.links[link_id].elems_len)) { + GENL_SET_ERR_MSG(info, + "cannot deal with fragmentation"); + err = -EINVAL; + goto free; + } + + if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, + req.links[link_id].elems, + req.links[link_id].elems_len)) { + GENL_SET_ERR_MSG(info, + "cannot deal with non-inheritance"); + err = -EINVAL; + goto free; + } } } From patchwork Wed Jul 13 15:34:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590788 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6B08CCA481 for ; Wed, 13 Jul 2022 15:34:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236960AbiGMPep (ORCPT ); Wed, 13 Jul 2022 11:34:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40492 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236761AbiGMPem (ORCPT ); Wed, 13 Jul 2022 11:34:42 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE22332060 for ; Wed, 13 Jul 2022 08:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=kkm/OG427Lc0msYf2+SEk0QmCZYQY/OWdZpMSIeKX/I=; t=1657726481; x=1658936081; b=gpgF/JpS3ljJw1SD6u88aEOdd6VMWJ67ylTVnHB2YNNY68d yCmQMTAfWNL/Qo0BZca+ksQ9YBexiTGwPT2aamQ12+oi7oTyailkm+0e3h33DEnD0WuKi7B0kdw4s PiNzSIcbOBhT/qVD8NWqtpETUYYlwYW0Qr+rX1y5/OAMKwS1zXLX5P1q+pWPCHHEUWOD1iBbyWsVI kVnOKWjzL34+p99MNtya7iupv0BKPvBZ9m/QOlnpWPNjkHyPs1GMlZKmYVVyX4qrZkxFyBGki5k+w KzqXXWHKTDsvofz8D4mm+yYQWjftjSe1HnaSW/B55lyX4gP5CmTXt6c7qDKoNwPg==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNq-00EnaA-1E; Wed, 13 Jul 2022 17:34:38 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 03/21] wifi: nl80211: fix some attribute policy entries Date: Wed, 13 Jul 2022 17:34:15 +0200 Message-Id: <20220713173301.cba3a18d91b8.I2a913d5de4d7674bb62804a389666010ecf36553@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg The new NL80211_CMD_ADD_LINK_STA and NL80211_CMD_MODIFY_LINK_STA commands have strict policy validation, so fix the policy so it can be validated correctly. Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e2d1efe0174e..b6e640437568 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -456,6 +456,12 @@ nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = { [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG }, }; +static const struct nla_policy +nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = { + [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, + [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, +}; + static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD }, [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, @@ -560,9 +566,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32, NL80211_MFP_NO, NL80211_MFP_OPTIONAL), - [NL80211_ATTR_STA_FLAGS2] = { - .len = sizeof(struct nl80211_sta_flag_update), - }, + [NL80211_ATTR_STA_FLAGS2] = + NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_sta_flag_update)), [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, @@ -615,6 +620,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, IEEE80211_MAX_DATA_LEN), [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, + [NL80211_ATTR_STA_WME] = NLA_POLICY_NESTED(nl80211_sta_wme_policy), [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG }, [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 }, @@ -6722,12 +6728,6 @@ static struct net_device *get_vlan(struct genl_info *info, return ERR_PTR(ret); } -static const struct nla_policy -nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = { - [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, - [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, -}; - static int nl80211_parse_sta_wme(struct genl_info *info, struct station_parameters *params) { From patchwork Wed Jul 13 15:34:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590321 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9FCD3CCA479 for ; Wed, 13 Jul 2022 15:34:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236952AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40472 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236677AbiGMPel (ORCPT ); Wed, 13 Jul 2022 11:34:41 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8D4DE31204 for ; Wed, 13 Jul 2022 08:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=lxL7BGo8R2mpegwNTB2yu6uiciX2aGOMY3J4H9RR6rU=; t=1657726480; x=1658936080; b=Eu8e6s2VtAF1VTf/iFCUfyLZ+6xuqHqwIjmSaajxj0fmlmd amtp9GyAvBnNrrvckRilWOvzt0Eu91nk2LYkGLIf/ziseobHaXuCr2wtuI6NuY+DRbBeT4ZAjaWsi ZtFCTnDXE1bcM7cmGE+4/JzhthdiyrjTGEViU65HoPqjDJ3yOGeYK3IPbkZj0JRDX6CKnQ3r7mWVV BlbcrJAxPI7MsowtSGDh2uzzT/22hwYdx/HP7u6GahXibKqxo1pmYfwcGTCEg68jD3MbarvrTBOk9 qidtIRUlkf5VTOOWDJ6wx9UKsfLJqbgJOIDMpqO9iOPwg5xq28gSpAYO9i1li6ug==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNq-00EnaA-9F; Wed, 13 Jul 2022 17:34:38 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 04/21] wifi: mac80211: prohibit DEAUTH_NEED_MGD_TX_PREP in MLO Date: Wed, 13 Jul 2022 17:34:16 +0200 Message-Id: <20220713173301.bc46fd46a805.I373154f39adf68cffe1940ec88bb00830d546a1f@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg For now, prohibit DEAUTH_NEED_MGD_TX_PREP since we can't really transmit this on a specific link yet as we don't know which links are active. Signed-off-by: Johannes Berg --- net/mac80211/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 26bb30606282..5b1c47ed0cc0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1001,6 +1001,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (WARN_ON(!ieee80211_hw_check(hw, AP_LINK_PS))) return -EINVAL; + + if (WARN_ON(ieee80211_hw_check(hw, DEAUTH_NEED_MGD_TX_PREP))) + return -EINVAL; } #ifdef CONFIG_PM From patchwork Wed Jul 13 15:34:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590787 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43586CCA479 for ; Wed, 13 Jul 2022 15:34:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236968AbiGMPer (ORCPT ); Wed, 13 Jul 2022 11:34:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40502 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231655AbiGMPem (ORCPT ); Wed, 13 Jul 2022 11:34:42 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 072173FA22 for ; Wed, 13 Jul 2022 08:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=2gxJf+24sS74868SelZRPE/r131WVxGbsGNG97XeGEA=; t=1657726481; x=1658936081; b=pzAIew+rtsr/jW6o+gf3BuJCZ5fncElfk36NdAY4lFNRuf0 BiCOTV5021DMfCWaYWPP4r3V9zecmRCYCLpt2pmwADuULixpY7UyNg8gD2rJfVxAVJ0gN1EEDpy0P hPYGU5HRuM9hY0gqXpQOWNc7RimJzXQV4JCAYVCjLBAkD5GYsCAI/PGtDy9dsmADENJW8jtBjekBv ZH/Syp34/+JRw6y2xhqeoRPBR+BiSf17dz7Qj/XPAgyyF6Vj++rruZE/KmQZ88Sr3Q46N25ZkNL/H v/a8N64gO1edT+kpSmsSWJ6jyspi15+tVA/5IixJdJ07/0exHPqxL4kuB2p8g1zA==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNq-00EnaA-Gn; Wed, 13 Jul 2022 17:34:38 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 05/21] wifi: mac80211: release channel context on link stop Date: Wed, 13 Jul 2022 17:34:17 +0200 Message-Id: <20220713173301.be8c59cca5e7.Iec7ad2a4c925d9256891b75ba845540e93d12a99@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg When a link is stopped for removal, release the channel context it may have. Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 271fc81a5ea4..b11374115ff2 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -420,6 +420,8 @@ static void ieee80211_link_stop(struct ieee80211_link_data *link) { if (link->sdata->vif.type == NL80211_IFTYPE_STATION) ieee80211_mgd_stop_link(link); + + ieee80211_link_release_channel(link); } struct link_container { From patchwork Wed Jul 13 15:34:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590320 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA93DC43334 for ; Wed, 13 Jul 2022 15:34:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236963AbiGMPeq (ORCPT ); Wed, 13 Jul 2022 11:34:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236773AbiGMPem (ORCPT ); Wed, 13 Jul 2022 11:34:42 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 06B7E3E759 for ; Wed, 13 Jul 2022 08:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=kE7/DIY7Pnhnm1KcOZPfaD0L7gShX4/QnLHZsFOOwcM=; t=1657726481; x=1658936081; b=CGoYPH83juiLLCvp28DTJVLE+VK2Ci2Rb1stp/eHFAIEjzS WkhwIrpZyJx/VgeKRKEBd4zUTvfxQIT0RqIvsgfaYIJzkPFFAT+qZfsN0SUeKTALzpQXlG8XXkaEQ CpA+E5Rb5FIKh7WqLDIy96U2+5ZaEqwfXEON3lbkXtBjQ+n554mjc4cr2Vzecz84sFwxGZ2qkjqe3 aBzU+eUJVld6AhFvq/V3ydB55i/PPwnJzR+ejOA2BJSnbKLAR2Xrg/5USBQxQg2qQjqb1saWeMegy ifvoNWjm9q1PzhQEH+ABE59V0mc0iyv/AM7IlYbt21XTf4CuHtEql09XvU0sJcfw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNq-00EnaA-OJ; Wed, 13 Jul 2022 17:34:38 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 06/21] wifi: mac80211: mlme: clean up supported channels element code Date: Wed, 13 Jul 2022 17:34:18 +0200 Message-Id: <20220713173301.abefedad549e.Ia7c125ab1274ce850e1c8bf547621275d3294ab1@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Clean up the code building the supported channels element a little bit by using a local variable instead of the long line. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f261d42dd59f..042cd5439bb8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1078,8 +1078,9 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) *pos++ = WLAN_EID_SUPPORTED_CHANNELS; *pos++ = 2 * sband->n_channels; for (i = 0; i < sband->n_channels; i++) { - *pos++ = ieee80211_frequency_to_channel( - sband->channels[i].center_freq); + int cf = sband->channels[i].center_freq; + + *pos++ = ieee80211_frequency_to_channel(cf); *pos++ = 1; /* one channel in the subband*/ } } From patchwork Wed Jul 13 15:34:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590786 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1BE28CCA483 for ; Wed, 13 Jul 2022 15:34:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236971AbiGMPes (ORCPT ); Wed, 13 Jul 2022 11:34:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236784AbiGMPem (ORCPT ); Wed, 13 Jul 2022 11:34:42 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1562341D3A for ; Wed, 13 Jul 2022 08:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=bM5w5nfF6EkhHYX8Sz4nGkzE5bziwujdNy+U/ulO2cY=; t=1657726481; x=1658936081; b=oWjTSLWUQZ7AOPXeIdBty5OR4uMcH2Q9AJEo9PVxMqQFDSp mKZ5Vi8epy3OSfgEEMRbxVoyQpXMqbyC3iVgxNG3GGXRF/sWkTMneYUYU1swweD/byEJJUutWN5Jx bohxjFnUDLIZuXbrpoL78JMu5gD58ZJOuK7CwjitQrNLR2Siv1bW7DcZxMLjvRN31kQA65TtrsFlp psx8gB8CR0qHYX5wdrGRRc6RciVgJEb+xy0LT2RjsOhXsttwuVcn/dT4mgMkFxGJoPn6xpkhA3fIU M5C3a0wJgEO5MuHFwBuAqLQb3paRtudx9vj45EwF9mSVAc/Shnknd3rfqz1s0ZXA==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNq-00EnaA-Ve; Wed, 13 Jul 2022 17:34:39 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 07/21] wifi: mac80211: add multi-link element to AUTH frames Date: Wed, 13 Jul 2022 17:34:19 +0200 Message-Id: <20220713173301.8ce1b3fb7c9d.I8b2ece0e92aa8454f106730cac9d31a86495f540@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg When sending an authentication frame from an MLD, include the multi-link element with the MLD address and use the link address for transmission. Signed-off-by: Johannes Berg --- net/mac80211/util.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 994a49b892a6..b6ddcbbb22e8 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1711,11 +1711,28 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; + bool multi_link = sdata->vif.valid_links; + struct { + u8 id; + u8 len; + u8 ext_id; + struct ieee80211_multi_link_elem ml; + struct ieee80211_mle_basic_common_info basic; + } __packed mle = { + .id = WLAN_EID_EXTENSION, + .len = sizeof(mle) - 2, + .ext_id = WLAN_EID_EXT_EHT_MULTI_LINK, + .ml.control = cpu_to_le16(IEEE80211_ML_CONTROL_TYPE_BASIC), + .basic.len = sizeof(mle.basic), + }; int err; + memcpy(mle.basic.mld_mac_addr, sdata->vif.addr, ETH_ALEN); + /* 24 + 6 = header + auth_algo + auth_transaction + status_code */ skb = dev_alloc_skb(local->hw.extra_tx_headroom + IEEE80211_WEP_IV_LEN + - 24 + 6 + extra_len + IEEE80211_WEP_ICV_LEN); + 24 + 6 + extra_len + IEEE80211_WEP_ICV_LEN + + multi_link * sizeof(mle)); if (!skb) return; @@ -1732,6 +1749,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, mgmt->u.auth.status_code = cpu_to_le16(status); if (extra) skb_put_data(skb, extra, extra_len); + if (multi_link) + skb_put_data(skb, &mle, sizeof(mle)); if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) { mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); From patchwork Wed Jul 13 15:34:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590318 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E9A11C433EF for ; Wed, 13 Jul 2022 15:34:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236973AbiGMPet (ORCPT ); Wed, 13 Jul 2022 11:34:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236806AbiGMPem (ORCPT ); Wed, 13 Jul 2022 11:34:42 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 077CC41D38 for ; Wed, 13 Jul 2022 08:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=byRy5DE04FosmI7ShOE9jYDvUvldHf+9y/jdXN2TQzs=; t=1657726481; x=1658936081; b=C7C+kfc+7MNwW9o1tcnyhRbXVfUH15DYysDhgjk3YupC2Vz jLIhU87isWlEzy9uifROrcXLSaPOgQiLrYesB6dKj/5ZHrhf+XkYL3s6WOdau8IxqUs5T5xanb0ny OtljnRFnndioKFFYYF3I6CpsVpkN8vAKC5/GfGzGRAV0HUu26CmmAnAJ39WTDiBalzhcsmhaacrzv cik810BaxknQg2bjAy3jjBj21TORc/xPk7Klpw+ScMh3wvoqjXWSNjhP2+pZfk+BVD31PqoSANHKv u4MBolxTyW4amB6tANYmzAROWZi3+/S+EgrBep6aG2DKquy6Gg6VcVtTpY6O+npg==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNr-00EnaA-6x; Wed, 13 Jul 2022 17:34:39 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 08/21] wifi: mac80211: make ieee80211_check_rate_mask() link-aware Date: Wed, 13 Jul 2022 17:34:20 +0200 Message-Id: <20220713173301.e6ac357a8943.I68489f528743ecf1b4f31f7e7bc786f5adca4b21@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Change ieee80211_check_rate_mask() to use a link rather than the sdata and deflink/bss_conf. Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 +- net/mac80211/mlme.c | 2 +- net/mac80211/rate.c | 9 +++++---- net/mac80211/rate.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 498dce37adad..bc2aaecd2a8c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2524,7 +2524,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, params->basic_rates_len, &sdata->vif.bss_conf.basic_rates); changed |= BSS_CHANGED_BASIC_RATES; - ieee80211_check_rate_mask(sdata); + ieee80211_check_rate_mask(&sdata->deflink); } if (params->ap_isolate >= 0) { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 042cd5439bb8..3986bf70fc5c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2360,7 +2360,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, memcpy(link->u.mgd.bssid, cbss->bssid, ETH_ALEN); memcpy(sdata->vif.cfg.ap_addr, cbss->bssid, ETH_ALEN); - ieee80211_check_rate_mask(sdata); + ieee80211_check_rate_mask(link); if (sdata->vif.p2p || sdata->vif.driver_flags & IEEE80211_VIF_GET_NOA_UPDATE) { diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 7947e9a162a9..d5ea5f5bcf3a 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -270,17 +270,18 @@ static void rate_control_free(struct ieee80211_local *local, kfree(ctrl_ref); } -void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata) +void ieee80211_check_rate_mask(struct ieee80211_link_data *link) { + struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; - u32 user_mask, basic_rates = sdata->vif.bss_conf.basic_rates; + u32 user_mask, basic_rates = link->conf->basic_rates; enum nl80211_band band; - if (WARN_ON(!sdata->vif.bss_conf.chandef.chan)) + if (WARN_ON(!link->conf->chandef.chan)) return; - band = sdata->vif.bss_conf.chandef.chan->band; + band = link->conf->chandef.chan->band; if (band == NL80211_BAND_S1GHZ) { /* TODO */ return; diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index d89c13584dc8..d6190f10fe7c 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -85,7 +85,7 @@ static inline void rate_control_add_debugfs(struct ieee80211_local *local) #endif } -void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata); +void ieee80211_check_rate_mask(struct ieee80211_link_data *link); /* Get a reference to the rate control algorithm. If `name' is NULL, get the * first available algorithm. */ From patchwork Wed Jul 13 15:34:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590317 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E50FAC43334 for ; Wed, 13 Jul 2022 15:34:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236979AbiGMPev (ORCPT ); Wed, 13 Jul 2022 11:34:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236945AbiGMPen (ORCPT ); Wed, 13 Jul 2022 11:34:43 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9CAD34B0E2 for ; Wed, 13 Jul 2022 08:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=6nXTKEIE53vQkJfwYXrTV8vCLa+VW5ygDMmFJAiD4d8=; t=1657726481; x=1658936081; b=HQNRx5lZbsXr0juO5R7IZJOjUwZqoffmCP8Mk/clBH3uF9+ WJVMOyzzKcTQZVYmcSvd2YBBcz5Y6SQz1QpVw+nrXOTBQXCO34kaXbJBaQM+4AXIgXFmfU6ONvDA6 xR2MrKInYJUCviFAzeznrOZOjV42VlgFkChTSkPdtUOwPHUD4DgMzdkVasmMwLluMGCFE9+9URxKm TGdWL/H+CfmNJNqG7Wo8B62AvvvvZDM1YWgXN/W7iwDOR3UVyKBb3u17B85T3R+Uvl4NAkca2QYUb w49nX0B+hAlt2fLsj1oa5Au59JtBPMAA0vfpKB5qS+1tVli+c0wdiMizZVlECIOQ==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNr-00EnaA-EH; Wed, 13 Jul 2022 17:34:39 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 09/21] wifi: mac80211: move IEEE80211_SDATA_OPERATING_GMODE to link Date: Wed, 13 Jul 2022 17:34:21 +0200 Message-Id: <20220713173301.5533c438e2a3.Ia6f6f76d35f30a669968cb7bdb3912c2a89227e2@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg The flag here is currently per interface, but the way we set and clear it means it should be per link, so change it. Signed-off-by: Johannes Berg --- net/mac80211/ibss.c | 6 ++---- net/mac80211/ieee80211_i.h | 6 ++++-- net/mac80211/mlme.c | 7 ++----- net/mac80211/ocb.c | 2 +- net/mac80211/tx.c | 2 +- net/mac80211/util.c | 8 ++++---- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index e8df4ce33984..60b5230778a3 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -351,10 +351,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, bss_change |= BSS_CHANGED_ERP_SLOT; /* cf. IEEE 802.11 9.2.12 */ - if (chan->band == NL80211_BAND_2GHZ && have_higher_than_11mbit) - sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; - else - sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; + sdata->deflink.operating_11g_mode = + chan->band == NL80211_BAND_2GHZ && have_higher_than_11mbit; ieee80211_set_wmm_default(&sdata->deflink, true, false); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 877f2441b74b..baaff4c7a79c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -726,7 +726,6 @@ struct ieee80211_if_mesh { * enum ieee80211_sub_if_data_flags - virtual interface flags * * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets - * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between * associated stations and deliver multicast frames both * back to wireless media and to the local net stack. @@ -737,7 +736,6 @@ struct ieee80211_if_mesh { */ enum ieee80211_sub_if_data_flags { IEEE80211_SDATA_ALLMULTI = BIT(0), - IEEE80211_SDATA_OPERATING_GMODE = BIT(2), IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), IEEE80211_SDATA_IN_DRIVER = BIT(5), @@ -884,6 +882,7 @@ struct ieee80211_link_data_managed { bool have_beacon; bool tracking_signal_avg; bool disable_wmm_tracking; + bool operating_11g_mode; bool csa_waiting_bcn; bool csa_ignored_same_chan; @@ -946,6 +945,9 @@ struct ieee80211_link_data { struct work_struct csa_finalize_work; bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ + + bool operating_11g_mode; + struct cfg80211_chan_def csa_chandef; struct work_struct color_change_finalize_work; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3986bf70fc5c..6822bf1c3cae 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -5810,11 +5810,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, link->conf->basic_rates = basic_rates; /* cf. IEEE 802.11 9.2.12 */ - if (cbss->channel->band == NL80211_BAND_2GHZ && - have_higher_than_11mbit) - sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; - else - sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; + link->operating_11g_mode = sband->band == NL80211_BAND_2GHZ && + have_higher_than_11mbit; skip_rates: memcpy(link->u.mgd.bssid, cbss->bssid, ETH_ALEN); diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c index 2ca2164a3098..8664fee699e9 100644 --- a/net/mac80211/ocb.c +++ b/net/mac80211/ocb.c @@ -181,7 +181,7 @@ int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata, if (ifocb->joined == true) return -EINVAL; - sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; + sdata->deflink.operating_11g_mode = true; sdata->deflink.smps_mode = IEEE80211_SMPS_OFF; sdata->deflink.needed_rx_chains = sdata->local->rx_chains; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b9cb71dfa6cf..f10318cadd4c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -148,7 +148,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, case NL80211_BAND_2GHZ: case NL80211_BAND_LC: { u32 flag; - if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + if (tx->sdata->deflink.operating_11g_mode) flag = IEEE80211_RATE_MANDATORY_G; else flag = IEEE80211_RATE_MANDATORY_B; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b6ddcbbb22e8..a6963feaf75d 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -191,7 +191,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, if (vif) { sdata = vif_to_sdata(vif); short_preamble = sdata->vif.bss_conf.use_short_preamble; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + if (sdata->deflink.operating_11g_mode) erp = rate->flags & IEEE80211_RATE_ERP_G; shift = ieee80211_vif_get_shift(vif); } @@ -225,7 +225,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, if (vif) { sdata = vif_to_sdata(vif); short_preamble = sdata->vif.bss_conf.use_short_preamble; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + if (sdata->deflink.operating_11g_mode) erp = rate->flags & IEEE80211_RATE_ERP_G; shift = ieee80211_vif_get_shift(vif); } @@ -268,7 +268,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, if (vif) { sdata = vif_to_sdata(vif); short_preamble = sdata->vif.bss_conf.use_short_preamble; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + if (sdata->deflink.operating_11g_mode) erp = rate->flags & IEEE80211_RATE_ERP_G; shift = ieee80211_vif_get_shift(vif); } @@ -1614,7 +1614,7 @@ void ieee80211_set_wmm_default(struct ieee80211_link_data *link, chanctx_conf = rcu_dereference(link->conf->chanctx_conf); use_11b = (chanctx_conf && chanctx_conf->def.chan->band == NL80211_BAND_2GHZ) && - !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); + !link->operating_11g_mode; rcu_read_unlock(); is_ocb = (sdata->vif.type == NL80211_IFTYPE_OCB); From patchwork Wed Jul 13 15:34:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590785 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C59DC433EF for ; Wed, 13 Jul 2022 15:34:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236977AbiGMPev (ORCPT ); Wed, 13 Jul 2022 11:34:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236943AbiGMPen (ORCPT ); Wed, 13 Jul 2022 11:34:43 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 914E430F46 for ; Wed, 13 Jul 2022 08:34:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=IBwzJ2pYjQdKlLTvLxk5WbODqcT3/OVmRQWSGr+aRTE=; t=1657726481; x=1658936081; b=ug15WYw3mhgtLnTyd0IeXd5IxY+B+vsYNvdQNfgvus9H6fX dB4yPLGGF019EUP3DJMiKEgs++Ib34JKUh3n5a2Yyx/S/TYwUXaII9hZ3idbgVCv6CbSWJvcn/SBP NilZ3ES4lck5905++RyQ1KiEQ5sABO3wRpKujTB/1EmA3+xSjsyWRM61Sa/mk1OvvN0LPBYow/BXJ zWfXF2ytlfogPB+qeafhoNABs1KxWuyipYz/fV4Lx9fmTHONyL7bP5JExmurwMZJDRugnkZ23DXgr fw3TL7MeQT3kYjglA0b4YM2yn9sjGauboxF8dxRRXv79OaS0dUMFNcy5waoRPSfw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNr-00EnaA-Mw; Wed, 13 Jul 2022 17:34:39 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 10/21] wifi: mac80211: mlme: refactor link station setup Date: Wed, 13 Jul 2022 17:34:22 +0200 Message-Id: <20220713173301.c21bda9e2df3.I3a34da939f6aa4772c07b59e9aaaa08601c20ddb@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Refactor the code here since we need to have it also for each link station after association in MLO later. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 119 ++++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6822bf1c3cae..78b8fcd5fdb2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3484,6 +3484,67 @@ static bool ieee80211_twt_bcast_support(struct ieee80211_sub_if_data *sdata, IEEE80211_HE_MAC_CAP2_BCAST_TWT); } +static int ieee80211_mgd_setup_link_sta(struct ieee80211_link_data *link, + struct sta_info *sta, + struct ieee80211_link_sta *link_sta, + struct cfg80211_bss *cbss) +{ + struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_local *local = sdata->local; + struct ieee80211_bss *bss = (void *)cbss->priv; + u32 rates = 0, basic_rates = 0; + bool have_higher_than_11mbit = false; + int min_rate = INT_MAX, min_rate_index = -1; + /* this is clearly wrong for MLO but we'll just remove it later */ + int shift = ieee80211_vif_get_shift(&sdata->vif); + struct ieee80211_supported_band *sband; + + memcpy(link_sta->addr, cbss->bssid, ETH_ALEN); + + /* TODO: S1G Basic Rate Set is expressed elsewhere */ + if (cbss->channel->band == NL80211_BAND_S1GHZ) { + ieee80211_s1g_sta_rate_init(sta); + return 0; + } + + sband = local->hw.wiphy->bands[cbss->channel->band]; + + ieee80211_get_rates(sband, bss->supp_rates, bss->supp_rates_len, + &rates, &basic_rates, &have_higher_than_11mbit, + &min_rate, &min_rate_index, shift); + + /* + * This used to be a workaround for basic rates missing + * in the association response frame. Now that we no + * longer use the basic rates from there, it probably + * doesn't happen any more, but keep the workaround so + * in case some *other* APs are buggy in different ways + * we can connect -- with a warning. + * Allow this workaround only in case the AP provided at least + * one rate. + */ + if (min_rate_index < 0) { + link_info(link, "No legacy rates in association response\n"); + return -EINVAL; + } else if (!basic_rates) { + link_info(link, "No basic rates, using min rate instead\n"); + basic_rates = BIT(min_rate_index); + } + + if (rates) + link_sta->supp_rates[cbss->channel->band] = rates; + else + link_info(link, "No rates found, keeping mandatory only\n"); + + link->conf->basic_rates = basic_rates; + + /* cf. IEEE 802.11 9.2.12 */ + link->operating_11g_mode = sband->band == NL80211_BAND_2GHZ && + have_higher_than_11mbit; + + return 0; +} + static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, struct cfg80211_bss *cbss, struct ieee80211_mgmt *mgmt, size_t len, @@ -5717,13 +5778,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss *bss = (void *)cbss->priv; struct sta_info *new_sta = NULL; - struct ieee80211_supported_band *sband; struct ieee80211_link_data *link = &sdata->deflink; bool have_sta = false; int err; - sband = local->hw.wiphy->bands[cbss->channel->band]; - if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) return -EINVAL; @@ -5757,63 +5815,16 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, * it might need the new channel for that. */ if (new_sta) { - u32 rates = 0, basic_rates = 0; - bool have_higher_than_11mbit = false; - int min_rate = INT_MAX, min_rate_index = -1; const struct cfg80211_bss_ies *ies; - int shift = ieee80211_vif_get_shift(&sdata->vif); struct ieee80211_link_sta *link_sta = &new_sta->sta.deflink; - memcpy(link_sta->addr, cbss->bssid, ETH_ALEN); - - /* TODO: S1G Basic Rate Set is expressed elsewhere */ - if (cbss->channel->band == NL80211_BAND_S1GHZ) { - ieee80211_s1g_sta_rate_init(new_sta); - goto skip_rates; - } - - ieee80211_get_rates(sband, bss->supp_rates, - bss->supp_rates_len, - &rates, &basic_rates, - &have_higher_than_11mbit, - &min_rate, &min_rate_index, - shift); - - /* - * This used to be a workaround for basic rates missing - * in the association response frame. Now that we no - * longer use the basic rates from there, it probably - * doesn't happen any more, but keep the workaround so - * in case some *other* APs are buggy in different ways - * we can connect -- with a warning. - * Allow this workaround only in case the AP provided at least - * one rate. - */ - if (min_rate_index < 0) { - sdata_info(sdata, - "No legacy rates in association response\n"); - + err = ieee80211_mgd_setup_link_sta(link, new_sta, + link_sta, cbss); + if (err) { sta_info_free(local, new_sta); - return -EINVAL; - } else if (!basic_rates) { - sdata_info(sdata, - "No basic rates, using min rate instead\n"); - basic_rates = BIT(min_rate_index); + return err; } - if (rates) - link_sta->supp_rates[cbss->channel->band] = rates; - else - sdata_info(sdata, - "No rates found, keeping mandatory only\n"); - - link->conf->basic_rates = basic_rates; - - /* cf. IEEE 802.11 9.2.12 */ - link->operating_11g_mode = sband->band == NL80211_BAND_2GHZ && - have_higher_than_11mbit; - -skip_rates: memcpy(link->u.mgd.bssid, cbss->bssid, ETH_ALEN); /* set timing information */ From patchwork Wed Jul 13 15:34:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590781 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C55A6CCA479 for ; Wed, 13 Jul 2022 15:34:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236974AbiGMPe4 (ORCPT ); Wed, 13 Jul 2022 11:34:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236956AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2CCBE4C629 for ; Wed, 13 Jul 2022 08:34:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=jVVwoo5aETTzk3HglV68XdYAH54lURre97D4ulQln0E=; t=1657726482; x=1658936082; b=rq8MJfKjEziUxNYeInueC8Gw+bSPcXqdVu3FzGtQs9mZuoa CszBUonGzqVn8A9tJIzstHtFVzpsw2SqVD+Ozc2ZLpv3+M9Ti54mp0PmHwaVf1kpMtjPIJpps2Y7F pW3bKAsIJslori/6qDiRERgLeLRcYoX6O+WHiv007N4tYDkKKHaeKq6Z8I8zTlmn8mSfESxPmYXiN sDBQPFEl1QhK3W8nkAQEjenal6zezpSb8mcFPPl699F6BesXVraPXCCFHUCbQenPT2H79XrYn3kB+ x8+Sbr6bLcnfV1J6etRCl/Tli9WivBns9cNvvJE3i4HosZ1/+qqq4Dg7LwXb9JpQ==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNr-00EnaA-Vs; Wed, 13 Jul 2022 17:34:40 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 11/21] wifi: mac80211: mlme: shift some code around Date: Wed, 13 Jul 2022 17:34:23 +0200 Message-Id: <20220713173301.844f9be241c0.I26f763e5fe6fb7cb38ad38915642086a9c4a21a7@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg We'll need ieee80211_prep_channel() in other code for MLO later, so move the code up - unchanged for now - to avoid forward declarations in the future. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 1002 ++++++++++++++++++++++--------------------- 1 file changed, 509 insertions(+), 493 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 78b8fcd5fdb2..3b4d0bc35b5d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3545,6 +3545,515 @@ static int ieee80211_mgd_setup_link_sta(struct ieee80211_link_data *link, return 0; } +static u8 ieee80211_max_rx_chains(struct ieee80211_link_data *link, + struct cfg80211_bss *cbss) +{ + struct ieee80211_he_mcs_nss_supp *he_mcs_nss_supp; + const struct element *ht_cap_elem, *vht_cap_elem; + const struct cfg80211_bss_ies *ies; + const struct ieee80211_ht_cap *ht_cap; + const struct ieee80211_vht_cap *vht_cap; + const struct ieee80211_he_cap_elem *he_cap; + const struct element *he_cap_elem; + u16 mcs_80_map, mcs_160_map; + int i, mcs_nss_size; + bool support_160; + u8 chains = 1; + + if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) + return chains; + + ht_cap_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_HT_CAPABILITY); + if (ht_cap_elem && ht_cap_elem->datalen >= sizeof(*ht_cap)) { + ht_cap = (void *)ht_cap_elem->data; + chains = ieee80211_mcs_to_chains(&ht_cap->mcs); + /* + * TODO: use "Tx Maximum Number Spatial Streams Supported" and + * "Tx Unequal Modulation Supported" fields. + */ + } + + if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) + return chains; + + vht_cap_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_VHT_CAPABILITY); + if (vht_cap_elem && vht_cap_elem->datalen >= sizeof(*vht_cap)) { + u8 nss; + u16 tx_mcs_map; + + vht_cap = (void *)vht_cap_elem->data; + tx_mcs_map = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map); + for (nss = 8; nss > 0; nss--) { + if (((tx_mcs_map >> (2 * (nss - 1))) & 3) != + IEEE80211_VHT_MCS_NOT_SUPPORTED) + break; + } + /* TODO: use "Tx Highest Supported Long GI Data Rate" field? */ + chains = max(chains, nss); + } + + if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) + return chains; + + ies = rcu_dereference(cbss->ies); + he_cap_elem = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, + ies->data, ies->len); + + if (!he_cap_elem || he_cap_elem->datalen < sizeof(*he_cap)) + return chains; + + /* skip one byte ext_tag_id */ + he_cap = (void *)(he_cap_elem->data + 1); + mcs_nss_size = ieee80211_he_mcs_nss_size(he_cap); + + /* invalid HE IE */ + if (he_cap_elem->datalen < 1 + mcs_nss_size + sizeof(*he_cap)) + return chains; + + /* mcs_nss is right after he_cap info */ + he_mcs_nss_supp = (void *)(he_cap + 1); + + mcs_80_map = le16_to_cpu(he_mcs_nss_supp->tx_mcs_80); + + for (i = 7; i >= 0; i--) { + u8 mcs_80 = mcs_80_map >> (2 * i) & 3; + + if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) { + chains = max_t(u8, chains, i + 1); + break; + } + } + + support_160 = he_cap->phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; + + if (!support_160) + return chains; + + mcs_160_map = le16_to_cpu(he_mcs_nss_supp->tx_mcs_160); + for (i = 7; i >= 0; i--) { + u8 mcs_160 = mcs_160_map >> (2 * i) & 3; + + if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) { + chains = max_t(u8, chains, i + 1); + break; + } + } + + return chains; +} + +static bool +ieee80211_verify_peer_he_mcs_support(struct ieee80211_sub_if_data *sdata, + const struct cfg80211_bss_ies *ies, + const struct ieee80211_he_operation *he_op) +{ + const struct element *he_cap_elem; + const struct ieee80211_he_cap_elem *he_cap; + struct ieee80211_he_mcs_nss_supp *he_mcs_nss_supp; + u16 mcs_80_map_tx, mcs_80_map_rx; + u16 ap_min_req_set; + int mcs_nss_size; + int nss; + + he_cap_elem = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, + ies->data, ies->len); + + /* invalid HE IE */ + if (!he_cap_elem || he_cap_elem->datalen < 1 + sizeof(*he_cap)) { + sdata_info(sdata, + "Invalid HE elem, Disable HE\n"); + return false; + } + + /* skip one byte ext_tag_id */ + he_cap = (void *)(he_cap_elem->data + 1); + mcs_nss_size = ieee80211_he_mcs_nss_size(he_cap); + + /* invalid HE IE */ + if (he_cap_elem->datalen < 1 + sizeof(*he_cap) + mcs_nss_size) { + sdata_info(sdata, + "Invalid HE elem with nss size, Disable HE\n"); + return false; + } + + /* mcs_nss is right after he_cap info */ + he_mcs_nss_supp = (void *)(he_cap + 1); + + mcs_80_map_tx = le16_to_cpu(he_mcs_nss_supp->tx_mcs_80); + mcs_80_map_rx = le16_to_cpu(he_mcs_nss_supp->rx_mcs_80); + + /* P802.11-REVme/D0.3 + * 27.1.1 Introduction to the HE PHY + * ... + * An HE STA shall support the following features: + * ... + * Single spatial stream HE-MCSs 0 to 7 (transmit and receive) in all + * supported channel widths for HE SU PPDUs + */ + if ((mcs_80_map_tx & 0x3) == IEEE80211_HE_MCS_NOT_SUPPORTED || + (mcs_80_map_rx & 0x3) == IEEE80211_HE_MCS_NOT_SUPPORTED) { + sdata_info(sdata, + "Missing mandatory rates for 1 Nss, rx 0x%x, tx 0x%x, disable HE\n", + mcs_80_map_tx, mcs_80_map_rx); + return false; + } + + if (!he_op) + return true; + + ap_min_req_set = le16_to_cpu(he_op->he_mcs_nss_set); + + /* + * Apparently iPhone 13 (at least iOS version 15.3.1) sets this to all + * zeroes, which is nonsense, and completely inconsistent with itself + * (it doesn't have 8 streams). Accept the settings in this case anyway. + */ + if (!ap_min_req_set) + return true; + + /* make sure the AP is consistent with itself + * + * P802.11-REVme/D0.3 + * 26.17.1 Basic HE BSS operation + * + * A STA that is operating in an HE BSS shall be able to receive and + * transmit at each of the tuple values indicated by the + * Basic HE-MCS And NSS Set field of the HE Operation parameter of the + * MLME-START.request primitive and shall be able to receive at each of + * the tuple values indicated by the Supported HE-MCS and + * NSS Set field in the HE Capabilities parameter of the MLMESTART.request + * primitive + */ + for (nss = 8; nss > 0; nss--) { + u8 ap_op_val = (ap_min_req_set >> (2 * (nss - 1))) & 3; + u8 ap_rx_val; + u8 ap_tx_val; + + if (ap_op_val == IEEE80211_HE_MCS_NOT_SUPPORTED) + continue; + + ap_rx_val = (mcs_80_map_rx >> (2 * (nss - 1))) & 3; + ap_tx_val = (mcs_80_map_tx >> (2 * (nss - 1))) & 3; + + if (ap_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || + ap_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || + ap_rx_val < ap_op_val || ap_tx_val < ap_op_val) { + sdata_info(sdata, + "Invalid rates for %d Nss, rx %d, tx %d oper %d, disable HE\n", + nss, ap_rx_val, ap_rx_val, ap_op_val); + return false; + } + } + + return true; +} + +static bool +ieee80211_verify_sta_he_mcs_support(struct ieee80211_sub_if_data *sdata, + struct ieee80211_supported_band *sband, + const struct ieee80211_he_operation *he_op) +{ + const struct ieee80211_sta_he_cap *sta_he_cap = + ieee80211_get_he_iftype_cap(sband, + ieee80211_vif_type_p2p(&sdata->vif)); + u16 ap_min_req_set; + int i; + + if (!sta_he_cap || !he_op) + return false; + + ap_min_req_set = le16_to_cpu(he_op->he_mcs_nss_set); + + /* + * Apparently iPhone 13 (at least iOS version 15.3.1) sets this to all + * zeroes, which is nonsense, and completely inconsistent with itself + * (it doesn't have 8 streams). Accept the settings in this case anyway. + */ + if (!ap_min_req_set) + return true; + + /* Need to go over for 80MHz, 160MHz and for 80+80 */ + for (i = 0; i < 3; i++) { + const struct ieee80211_he_mcs_nss_supp *sta_mcs_nss_supp = + &sta_he_cap->he_mcs_nss_supp; + u16 sta_mcs_map_rx = + le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i]); + u16 sta_mcs_map_tx = + le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i + 1]); + u8 nss; + bool verified = true; + + /* + * For each band there is a maximum of 8 spatial streams + * possible. Each of the sta_mcs_map_* is a 16-bit struct built + * of 2 bits per NSS (1-8), with the values defined in enum + * ieee80211_he_mcs_support. Need to make sure STA TX and RX + * capabilities aren't less than the AP's minimum requirements + * for this HE BSS per SS. + * It is enough to find one such band that meets the reqs. + */ + for (nss = 8; nss > 0; nss--) { + u8 sta_rx_val = (sta_mcs_map_rx >> (2 * (nss - 1))) & 3; + u8 sta_tx_val = (sta_mcs_map_tx >> (2 * (nss - 1))) & 3; + u8 ap_val = (ap_min_req_set >> (2 * (nss - 1))) & 3; + + if (ap_val == IEEE80211_HE_MCS_NOT_SUPPORTED) + continue; + + /* + * Make sure the HE AP doesn't require MCSs that aren't + * supported by the client as required by spec + * + * P802.11-REVme/D0.3 + * 26.17.1 Basic HE BSS operation + * + * An HE STA shall not attempt to join * (MLME-JOIN.request primitive) + * a BSS, unless it supports (i.e., is able to both transmit and + * receive using) all of the tuples in the basic + * HE-MCS and NSS set. + */ + if (sta_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || + sta_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || + (ap_val > sta_rx_val) || (ap_val > sta_tx_val)) { + verified = false; + break; + } + } + + if (verified) + return true; + } + + /* If here, STA doesn't meet AP's HE min requirements */ + return false; +} + +static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_data *link, + struct cfg80211_bss *cbss) +{ + struct ieee80211_local *local = sdata->local; + const struct ieee80211_ht_cap *ht_cap = NULL; + const struct ieee80211_ht_operation *ht_oper = NULL; + const struct ieee80211_vht_operation *vht_oper = NULL; + const struct ieee80211_he_operation *he_oper = NULL; + const struct ieee80211_eht_operation *eht_oper = NULL; + const struct ieee80211_s1g_oper_ie *s1g_oper = NULL; + struct ieee80211_supported_band *sband; + struct cfg80211_chan_def chandef; + bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; + bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ; + struct ieee80211_bss *bss = (void *)cbss->priv; + struct ieee802_11_elems *elems; + const struct cfg80211_bss_ies *ies; + int ret; + u32 i; + bool have_80mhz; + + rcu_read_lock(); + + ies = rcu_dereference(cbss->ies); + elems = ieee802_11_parse_elems(ies->data, ies->len, false, cbss); + if (!elems) { + rcu_read_unlock(); + return -ENOMEM; + } + + sband = local->hw.wiphy->bands[cbss->channel->band]; + + link->u.mgd.conn_flags &= ~(IEEE80211_CONN_DISABLE_40MHZ | + IEEE80211_CONN_DISABLE_80P80MHZ | + IEEE80211_CONN_DISABLE_160MHZ); + + /* disable HT/VHT/HE if we don't support them */ + if (!sband->ht_cap.ht_supported && !is_6ghz) { + mlme_dbg(sdata, "HT not supported, disabling HT/VHT/HE/EHT\n"); + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + } + + if (!sband->vht_cap.vht_supported && is_5ghz) { + mlme_dbg(sdata, "VHT not supported, disabling VHT/HE/EHT\n"); + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + } + + if (!ieee80211_get_he_iftype_cap(sband, + ieee80211_vif_type_p2p(&sdata->vif))) { + mlme_dbg(sdata, "HE not supported, disabling HE and EHT\n"); + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + } + + if (!ieee80211_get_eht_iftype_cap(sband, + ieee80211_vif_type_p2p(&sdata->vif))) { + mlme_dbg(sdata, "EHT not supported, disabling EHT\n"); + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + } + + if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && !is_6ghz) { + ht_oper = elems->ht_operation; + ht_cap = elems->ht_cap_elem; + + if (!ht_cap) { + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; + ht_oper = NULL; + } + } + + if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && !is_6ghz) { + vht_oper = elems->vht_operation; + if (vht_oper && !ht_oper) { + vht_oper = NULL; + sdata_info(sdata, + "AP advertised VHT without HT, disabling HT/VHT/HE\n"); + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + } + + if (!elems->vht_cap_elem) { + sdata_info(sdata, + "bad VHT capabilities, disabling VHT\n"); + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; + vht_oper = NULL; + } + } + + if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) { + he_oper = elems->he_operation; + + if (is_6ghz) { + struct ieee80211_bss_conf *bss_conf; + u8 j = 0; + + bss_conf = link->conf; + + if (elems->pwr_constr_elem) + bss_conf->pwr_reduction = *elems->pwr_constr_elem; + + BUILD_BUG_ON(ARRAY_SIZE(bss_conf->tx_pwr_env) != + ARRAY_SIZE(elems->tx_pwr_env)); + + for (i = 0; i < elems->tx_pwr_env_num; i++) { + if (elems->tx_pwr_env_len[i] > + sizeof(bss_conf->tx_pwr_env[j])) + continue; + + bss_conf->tx_pwr_env_num++; + memcpy(&bss_conf->tx_pwr_env[j], elems->tx_pwr_env[i], + elems->tx_pwr_env_len[i]); + j++; + } + } + + if (!ieee80211_verify_peer_he_mcs_support(sdata, ies, he_oper) || + !ieee80211_verify_sta_he_mcs_support(sdata, sband, he_oper)) + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE | + IEEE80211_CONN_DISABLE_EHT; + } + + /* + * EHT requires HE to be supported as well. Specifically for 6 GHz + * channels, the operation channel information can only be deduced from + * both the 6 GHz operation information (from the HE operation IE) and + * EHT operation. + */ + if (!(link->u.mgd.conn_flags & + (IEEE80211_CONN_DISABLE_HE | + IEEE80211_CONN_DISABLE_EHT)) && + he_oper) { + const struct cfg80211_bss_ies *cbss_ies; + const u8 *eht_oper_ie; + + cbss_ies = rcu_dereference(cbss->ies); + eht_oper_ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_OPERATION, + cbss_ies->data, cbss_ies->len); + if (eht_oper_ie && eht_oper_ie[1] >= + 1 + sizeof(struct ieee80211_eht_operation)) + eht_oper = (void *)(eht_oper_ie + 3); + else + eht_oper = NULL; + } + + /* Allow VHT if at least one channel on the sband supports 80 MHz */ + have_80mhz = false; + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | + IEEE80211_CHAN_NO_80MHZ)) + continue; + + have_80mhz = true; + break; + } + + if (!have_80mhz) { + sdata_info(sdata, "80 MHz not supported, disabling VHT\n"); + link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; + } + + if (sband->band == NL80211_BAND_S1GHZ) { + s1g_oper = elems->s1g_oper; + if (!s1g_oper) + sdata_info(sdata, + "AP missing S1G operation element?\n"); + } + + link->u.mgd.conn_flags |= + ieee80211_determine_chantype(link, sband, + cbss->channel, + bss->vht_cap_info, + ht_oper, vht_oper, + he_oper, eht_oper, + s1g_oper, + &chandef, false); + + link->needed_rx_chains = + min(ieee80211_max_rx_chains(link, cbss), local->rx_chains); + + rcu_read_unlock(); + /* the element data was RCU protected so no longer valid anyway */ + kfree(elems); + elems = NULL; + + if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE && is_6ghz) { + sdata_info(sdata, "Rejecting non-HE 6/7 GHz connection"); + return -EINVAL; + } + + /* will change later if needed */ + link->smps_mode = IEEE80211_SMPS_OFF; + + mutex_lock(&local->mtx); + /* + * If this fails (possibly due to channel context sharing + * on incompatible channels, e.g. 80+80 and 160 sharing the + * same control channel) try to use a smaller bandwidth. + */ + ret = ieee80211_link_use_channel(link, &chandef, + IEEE80211_CHANCTX_SHARED); + + /* don't downgrade for 5 and 10 MHz channels, though. */ + if (chandef.width == NL80211_CHAN_WIDTH_5 || + chandef.width == NL80211_CHAN_WIDTH_10) + goto out; + + while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { + link->u.mgd.conn_flags |= + ieee80211_chandef_downgrade(&chandef); + ret = ieee80211_link_use_channel(link, &chandef, + IEEE80211_CHANCTX_SHARED); + } + out: + mutex_unlock(&local->mtx); + return ret; +} + static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, struct cfg80211_bss *cbss, struct ieee80211_mgmt *mgmt, size_t len, @@ -5243,499 +5752,6 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) rcu_read_unlock(); } -static u8 ieee80211_max_rx_chains(struct ieee80211_link_data *link, - struct cfg80211_bss *cbss) -{ - struct ieee80211_he_mcs_nss_supp *he_mcs_nss_supp; - const struct element *ht_cap_elem, *vht_cap_elem; - const struct cfg80211_bss_ies *ies; - const struct ieee80211_ht_cap *ht_cap; - const struct ieee80211_vht_cap *vht_cap; - const struct ieee80211_he_cap_elem *he_cap; - const struct element *he_cap_elem; - u16 mcs_80_map, mcs_160_map; - int i, mcs_nss_size; - bool support_160; - u8 chains = 1; - - if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) - return chains; - - ht_cap_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_HT_CAPABILITY); - if (ht_cap_elem && ht_cap_elem->datalen >= sizeof(*ht_cap)) { - ht_cap = (void *)ht_cap_elem->data; - chains = ieee80211_mcs_to_chains(&ht_cap->mcs); - /* - * TODO: use "Tx Maximum Number Spatial Streams Supported" and - * "Tx Unequal Modulation Supported" fields. - */ - } - - if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) - return chains; - - vht_cap_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_VHT_CAPABILITY); - if (vht_cap_elem && vht_cap_elem->datalen >= sizeof(*vht_cap)) { - u8 nss; - u16 tx_mcs_map; - - vht_cap = (void *)vht_cap_elem->data; - tx_mcs_map = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map); - for (nss = 8; nss > 0; nss--) { - if (((tx_mcs_map >> (2 * (nss - 1))) & 3) != - IEEE80211_VHT_MCS_NOT_SUPPORTED) - break; - } - /* TODO: use "Tx Highest Supported Long GI Data Rate" field? */ - chains = max(chains, nss); - } - - if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) - return chains; - - ies = rcu_dereference(cbss->ies); - he_cap_elem = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, - ies->data, ies->len); - - if (!he_cap_elem || he_cap_elem->datalen < sizeof(*he_cap)) - return chains; - - /* skip one byte ext_tag_id */ - he_cap = (void *)(he_cap_elem->data + 1); - mcs_nss_size = ieee80211_he_mcs_nss_size(he_cap); - - /* invalid HE IE */ - if (he_cap_elem->datalen < 1 + mcs_nss_size + sizeof(*he_cap)) - return chains; - - /* mcs_nss is right after he_cap info */ - he_mcs_nss_supp = (void *)(he_cap + 1); - - mcs_80_map = le16_to_cpu(he_mcs_nss_supp->tx_mcs_80); - - for (i = 7; i >= 0; i--) { - u8 mcs_80 = mcs_80_map >> (2 * i) & 3; - - if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) { - chains = max_t(u8, chains, i + 1); - break; - } - } - - support_160 = he_cap->phy_cap_info[0] & - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; - - if (!support_160) - return chains; - - mcs_160_map = le16_to_cpu(he_mcs_nss_supp->tx_mcs_160); - for (i = 7; i >= 0; i--) { - u8 mcs_160 = mcs_160_map >> (2 * i) & 3; - - if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) { - chains = max_t(u8, chains, i + 1); - break; - } - } - - return chains; -} - -static bool -ieee80211_verify_peer_he_mcs_support(struct ieee80211_sub_if_data *sdata, - const struct cfg80211_bss_ies *ies, - const struct ieee80211_he_operation *he_op) -{ - const struct element *he_cap_elem; - const struct ieee80211_he_cap_elem *he_cap; - struct ieee80211_he_mcs_nss_supp *he_mcs_nss_supp; - u16 mcs_80_map_tx, mcs_80_map_rx; - u16 ap_min_req_set; - int mcs_nss_size; - int nss; - - he_cap_elem = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, - ies->data, ies->len); - - /* invalid HE IE */ - if (!he_cap_elem || he_cap_elem->datalen < 1 + sizeof(*he_cap)) { - sdata_info(sdata, - "Invalid HE elem, Disable HE\n"); - return false; - } - - /* skip one byte ext_tag_id */ - he_cap = (void *)(he_cap_elem->data + 1); - mcs_nss_size = ieee80211_he_mcs_nss_size(he_cap); - - /* invalid HE IE */ - if (he_cap_elem->datalen < 1 + sizeof(*he_cap) + mcs_nss_size) { - sdata_info(sdata, - "Invalid HE elem with nss size, Disable HE\n"); - return false; - } - - /* mcs_nss is right after he_cap info */ - he_mcs_nss_supp = (void *)(he_cap + 1); - - mcs_80_map_tx = le16_to_cpu(he_mcs_nss_supp->tx_mcs_80); - mcs_80_map_rx = le16_to_cpu(he_mcs_nss_supp->rx_mcs_80); - - /* P802.11-REVme/D0.3 - * 27.1.1 Introduction to the HE PHY - * ... - * An HE STA shall support the following features: - * ... - * Single spatial stream HE-MCSs 0 to 7 (transmit and receive) in all - * supported channel widths for HE SU PPDUs - */ - if ((mcs_80_map_tx & 0x3) == IEEE80211_HE_MCS_NOT_SUPPORTED || - (mcs_80_map_rx & 0x3) == IEEE80211_HE_MCS_NOT_SUPPORTED) { - sdata_info(sdata, - "Missing mandatory rates for 1 Nss, rx 0x%x, tx 0x%x, disable HE\n", - mcs_80_map_tx, mcs_80_map_rx); - return false; - } - - if (!he_op) - return true; - - ap_min_req_set = le16_to_cpu(he_op->he_mcs_nss_set); - - /* make sure the AP is consistent with itself - * - * P802.11-REVme/D0.3 - * 26.17.1 Basic HE BSS operation - * - * A STA that is operating in an HE BSS shall be able to receive and - * transmit at each of the tuple values indicated by the - * Basic HE-MCS And NSS Set field of the HE Operation parameter of the - * MLME-START.request primitive and shall be able to receive at each of - * the tuple values indicated by the Supported HE-MCS and - * NSS Set field in the HE Capabilities parameter of the MLMESTART.request - * primitive - */ - for (nss = 8; nss > 0; nss--) { - u8 ap_op_val = (ap_min_req_set >> (2 * (nss - 1))) & 3; - u8 ap_rx_val; - u8 ap_tx_val; - - if (ap_op_val == IEEE80211_HE_MCS_NOT_SUPPORTED) - continue; - - ap_rx_val = (mcs_80_map_rx >> (2 * (nss - 1))) & 3; - ap_tx_val = (mcs_80_map_tx >> (2 * (nss - 1))) & 3; - - if (ap_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || - ap_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || - ap_rx_val < ap_op_val || ap_tx_val < ap_op_val) { - sdata_info(sdata, - "Invalid rates for %d Nss, rx %d, tx %d oper %d, disable HE\n", - nss, ap_rx_val, ap_rx_val, ap_op_val); - return false; - } - } - - return true; -} - -static bool -ieee80211_verify_sta_he_mcs_support(struct ieee80211_sub_if_data *sdata, - struct ieee80211_supported_band *sband, - const struct ieee80211_he_operation *he_op) -{ - const struct ieee80211_sta_he_cap *sta_he_cap = - ieee80211_get_he_iftype_cap(sband, - ieee80211_vif_type_p2p(&sdata->vif)); - u16 ap_min_req_set; - int i; - - if (!sta_he_cap || !he_op) - return false; - - ap_min_req_set = le16_to_cpu(he_op->he_mcs_nss_set); - - /* Need to go over for 80MHz, 160MHz and for 80+80 */ - for (i = 0; i < 3; i++) { - const struct ieee80211_he_mcs_nss_supp *sta_mcs_nss_supp = - &sta_he_cap->he_mcs_nss_supp; - u16 sta_mcs_map_rx = - le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i]); - u16 sta_mcs_map_tx = - le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i + 1]); - u8 nss; - bool verified = true; - - /* - * For each band there is a maximum of 8 spatial streams - * possible. Each of the sta_mcs_map_* is a 16-bit struct built - * of 2 bits per NSS (1-8), with the values defined in enum - * ieee80211_he_mcs_support. Need to make sure STA TX and RX - * capabilities aren't less than the AP's minimum requirements - * for this HE BSS per SS. - * It is enough to find one such band that meets the reqs. - */ - for (nss = 8; nss > 0; nss--) { - u8 sta_rx_val = (sta_mcs_map_rx >> (2 * (nss - 1))) & 3; - u8 sta_tx_val = (sta_mcs_map_tx >> (2 * (nss - 1))) & 3; - u8 ap_val = (ap_min_req_set >> (2 * (nss - 1))) & 3; - - if (ap_val == IEEE80211_HE_MCS_NOT_SUPPORTED) - continue; - - /* - * Make sure the HE AP doesn't require MCSs that aren't - * supported by the client as required by spec - * - * P802.11-REVme/D0.3 - * 26.17.1 Basic HE BSS operation - * - * An HE STA shall not attempt to join * (MLME-JOIN.request primitive) - * a BSS, unless it supports (i.e., is able to both transmit and - * receive using) all of the tuples in the basic - * HE-MCS and NSS set. - */ - if (sta_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || - sta_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || - (ap_val > sta_rx_val) || (ap_val > sta_tx_val)) { - verified = false; - break; - } - } - - if (verified) - return true; - } - - /* If here, STA doesn't meet AP's HE min requirements */ - return false; -} - -static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, - struct ieee80211_link_data *link, - struct cfg80211_bss *cbss) -{ - struct ieee80211_local *local = sdata->local; - const struct ieee80211_ht_cap *ht_cap = NULL; - const struct ieee80211_ht_operation *ht_oper = NULL; - const struct ieee80211_vht_operation *vht_oper = NULL; - const struct ieee80211_he_operation *he_oper = NULL; - const struct ieee80211_eht_operation *eht_oper = NULL; - const struct ieee80211_s1g_oper_ie *s1g_oper = NULL; - struct ieee80211_supported_band *sband; - struct cfg80211_chan_def chandef; - bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; - bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ; - struct ieee80211_bss *bss = (void *)cbss->priv; - struct ieee802_11_elems *elems; - const struct cfg80211_bss_ies *ies; - int ret; - u32 i; - bool have_80mhz; - - rcu_read_lock(); - - ies = rcu_dereference(cbss->ies); - elems = ieee802_11_parse_elems(ies->data, ies->len, false, cbss); - if (!elems) { - rcu_read_unlock(); - return -ENOMEM; - } - - sband = local->hw.wiphy->bands[cbss->channel->band]; - - link->u.mgd.conn_flags &= ~(IEEE80211_CONN_DISABLE_40MHZ | - IEEE80211_CONN_DISABLE_80P80MHZ | - IEEE80211_CONN_DISABLE_160MHZ); - - /* disable HT/VHT/HE if we don't support them */ - if (!sband->ht_cap.ht_supported && !is_6ghz) { - mlme_dbg(sdata, "HT not supported, disabling HT/VHT/HE/EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; - } - - if (!sband->vht_cap.vht_supported && is_5ghz) { - mlme_dbg(sdata, "VHT not supported, disabling VHT/HE/EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; - } - - if (!ieee80211_get_he_iftype_cap(sband, - ieee80211_vif_type_p2p(&sdata->vif))) { - mlme_dbg(sdata, "HE not supported, disabling HE and EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; - } - - if (!ieee80211_get_eht_iftype_cap(sband, - ieee80211_vif_type_p2p(&sdata->vif))) { - mlme_dbg(sdata, "EHT not supported, disabling EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; - } - - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && !is_6ghz) { - ht_oper = elems->ht_operation; - ht_cap = elems->ht_cap_elem; - - if (!ht_cap) { - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - ht_oper = NULL; - } - } - - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && !is_6ghz) { - vht_oper = elems->vht_operation; - if (vht_oper && !ht_oper) { - vht_oper = NULL; - sdata_info(sdata, - "AP advertised VHT without HT, disabling HT/VHT/HE\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; - } - - if (!elems->vht_cap_elem) { - sdata_info(sdata, - "bad VHT capabilities, disabling VHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - vht_oper = NULL; - } - } - - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) { - he_oper = elems->he_operation; - - if (is_6ghz) { - struct ieee80211_bss_conf *bss_conf; - u8 i, j = 0; - - bss_conf = link->conf; - - if (elems->pwr_constr_elem) - bss_conf->pwr_reduction = *elems->pwr_constr_elem; - - BUILD_BUG_ON(ARRAY_SIZE(bss_conf->tx_pwr_env) != - ARRAY_SIZE(elems->tx_pwr_env)); - - for (i = 0; i < elems->tx_pwr_env_num; i++) { - if (elems->tx_pwr_env_len[i] > - sizeof(bss_conf->tx_pwr_env[j])) - continue; - - bss_conf->tx_pwr_env_num++; - memcpy(&bss_conf->tx_pwr_env[j], elems->tx_pwr_env[i], - elems->tx_pwr_env_len[i]); - j++; - } - } - - if (!ieee80211_verify_peer_he_mcs_support(sdata, ies, he_oper) || - !ieee80211_verify_sta_he_mcs_support(sdata, sband, he_oper)) - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE | - IEEE80211_CONN_DISABLE_EHT; - } - - /* - * EHT requires HE to be supported as well. Specifically for 6 GHz - * channels, the operation channel information can only be deduced from - * both the 6 GHz operation information (from the HE operation IE) and - * EHT operation. - */ - if (!(link->u.mgd.conn_flags & - (IEEE80211_CONN_DISABLE_HE | - IEEE80211_CONN_DISABLE_EHT)) && - he_oper) { - const struct cfg80211_bss_ies *ies; - const u8 *eht_oper_ie; - - ies = rcu_dereference(cbss->ies); - eht_oper_ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_OPERATION, - ies->data, ies->len); - if (eht_oper_ie && eht_oper_ie[1] >= - 1 + sizeof(struct ieee80211_eht_operation)) - eht_oper = (void *)(eht_oper_ie + 3); - else - eht_oper = NULL; - } - - /* Allow VHT if at least one channel on the sband supports 80 MHz */ - have_80mhz = false; - for (i = 0; i < sband->n_channels; i++) { - if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | - IEEE80211_CHAN_NO_80MHZ)) - continue; - - have_80mhz = true; - break; - } - - if (!have_80mhz) { - sdata_info(sdata, "80 MHz not supported, disabling VHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - } - - if (sband->band == NL80211_BAND_S1GHZ) { - s1g_oper = elems->s1g_oper; - if (!s1g_oper) - sdata_info(sdata, - "AP missing S1G operation element?\n"); - } - - link->u.mgd.conn_flags |= - ieee80211_determine_chantype(link, sband, - cbss->channel, - bss->vht_cap_info, - ht_oper, vht_oper, - he_oper, eht_oper, - s1g_oper, - &chandef, false); - - link->needed_rx_chains = - min(ieee80211_max_rx_chains(link, cbss), local->rx_chains); - - rcu_read_unlock(); - /* the element data was RCU protected so no longer valid anyway */ - kfree(elems); - elems = NULL; - - if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE && is_6ghz) { - sdata_info(sdata, "Rejecting non-HE 6/7 GHz connection"); - return -EINVAL; - } - - /* will change later if needed */ - link->smps_mode = IEEE80211_SMPS_OFF; - - mutex_lock(&local->mtx); - /* - * If this fails (possibly due to channel context sharing - * on incompatible channels, e.g. 80+80 and 160 sharing the - * same control channel) try to use a smaller bandwidth. - */ - ret = ieee80211_link_use_channel(link, &chandef, - IEEE80211_CHANCTX_SHARED); - - /* don't downgrade for 5 and 10 MHz channels, though. */ - if (chandef.width == NL80211_CHAN_WIDTH_5 || - chandef.width == NL80211_CHAN_WIDTH_10) - goto out; - - while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { - link->u.mgd.conn_flags |= - ieee80211_chandef_downgrade(&chandef); - ret = ieee80211_link_use_channel(link, &chandef, - IEEE80211_CHANCTX_SHARED); - } - out: - mutex_unlock(&local->mtx); - return ret; -} - static bool ieee80211_get_dtim(const struct cfg80211_bss_ies *ies, u8 *dtim_count, u8 *dtim_period) { From patchwork Wed Jul 13 15:34:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590316 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2219CCA481 for ; Wed, 13 Jul 2022 15:34:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236983AbiGMPex (ORCPT ); Wed, 13 Jul 2022 11:34:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236948AbiGMPen (ORCPT ); Wed, 13 Jul 2022 11:34:43 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C14533E759 for ; Wed, 13 Jul 2022 08:34:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=SYp1nGWB1c7Fqq0rzR1qutAi5Q5rPYKGDJF8yVQI5oc=; t=1657726482; x=1658936082; b=vaxByOH+7MTZCBwYuV2qi5PSVTUB8JPgGqo+Z5OeQeAaQsv rID4do5HFq3Zu7czOu44RspfydbtvHq/lQzsbfdwhINoylpAt3onC978wj/lvQKojnK3IEaTmgasM EJIQa+b8kijbgvHWBsCi9voKdz6cnmRoZENOZOxt9E8X9DdumuEimz/QPUiFKwpcB6GbDl1+zvvgP X+80VwOJ5LmJWWaf05Cqn0yVg0bndnBqCdxwChgFXnKBJqjAEO/NpFOCcmkvmAqxFgzc0eUmhr6+z DjdQUUKj1gYmrgLLCBVxEMIH6Vo6MdxmpBOa/P48RPcx+9GAynJMx92jeEBMVJsw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNs-00EnaA-8N; Wed, 13 Jul 2022 17:34:40 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 12/21] wifi: mac80211: mlme: change flags in ieee80211_determine_chantype() Date: Wed, 13 Jul 2022 17:34:24 +0200 Message-Id: <20220713173301.489328a4528e.I0992138c10a86c160a24a52944fbf5639d0de179@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg For MLO we'll need to read flags not directly from the link as it may not even exist yet if we're just setting up flags for a secondary link before sending the association request, so pass the incoming conn_flags separately. Also, while at it, pass the sdata/link separately as for non-tracking now the link may be NULL. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3b4d0bc35b5d..03f6da885ce4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -143,7 +143,9 @@ static int ecw2cw(int ecw) } static ieee80211_conn_flags_t -ieee80211_determine_chantype(struct ieee80211_link_data *link, +ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_data *link, + ieee80211_conn_flags_t conn_flags, struct ieee80211_supported_band *sband, struct ieee80211_channel *channel, u32 vht_cap_info, @@ -154,7 +156,6 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, const struct ieee80211_s1g_oper_ie *s1g_oper, struct cfg80211_chan_def *chandef, bool tracking) { - struct ieee80211_sub_if_data *sdata = link->sdata; struct cfg80211_chan_def vht_chandef; struct ieee80211_sta_ht_cap sta_ht_cap; ieee80211_conn_flags_t ret; @@ -249,7 +250,7 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, } vht_chandef = *chandef; - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && + if (!(conn_flags & IEEE80211_CONN_DISABLE_HE) && he_oper && (le32_to_cpu(he_oper->he_oper_params) & IEEE80211_HE_OPERATION_VHT_OPER_INFO)) { @@ -265,7 +266,7 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, if (!ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info, &he_oper_vht_cap, ht_oper, &vht_chandef)) { - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) + if (!(conn_flags & IEEE80211_CONN_DISABLE_HE)) sdata_info(sdata, "HE AP VHT information is invalid, disabling HE\n"); ret = IEEE80211_CONN_DISABLE_HE | IEEE80211_CONN_DISABLE_EHT; @@ -275,7 +276,7 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, vht_cap_info, vht_oper, ht_oper, &vht_chandef)) { - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) + if (!(conn_flags & IEEE80211_CONN_DISABLE_VHT)) sdata_info(sdata, "AP VHT information is invalid, disabling VHT\n"); ret = IEEE80211_CONN_DISABLE_VHT; @@ -283,7 +284,7 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, } if (!cfg80211_chandef_valid(&vht_chandef)) { - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) + if (!(conn_flags & IEEE80211_CONN_DISABLE_VHT)) sdata_info(sdata, "AP VHT information is invalid, disabling VHT\n"); ret = IEEE80211_CONN_DISABLE_VHT; @@ -296,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, } if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) + if (!(conn_flags & IEEE80211_CONN_DISABLE_VHT)) sdata_info(sdata, "AP VHT information doesn't match HT, disabling VHT\n"); ret = IEEE80211_CONN_DISABLE_VHT; @@ -319,7 +320,7 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, false, &eht_chandef); if (!cfg80211_chandef_valid(&eht_chandef)) { - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) + if (!(conn_flags & IEEE80211_CONN_DISABLE_EHT)) sdata_info(sdata, "AP EHT information is invalid, disabling EHT\n"); ret = IEEE80211_CONN_DISABLE_EHT; @@ -327,7 +328,7 @@ ieee80211_determine_chantype(struct ieee80211_link_data *link, } if (!cfg80211_chandef_compatible(chandef, &eht_chandef)) { - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) + if (!(conn_flags & IEEE80211_CONN_DISABLE_EHT)) sdata_info(sdata, "AP EHT information is incompatible, disabling EHT\n"); ret = IEEE80211_CONN_DISABLE_EHT; @@ -462,7 +463,9 @@ static int ieee80211_config_bw(struct ieee80211_link_data *link, vht_cap_info = le32_to_cpu(vht_cap->vht_cap_info); /* calculate new channel (type) based on HT/VHT/HE operation IEs */ - flags = ieee80211_determine_chantype(link, sband, chan, vht_cap_info, + flags = ieee80211_determine_chantype(sdata, link, + link->u.mgd.conn_flags, + sband, chan, vht_cap_info, ht_oper, vht_oper, he_oper, eht_oper, s1g_oper, &chandef, true); @@ -4005,8 +4008,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, } link->u.mgd.conn_flags |= - ieee80211_determine_chantype(link, sband, - cbss->channel, + ieee80211_determine_chantype(sdata, link, + link->u.mgd.conn_flags, + sband, cbss->channel, bss->vht_cap_info, ht_oper, vht_oper, he_oper, eht_oper, From patchwork Wed Jul 13 15:34:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590315 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B371C43334 for ; Wed, 13 Jul 2022 15:34:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236978AbiGMPez (ORCPT ); Wed, 13 Jul 2022 11:34:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40576 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236950AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAF764C638 for ; Wed, 13 Jul 2022 08:34:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=NDVuU4hUY8s4cKu/LRQDiVWaVDRW97RVN78U/lr/wIk=; t=1657726483; x=1658936083; b=JC5VNMHHDqnweiI+rMDohxK3iTP0Zsm1cqMbygU4+PMpKu+ w3Z5eeMJI+gSrYB1NmxPdgPshFeRqKZ1JSBjWgVNHZ0twGIchS8xC5GBnILkiYIWwfrOUYG6zvxym xsQvfPDuHQgDC1wGPXuCJ9a+CKU7BoonG+WE9YMrEsfKP0XAyAdOEJiUwfkT0TULELwwKXuVYyqY6 c5LLHoCU4cnbQcPztEcmUaBMpdvWyuB3kuuQyb+tjnLIHsKVgfH6oAXekAzqVmUNz5L4tdwIKv15n JmmHY/+Ryc1v2cNCFUgzErAG5H7xZDNlsBT1ELiSN6w8utmwr5T7KBLVGP4HFzJA==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNs-00EnaA-GF; Wed, 13 Jul 2022 17:34:40 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 13/21] wifi: mac80211: mlme: switch some things back to deflink Date: Wed, 13 Jul 2022 17:34:25 +0200 Message-Id: <20220713173301.2941d7b03f50.I1da3e7cbc88305d2c2c89bd3e345d7f6b73a1ea7@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg With MLO, when we'll disconnect from an AP MLD, we'll just destroy all the links. Therefore, the only thing we (may) need to reset is the deflink data, so switch back to that and adjust the comments accordingly. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 71 +++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 03f6da885ce4..999eead2129e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2437,7 +2437,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; struct ieee80211_link_data *link = &sdata->deflink; u32 changed = 0; struct ieee80211_prep_tx_info info = { @@ -2455,7 +2454,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_stop_poll(sdata); ifmgd->associated = false; - link->u.mgd.bss = NULL; + + /* other links will be destroyed */ + sdata->deflink.u.mgd.bss = NULL; + netif_carrier_off(sdata->dev); /* @@ -2493,7 +2495,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, * driver requested so. */ if (ieee80211_hw_check(&local->hw, DEAUTH_NEED_MGD_TX_PREP) && - !link->u.mgd.have_beacon) { + !sdata->deflink.u.mgd.have_beacon) { drv_mgd_prepare_tx(sdata->local, sdata, &info); } @@ -2524,9 +2526,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, changed |= BSS_CHANGED_ASSOC; sdata->vif.cfg.assoc = false; - link->u.mgd.p2p_noa_index = -1; - memset(&link->conf->p2p_noa_attr, 0, - sizeof(link->conf->p2p_noa_attr)); + sdata->deflink.u.mgd.p2p_noa_index = -1; + memset(&sdata->vif.bss_conf.p2p_noa_attr, 0, + sizeof(sdata->vif.bss_conf.p2p_noa_attr)); /* on the next assoc, re-program HT/VHT parameters */ memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); @@ -2534,15 +2536,19 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa)); memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask)); - /* reset MU-MIMO ownership and group data */ - memset(link->conf->mu_group.membership, 0, - sizeof(link->conf->mu_group.membership)); - memset(link->conf->mu_group.position, 0, - sizeof(link->conf->mu_group.position)); - changed |= BSS_CHANGED_MU_GROUPS; - link->conf->mu_mimo_owner = false; + /* + * reset MU-MIMO ownership and group data in default link, + * if used, other links are destroyed + */ + memset(sdata->vif.bss_conf.mu_group.membership, 0, + sizeof(sdata->vif.bss_conf.mu_group.membership)); + memset(sdata->vif.bss_conf.mu_group.position, 0, + sizeof(sdata->vif.bss_conf.mu_group.position)); + if (!sdata->vif.valid_links) + changed |= BSS_CHANGED_MU_GROUPS; + sdata->vif.bss_conf.mu_mimo_owner = false; - link->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; + sdata->deflink.ap_power_level = IEEE80211_UNSET_POWER_LEVEL; del_timer_sync(&local->dynamic_ps_timer); cancel_work_sync(&local->dynamic_ps_enable_work); @@ -2551,7 +2557,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, if (sdata->vif.cfg.arp_addr_cnt) changed |= BSS_CHANGED_ARP_FILTER; - link->conf->qos = false; + sdata->vif.bss_conf.qos = false; changed |= BSS_CHANGED_QOS; /* The BSSID (not really interesting) and HT changed */ @@ -2564,27 +2570,27 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.conn_mon_timer); del_timer_sync(&sdata->u.mgd.bcn_mon_timer); del_timer_sync(&sdata->u.mgd.timer); - del_timer_sync(&link->u.mgd.chswitch_timer); + del_timer_sync(&sdata->deflink.u.mgd.chswitch_timer); - link->conf->dtim_period = 0; - link->conf->beacon_rate = NULL; + sdata->vif.bss_conf.dtim_period = 0; + sdata->vif.bss_conf.beacon_rate = NULL; - link->u.mgd.have_beacon = false; - link->u.mgd.tracking_signal_avg = false; - link->u.mgd.disable_wmm_tracking = false; + sdata->deflink.u.mgd.have_beacon = false; + sdata->deflink.u.mgd.tracking_signal_avg = false; + sdata->deflink.u.mgd.disable_wmm_tracking = false; ifmgd->flags = 0; - link->u.mgd.conn_flags = 0; + sdata->deflink.u.mgd.conn_flags = 0; mutex_lock(&local->mtx); ieee80211_link_release_channel(link); - link->conf->csa_active = false; - link->u.mgd.csa_waiting_bcn = false; - link->u.mgd.csa_ignored_same_chan = false; - if (link->csa_block_tx) { + sdata->vif.bss_conf.csa_active = false; + sdata->deflink.u.mgd.csa_waiting_bcn = false; + sdata->deflink.u.mgd.csa_ignored_same_chan = false; + if (sdata->deflink.csa_block_tx) { ieee80211_wake_vif_queues(local, sdata, IEEE80211_QUEUE_STOP_REASON_CSA); - link->csa_block_tx = false; + sdata->deflink.csa_block_tx = false; } mutex_unlock(&local->mtx); @@ -2592,9 +2598,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec)); cancel_delayed_work_sync(&ifmgd->tx_tspec_wk); - bss_conf->pwr_reduction = 0; - bss_conf->tx_pwr_env_num = 0; - memset(bss_conf->tx_pwr_env, 0, sizeof(bss_conf->tx_pwr_env)); + sdata->vif.bss_conf.pwr_reduction = 0; + sdata->vif.bss_conf.tx_pwr_env_num = 0; + memset(sdata->vif.bss_conf.tx_pwr_env, 0, + sizeof(sdata->vif.bss_conf.tx_pwr_env)); } static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) @@ -2911,6 +2918,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, tx, frame_buf); mutex_lock(&local->mtx); + /* the other links will be destroyed */ sdata->vif.bss_conf.csa_active = false; sdata->deflink.u.mgd.csa_waiting_bcn = false; if (sdata->deflink.csa_block_tx) { @@ -3057,7 +3065,6 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.timer); sta_info_destroy_addr(sdata, assoc_data->bss->bssid); - /* FIXME: other links are destroyed? */ sdata->deflink.u.mgd.conn_flags = 0; eth_zero_addr(sdata->deflink.u.mgd.bssid); ieee80211_link_info_change_notify(sdata, &sdata->deflink, @@ -6407,7 +6414,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, return 0; err_clear: - eth_zero_addr(link->u.mgd.bssid); + eth_zero_addr(sdata->deflink.u.mgd.bssid); ieee80211_link_info_change_notify(sdata, &sdata->deflink, BSS_CHANGED_BSSID); ifmgd->assoc_data = NULL; From patchwork Wed Jul 13 15:34:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590783 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 97FD0C433EF for ; Wed, 13 Jul 2022 15:34:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236951AbiGMPey (ORCPT ); Wed, 13 Jul 2022 11:34:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236949AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E3D832060 for ; Wed, 13 Jul 2022 08:34:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=b+c44Roxnzht342gdjNbU8KZbA09y+EyQAFVX3RYmPg=; t=1657726482; x=1658936082; b=dCGWwhSG7lYUne3s7hvEJEKo+ujYir55kiZ2Q+dzPbdPzKi oEhm6EhYu4Hzpwao2oPpXCn9wVUd1gLRtDHiehiNCVDHTEYYS05d6OyOo2lWmorikGfeRDuuGMmCw eejdwO3utU/Xqpz/t1J/cZSN+9RB3rEW42q0WjXOgltuE6MM2V5cPOfpsZkLxWI8u1BMPtaIfB4+O cHUhZKqKypZO8ODEsHNeHtrS2kqshvJMt1mxYiiNKDu+7HINVVRGKixK5Nua8IN9dP+lSbLj3Ch0f G2i6qRWsowNDnF0JoRqmnGTUHzqGGIKhiMYEk35o79ES0SSPiQothFRAOVd94rLg==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNs-00EnaA-Ob; Wed, 13 Jul 2022 17:34:40 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 14/21] wifi: mac80211: mlme: refactor assoc req element building Date: Wed, 13 Jul 2022 17:34:26 +0200 Message-Id: <20220713173301.fdc756ca1a1c.Id2b09ee06bb8ebe3cd5125ba1db9963b4bda5aa0@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg For MLO, we will need to build these elements per link, so factor out the code that does this, returning the capability, to simplify building the multi-link element in the future. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 278 ++++++++++++++++++++++++++------------------ 1 file changed, 162 insertions(+), 116 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 999eead2129e..26c354e1b042 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -936,17 +936,158 @@ static size_t ieee80211_add_before_he_elems(struct sk_buff *skb, return noffset; } +static size_t ieee80211_assoc_link_elems(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, u16 *capab, + const struct element *ext_capa, + const u8 *extra_elems, + size_t extra_elems_len, + struct ieee80211_link_data *link) +{ + enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif); + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; + struct cfg80211_bss *cbss = assoc_data->bss; + struct ieee80211_channel *chan = cbss->channel; + const struct ieee80211_sband_iftype_data *iftd; + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20; + struct ieee80211_chanctx_conf *chanctx_conf; + size_t offset = 0; + u8 *pos; + int i; + + /* + * 5/10 MHz scenarios are only viable without MLO, in which + * case this pointer should be used ... All of this is a bit + * unclear though, not sure this even works at all. + */ + rcu_read_lock(); + chanctx_conf = rcu_dereference(link->conf->chanctx_conf); + if (chanctx_conf) + width = chanctx_conf->def.width; + rcu_read_unlock(); + + sband = local->hw.wiphy->bands[chan->band]; + iftd = ieee80211_get_sband_iftype_data(sband, iftype); + + if (sband->band == NL80211_BAND_2GHZ) { + *capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; + *capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; + } + + if ((cbss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && + ieee80211_hw_check(&local->hw, SPECTRUM_MGMT)) + *capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; + + if (sband->band != NL80211_BAND_S1GHZ) + ieee80211_assoc_add_rates(skb, width, sband, assoc_data); + + if (*capab & WLAN_CAPABILITY_SPECTRUM_MGMT || + *capab & WLAN_CAPABILITY_RADIO_MEASURE) { + struct cfg80211_chan_def chandef = { + .width = width, + .chan = chan, + }; + + pos = skb_put(skb, 4); + *pos++ = WLAN_EID_PWR_CAPABILITY; + *pos++ = 2; + *pos++ = 0; /* min tx power */ + /* max tx power */ + *pos++ = ieee80211_chandef_max_power(&chandef); + } + + /* + * Per spec, we shouldn't include the list of channels if we advertise + * support for extended channel switching, but we've always done that; + * (for now?) apply this restriction only on the (new) 6 GHz band. + */ + if (*capab & WLAN_CAPABILITY_SPECTRUM_MGMT && + (sband->band != NL80211_BAND_6GHZ || + !ext_capa || ext_capa->datalen < 1 || + !(ext_capa->data[0] & WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING))) { + /* TODO: get this in reg domain format */ + pos = skb_put(skb, 2 * sband->n_channels + 2); + *pos++ = WLAN_EID_SUPPORTED_CHANNELS; + *pos++ = 2 * sband->n_channels; + for (i = 0; i < sband->n_channels; i++) { + int cf = sband->channels[i].center_freq; + + *pos++ = ieee80211_frequency_to_channel(cf); + *pos++ = 1; /* one channel in the subband*/ + } + } + + /* if present, add any custom IEs that go before HT */ + offset = ieee80211_add_before_ht_elems(skb, extra_elems, + extra_elems_len, + offset); + + if (sband->band != NL80211_BAND_6GHZ && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) + ieee80211_add_ht_ie(sdata, skb, + assoc_data->ap_ht_param, + sband, chan, link->smps_mode, + link->u.mgd.conn_flags); + + /* if present, add any custom IEs that go before VHT */ + offset = ieee80211_add_before_vht_elems(skb, extra_elems, + extra_elems_len, + offset); + + if (sband->band != NL80211_BAND_6GHZ && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) + link->conf->mu_mimo_owner = + ieee80211_add_vht_ie(sdata, skb, sband, + &assoc_data->ap_vht_cap, + link->u.mgd.conn_flags); + + /* + * If AP doesn't support HT, mark HE and EHT as disabled. + * If on the 5GHz band, make sure it supports VHT. + */ + if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT || + (sband->band == NL80211_BAND_5GHZ && + link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) + link->u.mgd.conn_flags |= + IEEE80211_CONN_DISABLE_HE | + IEEE80211_CONN_DISABLE_EHT; + + /* if present, add any custom IEs that go before HE */ + offset = ieee80211_add_before_he_elems(skb, extra_elems, + extra_elems_len, + offset); + + if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) + ieee80211_add_he_ie(sdata, skb, sband, + link->u.mgd.conn_flags); + + if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) + ieee80211_add_eht_ie(sdata, skb, sband); + + if (sband->band == NL80211_BAND_S1GHZ) { + ieee80211_add_aid_request_ie(sdata, skb); + ieee80211_add_s1g_capab_ie(sdata, &sband->s1g_cap, skb); + } + + if (iftd && iftd->vendor_elems.data && iftd->vendor_elems.len) + skb_put_data(skb, iftd->vendor_elems.data, iftd->vendor_elems.len); + + return offset; +} + static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; + struct ieee80211_link_data *link = &sdata->deflink; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, qos_info, *ie_start; - size_t offset = 0, noffset; - int i; - u16 capab; + size_t offset, noffset; + u16 capab = WLAN_CAPABILITY_ESS; struct ieee80211_supported_band *sband; struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_channel *chan; @@ -955,7 +1096,7 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif); const struct ieee80211_sband_iftype_data *iftd; struct ieee80211_prep_tx_info info = {}; - struct ieee80211_link_data *link = &sdata->deflink; + void *capab_pos; int ret; /* we know it's writable, cast away the const */ @@ -1003,23 +1144,18 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) skb_reserve(skb, local->hw.extra_tx_headroom); - capab = WLAN_CAPABILITY_ESS; - - if (sband->band == NL80211_BAND_2GHZ) { - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; - } - if (assoc_data->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; - if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && - ieee80211_hw_check(&local->hw, SPECTRUM_MGMT)) - capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; - if (ifmgd->flags & IEEE80211_STA_ENABLE_RRM) capab |= WLAN_CAPABILITY_RADIO_MEASURE; + /* Set MBSSID support for HE AP if needed */ + if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && + ext_capa && ext_capa->datalen >= 3) + ext_capa->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT; + mgmt = skb_put_zero(skb, 24); memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); @@ -1032,7 +1168,7 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) skb_put(skb, 10); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); - mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); + capab_pos = &mgmt->u.reassoc_req.capab_info; mgmt->u.reassoc_req.listen_interval = listen_int; memcpy(mgmt->u.reassoc_req.current_ap, assoc_data->prev_bssid, ETH_ALEN); @@ -1041,7 +1177,7 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) skb_put(skb, 4); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); - mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); + capab_pos = &mgmt->u.assoc_req.capab_info; mgmt->u.assoc_req.listen_interval = listen_int; info.subtype = IEEE80211_STYPE_ASSOC_REQ; } @@ -1053,97 +1189,15 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) *pos++ = assoc_data->ssid_len; memcpy(pos, assoc_data->ssid, assoc_data->ssid_len); - if (sband->band != NL80211_BAND_S1GHZ) - ieee80211_assoc_add_rates(skb, chanctx_conf->def.width, - sband, assoc_data); - - if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT || - capab & WLAN_CAPABILITY_RADIO_MEASURE) { - pos = skb_put(skb, 4); - *pos++ = WLAN_EID_PWR_CAPABILITY; - *pos++ = 2; - *pos++ = 0; /* min tx power */ - /* max tx power */ - *pos++ = ieee80211_chandef_max_power(&chanctx_conf->def); - } - - /* - * Per spec, we shouldn't include the list of channels if we advertise - * support for extended channel switching, but we've always done that; - * (for now?) apply this restriction only on the (new) 6 GHz band. - */ - if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT && - (sband->band != NL80211_BAND_6GHZ || - !ext_capa || ext_capa->datalen < 1 || - !(ext_capa->data[0] & WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING))) { - /* TODO: get this in reg domain format */ - pos = skb_put(skb, 2 * sband->n_channels + 2); - *pos++ = WLAN_EID_SUPPORTED_CHANNELS; - *pos++ = 2 * sband->n_channels; - for (i = 0; i < sband->n_channels; i++) { - int cf = sband->channels[i].center_freq; - - *pos++ = ieee80211_frequency_to_channel(cf); - *pos++ = 1; /* one channel in the subband*/ - } - } - - /* Set MBSSID support for HE AP if needed */ - if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && - ext_capa && ext_capa->datalen >= 3) - ext_capa->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT; - - /* if present, add any custom IEs that go before HT */ - offset = ieee80211_add_before_ht_elems(skb, assoc_data->ie, - assoc_data->ie_len, - offset); - - if (WARN_ON_ONCE((link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))) - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - - if (sband->band != NL80211_BAND_6GHZ && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) - ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, - sband, chan, link->smps_mode, - link->u.mgd.conn_flags); - - /* if present, add any custom IEs that go before VHT */ - offset = ieee80211_add_before_vht_elems(skb, assoc_data->ie, - assoc_data->ie_len, - offset); - - if (sband->band != NL80211_BAND_6GHZ && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) - link->conf->mu_mimo_owner = - ieee80211_add_vht_ie(sdata, skb, sband, - &assoc_data->ap_vht_cap, - link->u.mgd.conn_flags); - - /* - * If AP doesn't support HT, mark HE and EHT as disabled. - * If on the 5GHz band, make sure it supports VHT. - */ - if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT || - (sband->band == NL80211_BAND_5GHZ && - link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE | - IEEE80211_CONN_DISABLE_EHT; - - /* if present, add any custom IEs that go before HE */ - offset = ieee80211_add_before_he_elems(skb, assoc_data->ie, - assoc_data->ie_len, - offset); - - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) { - ieee80211_add_he_ie(sdata, skb, sband, link->u.mgd.conn_flags); - - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) - ieee80211_add_eht_ie(sdata, skb, sband); - } - - /* if present, add any custom non-vendor IEs that go after HE */ + /* add the elements for the assoc (main) link */ + offset = ieee80211_assoc_link_elems(sdata, skb, &capab, + ext_capa, + assoc_data->ie, + assoc_data->ie_len, + link); + put_unaligned_le16(capab, capab_pos); + + /* if present, add any custom non-vendor IEs */ if (assoc_data->ie_len) { noffset = ieee80211_ie_split_vendor(assoc_data->ie, assoc_data->ie_len, @@ -1164,14 +1218,6 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info); } - if (sband->band == NL80211_BAND_S1GHZ) { - ieee80211_add_aid_request_ie(sdata, skb); - ieee80211_add_s1g_capab_ie(sdata, &sband->s1g_cap, skb); - } - - if (iftd && iftd->vendor_elems.data && iftd->vendor_elems.len) - skb_put_data(skb, iftd->vendor_elems.data, iftd->vendor_elems.len); - /* add any remaining custom (i.e. vendor specific here) IEs */ if (assoc_data->ie_len) { noffset = assoc_data->ie_len; From patchwork Wed Jul 13 15:34:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590782 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CF2DCCA483 for ; Wed, 13 Jul 2022 15:34:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236976AbiGMPe4 (ORCPT ); Wed, 13 Jul 2022 11:34:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40502 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236953AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 167C74D141 for ; Wed, 13 Jul 2022 08:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=C2Wce6sXZ+PzZgeWx+oU5YujEGCViiUVKyqEEqUlbGY=; t=1657726483; x=1658936083; b=sfrhd1iURG/1dypIazDSfV892RxuiduLfYHHb64A2l7Pjl7 Y99Lc3EwD0hv/Ty6ur6sV30h4nPYqY1jCw6gk/5pNzxEqECuTX0Ga5ErWejCvn53aotGDDkToPDjE LrcQUSzoNj71auj6XWXf5Zt6MsfuG1mCgk6M7MYfJUBWcqp1dSsAgpU9d0DqkisG0P+PxkzaqcEof g85DcKvWOK7CNRuAb58XaL8YMHu66NKKfkIPNbiH5/PtlzP269g2uyG0eIDJuEI6fACR+/k4SuvBq Gj3gfzpnWtB2WNasex+YnKPuZOqP5Zvm4X6QObTHNll/8H4iqJlSSALJW7wORw6w==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNt-00EnaA-25; Wed, 13 Jul 2022 17:34:41 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 15/21] wifi: mac80211: mlme: refactor ieee80211_prep_channel() a bit Date: Wed, 13 Jul 2022 17:34:27 +0200 Message-Id: <20220713173301.d1c18ba15a6e.I84e9c2a7bee6a956a20bd5ceaa87fdf53add9203@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Refactor ieee80211_prep_channel() to make the link argument optional and add a conn_flags pointer argument instead, so that we can later use this for links that don't exist yet to build the right information for MLO. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 81 ++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 26c354e1b042..308b4ede10b9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3887,7 +3887,8 @@ ieee80211_verify_sta_he_mcs_support(struct ieee80211_sub_if_data *sdata, static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, struct ieee80211_link_data *link, - struct cfg80211_bss *cbss) + struct cfg80211_bss *cbss, + ieee80211_conn_flags_t *conn_flags) { struct ieee80211_local *local = sdata->local; const struct ieee80211_ht_cap *ht_cap = NULL; @@ -3918,73 +3919,73 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, sband = local->hw.wiphy->bands[cbss->channel->band]; - link->u.mgd.conn_flags &= ~(IEEE80211_CONN_DISABLE_40MHZ | - IEEE80211_CONN_DISABLE_80P80MHZ | - IEEE80211_CONN_DISABLE_160MHZ); + *conn_flags &= ~(IEEE80211_CONN_DISABLE_40MHZ | + IEEE80211_CONN_DISABLE_80P80MHZ | + IEEE80211_CONN_DISABLE_160MHZ); /* disable HT/VHT/HE if we don't support them */ if (!sband->ht_cap.ht_supported && !is_6ghz) { mlme_dbg(sdata, "HT not supported, disabling HT/VHT/HE/EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + *conn_flags |= IEEE80211_CONN_DISABLE_HT; + *conn_flags |= IEEE80211_CONN_DISABLE_VHT; + *conn_flags |= IEEE80211_CONN_DISABLE_HE; + *conn_flags |= IEEE80211_CONN_DISABLE_EHT; } if (!sband->vht_cap.vht_supported && is_5ghz) { mlme_dbg(sdata, "VHT not supported, disabling VHT/HE/EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + *conn_flags |= IEEE80211_CONN_DISABLE_VHT; + *conn_flags |= IEEE80211_CONN_DISABLE_HE; + *conn_flags |= IEEE80211_CONN_DISABLE_EHT; } if (!ieee80211_get_he_iftype_cap(sband, ieee80211_vif_type_p2p(&sdata->vif))) { mlme_dbg(sdata, "HE not supported, disabling HE and EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + *conn_flags |= IEEE80211_CONN_DISABLE_HE; + *conn_flags |= IEEE80211_CONN_DISABLE_EHT; } if (!ieee80211_get_eht_iftype_cap(sband, ieee80211_vif_type_p2p(&sdata->vif))) { mlme_dbg(sdata, "EHT not supported, disabling EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + *conn_flags |= IEEE80211_CONN_DISABLE_EHT; } - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && !is_6ghz) { + if (!(*conn_flags & IEEE80211_CONN_DISABLE_HT) && !is_6ghz) { ht_oper = elems->ht_operation; ht_cap = elems->ht_cap_elem; if (!ht_cap) { - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; + *conn_flags |= IEEE80211_CONN_DISABLE_HT; ht_oper = NULL; } } - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && !is_6ghz) { + if (!(*conn_flags & IEEE80211_CONN_DISABLE_VHT) && !is_6ghz) { vht_oper = elems->vht_operation; if (vht_oper && !ht_oper) { vht_oper = NULL; sdata_info(sdata, "AP advertised VHT without HT, disabling HT/VHT/HE\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + *conn_flags |= IEEE80211_CONN_DISABLE_HT; + *conn_flags |= IEEE80211_CONN_DISABLE_VHT; + *conn_flags |= IEEE80211_CONN_DISABLE_HE; + *conn_flags |= IEEE80211_CONN_DISABLE_EHT; } if (!elems->vht_cap_elem) { sdata_info(sdata, "bad VHT capabilities, disabling VHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; + *conn_flags |= IEEE80211_CONN_DISABLE_VHT; vht_oper = NULL; } } - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE)) { + if (!(*conn_flags & IEEE80211_CONN_DISABLE_HE)) { he_oper = elems->he_operation; - if (is_6ghz) { + if (link && is_6ghz) { struct ieee80211_bss_conf *bss_conf; u8 j = 0; @@ -4010,8 +4011,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, if (!ieee80211_verify_peer_he_mcs_support(sdata, ies, he_oper) || !ieee80211_verify_sta_he_mcs_support(sdata, sband, he_oper)) - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE | - IEEE80211_CONN_DISABLE_EHT; + *conn_flags |= IEEE80211_CONN_DISABLE_HE | + IEEE80211_CONN_DISABLE_EHT; } /* @@ -4020,7 +4021,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, * both the 6 GHz operation information (from the HE operation IE) and * EHT operation. */ - if (!(link->u.mgd.conn_flags & + if (!(*conn_flags & (IEEE80211_CONN_DISABLE_HE | IEEE80211_CONN_DISABLE_EHT)) && he_oper) { @@ -4050,7 +4051,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, if (!have_80mhz) { sdata_info(sdata, "80 MHz not supported, disabling VHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; + *conn_flags |= IEEE80211_CONN_DISABLE_VHT; } if (sband->band == NL80211_BAND_S1GHZ) { @@ -4060,29 +4061,34 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, "AP missing S1G operation element?\n"); } - link->u.mgd.conn_flags |= - ieee80211_determine_chantype(sdata, link, - link->u.mgd.conn_flags, - sband, cbss->channel, + *conn_flags |= + ieee80211_determine_chantype(sdata, link, *conn_flags, + sband, + cbss->channel, bss->vht_cap_info, ht_oper, vht_oper, he_oper, eht_oper, s1g_oper, &chandef, false); - link->needed_rx_chains = - min(ieee80211_max_rx_chains(link, cbss), local->rx_chains); + if (link) + link->needed_rx_chains = + min(ieee80211_max_rx_chains(link, cbss), + local->rx_chains); rcu_read_unlock(); /* the element data was RCU protected so no longer valid anyway */ kfree(elems); elems = NULL; - if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE && is_6ghz) { + if (*conn_flags & IEEE80211_CONN_DISABLE_HE && is_6ghz) { sdata_info(sdata, "Rejecting non-HE 6/7 GHz connection"); return -EINVAL; } + if (!link) + return 0; + /* will change later if needed */ link->smps_mode = IEEE80211_SMPS_OFF; @@ -4101,7 +4107,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, goto out; while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { - link->u.mgd.conn_flags |= + *conn_flags |= ieee80211_chandef_downgrade(&chandef); ret = ieee80211_link_use_channel(link, &chandef, IEEE80211_CHANCTX_SHARED); @@ -5929,7 +5935,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, } if (new_sta || override) { - err = ieee80211_prep_channel(sdata, link, cbss); + err = ieee80211_prep_channel(sdata, link, cbss, + &link->u.mgd.conn_flags); if (err) { if (new_sta) sta_info_free(local, new_sta); From patchwork Wed Jul 13 15:34:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590779 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 62067CCA479 for ; Wed, 13 Jul 2022 15:35:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236989AbiGMPe7 (ORCPT ); Wed, 13 Jul 2022 11:34:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236961AbiGMPep (ORCPT ); Wed, 13 Jul 2022 11:34:45 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3845B4D144 for ; Wed, 13 Jul 2022 08:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=rO1Bgjw2mlkdERj+oDRv7dUs7I15gVJle2H4170vmrA=; t=1657726483; x=1658936083; b=yUf+QSNcW5wZ+IKhhVdcz75WEPnrejv5SSeuAyQnU3shJWl sgG/00pzdPZ+jKXiFVOraQ7ZVLZ8IVKe4WsbJH86gzkVede02+2h4OWv+VROoMxtDtTmogDoBzrEB c18zq/DmHlN2HM2jYkPl3h8ofqtmi71bVsSVHgImKawC09GaaJINVFbaxfAI6fpAkho79Q3rbF+eo +HgWILvcg7SicVkzkf9UvxezvFMmjpft8CUveEBsPvghvbsspASUVQ9gBW0LWux37MAYW2PieMd4r +2HD0d2zTpLSlX0IfWFAjazzvzl6ZvSppk+YNDLWqaOZqk9o4PDjlkw/ZbHWHsnw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNt-00EnaA-An; Wed, 13 Jul 2022 17:34:41 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 16/21] wifi: mac80211: mlme: refactor assoc success handling Date: Wed, 13 Jul 2022 17:34:28 +0200 Message-Id: <20220713173301.5bf795ac3166.Ica375e701ab260cf57ca562d8563789f29a76668@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Refactor the per-link setup out of ieee80211_assoc_success() into a new function ieee80211_assoc_config_link(). It looks useless for now to parse the elements again inside ieee80211_assoc_config_link(), but that will be done with the link ID in the future. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 737 ++++++++++++++++++++++---------------------- 1 file changed, 376 insertions(+), 361 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 308b4ede10b9..873f7f6e03ce 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3540,6 +3540,326 @@ static bool ieee80211_twt_bcast_support(struct ieee80211_sub_if_data *sdata, IEEE80211_HE_MAC_CAP2_BCAST_TWT); } +static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + struct link_sta_info *link_sta, + struct cfg80211_bss *cbss, + struct ieee80211_mgmt *mgmt, + const u8 *elem_start, + unsigned int elem_len, + u64 *changed) +{ + struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; + struct ieee80211_bss_conf *bss_conf = link->conf; + struct ieee80211_local *local = sdata->local; + struct ieee80211_elems_parse_params parse_params = { + .start = elem_start, + .len = elem_len, + .bss = cbss, + }; + bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; + bool is_s1g = cbss->channel->band == NL80211_BAND_S1GHZ; + const struct cfg80211_bss_ies *bss_ies = NULL; + struct ieee80211_supported_band *sband; + struct ieee802_11_elems *elems; + u16 capab_info; + bool ret; + + elems = ieee802_11_parse_elems_full(&parse_params); + if (!elems) + return false; + + capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); + + if (!is_s1g && !elems->supp_rates) { + sdata_info(sdata, "no SuppRates element in AssocResp\n"); + ret = false; + goto out; + } + + link->u.mgd.tdls_chan_switch_prohibited = + elems->ext_capab && elems->ext_capab_len >= 5 && + (elems->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED); + + /* + * Some APs are erroneously not including some information in their + * (re)association response frames. Try to recover by using the data + * from the beacon or probe response. This seems to afflict mobile + * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", + * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. + */ + if (!is_6ghz && + ((assoc_data->wmm && !elems->wmm_param) || + (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && + (!elems->ht_cap_elem || !elems->ht_operation)) || + (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && + (!elems->vht_cap_elem || !elems->vht_operation)))) { + const struct cfg80211_bss_ies *ies; + struct ieee802_11_elems *bss_elems; + + rcu_read_lock(); + ies = rcu_dereference(cbss->ies); + if (ies) + bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, + GFP_ATOMIC); + rcu_read_unlock(); + if (!bss_ies) { + ret = false; + goto out; + } + + parse_params.start = bss_ies->data; + parse_params.len = bss_ies->len; + bss_elems = ieee802_11_parse_elems_full(&parse_params); + if (!bss_elems) { + ret = false; + goto out; + } + + if (assoc_data->wmm && + !elems->wmm_param && bss_elems->wmm_param) { + elems->wmm_param = bss_elems->wmm_param; + sdata_info(sdata, + "AP bug: WMM param missing from AssocResp\n"); + } + + /* + * Also check if we requested HT/VHT, otherwise the AP doesn't + * have to include the IEs in the (re)association response. + */ + if (!elems->ht_cap_elem && bss_elems->ht_cap_elem && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) { + elems->ht_cap_elem = bss_elems->ht_cap_elem; + sdata_info(sdata, + "AP bug: HT capability missing from AssocResp\n"); + } + if (!elems->ht_operation && bss_elems->ht_operation && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) { + elems->ht_operation = bss_elems->ht_operation; + sdata_info(sdata, + "AP bug: HT operation missing from AssocResp\n"); + } + if (!elems->vht_cap_elem && bss_elems->vht_cap_elem && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) { + elems->vht_cap_elem = bss_elems->vht_cap_elem; + sdata_info(sdata, + "AP bug: VHT capa missing from AssocResp\n"); + } + if (!elems->vht_operation && bss_elems->vht_operation && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) { + elems->vht_operation = bss_elems->vht_operation; + sdata_info(sdata, + "AP bug: VHT operation missing from AssocResp\n"); + } + + kfree(bss_elems); + } + + /* + * We previously checked these in the beacon/probe response, so + * they should be present here. This is just a safety net. + */ + if (!is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && + (!elems->wmm_param || !elems->ht_cap_elem || !elems->ht_operation)) { + sdata_info(sdata, + "HT AP is missing WMM params or HT capability/operation\n"); + ret = false; + goto out; + } + + if (!is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && + (!elems->vht_cap_elem || !elems->vht_operation)) { + sdata_info(sdata, + "VHT AP is missing VHT capability/operation\n"); + ret = false; + goto out; + } + + if (is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && + !elems->he_6ghz_capa) { + sdata_info(sdata, + "HE 6 GHz AP is missing HE 6 GHz band capability\n"); + ret = false; + goto out; + } + + sband = ieee80211_get_link_sband(link); + if (!sband) { + ret = false; + goto out; + } + + if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && + (!elems->he_cap || !elems->he_operation)) { + mutex_unlock(&sdata->local->sta_mtx); + sdata_info(sdata, + "HE AP is missing HE capability/operation\n"); + ret = false; + goto out; + } + + /* Set up internal HT/VHT capabilities */ + if (elems->ht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) + ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, + elems->ht_cap_elem, + link_sta); + + if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) + ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, + elems->vht_cap_elem, + link_sta); + + if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && + elems->he_cap) { + ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, + elems->he_cap, + elems->he_cap_len, + elems->he_6ghz_capa, + link_sta); + + bss_conf->he_support = link_sta->pub->he_cap.has_he; + if (elems->rsnx && elems->rsnx_len && + (elems->rsnx[0] & WLAN_RSNX_CAPA_PROTECTED_TWT) && + wiphy_ext_feature_isset(local->hw.wiphy, + NL80211_EXT_FEATURE_PROTECTED_TWT)) + bss_conf->twt_protected = true; + else + bss_conf->twt_protected = false; + + *changed |= ieee80211_recalc_twt_req(link, link_sta, elems); + + if (elems->eht_operation && elems->eht_cap && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) { + ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, + elems->he_cap, + elems->he_cap_len, + elems->eht_cap, + elems->eht_cap_len, + link_sta); + + bss_conf->eht_support = link_sta->pub->eht_cap.has_eht; + } else { + bss_conf->eht_support = false; + } + } else { + bss_conf->he_support = false; + bss_conf->twt_requester = false; + bss_conf->twt_protected = false; + bss_conf->eht_support = false; + } + + bss_conf->twt_broadcast = + ieee80211_twt_bcast_support(sdata, bss_conf, sband, link_sta); + + if (bss_conf->he_support) { + bss_conf->he_bss_color.color = + le32_get_bits(elems->he_operation->he_oper_params, + IEEE80211_HE_OPERATION_BSS_COLOR_MASK); + bss_conf->he_bss_color.partial = + le32_get_bits(elems->he_operation->he_oper_params, + IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR); + bss_conf->he_bss_color.enabled = + !le32_get_bits(elems->he_operation->he_oper_params, + IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED); + + if (bss_conf->he_bss_color.enabled) + *changed |= BSS_CHANGED_HE_BSS_COLOR; + + bss_conf->htc_trig_based_pkt_ext = + le32_get_bits(elems->he_operation->he_oper_params, + IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK); + bss_conf->frame_time_rts_th = + le32_get_bits(elems->he_operation->he_oper_params, + IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK); + + bss_conf->uora_exists = !!elems->uora_element; + if (elems->uora_element) + bss_conf->uora_ocw_range = elems->uora_element[0]; + + ieee80211_he_op_ie_to_bss_conf(&sdata->vif, elems->he_operation); + ieee80211_he_spr_ie_to_bss_conf(&sdata->vif, elems->he_spr); + /* TODO: OPEN: what happens if BSS color disable is set? */ + } + + if (cbss->transmitted_bss) { + bss_conf->nontransmitted = true; + ether_addr_copy(bss_conf->transmitter_bssid, + cbss->transmitted_bss->bssid); + bss_conf->bssid_indicator = cbss->max_bssid_indicator; + bss_conf->bssid_index = cbss->bssid_index; + } + + /* + * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data + * in their association response, so ignore that data for our own + * configuration. If it changed since the last beacon, we'll get the + * next beacon and update then. + */ + + /* + * If an operating mode notification IE is present, override the + * NSS calculation (that would be done in rate_control_rate_init()) + * and use the # of streams from that element. + */ + if (elems->opmode_notif && + !(*elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)) { + u8 nss; + + nss = *elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; + nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; + nss += 1; + link_sta->pub->rx_nss = nss; + } + + /* + * Always handle WMM once after association regardless + * of the first value the AP uses. Setting -1 here has + * that effect because the AP values is an unsigned + * 4-bit value. + */ + link->u.mgd.wmm_last_param_set = -1; + link->u.mgd.mu_edca_last_param_set = -1; + + if (link->u.mgd.disable_wmm_tracking) { + ieee80211_set_wmm_default(link, false, false); + } else if (!ieee80211_sta_wmm_params(local, link, elems->wmm_param, + elems->wmm_param_len, + elems->mu_edca_param_set)) { + /* still enable QoS since we might have HT/VHT */ + ieee80211_set_wmm_default(link, false, true); + /* disable WMM tracking in this case to disable + * tracking WMM parameter changes in the beacon if + * the parameters weren't actually valid. Doing so + * avoids changing parameters very strangely when + * the AP is going back and forth between valid and + * invalid parameters. + */ + link->u.mgd.disable_wmm_tracking = true; + } + + if (elems->max_idle_period_ie) { + bss_conf->max_idle_period = + le16_to_cpu(elems->max_idle_period_ie->max_idle_period); + bss_conf->protected_keep_alive = + !!(elems->max_idle_period_ie->idle_options & + WLAN_IDLE_OPTIONS_PROTECTED_KEEP_ALIVE); + *changed |= BSS_CHANGED_KEEP_ALIVE; + } else { + bss_conf->max_idle_period = 0; + bss_conf->protected_keep_alive = false; + } + + /* set assoc capability (AID was already set earlier), + * ieee80211_set_associated() will tell the driver */ + bss_conf->assoc_capability = capab_info; + + ret = true; +out: + kfree(elems); + kfree(bss_ies); + return ret; +} + static int ieee80211_mgd_setup_link_sta(struct ieee80211_link_data *link, struct sta_info *sta, struct ieee80211_link_sta *link_sta, @@ -4119,160 +4439,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, struct cfg80211_bss *cbss, - struct ieee80211_mgmt *mgmt, size_t len, - struct ieee802_11_elems *elems) + struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + const u8 *elem_start, unsigned int elem_len) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - struct link_sta_info *link_sta; struct sta_info *sta; - u16 capab_info, aid; - struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; - const struct cfg80211_bss_ies *bss_ies = NULL; - struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; - bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; - bool is_s1g = cbss->channel->band == NL80211_BAND_S1GHZ; - struct ieee80211_link_data *link = &sdata->deflink; - u32 changed = 0; + u64 changed = 0; int err; - bool ret; - - capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); - - if (elems->aid_resp) - aid = le16_to_cpu(elems->aid_resp->aid); - else if (is_s1g) - aid = 0; /* TODO */ - else - aid = le16_to_cpu(mgmt->u.assoc_resp.aid); - - /* - * The 5 MSB of the AID field are reserved - * (802.11-2016 9.4.1.8 AID field) - */ - aid &= 0x7ff; - - ifmgd->broken_ap = false; - - if (aid == 0 || aid > IEEE80211_MAX_AID) { - sdata_info(sdata, "invalid AID value %d (out of range), turn off PS\n", - aid); - aid = 0; - ifmgd->broken_ap = true; - } - - if (!is_s1g && !elems->supp_rates) { - sdata_info(sdata, "no SuppRates element in AssocResp\n"); - ret = false; - goto out; - } - - sdata->vif.cfg.aid = aid; - sdata->deflink.u.mgd.tdls_chan_switch_prohibited = - elems->ext_capab && elems->ext_capab_len >= 5 && - (elems->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED); - - /* - * Some APs are erroneously not including some information in their - * (re)association response frames. Try to recover by using the data - * from the beacon or probe response. This seems to afflict mobile - * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", - * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. - */ - if (!is_6ghz && - ((assoc_data->wmm && !elems->wmm_param) || - (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && - (!elems->ht_cap_elem || !elems->ht_operation)) || - (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && - (!elems->vht_cap_elem || !elems->vht_operation)))) { - const struct cfg80211_bss_ies *ies; - struct ieee802_11_elems *bss_elems; - - rcu_read_lock(); - ies = rcu_dereference(cbss->ies); - if (ies) - bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, - GFP_ATOMIC); - rcu_read_unlock(); - if (!bss_ies) { - ret = false; - goto out; - } - - bss_elems = ieee802_11_parse_elems(bss_ies->data, bss_ies->len, - false, assoc_data->bss); - if (!bss_elems) { - ret = false; - goto out; - } - - if (assoc_data->wmm && - !elems->wmm_param && bss_elems->wmm_param) { - elems->wmm_param = bss_elems->wmm_param; - sdata_info(sdata, - "AP bug: WMM param missing from AssocResp\n"); - } - - /* - * Also check if we requested HT/VHT, otherwise the AP doesn't - * have to include the IEs in the (re)association response. - */ - if (!elems->ht_cap_elem && bss_elems->ht_cap_elem && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) { - elems->ht_cap_elem = bss_elems->ht_cap_elem; - sdata_info(sdata, - "AP bug: HT capability missing from AssocResp\n"); - } - if (!elems->ht_operation && bss_elems->ht_operation && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) { - elems->ht_operation = bss_elems->ht_operation; - sdata_info(sdata, - "AP bug: HT operation missing from AssocResp\n"); - } - if (!elems->vht_cap_elem && bss_elems->vht_cap_elem && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) { - elems->vht_cap_elem = bss_elems->vht_cap_elem; - sdata_info(sdata, - "AP bug: VHT capa missing from AssocResp\n"); - } - if (!elems->vht_operation && bss_elems->vht_operation && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) { - elems->vht_operation = bss_elems->vht_operation; - sdata_info(sdata, - "AP bug: VHT operation missing from AssocResp\n"); - } - - kfree(bss_elems); - } - - /* - * We previously checked these in the beacon/probe response, so - * they should be present here. This is just a safety net. - */ - if (!is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT) && - (!elems->wmm_param || !elems->ht_cap_elem || !elems->ht_operation)) { - sdata_info(sdata, - "HT AP is missing WMM params or HT capability/operation\n"); - ret = false; - goto out; - } - - if (!is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && - (!elems->vht_cap_elem || !elems->vht_operation)) { - sdata_info(sdata, - "VHT AP is missing VHT capability/operation\n"); - ret = false; - goto out; - } - - if (is_6ghz && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && - !elems->he_6ghz_capa) { - sdata_info(sdata, - "HE 6 GHz AP is missing HE 6 GHz band capability\n"); - ret = false; - goto out; - } mutex_lock(&sdata->local->sta_mtx); /* @@ -4280,154 +4455,13 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, * the association and should be available to us */ sta = sta_info_get(sdata, cbss->bssid); - if (WARN_ON(!sta)) { - mutex_unlock(&sdata->local->sta_mtx); - ret = false; - goto out; - } + if (WARN_ON(!sta)) + goto out_err; - link_sta = rcu_dereference_protected(sta->link[link->link_id], - lockdep_is_held(&local->sta_mtx)); - if (WARN_ON(!link_sta)) { - mutex_unlock(&sdata->local->sta_mtx); - ret = false; - goto out; - } - - sband = ieee80211_get_link_sband(link); - if (!sband) { - mutex_unlock(&sdata->local->sta_mtx); - ret = false; - goto out; - } - - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && - (!elems->he_cap || !elems->he_operation)) { - mutex_unlock(&sdata->local->sta_mtx); - sdata_info(sdata, - "HE AP is missing HE capability/operation\n"); - ret = false; - goto out; - } - - /* Set up internal HT/VHT capabilities */ - if (elems->ht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) - ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, - elems->ht_cap_elem, - link_sta); - - if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) - ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, - elems->vht_cap_elem, - link_sta); - - if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && - elems->he_cap) { - ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, - elems->he_cap, - elems->he_cap_len, - elems->he_6ghz_capa, - link_sta); - - bss_conf->he_support = link_sta->pub->he_cap.has_he; - if (elems->rsnx && elems->rsnx_len && - (elems->rsnx[0] & WLAN_RSNX_CAPA_PROTECTED_TWT) && - wiphy_ext_feature_isset(local->hw.wiphy, - NL80211_EXT_FEATURE_PROTECTED_TWT)) - bss_conf->twt_protected = true; - else - bss_conf->twt_protected = false; - - changed |= ieee80211_recalc_twt_req(link, link_sta, elems); - - if (elems->eht_operation && elems->eht_cap && - !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) { - ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, - elems->he_cap, - elems->he_cap_len, - elems->eht_cap, - elems->eht_cap_len, - link_sta); - - bss_conf->eht_support = link_sta->pub->eht_cap.has_eht; - } else { - bss_conf->eht_support = false; - } - } else { - bss_conf->he_support = false; - bss_conf->twt_requester = false; - bss_conf->twt_protected = false; - bss_conf->eht_support = false; - } - - bss_conf->twt_broadcast = - ieee80211_twt_bcast_support(sdata, bss_conf, sband, link_sta); - - if (bss_conf->he_support) { - bss_conf->he_bss_color.color = - le32_get_bits(elems->he_operation->he_oper_params, - IEEE80211_HE_OPERATION_BSS_COLOR_MASK); - bss_conf->he_bss_color.partial = - le32_get_bits(elems->he_operation->he_oper_params, - IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR); - bss_conf->he_bss_color.enabled = - !le32_get_bits(elems->he_operation->he_oper_params, - IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED); - - if (bss_conf->he_bss_color.enabled) - changed |= BSS_CHANGED_HE_BSS_COLOR; - - bss_conf->htc_trig_based_pkt_ext = - le32_get_bits(elems->he_operation->he_oper_params, - IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK); - bss_conf->frame_time_rts_th = - le32_get_bits(elems->he_operation->he_oper_params, - IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK); - - bss_conf->uora_exists = !!elems->uora_element; - if (elems->uora_element) - bss_conf->uora_ocw_range = elems->uora_element[0]; - - ieee80211_he_op_ie_to_bss_conf(&sdata->vif, elems->he_operation); - ieee80211_he_spr_ie_to_bss_conf(&sdata->vif, elems->he_spr); - /* TODO: OPEN: what happens if BSS color disable is set? */ - } - - if (cbss->transmitted_bss) { - bss_conf->nontransmitted = true; - ether_addr_copy(bss_conf->transmitter_bssid, - cbss->transmitted_bss->bssid); - bss_conf->bssid_indicator = cbss->max_bssid_indicator; - bss_conf->bssid_index = cbss->bssid_index; - } else { - bss_conf->nontransmitted = false; - memset(bss_conf->transmitter_bssid, 0, - sizeof(bss_conf->transmitter_bssid)); - bss_conf->bssid_indicator = 0; - bss_conf->bssid_index = 0; - } - - /* - * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data - * in their association response, so ignore that data for our own - * configuration. If it changed since the last beacon, we'll get the - * next beacon and update then. - */ - - /* - * If an operating mode notification IE is present, override the - * NSS calculation (that would be done in rate_control_rate_init()) - * and use the # of streams from that element. - */ - if (elems->opmode_notif && - !(*elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)) { - u8 nss; - - nss = *elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; - nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; - nss += 1; - link_sta->pub->rx_nss = nss; - } + if (!ieee80211_assoc_config_link(&sdata->deflink, &sta->deflink, + cbss, mgmt, elem_start, elem_len, + &changed)) + goto out_err; rate_control_rate_init(sta); @@ -4449,9 +4483,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, "failed to move station %pM to desired state\n", sta->sta.addr); WARN_ON(__sta_info_destroy(sta)); - mutex_unlock(&sdata->local->sta_mtx); - ret = false; - goto out; + goto out_err; } if (sdata->wdev.use_4addr) @@ -4459,48 +4491,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, mutex_unlock(&sdata->local->sta_mtx); - /* - * Always handle WMM once after association regardless - * of the first value the AP uses. Setting -1 here has - * that effect because the AP values is an unsigned - * 4-bit value. - */ - link->u.mgd.wmm_last_param_set = -1; - link->u.mgd.mu_edca_last_param_set = -1; - - if (link->u.mgd.disable_wmm_tracking) { - ieee80211_set_wmm_default(link, false, false); - } else if (!ieee80211_sta_wmm_params(local, link, elems->wmm_param, - elems->wmm_param_len, - elems->mu_edca_param_set)) { - /* still enable QoS since we might have HT/VHT */ - ieee80211_set_wmm_default(link, false, true); - /* disable WMM tracking in this case to disable - * tracking WMM parameter changes in the beacon if - * the parameters weren't actually valid. Doing so - * avoids changing parameters very strangely when - * the AP is going back and forth between valid and - * invalid parameters. - */ - link->u.mgd.disable_wmm_tracking = true; - } - changed |= BSS_CHANGED_QOS; - - if (elems->max_idle_period_ie) { - bss_conf->max_idle_period = - le16_to_cpu(elems->max_idle_period_ie->max_idle_period); - bss_conf->protected_keep_alive = - !!(elems->max_idle_period_ie->idle_options & - WLAN_IDLE_OPTIONS_PROTECTED_KEEP_ALIVE); - changed |= BSS_CHANGED_KEEP_ALIVE; - } else { - bss_conf->max_idle_period = 0; - bss_conf->protected_keep_alive = false; - } - - /* set assoc capability (AID was already set earlier), - * ieee80211_set_associated() will tell the driver */ - bss_conf->assoc_capability = capab_info; ieee80211_set_associated(sdata, cbss, changed); /* @@ -4517,10 +4507,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ieee80211_sta_reset_beacon_monitor(sdata); ieee80211_sta_reset_conn_monitor(sdata); - ret = true; - out: - kfree(bss_ies); - return ret; + return true; +out_err: + mutex_unlock(&sdata->local->sta_mtx); + return false; } static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, @@ -4532,7 +4522,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, u16 capab_info, status_code, aid; struct ieee802_11_elems *elems; int ac; - u8 *pos; + const u8 *elem_start; + unsigned int elem_len; bool reassoc; struct cfg80211_bss *cbss; struct ieee80211_event event = { @@ -4565,12 +4556,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, reassoc = ieee80211_is_reassoc_resp(mgmt->frame_control); capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); - pos = mgmt->u.assoc_resp.variable; - aid = le16_to_cpu(mgmt->u.assoc_resp.aid); - if (cbss->channel->band == NL80211_BAND_S1GHZ) { - pos = (u8 *) mgmt->u.s1g_assoc_resp.variable; - aid = 0; /* TODO */ - } + if (cbss->channel->band == NL80211_BAND_S1GHZ) + elem_start = mgmt->u.s1g_assoc_resp.variable; + else + elem_start = mgmt->u.assoc_resp.variable; /* * Note: this may not be perfect, AP might misbehave - if @@ -4581,19 +4570,34 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, info.subtype = reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ; + if (assoc_data->fils_kek_len && + fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0) + return; + + elem_len = len - (elem_start - (u8 *)mgmt); + elems = ieee802_11_parse_elems(elem_start, elem_len, false, NULL); + if (!elems) + goto notify_driver; + + if (elems->aid_resp) + aid = le16_to_cpu(elems->aid_resp->aid); + else if (cbss->channel->band == NL80211_BAND_S1GHZ) + aid = 0; /* TODO */ + else + aid = le16_to_cpu(mgmt->u.assoc_resp.aid); + + /* + * The 5 MSB of the AID field are reserved + * (802.11-2016 9.4.1.8 AID field) + */ + aid &= 0x7ff; + sdata_info(sdata, "RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n", reassoc ? "Rea" : "A", mgmt->sa, capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); - if (assoc_data->fils_kek_len && - fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0) - return; - - elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, - assoc_data->bss); - if (!elems) - goto notify_driver; + ifmgd->broken_ap = false; if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && elems->timeout_int && @@ -4623,7 +4627,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, event.u.mlme.reason = status_code; drv_event_callback(sdata->local, sdata, &event); } else { - if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, elems)) { + if (aid == 0 || aid > IEEE80211_MAX_AID) { + sdata_info(sdata, + "invalid AID value %d (out of range), turn off PS\n", + aid); + aid = 0; + ifmgd->broken_ap = true; + } + + sdata->vif.cfg.aid = aid; + + if (!ieee80211_assoc_success(sdata, cbss, mgmt, elems, + elem_start, elem_len)) { /* oops -- internal error -- send timeout for now */ ieee80211_destroy_assoc_data(sdata, ASSOC_TIMEOUT); goto notify_driver; From patchwork Wed Jul 13 15:34:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590784 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21DB1CCA483 for ; Wed, 13 Jul 2022 15:34:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236975AbiGMPey (ORCPT ); Wed, 13 Jul 2022 11:34:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236951AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3130841D3A for ; Wed, 13 Jul 2022 08:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=hfIkoZFbhsb8c49thvM9DtEIbRl0dhXgdw3pdwdyRcQ=; t=1657726483; x=1658936083; b=nF8EmrPFRRrepJranncumgzdAVNH+nosUdmZTVpnmrYMrv6 RfWMQmY5oW/sY2Xnt/p3awIg2FUWYHWBChLNx4zFCRgL3kY+wgTK+iHFjpGkOcXVVP6iQGcv1hq1b Zb2CBdHKZEMi3F6+2CB7I1e2NihioU19gPg5rtSHNGGQNgn+qjW9jMUlErSjPZKuDY1o6NbKhuxnT 2jXzaKdiJgitdZVwVw7kR8z9zr75M9+SKwUE57DE6/uYYRVcJ7fdK1hm4WKypphwCP6xlFKesOdIS tRFp26CzW+M5n2d9w5L0DJCDe7OCdLBhippCV4iLD7nAC4N8fhCI1ZdD5FOXGDnQ==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNt-00EnaA-KZ; Wed, 13 Jul 2022 17:34:41 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 17/21] wifi: mac80211: mlme: remove address arg to ieee80211_mark_sta_auth() Date: Wed, 13 Jul 2022 17:34:29 +0200 Message-Id: <20220713173301.525ca9d43170.Idfca3a6359d1f0d71c7963e5e3fb130487d0296b@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg There's no need to pass the address, we can look at the auth_data inside the function rather than outside. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 873f7f6e03ce..62bb5fec01c9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3166,10 +3166,10 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, auth_data->key_idx, tx_flags); } -static bool ieee80211_mark_sta_auth(struct ieee80211_sub_if_data *sdata, - const u8 *ap_addr) +static bool ieee80211_mark_sta_auth(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + const u8 *ap_addr = ifmgd->auth_data->bss->bssid; struct sta_info *sta; bool result = true; @@ -3296,7 +3296,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, if (ifmgd->auth_data->algorithm != WLAN_AUTH_SAE || (auth_transaction == 2 && ifmgd->auth_data->expected_transaction == 2)) { - if (!ieee80211_mark_sta_auth(sdata, bssid)) + if (!ieee80211_mark_sta_auth(sdata)) return; /* ignore frame -- wait for timeout */ } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && auth_transaction == 2) { @@ -6098,7 +6098,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, */ if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE && auth_data->peer_confirmed && auth_data->sae_trans == 2) - ieee80211_mark_sta_auth(sdata, req->bss->bssid); + ieee80211_mark_sta_auth(sdata); if (ifmgd->associated) { u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; From patchwork Wed Jul 13 15:34:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590312 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 928DFC433EF for ; Wed, 13 Jul 2022 15:34:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236984AbiGMPe5 (ORCPT ); Wed, 13 Jul 2022 11:34:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236959AbiGMPep (ORCPT ); Wed, 13 Jul 2022 11:34:45 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3DF64D149 for ; Wed, 13 Jul 2022 08:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=OPHKYXWXbYif1zEAyJJUZqBrwqAi3zBycKnCGL1CPtA=; t=1657726483; x=1658936083; b=l8inS3ivunYIEoAPGDbNuAINlr4PlEY0IsoF21YHR14Y/6Q mzOxmQNxXgA3a8/a/u8jzA9ZFV8Ois23NthnwQhl2Hyxxls9fX8hbDVtz/zLwKK14FFJM7G0q+YLA edhXODnnC0W3ubIRRp8YAXF9TfbgqD46odmcD8+FWRguf+qj8FBDikaEEa8eO/3rR8rBS7V+h2UQ+ I8KHOBi75wVmoqI9ciuZwkUFpQ0gP0jLv6h3OjJ14k5lWk+PGenykqOYxY/tU+Zd9l3f8vsYrUFjc vgFCTV8MzlqkMIQ1lq36q4CWwUGSEp+O75CiA1I69B/e4/Am2SibE76hj3FL0gzA==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNt-00EnaA-Rd; Wed, 13 Jul 2022 17:34:41 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 18/21] wifi: mac80211: mlme: refactor assoc link setup Date: Wed, 13 Jul 2022 17:34:30 +0200 Message-Id: <20220713173301.8aa30902c9cc.I4202bf90f873ed62ebf879cac380800a4e32b6b9@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Factor out the code to set up the assoc link into a new function ieee80211_setup_assoc_link(). While at it, also modify the 'override' handling to just take into account whether or not the conn_flags were changed, which is what we need to setup again the channel later. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 286 ++++++++++++++++++++++++-------------------- 1 file changed, 156 insertions(+), 130 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 62bb5fec01c9..09b79fb42bb8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -6144,22 +6144,138 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, return err; } +static ieee80211_conn_flags_t +ieee80211_setup_assoc_link(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgd_assoc_data *assoc_data, + struct cfg80211_assoc_request *req, + ieee80211_conn_flags_t conn_flags) +{ + struct ieee80211_local *local = sdata->local; + const struct cfg80211_bss_ies *beacon_ies; + struct ieee80211_supported_band *sband; + const struct element *ht_elem, *vht_elem; + struct ieee80211_link_data *link = &sdata->deflink; + struct cfg80211_bss *cbss = req->bss; + struct ieee80211_bss *bss = (void *)cbss->priv; + bool is_5ghz, is_6ghz; + + sband = local->hw.wiphy->bands[cbss->channel->band]; + if (WARN_ON(!sband)) + return false; + + is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ; + is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; + + assoc_data->supp_rates = bss->supp_rates; + assoc_data->supp_rates_len = bss->supp_rates_len; + + rcu_read_lock(); + ht_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_HT_OPERATION); + if (ht_elem && ht_elem->datalen >= sizeof(struct ieee80211_ht_operation)) + assoc_data->ap_ht_param = + ((struct ieee80211_ht_operation *)(ht_elem->data))->ht_param; + else if (!is_6ghz) + conn_flags |= IEEE80211_CONN_DISABLE_HT; + vht_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_VHT_CAPABILITY); + if (vht_elem && vht_elem->datalen >= sizeof(struct ieee80211_vht_cap)) { + memcpy(&assoc_data->ap_vht_cap, vht_elem->data, + sizeof(struct ieee80211_vht_cap)); + } else if (is_5ghz) { + link_info(link, + "VHT capa missing/short, disabling VHT/HE/EHT\n"); + conn_flags |= IEEE80211_CONN_DISABLE_VHT | + IEEE80211_CONN_DISABLE_HE | + IEEE80211_CONN_DISABLE_EHT; + } + rcu_read_unlock(); + + link->u.mgd.beacon_crc_valid = false; + link->u.mgd.dtim_period = 0; + link->u.mgd.have_beacon = false; + + /* override HT/VHT configuration only if the AP and we support it */ + if (!(conn_flags & IEEE80211_CONN_DISABLE_HT)) { + struct ieee80211_sta_ht_cap sta_ht_cap; + + memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); + ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); + } + + rcu_read_lock(); + beacon_ies = rcu_dereference(cbss->beacon_ies); + if (beacon_ies) { + const struct element *elem; + u8 dtim_count = 0; + + ieee80211_get_dtim(beacon_ies, &dtim_count, + &link->u.mgd.dtim_period); + + sdata->deflink.u.mgd.have_beacon = true; + + if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { + link->conf->sync_tsf = beacon_ies->tsf; + link->conf->sync_device_ts = bss->device_ts_beacon; + link->conf->sync_dtim_count = dtim_count; + } + + elem = cfg80211_find_ext_elem(WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION, + beacon_ies->data, beacon_ies->len); + if (elem && elem->datalen >= 3) + link->conf->profile_periodicity = elem->data[2]; + else + link->conf->profile_periodicity = 0; + + elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, + beacon_ies->data, beacon_ies->len); + if (elem && elem->datalen >= 11 && + (elem->data[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) + link->conf->ema_ap = true; + else + link->conf->ema_ap = false; + } + rcu_read_unlock(); + + if (bss->corrupt_data) { + char *corrupt_type = "data"; + + if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_BEACON) { + if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) + corrupt_type = "beacon and probe response"; + else + corrupt_type = "beacon"; + } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) { + corrupt_type = "probe response"; + } + sdata_info(sdata, "associating to AP %pM with corrupt %s\n", + cbss->bssid, corrupt_type); + } + + if (link->u.mgd.req_smps == IEEE80211_SMPS_AUTOMATIC) { + if (sdata->u.mgd.powersave) + link->smps_mode = IEEE80211_SMPS_DYNAMIC; + else + link->smps_mode = IEEE80211_SMPS_OFF; + } else { + link->smps_mode = link->u.mgd.req_smps; + } + + return conn_flags; +} + int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct cfg80211_assoc_request *req) { - bool is_6ghz = req->bss->channel->band == NL80211_BAND_6GHZ; - bool is_5ghz = req->bss->channel->band == NL80211_BAND_5GHZ; struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss *bss = (void *)req->bss->priv; struct ieee80211_mgd_assoc_data *assoc_data; const struct cfg80211_bss_ies *beacon_ies; - struct ieee80211_supported_band *sband; struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg; - const struct element *ssid_elem, *ht_elem, *vht_elem; + const struct element *ssid_elem; struct ieee80211_link_data *link = &sdata->deflink; + ieee80211_conn_flags_t conn_flags = 0; int i, err; - bool override = false; + bool override; assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); if (!assoc_data) @@ -6215,8 +6331,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, /* prepare assoc data */ - link->u.mgd.beacon_crc_valid = false; - assoc_data->wmm = bss->wmm_used && (local->hw.queues >= IEEE80211_NUM_ACS); @@ -6231,27 +6345,44 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + conn_flags |= IEEE80211_CONN_DISABLE_HT; + conn_flags |= IEEE80211_CONN_DISABLE_VHT; + conn_flags |= IEEE80211_CONN_DISABLE_HE; + conn_flags |= IEEE80211_CONN_DISABLE_EHT; netdev_info(sdata->dev, "disabling HT/VHT/HE due to WEP/TKIP use\n"); } } - sband = local->hw.wiphy->bands[req->bss->channel->band]; - /* also disable HT/VHT/HE/EHT if the AP doesn't use WMM */ if (!bss->wmm_used) { - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; + conn_flags |= IEEE80211_CONN_DISABLE_HT; + conn_flags |= IEEE80211_CONN_DISABLE_VHT; + conn_flags |= IEEE80211_CONN_DISABLE_HE; + conn_flags |= IEEE80211_CONN_DISABLE_EHT; netdev_info(sdata->dev, "disabling HT/VHT/HE as WMM/QoS is not supported by the AP\n"); } + if (req->flags & ASSOC_REQ_DISABLE_HT) { + mlme_dbg(sdata, "HT disabled by flag, disabling HT/VHT/HE\n"); + conn_flags |= IEEE80211_CONN_DISABLE_HT; + conn_flags |= IEEE80211_CONN_DISABLE_VHT; + conn_flags |= IEEE80211_CONN_DISABLE_HE; + conn_flags |= IEEE80211_CONN_DISABLE_EHT; + } + + if (req->flags & ASSOC_REQ_DISABLE_VHT) { + mlme_dbg(sdata, "VHT disabled by flag, disabling VHT\n"); + conn_flags |= IEEE80211_CONN_DISABLE_VHT; + } + + if (req->flags & ASSOC_REQ_DISABLE_HE) { + mlme_dbg(sdata, "HE disabled by flag, disabling HE/EHT\n"); + conn_flags |= IEEE80211_CONN_DISABLE_HE; + conn_flags |= IEEE80211_CONN_DISABLE_EHT; + } + memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, sizeof(ifmgd->ht_capa_mask)); @@ -6286,28 +6417,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, assoc_data->bss = req->bss; assoc_data->capability = req->bss->capability; - assoc_data->supp_rates = bss->supp_rates; - assoc_data->supp_rates_len = bss->supp_rates_len; - rcu_read_lock(); - ht_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_HT_OPERATION); - if (ht_elem && ht_elem->datalen >= sizeof(struct ieee80211_ht_operation)) - assoc_data->ap_ht_param = - ((struct ieee80211_ht_operation *)(ht_elem->data))->ht_param; - else if (!is_6ghz) - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - vht_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_VHT_CAPABILITY); - if (vht_elem && vht_elem->datalen >= sizeof(struct ieee80211_vht_cap)) { - memcpy(&assoc_data->ap_vht_cap, vht_elem->data, - sizeof(struct ieee80211_vht_cap)); - } else if (is_5ghz) { - sdata_info(sdata, - "VHT capa missing/short, disabling VHT/HE/EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT | - IEEE80211_CONN_DISABLE_HE | - IEEE80211_CONN_DISABLE_EHT; - } - rcu_read_unlock(); + /* default timeout */ + assoc_data->timeout = jiffies; + assoc_data->timeout_started = true; + + conn_flags |= ieee80211_setup_assoc_link(sdata, assoc_data, req, + conn_flags); + override = link->u.mgd.conn_flags != conn_flags; + link->u.mgd.conn_flags |= conn_flags; if (WARN((sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD) && ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK), @@ -6351,50 +6469,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sdata->control_port_no_preauth = req->crypto.control_port_no_preauth; /* kick off associate process */ - ifmgd->assoc_data = assoc_data; - link->u.mgd.dtim_period = 0; - link->u.mgd.have_beacon = false; - - /* override HT/VHT configuration only if the AP and we support it */ - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HT)) { - struct ieee80211_sta_ht_cap sta_ht_cap; - - if (req->flags & ASSOC_REQ_DISABLE_HT) - override = true; - - memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); - ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); - - /* check for 40 MHz disable override */ - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ) && - sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && - !(sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - override = true; - - if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT) && - req->flags & ASSOC_REQ_DISABLE_VHT) - override = true; - } - - if (req->flags & ASSOC_REQ_DISABLE_HT) { - mlme_dbg(sdata, "HT disabled by flag, disabling HT/VHT/HE\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; - } - - if (req->flags & ASSOC_REQ_DISABLE_VHT) { - mlme_dbg(sdata, "VHT disabled by flag, disabling VHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_VHT; - } - - if (req->flags & ASSOC_REQ_DISABLE_HE) { - mlme_dbg(sdata, "HE disabled by flag, disabling HE/EHT\n"); - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_HE; - link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; - } if (req->flags & ASSOC_REQ_DISABLE_EHT) link->u.mgd.conn_flags |= IEEE80211_CONN_DISABLE_EHT; @@ -6426,60 +6501,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); assoc_data->timeout_started = true; assoc_data->need_beacon = true; - } else if (beacon_ies) { - const struct element *elem; - u8 dtim_count = 0; - - ieee80211_get_dtim(beacon_ies, &dtim_count, - &link->u.mgd.dtim_period); - - link->u.mgd.have_beacon = true; - assoc_data->timeout = jiffies; - assoc_data->timeout_started = true; - - if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { - link->conf->sync_tsf = beacon_ies->tsf; - link->conf->sync_device_ts = - bss->device_ts_beacon; - link->conf->sync_dtim_count = dtim_count; - } - - elem = cfg80211_find_ext_elem(WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION, - beacon_ies->data, beacon_ies->len); - if (elem && elem->datalen >= 3) - link->conf->profile_periodicity = elem->data[2]; - else - link->conf->profile_periodicity = 0; - - elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, - beacon_ies->data, beacon_ies->len); - if (elem && elem->datalen >= 11 && - (elem->data[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) - link->conf->ema_ap = true; - else - link->conf->ema_ap = false; - } else { - assoc_data->timeout = jiffies; - assoc_data->timeout_started = true; } rcu_read_unlock(); run_again(sdata, assoc_data->timeout); - if (bss->corrupt_data) { - char *corrupt_type = "data"; - if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_BEACON) { - if (bss->corrupt_data & - IEEE80211_BSS_CORRUPT_PROBE_RESP) - corrupt_type = "beacon and probe response"; - else - corrupt_type = "beacon"; - } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) - corrupt_type = "probe response"; - sdata_info(sdata, "associating with AP with corrupt %s\n", - corrupt_type); - } - return 0; err_clear: eth_zero_addr(sdata->deflink.u.mgd.bssid); From patchwork Wed Jul 13 15:34:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590780 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A774AC43334 for ; Wed, 13 Jul 2022 15:34:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236986AbiGMPe6 (ORCPT ); Wed, 13 Jul 2022 11:34:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236954AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB00730F46 for ; Wed, 13 Jul 2022 08:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=mJvh0OLazZCuKrSanYZTk8Uh20wCU1+5gS0MP7RJq4Y=; t=1657726483; x=1658936083; b=ALlUFONThWXs5Blxu+Qd6Qq84ZTNgYjsrl0qVj7EF97/5im XUHYLs69u2LU7kYHJsniRIIrZZCeudpJfHCdJl4YEfdoEFTNImKQBcpnuBaRghcsEteDmi40zc05X 8qay/Sn/VXmG1iK7TMPaZUzauGKfRbAJjD2fv5ehURyNRuQKN8S92BBkYtSh+omH3HhB1jTrwf2O8 YkxPWQudGLqNdFw03nzpVxXHuCfaxt3gfxHMINKevGsPdIEzyOe6qL1PXZgsJ0BAbWMZLkBNhubL+ xyxVJ3rfauJU2i97J0SYJJ4jUobChTL26sePIZph54pUxTfj9vrKQuptAyCuimEw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNu-00EnaA-3T; Wed, 13 Jul 2022 17:34:42 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 19/21] wifi: mac80211: mlme: look up beacon elems only if needed Date: Wed, 13 Jul 2022 17:34:31 +0200 Message-Id: <20220713173301.b27a0272f45a.If385834be226619b7581a6b343adfc97c638b1aa@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg If NEED_DTIM_BEFORE_ASSOC isn't set, then we don't need to enter an RCU critical section and look up the beacon elements. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 09b79fb42bb8..0614712236de 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -6269,7 +6269,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss *bss = (void *)req->bss->priv; struct ieee80211_mgd_assoc_data *assoc_data; - const struct cfg80211_bss_ies *beacon_ies; struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg; const struct element *ssid_elem; struct ieee80211_link_data *link = &sdata->deflink; @@ -6487,22 +6486,25 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, link->smps_mode = link->u.mgd.req_smps; } - rcu_read_lock(); - beacon_ies = rcu_dereference(req->bss->beacon_ies); + if (ieee80211_hw_check(&sdata->local->hw, NEED_DTIM_BEFORE_ASSOC)) { + const struct cfg80211_bss_ies *beacon_ies; - if (ieee80211_hw_check(&sdata->local->hw, NEED_DTIM_BEFORE_ASSOC) && - !beacon_ies) { - /* - * Wait up to one beacon interval ... - * should this be more if we miss one? - */ - sdata_info(sdata, "waiting for beacon from %pM\n", - link->u.mgd.bssid); - assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); - assoc_data->timeout_started = true; - assoc_data->need_beacon = true; + rcu_read_lock(); + beacon_ies = rcu_dereference(req->bss->beacon_ies); + + if (beacon_ies) { + /* + * Wait up to one beacon interval ... + * should this be more if we miss one? + */ + sdata_info(sdata, "waiting for beacon from %pM\n", + link->u.mgd.bssid); + assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); + assoc_data->timeout_started = true; + assoc_data->need_beacon = true; + } + rcu_read_unlock(); } - rcu_read_unlock(); run_again(sdata, assoc_data->timeout); From patchwork Wed Jul 13 15:34:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590314 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1FF7CCA481 for ; Wed, 13 Jul 2022 15:34:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236980AbiGMPe5 (ORCPT ); Wed, 13 Jul 2022 11:34:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40602 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236957AbiGMPeo (ORCPT ); Wed, 13 Jul 2022 11:34:44 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EDBC54D14D for ; Wed, 13 Jul 2022 08:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=8R4gLuaWO4yBwmjU8j2mRUm6l1qV5IC6zelvF/k2iRA=; t=1657726484; x=1658936084; b=jZTKadCmfhu6Cdbw1rPw8urngRozd5HQsNzSyP7BAcA5cJT tTCKAEyuXRmlKEqnaXiMB42ORc8I8OY5uNpX93uhmQi4aHY0EX0W+B/5e8ZloT40oX8lLXAhLdL7W vCB8v1+eB3I+pDijQmTNVpBKaJ2YngnyNBLEZoV5BqmeGVLCLkQ1Prw33AXXIZKcmU83vPR6ho2Cn bzT6gxH9BhE8kvYvlnvys3q+1BGD1KKpMD+tusawOI5kheVTOR/piBoR99gLg2agB3ji3OMf7ONEp HUidFuxrVjkoqZu1oEN9vc2kBS5MNCOlB2gYwQKA6ldhvHsb9Kp/Q1YasmaauD0g==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNu-00EnaA-Ag; Wed, 13 Jul 2022 17:34:42 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 20/21] wifi: cfg80211: add cfg80211_get_iftype_ext_capa() Date: Wed, 13 Jul 2022 17:34:32 +0200 Message-Id: <20220713173301.4046adad13f5.I49eec9ff191d8cde7e17d37f6ddca714cc02a7da@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Add a helper function cfg80211_get_iftype_ext_capa() to look up interface type-specific (extended) capabilities. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 8 ++++++++ net/wireless/util.c | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index c2fd971e5c4d..6324e1b15ee0 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5005,6 +5005,14 @@ struct wiphy_iftype_ext_capab { u16 mld_capa_and_ops; }; +/** + * cfg80211_get_iftype_ext_capa - lookup interface type extended capability + * @wiphy: the wiphy to look up from + * @type: the interface type to look up + */ +const struct wiphy_iftype_ext_capab * +cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type); + /** * struct cfg80211_pmsr_capabilities - cfg80211 peer measurement capabilities * @max_peers: maximum number of peers in a single measurement diff --git a/net/wireless/util.c b/net/wireless/util.c index fe7956c8c6da..2c127951764a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -2490,3 +2490,17 @@ int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev, return rdev_del_virtual_intf(rdev, wdev); } + +const struct wiphy_iftype_ext_capab * +cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type) +{ + int i; + + for (i = 0; i < wiphy->num_iftype_ext_capab; i++) { + if (wiphy->iftype_ext_capab[i].iftype == type) + return &wiphy->iftype_ext_capab[i]; + } + + return NULL; +} +EXPORT_SYMBOL(cfg80211_get_iftype_ext_capa); From patchwork Wed Jul 13 15:34:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 590313 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 25B59CCA486 for ; Wed, 13 Jul 2022 15:34:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236981AbiGMPe5 (ORCPT ); Wed, 13 Jul 2022 11:34:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40576 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236946AbiGMPep (ORCPT ); Wed, 13 Jul 2022 11:34:45 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A20AE3E759 for ; Wed, 13 Jul 2022 08:34:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=tSv1WmBbVAdt4ofDkoF1Oqmtk2vFmui+wpujQYU3ehw=; t=1657726484; x=1658936084; b=RQrxiTTuIsH9JCiM9EAoy55YfofyfKOOlgUrHkh12lO7twJ WLhu1SLxbjQTjft096Ixt7EpFWk5hkYRSVidE2F41r8nxqIGOGjripO3Z7rskqJbu3719wXEG1v8B r5izMFgsNQIabWqtIT2QuNREOwiLRVXCFCe+zt64UuJUxIa3E8sjP7bhJthxBgxXatwIa9QiTR7BC ObIPhZ5NZNY78uyaHFSZF0dTkorc/cGV6jvajeCXHv9qwPeJAwEizbKr0mgDd8ufjWQfl3jj/zjn5 TL3eqsdrY40Ufb1NREErW6hAKsam0zcI6vLHo8PYUaJVhzY3T7QQu5KPciuR/Tcg==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) (envelope-from ) id 1oBeNu-00EnaA-J7; Wed, 13 Jul 2022 17:34:42 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg Subject: [PATCH 21/21] wifi: mac80211: mlme: refactor ieee80211_set_associated() Date: Wed, 13 Jul 2022 17:34:33 +0200 Message-Id: <20220713173301.98639a6d390e.I9562d40805f25728f9ac08102f91f202e198a590@changeid> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220713153433.279227-1-johannes@sipsolutions.net> References: <20220713153433.279227-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg Split out much of the code in ieee80211_set_associated() into a new ieee80211_link_set_associated() which can be called per link later for MLO. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 67 +++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0614712236de..d8e0ca4b316f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2387,29 +2387,27 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_link_data *link, return changed; } -static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, - struct cfg80211_bss *cbss, - u32 bss_info_changed) +static u32 ieee80211_link_set_associated(struct ieee80211_link_data *link, + struct cfg80211_bss *cbss) { - struct ieee80211_bss *bss = (void *)cbss->priv; - struct ieee80211_local *local = sdata->local; - struct ieee80211_link_data *link = &sdata->deflink; + struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_bss_conf *bss_conf = link->conf; - struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg; + struct ieee80211_bss *bss = (void *)cbss->priv; + u32 changed = 0; - bss_info_changed |= BSS_CHANGED_ASSOC; - bss_info_changed |= ieee80211_handle_bss_capability(link, - bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value); + sdata->u.mgd.beacon_timeout = + usecs_to_jiffies(ieee80211_tu_to_usec(beacon_loss_count * + bss_conf->beacon_int)); - sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( - beacon_loss_count * bss_conf->beacon_int)); + changed |= ieee80211_handle_bss_capability(link, + bss_conf->assoc_capability, + bss->has_erp_value, + bss->erp_value); + + ieee80211_check_rate_mask(link); - sdata->u.mgd.associated = true; link->u.mgd.bss = cbss; memcpy(link->u.mgd.bssid, cbss->bssid, ETH_ALEN); - memcpy(sdata->vif.cfg.ap_addr, cbss->bssid, ETH_ALEN); - - ieee80211_check_rate_mask(link); if (sdata->vif.p2p || sdata->vif.driver_flags & IEEE80211_VIF_GET_NOA_UPDATE) { @@ -2428,17 +2426,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, if (ret >= 2) { link->u.mgd.p2p_noa_index = bss_conf->p2p_noa_attr.index; - bss_info_changed |= BSS_CHANGED_P2P_PS; + changed |= BSS_CHANGED_P2P_PS; } } rcu_read_unlock(); } - /* just to be sure */ - ieee80211_stop_poll(sdata); - - ieee80211_led_assoc(local, 1); - if (link->u.mgd.have_beacon) { /* * If the AP is buggy we may get here with no DTIM period @@ -2448,18 +2441,40 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, */ bss_conf->dtim_period = link->u.mgd.dtim_period ?: 1; bss_conf->beacon_rate = bss->beacon_rate; - bss_info_changed |= BSS_CHANGED_BEACON_INFO; + changed |= BSS_CHANGED_BEACON_INFO; } else { bss_conf->beacon_rate = NULL; bss_conf->dtim_period = 0; } - vif_cfg->assoc = 1; - /* Tell the driver to monitor connection quality (if supported) */ if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI && bss_conf->cqm_rssi_thold) - bss_info_changed |= BSS_CHANGED_CQM; + changed |= BSS_CHANGED_CQM; + + return changed; +} + +static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, + struct cfg80211_bss *cbss, + u32 bss_info_changed) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_link_data *link = &sdata->deflink; + struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg; + + bss_info_changed |= BSS_CHANGED_ASSOC; + bss_info_changed |= ieee80211_link_set_associated(link, cbss); + + sdata->u.mgd.associated = true; + memcpy(sdata->vif.cfg.ap_addr, cbss->bssid, ETH_ALEN); + + /* just to be sure */ + ieee80211_stop_poll(sdata); + + ieee80211_led_assoc(local, 1); + + vif_cfg->assoc = 1; /* Enable ARP filtering */ if (vif_cfg->arp_addr_cnt)