From patchwork Wed Jan 20 00:51:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aloka Dixit X-Patchwork-Id: 12031169 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 128DFC433DB for ; Wed, 20 Jan 2021 00:52:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C45BF23108 for ; Wed, 20 Jan 2021 00:52:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729019AbhATAwd (ORCPT ); Tue, 19 Jan 2021 19:52:33 -0500 Received: from m42-8.mailgun.net ([69.72.42.8]:51375 "EHLO m42-8.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730829AbhATAw3 (ORCPT ); Tue, 19 Jan 2021 19:52:29 -0500 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1611103928; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=7Bjp9cr7MZ8j3HjFzWGHpyK/1RKlL8TzbyTJ5Al7el4=; b=kxZgqjHwHB9Y3TTDk817Aq8iKuep7PnZSQ0mbadyykAshBfNJulukykwsgaU1aJtTNkCUjgb zDpqPXAIa5gVBgEbOorMhRt6/viASVAW/VCHthQ+haIrWMWCnOf6RuZhJlXWLbcHgSMYpqg3 8XWbHAZopZFbHOsHFGjL7GheFS0= X-Mailgun-Sending-Ip: 69.72.42.8 X-Mailgun-Sid: WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n07.prod.us-west-2.postgun.com with SMTP id 60077e9321210999ed8dc113 (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Wed, 20 Jan 2021 00:51:31 GMT Sender: alokad=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 94D54C433CA; Wed, 20 Jan 2021 00:51:31 +0000 (UTC) Received: from alokad-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: alokad) by smtp.codeaurora.org (Postfix) with ESMTPSA id 94C4DC433C6; Wed, 20 Jan 2021 00:51:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 94C4DC433C6 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=alokad@codeaurora.org From: Aloka Dixit To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, John Crispin , Aloka Dixit Subject: [PATCH V7 1/4] nl80211: add basic multiple bssid support Date: Tue, 19 Jan 2021 16:51:17 -0800 Message-Id: <20210120005120.32424-2-alokad@codeaurora.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20210120005120.32424-1-alokad@codeaurora.org> References: <20210120005120.32424-1-alokad@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: John Crispin This patch adds support for passing the multiple bssid config to the kernel when an AP gets started. If the BSS is non-transmitting we need to pass * the ifidx of the transmitting parent * the BSS index in the set * the BSS count of the set * flag indicating if we want to do EMA * the multiple bssid elements as an array inside the beacon data This allows use to generate multiple bssid beacons aswell as EMA ones. Signed-off-by: John Crispin Signed-off-by: Aloka Dixit --- v7: Added missing calls to kfree() in error cases. v6: Addressed V5 review comments such as, Dynamic memory allocation for netlink structures, Limits for variable array accepted from driver, Used _ELEMS instead of _IE in netlink attribute and made it nested, Used cfg80211_* instead of ieee80211_* for new struct, Modified descritptions in comments. include/net/cfg80211.h | 47 ++++++ include/uapi/linux/nl80211.h | 66 ++++++++ net/wireless/nl80211.c | 282 +++++++++++++++++++++++++++-------- 3 files changed, 334 insertions(+), 61 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9a4bbccddc7f..0573626b61d4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -485,6 +485,21 @@ struct ieee80211_supported_band { const struct ieee80211_sband_iftype_data *iftype_data; }; +/** + * struct cfg80211_multiple_bssid - AP settings for multi bssid + * + * @index: the index of this AP in the multi bssid group. + * @count: the total number of multi bssid peer APs. + * @parent: non-transmitted BSSs transmitted parents index + * @ema: Shall the beacons be sent out in EMA mode. + */ +struct cfg80211_multiple_bssid { + u8 index; + u8 count; + u32 parent; + bool ema; +}; + /** * ieee80211_get_sband_iftype_data - return sband data for a given iftype * @sband: the sband to search for the STA on @@ -1032,6 +1047,23 @@ struct cfg80211_crypto_settings { enum nl80211_sae_pwe_mechanism sae_pwe; }; +/** + * struct cfg80211_multiple_bssid_data - Multiple BSSID elements + * + * @cnt: Number of elements in array %elems. + * + * @elems: Array of multiple BSSID element(s) to be added into Beacon frames. + * @elems.data: Data for multiple BSSID elements. + * @elems.len: Length of data. + */ +struct cfg80211_multiple_bssid_data { + u8 cnt; + struct { + u8 *data; + size_t len; + } elems[]; +}; + /** * struct cfg80211_beacon_data - beacon data * @head: head portion of beacon (before TIM IE) @@ -1058,6 +1090,7 @@ struct cfg80211_crypto_settings { * Token (measurement type 11) * @lci_len: LCI data length * @civicloc_len: Civic location data length + * @multiple_bssid: multiple_bssid elements */ struct cfg80211_beacon_data { const u8 *head, *tail; @@ -1076,6 +1109,8 @@ struct cfg80211_beacon_data { size_t probe_resp_len; size_t lci_len; size_t civicloc_len; + + struct cfg80211_multiple_bssid_data *multiple_bssid; }; struct mac_address { @@ -1181,6 +1216,7 @@ enum cfg80211_ap_settings_flags { * @he_oper: HE operation IE (or %NULL if HE isn't enabled) * @fils_discovery: FILS discovery transmission parameters * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters + * @multiple_bssid: AP settings for multiple bssid. */ struct cfg80211_ap_settings { struct cfg80211_chan_def chandef; @@ -1213,6 +1249,7 @@ struct cfg80211_ap_settings { struct cfg80211_he_bss_color he_bss_color; struct cfg80211_fils_discovery fils_discovery; struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; + struct cfg80211_multiple_bssid multiple_bssid; }; /** @@ -4929,6 +4966,11 @@ struct wiphy_iftype_akm_suites { * @max_data_retry_count: maximum supported per TID retry count for * configuration through the %NL80211_TID_CONFIG_ATTR_RETRY_SHORT and * %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes + * + * @multiple_bssid: Describes device's multiple BSSID config support + * @multiple_bssid.max_num_vaps: Maximum number of VAPS supported by the driver + * @multiple_bssid.max_num_elems: Maximum number of multiple BSSID elements + * supported by the driver */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -5069,6 +5111,11 @@ struct wiphy { const struct cfg80211_sar_capa *sar_capa; + struct { + u8 max_num_vaps; + u8 max_profile_periodicity; + } multiple_bssid; + char priv[] __aligned(NETDEV_ALIGN); }; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 40832d13c2f1..02e6b4af7786 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2550,6 +2550,14 @@ enum nl80211_commands { * disassoc events to indicate that an immediate reconnect to the AP * is desired. * + * @NL80211_ATTR_MULTIPLE_BSSID_CONFIG: Optional parameter to configure multiple + * BSSID and enhanced multi-BSSID advertisements. + * It is a nested attribute, see &enum nl80211_multiple_bssid_attributes. + * + * @NL80211_ATTR_MULTIPLE_BSSID_ELEMS: Optional parameter for multiple BSSID + * elements. It is a nested attribute, see + * &enum nl80211_multiple_bssid_elems_attributes. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3045,6 +3053,9 @@ enum nl80211_attrs { NL80211_ATTR_SAR_SPEC, + NL80211_ATTR_MULTIPLE_BSSID_CONFIG, + NL80211_ATTR_MULTIPLE_BSSID_ELEMS, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -7268,4 +7279,59 @@ enum nl80211_sar_specs_attrs { NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, }; +/** + * enum nl80211_multiple_bssid_attributes - Attributes to configure + * multiple BSSID and enhanced multi-BSSID advertisements. + * + * @__NL80211_MULTIPLE_BSSID_ATTR_INVALID: Invalid + * + * @NL80211_MULTIPLE_BSSID_ATTR_PARENT: For a non-transmitted BSSID, this + * attribute provides the interface index (u32) of the transmitted profile + * in the multiple BSSID set. + * + * @NL80211_MULTIPLE_BSSID_ATTR_INDEX: The index of this BSS (u8) inside + * multiple BSSID set. + * + * @NL80211_MULTIPLE_BSSID_ATTR_COUNT: Total number of BSSs (u8) in the + * multiple BSSID set. + * + * @NL80211_MULTIPLE_BSSID_ATTR_EMA: Flag to indicate if enhanced multi-BSSID + * advertisements (EMA) feature is enabled. + * If set to 1, elements provided through attribute + * %NL80211_ATTR_MULTIPLE_BSSID_ELEMS are split into multiple beacons. + * Otherwise, all elements will be included in every beacon. + */ +enum nl80211_multiple_bssid_attributes { + __NL80211_MULTIPLE_BSSID_ATTR_INVALID, + + NL80211_MULTIPLE_BSSID_ATTR_PARENT, + NL80211_MULTIPLE_BSSID_ATTR_INDEX, + NL80211_MULTIPLE_BSSID_ATTR_COUNT, + NL80211_MULTIPLE_BSSID_ATTR_EMA, + + __NL80211_MULTIPLE_BSSID_ATTR_LAST, + NL80211_MULTIPLE_BSSID_ATTR_MAX = __NL80211_MULTIPLE_BSSID_ATTR_LAST - 1, +}; + +/** + * enum nl80211_multiple_bssid_elems_attributes - Attributes used to pass + * multiple BSSID elements data. + * + * @__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_INVALID: Invalid + * + * @NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT: Number of multiple BSSID + * elements (u8). + * + * @NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA: Array of multiple BSSID elements. + */ +enum nl80211_multiple_bssid_elems_attributes { + __NL80211_MULTIPLE_BSSID_ELEMS_ATTR_INVALID, + + NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT, + NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA, + + __NL80211_MULTIPLE_BSSID_ELEMS_ATTR_LAST, + NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX = __NL80211_MULTIPLE_BSSID_ELEMS_ATTR_LAST - 1, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 775d0c4d86c3..031f614c5ace 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -411,6 +411,20 @@ sar_policy[NL80211_SAR_ATTR_MAX + 1] = { [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy), }; +static const struct nla_policy +nl80211_multiple_bssid_elems_policy[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX + 1] = { + [NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT] = { .type = NLA_U8 }, + [NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA] = { .type = NLA_NESTED }, +}; + +static const struct nla_policy +nl80211_multiple_bssid_policy[NL80211_MULTIPLE_BSSID_ATTR_MAX + 1] = { + [NL80211_MULTIPLE_BSSID_ATTR_PARENT] = { .type = NLA_U32 }, + [NL80211_MULTIPLE_BSSID_ATTR_INDEX] = { .type = NLA_U8 }, + [NL80211_MULTIPLE_BSSID_ATTR_COUNT] = { .type = NLA_U8 }, + [NL80211_MULTIPLE_BSSID_ATTR_EMA] = { .type = NLA_FLAG }, +}; + 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 }, @@ -732,6 +746,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { NL80211_SAE_PWE_BOTH), [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy), + [NL80211_ATTR_MULTIPLE_BSSID_CONFIG] = + NLA_POLICY_NESTED(nl80211_multiple_bssid_policy), + [NL80211_ATTR_MULTIPLE_BSSID_ELEMS] = + NLA_POLICY_NESTED(nl80211_multiple_bssid_elems_policy), }; /* policy for the key attributes */ @@ -4864,6 +4882,79 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, return 0; } +static int +nl80211_parse_multiple_bssid_config(struct wiphy *wiphy, + struct nlattr *attrs, + struct cfg80211_ap_settings *params) +{ + struct nlattr *tb[NL80211_MULTIPLE_BSSID_ATTR_MAX + 1]; + int ret; + struct cfg80211_multiple_bssid *config = ¶ms->multiple_bssid; + + ret = nla_parse_nested(tb, NL80211_MULTIPLE_BSSID_ATTR_MAX, attrs, NULL, + NULL); + if (ret) + return ret; + + if (!tb[NL80211_MULTIPLE_BSSID_ATTR_COUNT]) + return -EINVAL; + + config->count = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_ATTR_COUNT]); + if (config->count > wiphy->multiple_bssid.max_num_vaps) + return -EINVAL; + + if (tb[NL80211_MULTIPLE_BSSID_ATTR_PARENT]) + config->parent = nla_get_u32(tb[NL80211_MULTIPLE_BSSID_ATTR_PARENT]); + + if (tb[NL80211_MULTIPLE_BSSID_ATTR_INDEX]) + config->index = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_ATTR_INDEX]); + + if (tb[NL80211_MULTIPLE_BSSID_ATTR_EMA]) { + config->ema = nla_get_flag(tb[NL80211_MULTIPLE_BSSID_ATTR_EMA]); + if (config->ema && + params->beacon.multiple_bssid->cnt > + wiphy->multiple_bssid.max_profile_periodicity) + return -EINVAL; + } + + return 0; +} + +static struct cfg80211_multiple_bssid_data * +nl80211_parse_multiple_bssid_elems(struct wiphy *wiphy, struct nlattr *attrs) +{ + struct cfg80211_multiple_bssid_data *multiple_bssid; + struct nlattr *nl_ie; + struct nlattr *tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX + 1]; + int rem_ie; + u8 i = 0, err, num_elems; + + err = nla_parse_nested(tb, NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX, + attrs, NULL, NULL); + if (err) + return NULL; + + if (!tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT] || + !tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA]) + return NULL; + + num_elems = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT]); + multiple_bssid = kzalloc(struct_size(multiple_bssid, elems, num_elems), + GFP_KERNEL); + if (!multiple_bssid) + return NULL; + + multiple_bssid->cnt = num_elems; + nla_for_each_nested(nl_ie, tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA], + rem_ie) { + multiple_bssid->elems[i].data = nla_data(nl_ie); + multiple_bssid->elems[i].len = nla_len(nl_ie); + i++; + } + + return multiple_bssid; +} + static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, struct nlattr *attrs[], struct cfg80211_beacon_data *bcn) @@ -4944,6 +5035,14 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, bcn->ftm_responder = -1; } + if (attrs[NL80211_ATTR_MULTIPLE_BSSID_ELEMS]) { + bcn->multiple_bssid = + nl80211_parse_multiple_bssid_elems(&rdev->wiphy, + attrs[NL80211_ATTR_MULTIPLE_BSSID_ELEMS]); + if (!bcn->multiple_bssid) + return -EINVAL; + } + return 0; } @@ -5229,7 +5328,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon); if (err) - return err; + goto out; params.beacon_interval = nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); @@ -5239,7 +5338,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype, params.beacon_interval); if (err) - return err; + goto out; /* * In theory, some of these attributes should be required here @@ -5252,8 +5351,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); params.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); - if (params.ssid_len == 0) - return -EINVAL; + if (params.ssid_len == 0) { + err = -EINVAL; + goto out; + } } if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) @@ -5266,57 +5367,73 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) params.auth_type = nla_get_u32( info->attrs[NL80211_ATTR_AUTH_TYPE]); if (!nl80211_valid_auth_type(rdev, params.auth_type, - NL80211_CMD_START_AP)) - return -EINVAL; + NL80211_CMD_START_AP)) { + err = -EINVAL; + goto out; + } } else params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; err = nl80211_crypto_settings(rdev, info, ¶ms.crypto, NL80211_MAX_NR_CIPHER_SUITES); if (err) - return err; + goto out; if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) { - if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) - return -EOPNOTSUPP; + if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) { + err = -EOPNOTSUPP; + goto out; + } params.inactivity_timeout = nla_get_u16( info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); } if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) { - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) - return -EINVAL; + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { + err = -EINVAL; + goto out; + } params.p2p_ctwindow = nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); if (params.p2p_ctwindow != 0 && - !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) - return -EINVAL; + !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) { + err = -EINVAL; + goto out; + } } if (info->attrs[NL80211_ATTR_P2P_OPPPS]) { u8 tmp; - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) - return -EINVAL; + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { + err = -EINVAL; + goto out; + } tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); params.p2p_opp_ps = tmp; if (params.p2p_opp_ps != 0 && - !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) - return -EINVAL; + !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) { + err = -EINVAL; + goto out; + } } if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); if (err) - return err; + goto out; } else if (wdev->preset_chandef.chan) { params.chandef = wdev->preset_chandef; - } else if (!nl80211_get_ap_channel(rdev, ¶ms)) - return -EINVAL; + } else if (!nl80211_get_ap_channel(rdev, ¶ms)) { + err = -EINVAL; + goto out; + } if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, - wdev->iftype)) - return -EINVAL; + wdev->iftype)) { + err = -EINVAL; + goto out; + } if (info->attrs[NL80211_ATTR_TX_RATES]) { err = nl80211_parse_tx_bitrate_mask(info, info->attrs, @@ -5324,12 +5441,12 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) ¶ms.beacon_rate, dev, false); if (err) - return err; + goto out; err = validate_beacon_tx_rate(rdev, params.chandef.chan->band, ¶ms.beacon_rate); if (err) - return err; + goto out; } if (info->attrs[NL80211_ATTR_SMPS_MODE]) { @@ -5340,29 +5457,38 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) break; case NL80211_SMPS_STATIC: if (!(rdev->wiphy.features & - NL80211_FEATURE_STATIC_SMPS)) - return -EINVAL; + NL80211_FEATURE_STATIC_SMPS)) { + err = -EINVAL; + goto out; + } break; case NL80211_SMPS_DYNAMIC: if (!(rdev->wiphy.features & - NL80211_FEATURE_DYNAMIC_SMPS)) - return -EINVAL; + NL80211_FEATURE_DYNAMIC_SMPS)) { + err = -EINVAL; + goto out; + } break; default: - return -EINVAL; + err = -EINVAL; + goto out; } } else { params.smps_mode = NL80211_SMPS_OFF; } params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]); - if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) - return -EOPNOTSUPP; + if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) { + err = -EOPNOTSUPP; + goto out; + } if (info->attrs[NL80211_ATTR_ACL_POLICY]) { params.acl = parse_acl_data(&rdev->wiphy, info); - if (IS_ERR(params.acl)) - return PTR_ERR(params.acl); + if (IS_ERR(params.acl)) { + err = PTR_ERR(params.acl); + goto out; + } } params.twt_responder = @@ -5397,7 +5523,15 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], ¶ms); if (err) - return err; + goto out; + } + + if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG]) { + err = nl80211_parse_multiple_bssid_config(&rdev->wiphy, + info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG], + ¶ms); + if (err) + goto out; } nl80211_calculate_ap_params(¶ms); @@ -5421,7 +5555,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) out: kfree(params.acl); - + kfree(params.beacon.multiple_bssid); return err; } @@ -5445,12 +5579,14 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) err = nl80211_parse_beacon(rdev, info->attrs, ¶ms); if (err) - return err; + goto out; wdev_lock(wdev); err = rdev_change_beacon(rdev, dev, ¶ms); wdev_unlock(wdev); +out: + kfree(params.multiple_bssid); return err; } @@ -9122,24 +9258,30 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) info->attrs[NL80211_ATTR_CSA_IES], nl80211_policy, info->extack); if (err) - return err; + goto out; err = nl80211_parse_beacon(rdev, csa_attrs, ¶ms.beacon_csa); if (err) - return err; + goto out; - if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) - return -EINVAL; + if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) { + err = -EINVAL; + goto out; + } len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]); - if (!len || (len % sizeof(u16))) - return -EINVAL; + if (!len || (len % sizeof(u16))) { + err = -EINVAL; + goto out; + } params.n_counter_offsets_beacon = len / sizeof(u16); if (rdev->wiphy.max_num_csa_counters && (params.n_counter_offsets_beacon > - rdev->wiphy.max_num_csa_counters)) - return -EINVAL; + rdev->wiphy.max_num_csa_counters)) { + err = -EINVAL; + goto out; + } params.counter_offsets_beacon = nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]); @@ -9148,23 +9290,31 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) for (i = 0; i < params.n_counter_offsets_beacon; i++) { u16 offset = params.counter_offsets_beacon[i]; - if (offset >= params.beacon_csa.tail_len) - return -EINVAL; + if (offset >= params.beacon_csa.tail_len) { + err = -EINVAL; + goto out; + } - if (params.beacon_csa.tail[offset] != params.count) - return -EINVAL; + if (params.beacon_csa.tail[offset] != params.count) { + err = -EINVAL; + goto out; + } } if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) { len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]); - if (!len || (len % sizeof(u16))) - return -EINVAL; + if (!len || (len % sizeof(u16))) { + err = -EINVAL; + goto out; + } params.n_counter_offsets_presp = len / sizeof(u16); if (rdev->wiphy.max_num_csa_counters && (params.n_counter_offsets_presp > - rdev->wiphy.max_num_csa_counters)) - return -EINVAL; + rdev->wiphy.max_num_csa_counters)) { + err = -EINVAL; + goto out; + } params.counter_offsets_presp = nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]); @@ -9173,35 +9323,42 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) for (i = 0; i < params.n_counter_offsets_presp; i++) { u16 offset = params.counter_offsets_presp[i]; - if (offset >= params.beacon_csa.probe_resp_len) - return -EINVAL; + if (offset >= params.beacon_csa.probe_resp_len) { + err = -EINVAL; + goto out; + } if (params.beacon_csa.probe_resp[offset] != - params.count) - return -EINVAL; + params.count) { + err = -EINVAL; + goto out; + } } } skip_beacons: err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); if (err) - return err; + goto out; if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, - wdev->iftype)) - return -EINVAL; + wdev->iftype)) { + err = -EINVAL; + goto out; + } err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef, wdev->iftype); if (err < 0) - return err; + goto out; if (err > 0) { params.radar_required = true; if (need_handle_dfs_flag && !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) { - return -EINVAL; + err = -EINVAL; + goto out; } } @@ -9212,6 +9369,9 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) err = rdev_channel_switch(rdev, dev, ¶ms); wdev_unlock(wdev); +out: + kfree(params.beacon_after.multiple_bssid); + kfree(params.beacon_csa.multiple_bssid); return err; } From patchwork Wed Jan 20 00:51:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aloka Dixit X-Patchwork-Id: 12031165 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 683FDC433DB for ; Wed, 20 Jan 2021 00:52:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 314D323109 for ; Wed, 20 Jan 2021 00:52:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730549AbhATAwY (ORCPT ); Tue, 19 Jan 2021 19:52:24 -0500 Received: from a1.mail.mailgun.net ([198.61.254.60]:24307 "EHLO a1.mail.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729187AbhATAwT (ORCPT ); Tue, 19 Jan 2021 19:52:19 -0500 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1611103917; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=IUSyWs5xsvnPxyr6q82u3Ob0sJrVbOUcpr9pYWFtEFg=; b=WFvHLc9HtOOIt7E8Yxeecr5/OyDHDSbuayaAZbLcQGkkkn5QN+AVU30xfs890eyRh5yJCp9o g6RcBO/aQK8AdW3Lj/R/tTOqdFos+FtwbtZIYPa+3Klky7lqzvbBZwixeR5gmVrfV26qnawx 0CskH6eC6ISjP/ve/n/zUxqxAgk= X-Mailgun-Sending-Ip: 198.61.254.60 X-Mailgun-Sid: WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n04.prod.us-west-2.postgun.com with SMTP id 60077e93bf6467edfbc0d8fc (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Wed, 20 Jan 2021 00:51:31 GMT Sender: alokad=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id E1CF1C43461; Wed, 20 Jan 2021 00:51:30 +0000 (UTC) Received: from alokad-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: alokad) by smtp.codeaurora.org (Postfix) with ESMTPSA id 9EC3FC433CA; Wed, 20 Jan 2021 00:51:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 9EC3FC433CA Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=alokad@codeaurora.org From: Aloka Dixit To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, John Crispin , Aloka Dixit Subject: [PATCH V7 2/4] mac80211: add multiple bssid support to interface handling Date: Tue, 19 Jan 2021 16:51:18 -0800 Message-Id: <20210120005120.32424-3-alokad@codeaurora.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20210120005120.32424-1-alokad@codeaurora.org> References: <20210120005120.32424-1-alokad@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: John Crispin Add a new helper ieee80211_set_multiple_bssid_options() takes propagating the cfg80211 data down the stack. The patch also makes sure that all members of the bss set will get closed when either of them is shutdown. Signed-off-by: John Crispin Signed-off-by: Aloka Dixit --- v7: No changes from v6. v6: No changes from v5. include/net/mac80211.h | 30 +++++++++++++++++++++++- net/mac80211/cfg.c | 53 ++++++++++++++++++++++++++++++++++++++++++ net/mac80211/debugfs.c | 1 + net/mac80211/iface.c | 6 +++++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d315740581f1..861156d7dfc3 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -631,6 +631,7 @@ struct ieee80211_fils_discovery { * @s1g: BSS is S1G BSS (affects Association Request format). * @beacon_tx_rate: The configured beacon transmit rate that needs to be passed * to driver when rate control is offloaded to firmware. + * @multiple_bssid: the multiple bssid settings of the AP. */ struct ieee80211_bss_conf { const u8 *bssid; @@ -700,6 +701,7 @@ struct ieee80211_bss_conf { u32 unsol_bcast_probe_resp_interval; bool s1g; struct cfg80211_bitrate_mask beacon_tx_rate; + struct cfg80211_multiple_bssid multiple_bssid; }; /** @@ -1656,6 +1658,19 @@ enum ieee80211_offload_flags { IEEE80211_OFFLOAD_ENCAP_4ADDR = BIT(1), }; +/** + * enum ieee80211_vif_multiple_bssid_flags - virtual interface multiple bssid flags + * + * @IEEE80211_VIF_MBSS_TRANSMITTING: this BSS is transmitting beacons + * @IEEE80211_VIF_MBSS_NON_TRANSMITTING: this BSS is not transmitting beacons + * @IEEE80211_VIF_MBSS_EMA_BEACON: beacons should be send out in EMA mode + */ +enum ieee80211_vif_multiple_bssid_flags { + IEEE80211_VIF_MBSS_TRANSMITTING = BIT(1), + IEEE80211_VIF_MBSS_NON_TRANSMITTING = BIT(2), + IEEE80211_VIF_MBSS_EMA_BEACON = BIT(3), +}; + /** * struct ieee80211_vif - per-interface data * @@ -1702,6 +1717,11 @@ enum ieee80211_offload_flags { * protected by fq->lock. * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see * &enum ieee80211_offload_flags. + * + * @multiple_bssid: Multiple BSSID configurations. + * @multiple_bssid.parent: Interface index of the transmitted BSS. + * @multiple_bssid.flags: multiple bssid flags, see + * enum ieee80211_vif_multiple_bssid_flags. */ struct ieee80211_vif { enum nl80211_iftype type; @@ -1730,6 +1750,11 @@ struct ieee80211_vif { bool txqs_stopped[IEEE80211_NUM_ACS]; + struct { + struct ieee80211_vif *parent; + u32 flags; + } multiple_bssid; + /* must be last */ u8 drv_priv[] __aligned(sizeof(void *)); }; @@ -2377,7 +2402,7 @@ struct ieee80211_txq { * @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU * length in tx status information * - * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID + * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID in STA mode * * @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID * only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set. @@ -2389,6 +2414,8 @@ struct ieee80211_txq { * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation * offload * + * @IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP: Hardware supports multi BSSID in AP mode + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2442,6 +2469,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID, IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT, IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, + IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c4c70e30ad7f..91e659a43f67 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -111,6 +111,39 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, return 0; } +static void ieee80211_set_multiple_bssid_options(struct ieee80211_sub_if_data *sdata, + struct cfg80211_ap_settings *params) +{ + struct ieee80211_local *local = sdata->local; + struct wiphy *wiphy = local->hw.wiphy; + struct net_device *parent; + struct ieee80211_sub_if_data *psdata; + + if (!ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID_AP)) + return; + + if (!params->multiple_bssid.count) + return; + + if (params->multiple_bssid.parent) { + parent = __dev_get_by_index(wiphy_net(wiphy), + params->multiple_bssid.parent); + if (!parent || !parent->ieee80211_ptr) + return; + psdata = IEEE80211_WDEV_TO_SUB_IF(parent->ieee80211_ptr); + if (psdata->vif.multiple_bssid.parent) + return; + sdata->vif.multiple_bssid.parent = &psdata->vif; + sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_NON_TRANSMITTING; + } else { + sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_TRANSMITTING; + } + + if (params->multiple_bssid.ema) + sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_EMA_BEACON; + sdata->vif.bss_conf.multiple_bssid = params->multiple_bssid; +} + static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, const char *name, unsigned char name_assign_type, @@ -141,6 +174,23 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) { + struct ieee80211_sub_if_data *sdata; + + sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); + if (sdata && sdata->vif.type == NL80211_IFTYPE_AP) { + if (sdata->vif.multiple_bssid.flags & IEEE80211_VIF_MBSS_TRANSMITTING) { + struct ieee80211_sub_if_data *child; + + rcu_read_lock(); + list_for_each_entry_rcu(child, &sdata->local->interfaces, list) + if (child->vif.multiple_bssid.parent == &sdata->vif) + dev_close(child->wdev.netdev); + rcu_read_unlock(); + } else { + sdata->vif.multiple_bssid.parent = NULL; + } + } + ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev)); return 0; @@ -1078,6 +1128,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, changed |= BSS_CHANGED_HE_BSS_COLOR; } + if (sdata->vif.type == NL80211_IFTYPE_AP) + ieee80211_set_multiple_bssid_options(sdata, params); + mutex_lock(&local->mtx); err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, IEEE80211_CHANCTX_SHARED); diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 48f144f107d5..f611a8caaf91 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -409,6 +409,7 @@ static const char *hw_flag_names[] = { FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID), FLAG(AMPDU_KEYBORDER_SUPPORT), FLAG(SUPPORTS_TX_ENCAP_OFFLOAD), + FLAG(SUPPORTS_MULTI_BSSID_AP), #undef FLAG }; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3b9ec4ef81c3..1879605f4434 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -373,6 +373,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool cancel_scan; struct cfg80211_nan_func *func; + /* make sure the parent is already down */ + if (sdata->vif.type == NL80211_IFTYPE_AP && + sdata->vif.multiple_bssid.parent && + ieee80211_sdata_running(vif_to_sdata(sdata->vif.multiple_bssid.parent))) + dev_close(vif_to_sdata(sdata->vif.multiple_bssid.parent)->wdev.netdev); + clear_bit(SDATA_STATE_RUNNING, &sdata->state); cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; From patchwork Wed Jan 20 00:51:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aloka Dixit X-Patchwork-Id: 12031167 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51741C433E0 for ; Wed, 20 Jan 2021 00:52:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0ACC123108 for ; Wed, 20 Jan 2021 00:52:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731000AbhATAw0 (ORCPT ); Tue, 19 Jan 2021 19:52:26 -0500 Received: from a1.mail.mailgun.net ([198.61.254.60]:26277 "EHLO a1.mail.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729436AbhATAwU (ORCPT ); Tue, 19 Jan 2021 19:52:20 -0500 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1611103921; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=wyBSV08qrPEkG/aQhxPiqiNKf/MtLPk/A84900aw4K0=; b=AXb97RVtv4dM8NDV3KIJa2S1CAThUF5qhoxJUKeR3Wr5+3E9llZVIOr2OXyGAGfscx5CXN/6 WUgho7rTOMYtdeGgLmiuek41B4uEX0zh3lqqWINtvdXHS+k1xRkb4T2dzRNaEsyGc8EW+fGY PQClqwYe51wWRe4q0/rStYMSotM= X-Mailgun-Sending-Ip: 198.61.254.60 X-Mailgun-Sid: WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n04.prod.us-east-1.postgun.com with SMTP id 60077e95e23dedcc3a94181b (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Wed, 20 Jan 2021 00:51:33 GMT Sender: alokad=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 2AB72C43463; Wed, 20 Jan 2021 00:51:32 +0000 (UTC) Received: from alokad-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: alokad) by smtp.codeaurora.org (Postfix) with ESMTPSA id 8DBC3C43462; Wed, 20 Jan 2021 00:51:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 8DBC3C43462 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=alokad@codeaurora.org From: Aloka Dixit To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, John Crispin , Aloka Dixit Subject: [PATCH V7 3/4] mac80211: add multiple bssid/EMA support to beacon handling Date: Tue, 19 Jan 2021 16:51:19 -0800 Message-Id: <20210120005120.32424-4-alokad@codeaurora.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20210120005120.32424-1-alokad@codeaurora.org> References: <20210120005120.32424-1-alokad@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: John Crispin With beacon_data now holding the additional information about the multiple bssid elements, we need to honour these in the various beacon handling code paths. Extend ieee80211_beacon_get_template() to allow generation of multiple bssid/EMA beacons. The API provides support for HW that can offload the EMA beaconing aswell as HW that will require periodic updates of the beacon template upon completion events. In case the HW can do full EMA offload, functions are provided that allow the driver to get a list of the periodicity number of beacons and their matching mutable offsets. Signed-off-by: John Crispin Signed-off-by: Aloka Dixit --- v7: No change v6: Addressed review comments. Dynamic memory allocation of MBSSID element structures in beacons. Added MBSSID config element length in beacon length calculation. include/net/mac80211.h | 86 +++++++++++++++++ net/mac80211/cfg.c | 117 ++++++++++++++++++++--- net/mac80211/ieee80211_i.h | 2 + net/mac80211/tx.c | 189 ++++++++++++++++++++++++++++++++----- 4 files changed, 362 insertions(+), 32 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 861156d7dfc3..6336b6a5a1be 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -4872,12 +4872,17 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); * @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets * to countdown counters. This array can contain zero values which * should be ignored. + * @multiple_bssid_offset: position of the multiple bssid element + * @multiple_bssid_length: size of the multiple bssid element */ struct ieee80211_mutable_offsets { u16 tim_offset; u16 tim_length; u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; + + u16 multiple_bssid_offset; + u16 multiple_bssid_length; }; /** @@ -4904,6 +4909,87 @@ ieee80211_beacon_get_template(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_mutable_offsets *offs); +/** + * enum ieee80211_bcn_tmpl_ema - EMA beacon generation type + * @IEEE80211_BCN_EMA_NONE: don't generate an EMA beacon. + * @IEEE80211_BCN_EMA_NEXT: generate the next periodicity beacon. + * @IEEE80211_BCN_EMA_INDEX: generate beacon by periodicity index + * if the value is >= this enum value. + */ +enum ieee80211_bcn_tmpl_ema { + IEEE80211_BCN_EMA_NONE = -2, + IEEE80211_BCN_EMA_NEXT = -1, + IEEE80211_BCN_EMA_INDEX = 0, +}; + +/** + * ieee80211_beacon_get_template_ema_next - EMA beacon template generation + * function for drivers using the sw offload path. + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @offs: &struct ieee80211_mutable_offsets pointer to struct that will + * receive the offsets that may be updated by the driver. + * + * This function differs from ieee80211_beacon_get_template in the sense that + * it generates EMA VAP templates. When we use multiple_bssid, the beacons can + * get very large costing a lot of airtime. To work around this, we iterate + * over the multiple bssid elements and only send one inside the beacon for + * 1..n. Calling this function will auto-increment the periodicity counter. + * + * This function needs to follow the same rules as ieee80211_beacon_get_template + * + * Return: The beacon template. %NULL on error. + */ +struct sk_buff *ieee80211_beacon_get_template_ema_next(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_mutable_offsets *offs); + +/** + * struct ieee80211_ema_bcn_list - list entry of an EMA beacon + * @list: the list pointer. + * @skb: the skb containing this specific beacon + * @offs: &struct ieee80211_mutable_offsets pointer to struct that will + * receive the offsets that may be updated by the driver. + */ +struct ieee80211_ema_bcn_list { + struct list_head list; + struct sk_buff *skb; + struct ieee80211_mutable_offsets offs; +}; + +/** + * ieee80211_beacon_get_template_ema_list - EMA beacon template generation + * function for drivers using the hw offload. + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @head: linked list head that will get populated with + * &struct ieee80211_ema_bcn_list pointers. + * + * This function differs from ieee80211_beacon_get_template in the sense that + * it generates EMA VAP templates. When we use multiple_bssid, the beacons can + * get very large costing a lot of airtime. To work around this, we iterate + * over the multiple bssid elements and only send one inside the beacon for + * 1..n. This function will populate a linked list that the driver can pass + * to the HW. + * + * This function needs to follow the same rules as ieee80211_beacon_get_template + * + * Return: The nuber of entries in the list or 0 on error. + */ + +int ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct list_head *head); + +/** + * ieee80211_beacon_free_ema_list - free an EMA beacon template list + * @head: linked list head containing &struct ieee80211_ema_bcn_list pointers. + * + * This function will free a list previously acquired by calling + * ieee80211_beacon_get_template_ema_list() + */ +void ieee80211_beacon_free_ema_list(struct list_head *head); + /** * ieee80211_beacon_get_tim - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 91e659a43f67..9c4346f69a7b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -984,12 +984,48 @@ static int ieee80211_set_ftm_responder_params( return 0; } + static int +ieee80211_get_multiple_bssid_beacon_len(struct cfg80211_multiple_bssid_data *data) +{ + int i, len = 0; + + if (!data) + return 0; + + for (i = 0; i < data->cnt; i++) + len += data->elems[i].len; + + return len; +} + +static u8 *ieee80211_copy_multiple_bssid_beacon(u8 *offset, + struct cfg80211_multiple_bssid_data *dest, + struct cfg80211_multiple_bssid_data *src) +{ + int i; + + if (!dest || !src) + return offset; + + dest->cnt = src->cnt; + for (i = 0; i < dest->cnt; i++) { + dest->elems[i].len = src->elems[i].len; + dest->elems[i].data = offset; + memcpy(dest->elems[i].data, src->elems[i].data, + dest->elems[i].len); + offset += dest->elems[i].len; + } + + return offset; +} + static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, struct cfg80211_beacon_data *params, const struct ieee80211_csa_settings *csa) { struct beacon_data *new, *old; - int new_head_len, new_tail_len; + int new_head_len, new_tail_len, new_multiple_bssid_len = 0; + u8 *new_multiple_bssid_offset; int size, err; u32 changed = BSS_CHANGED_BEACON; @@ -1013,12 +1049,30 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, else new_tail_len = old->tail_len; - size = sizeof(*new) + new_head_len + new_tail_len; + /* new or old multiple_bssid? */ + if (params->multiple_bssid) + new_multiple_bssid_len = + ieee80211_get_multiple_bssid_beacon_len(params->multiple_bssid); + else if (old && old->multiple_bssid) + new_multiple_bssid_len = + ieee80211_get_multiple_bssid_beacon_len(old->multiple_bssid); + + size = sizeof(*new) + new_head_len + new_tail_len + + new_multiple_bssid_len; new = kzalloc(size, GFP_KERNEL); if (!new) return -ENOMEM; + if (new_multiple_bssid_len) { + new->multiple_bssid = kzalloc(sizeof(*params->multiple_bssid), + GFP_KERNEL); + if (!new->multiple_bssid) { + kfree(new); + return -ENOMEM; + } + } + /* start filling the new info now */ /* @@ -1030,6 +1084,17 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, new->head_len = new_head_len; new->tail_len = new_tail_len; + /* copy in optional multiple_bssid_ies */ + new_multiple_bssid_offset = new->tail + new_tail_len; + if (params->multiple_bssid) + ieee80211_copy_multiple_bssid_beacon(new_multiple_bssid_offset, + new->multiple_bssid, + params->multiple_bssid); + else if (old && old->multiple_bssid) + ieee80211_copy_multiple_bssid_beacon(new_multiple_bssid_offset, + new->multiple_bssid, + old->multiple_bssid); + if (csa) { new->cntdwn_current_counter = csa->count; memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon, @@ -1053,6 +1118,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, err = ieee80211_set_probe_resp(sdata, params->probe_resp, params->probe_resp_len, csa); if (err < 0) { + kfree(new->multiple_bssid); kfree(new); return err; } @@ -1068,6 +1134,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, params->civicloc_len); if (err < 0) { + kfree(new->multiple_bssid); kfree(new); return err; } @@ -1077,9 +1144,10 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, rcu_assign_pointer(sdata->u.ap.beacon, new); - if (old) + if (old) { + kfree(old->multiple_bssid); kfree_rcu(old, rcu_head); - + } return changed; } @@ -1234,8 +1302,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, if (err) { old = sdata_dereference(sdata->u.ap.beacon, sdata); - if (old) + if (old) { + kfree(old->multiple_bssid); kfree_rcu(old, rcu_head); + } RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); goto error; } @@ -1315,8 +1385,11 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) mutex_unlock(&local->mtx); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; + if (sdata->u.ap.next_beacon) { + kfree(sdata->u.ap.next_beacon->multiple_bssid); + kfree(sdata->u.ap.next_beacon); + sdata->u.ap.next_beacon = NULL; + } /* turn off carrier for this interface and dependent VLANs */ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) @@ -1328,6 +1401,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); RCU_INIT_POINTER(sdata->u.ap.fils_discovery, NULL); RCU_INIT_POINTER(sdata->u.ap.unsol_bcast_probe_resp, NULL); + kfree(old_beacon->multiple_bssid); kfree_rcu(old_beacon, rcu_head); if (old_probe_resp) kfree_rcu(old_probe_resp, rcu_head); @@ -3084,13 +3158,24 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + beacon->proberesp_ies_len + beacon->assocresp_ies_len + - beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len; + beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + + ieee80211_get_multiple_bssid_beacon_len(beacon->multiple_bssid); new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); if (!new_beacon) return NULL; + if (beacon->multiple_bssid) { + new_beacon->multiple_bssid = kzalloc(sizeof(*beacon->multiple_bssid), + GFP_KERNEL); + if (!new_beacon->multiple_bssid) { + kfree(new_beacon); + return NULL; + } + } + pos = (u8 *)(new_beacon + 1); + if (beacon->head_len) { new_beacon->head_len = beacon->head_len; new_beacon->head = pos; @@ -3127,6 +3212,10 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); pos += beacon->probe_resp_len; } + if (beacon->multiple_bssid && beacon->multiple_bssid->cnt) + pos = ieee80211_copy_multiple_bssid_beacon(pos, + new_beacon->multiple_bssid, + beacon->multiple_bssid); /* might copy -1, meaning no changes requested */ new_beacon->ftm_responder = beacon->ftm_responder; @@ -3164,8 +3253,11 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_AP: err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, NULL); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; + if (sdata->u.ap.next_beacon) { + kfree(sdata->u.ap.next_beacon->multiple_bssid); + kfree(sdata->u.ap.next_beacon); + sdata->u.ap.next_beacon = NULL; + } if (err < 0) return err; @@ -3331,7 +3423,10 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa); if (err < 0) { - kfree(sdata->u.ap.next_beacon); + if (sdata->u.ap.next_beacon) { + kfree(sdata->u.ap.next_beacon->multiple_bssid); + kfree(sdata->u.ap.next_beacon); + } return err; } *changed |= err; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8bf9c0e974d6..beb8e2ea612b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -261,6 +261,8 @@ struct beacon_data { struct ieee80211_meshconf_ie *meshconf; u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; u8 cntdwn_current_counter; + struct cfg80211_multiple_bssid_data *multiple_bssid; + u16 ema_index; struct rcu_head rcu_head; }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6422da6690f7..c28eb17186d0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -4721,11 +4721,71 @@ static int ieee80211_beacon_protect(struct sk_buff *skb, return 0; } +static int ieee80211_beacon_multiple_bssid_len(struct beacon_data *beacon, + int index) +{ + int len = 0, i; + + if (index == IEEE80211_BCN_EMA_NEXT) { + index = beacon->ema_index; + beacon->ema_index++; + beacon->ema_index %= beacon->multiple_bssid->cnt; + } + + if (index != IEEE80211_BCN_EMA_NONE && + index >= beacon->multiple_bssid->cnt) + return -1; + + if (beacon->multiple_bssid->cnt) { + if (index >= IEEE80211_BCN_EMA_INDEX) { + len = beacon->multiple_bssid->elems[index].len; + } else { + for (i = 0; i < beacon->multiple_bssid->cnt; i++) + len += beacon->multiple_bssid->elems[i].len; + } + } + return len; +} + +static void +ieee80211_beacon_add_multiple_bssid_config(struct ieee80211_vif *vif, + struct sk_buff *skb, + struct cfg80211_multiple_bssid_data *config) +{ + u8 *pos = skb_put(skb, 5); + + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 3; + *pos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION; + *pos++ = vif->bss_conf.multiple_bssid.count; + *pos++ = config->cnt; +} + +static void +ieee80211_beacon_add_multiple_bssid(struct ieee80211_vif *vif, + struct sk_buff *skb, + struct cfg80211_multiple_bssid_data *config, + int index) +{ + if (index >= IEEE80211_BCN_EMA_INDEX) { + ieee80211_beacon_add_multiple_bssid_config(vif, skb, config); + skb_put_data(skb, config->elems[index].data, + config->elems[index].len); + } else { + int i; + + for (i = 0; i < config->cnt; i++) + skb_put_data(skb, config->elems[i].data, + config->elems[i].len); + } +} + static struct sk_buff * __ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_mutable_offsets *offs, - bool is_template) + bool is_template, + int ema_index) { struct ieee80211_local *local = hw_to_local(hw); struct beacon_data *beacon = NULL; @@ -4737,13 +4797,11 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *chanctx_conf; int csa_off_base = 0; - rcu_read_lock(); - sdata = vif_to_sdata(vif); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!ieee80211_sdata_running(sdata) || !chanctx_conf) - goto out; + return NULL; if (offs) memset(offs, 0, sizeof(*offs)); @@ -4753,6 +4811,9 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, beacon = rcu_dereference(ap->beacon); if (beacon) { + int multiple_bssid_elems_len = 0; + int multiple_bssid_config_len = 5; + if (beacon->cntdwn_counter_offsets[0]) { if (!is_template) ieee80211_beacon_update_cntdwn(vif); @@ -4760,6 +4821,14 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, ieee80211_set_beacon_cntdwn(sdata, beacon); } + if (beacon->multiple_bssid) { + multiple_bssid_elems_len = + ieee80211_beacon_multiple_bssid_len(beacon, + ema_index); + if (multiple_bssid_elems_len == -1) + return NULL; + } + /* * headroom, head length, * tail length and maximum TIM length @@ -4767,9 +4836,11 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + beacon->tail_len + 256 + - local->hw.extra_beacon_tailroom); + local->hw.extra_beacon_tailroom + + multiple_bssid_config_len + + multiple_bssid_elems_len); if (!skb) - goto out; + return NULL; skb_reserve(skb, local->tx_headroom); skb_put_data(skb, beacon->head, beacon->head_len); @@ -4785,21 +4856,32 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, csa_off_base = skb->len; } + if (multiple_bssid_elems_len) { + ieee80211_beacon_add_multiple_bssid(vif, skb, + beacon->multiple_bssid, + ema_index); + if (offs) { + offs->multiple_bssid_offset = skb->len - + multiple_bssid_elems_len; + csa_off_base = skb->len; + } + } + if (beacon->tail) skb_put_data(skb, beacon->tail, beacon->tail_len); if (ieee80211_beacon_protect(skb, local, sdata) < 0) - goto out; + return NULL; } else - goto out; + return NULL; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_hdr *hdr; beacon = rcu_dereference(ifibss->presp); if (!beacon) - goto out; + return NULL; if (beacon->cntdwn_counter_offsets[0]) { if (!is_template) @@ -4811,7 +4893,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + local->hw.extra_beacon_tailroom); if (!skb) - goto out; + return NULL; skb_reserve(skb, local->tx_headroom); skb_put_data(skb, beacon->head, beacon->head_len); @@ -4823,7 +4905,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, beacon = rcu_dereference(ifmsh->beacon); if (!beacon) - goto out; + return NULL; if (beacon->cntdwn_counter_offsets[0]) { if (!is_template) @@ -4846,7 +4928,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, beacon->tail_len + local->hw.extra_beacon_tailroom); if (!skb) - goto out; + return NULL; skb_reserve(skb, local->tx_headroom); skb_put_data(skb, beacon->head, beacon->head_len); ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template); @@ -4859,7 +4941,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, skb_put_data(skb, beacon->tail, beacon->tail_len); } else { WARN_ON(1); - goto out; + return NULL; } /* CSA offsets */ @@ -4902,27 +4984,92 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_ASSIGN_SEQ | IEEE80211_TX_CTL_FIRST_FRAGMENT; - out: - rcu_read_unlock(); return skb; } -struct sk_buff * -ieee80211_beacon_get_template(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_mutable_offsets *offs) +struct sk_buff *ieee80211_beacon_get_template(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_mutable_offsets *offs) { - return __ieee80211_beacon_get(hw, vif, offs, true); + struct sk_buff *bcn; + + rcu_read_lock(); + bcn = __ieee80211_beacon_get(hw, vif, offs, true, + IEEE80211_BCN_EMA_NONE); + rcu_read_unlock(); + + return bcn; } EXPORT_SYMBOL(ieee80211_beacon_get_template); +struct sk_buff *ieee80211_beacon_get_template_ema_next(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_mutable_offsets *offs) +{ + struct sk_buff *bcn; + + rcu_read_lock(); + bcn = __ieee80211_beacon_get(hw, vif, offs, true, + IEEE80211_BCN_EMA_NEXT); + rcu_read_unlock(); + + return bcn; +} +EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_next); + +void ieee80211_beacon_free_ema_list(struct list_head *head) +{ + struct ieee80211_ema_bcn_list *ema, *tmp; + + list_for_each_entry_safe(ema, tmp, head, list) { + kfree_skb(ema->skb); + kfree(ema); + } +} +EXPORT_SYMBOL(ieee80211_beacon_free_ema_list); + +int +ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct list_head *head) +{ + int cnt = 0; + + rcu_read_lock(); + while (true) { + struct ieee80211_ema_bcn_list *ema; + + ema = kmalloc(sizeof(*ema), GFP_KERNEL); + if (!ema) { + ieee80211_beacon_free_ema_list(head); + cnt = 0; + goto out; + } + + ema->skb = __ieee80211_beacon_get(hw, vif, &ema->offs, true, + cnt); + if (!ema->skb) { + kfree(ema); + break; + } + list_add_tail(&ema->list, head); + cnt++; + } +out: + rcu_read_unlock(); + + return cnt; +} +EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_list); + struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 *tim_offset, u16 *tim_length) { struct ieee80211_mutable_offsets offs = {}; - struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); + struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false, + IEEE80211_BCN_EMA_NONE); struct sk_buff *copy; struct ieee80211_supported_band *sband; int shift; From patchwork Wed Jan 20 00:51:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aloka Dixit X-Patchwork-Id: 12031163 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B583C433E6 for ; Wed, 20 Jan 2021 00:52:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E99BE23108 for ; Wed, 20 Jan 2021 00:52:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730664AbhATAwW (ORCPT ); Tue, 19 Jan 2021 19:52:22 -0500 Received: from a1.mail.mailgun.net ([198.61.254.60]:16929 "EHLO a1.mail.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730049AbhATAwT (ORCPT ); Tue, 19 Jan 2021 19:52:19 -0500 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1611103922; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=+QtXM30ufSSYv8f4Vzm5/FMSCikvlZtThoLdjudzQxo=; b=N4/cwbKQV7ctXVlXfU4RiUYhxxh0pfoDa+iqt2apAmc8iMPixRFcnhWGzCrWGHYpxY/Qnsbl XvnD77kZXfvSQNjTHR24c3TDZQ2+tvAKJbENbrEZiyZ6fn6bkb4r0nh43+lPdcowwNWBiJsO OmwUTZrEsEVK6am4xq/LKDCQ3eA= X-Mailgun-Sending-Ip: 198.61.254.60 X-Mailgun-Sid: WyI3YTAwOSIsICJsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmciLCAiYmU5ZTRhIl0= Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n06.prod.us-west-2.postgun.com with SMTP id 60077e94f94f20d8b7920abf (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Wed, 20 Jan 2021 00:51:32 GMT Sender: alokad=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 94BE3C43464; Wed, 20 Jan 2021 00:51:32 +0000 (UTC) Received: from alokad-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: alokad) by smtp.codeaurora.org (Postfix) with ESMTPSA id B5A2CC433C6; Wed, 20 Jan 2021 00:51:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org B5A2CC433C6 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=alokad@codeaurora.org From: Aloka Dixit To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, John Crispin , Aloka Dixit Subject: [PATCH V7 4/4] mac80211: CSA on non-transmitting interfaces Date: Tue, 19 Jan 2021 16:51:20 -0800 Message-Id: <20210120005120.32424-5-alokad@codeaurora.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20210120005120.32424-1-alokad@codeaurora.org> References: <20210120005120.32424-1-alokad@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: John Crispin Trigger ieee80211_csa_finish() on the non-transmitting interfaces when CSA concludes on the tranmitting interface. Modify offset in beacon generation to reflect multiple BSSID element length. Signed-off-by: John Crispin Signed-off-by: Aloka Dixit --- v7: No change v6: CSA is triggered on all interface, not only transmitting. net/mac80211/cfg.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9c4346f69a7b..11a22a3b9cab 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3239,6 +3239,17 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + if (sdata->vif.multiple_bssid.flags & IEEE80211_VIF_MBSS_TRANSMITTING) { + struct ieee80211_sub_if_data *child; + + rcu_read_lock(); + list_for_each_entry_rcu(child, &sdata->local->interfaces, list) + if (child->vif.multiple_bssid.parent == &sdata->vif) + ieee80211_queue_work(&child->local->hw, + &child->csa_finalize_work); + rcu_read_unlock(); + } + ieee80211_queue_work(&sdata->local->hw, &sdata->csa_finalize_work); }