From patchwork Thu Mar 2 16:03:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaewan Kim X-Patchwork-Id: 13157487 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 952F4C678D4 for ; Thu, 2 Mar 2023 16:03:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229673AbjCBQD0 (ORCPT ); Thu, 2 Mar 2023 11:03:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229523AbjCBQDX (ORCPT ); Thu, 2 Mar 2023 11:03:23 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5316A1BAF8 for ; Thu, 2 Mar 2023 08:03:22 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id e195-20020a25e7cc000000b00a1e59ba7ed9so4443621ybh.11 for ; Thu, 02 Mar 2023 08:03:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1677773001; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=k/LTS9GHPDZVgOXQLP5/udKsw1QQ6zaIho2Q5luUrIY=; b=VpC+R/I6Gj9gt/uc8N7p5rD42PqzDlyNPdgF+Bgrq06+8eOVVgoCynWAadoKwQSnlx xVZq72P/ZHPMIU3KbqJgZTLgnvoL6w6nYbV4fJyWxwQ/8XqTwfcxvPk5U8+hmUn3g3TX lO33IaNynflrUiXPp0he958BvUiPdaOgSnIx1HFusT404/oNLbJktQNejdZOL5xP0Sdq EDqgR0z1it+Q9p48jb2NXeg4KCM2mlIHhHg+vl28LWrZH4YW3qeUvd3NJoyU8GDN5kzQ F67ss1EF4xNQKtioiJC6nkKmpggMke8Rrt5fTGw5DY4TqAeXdaRQh13UE3KdI1dEhpxe AKug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677773001; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=k/LTS9GHPDZVgOXQLP5/udKsw1QQ6zaIho2Q5luUrIY=; b=OZ4JHvxvX7qqrvjMvv92OxcL1d/NYxQda6JLL+w8HLsJrCdxqadXjQaqjL7d7zPf22 8kSfiip6Zgs82mpjhTuJ7mWLa1tSKXjWS9L42RUesH0qUIl4J5exI0qhHr8aUxfTLjzP rXK2zmh1V6bonqIUvGbeY7CjdStKEJwYPAj4JKzOOzIe4e+alDeBoTzOtqDcDNXvgnj8 r9bZfVMZ5NRpo5T0t1z6+yvQCOAxf5II13o0QbKGMrweOiKjtueVC8GuAtD7VD+cNSTl FnlkI/3RX6wDhbG8aik3PcsVips0QF6ounfg2jCRMWS1hWCjFlZhRL0wxjeu1yVVHZHJ UgxA== X-Gm-Message-State: AO0yUKVQe989LTtnnHjrFz/68Cj10pPjRcszqV1iKtNdCqyv/z5BvNAl enBk1IWdfR+Eq06W4e0cPtYAhK47puc= X-Google-Smtp-Source: AK7set/UQkF8zCt65lM1B4dednYOvc45lSprYpQ8egKS0RkUlc9r5aztKy+v8RVBOuA5uwDIv0i9rBefsf8= X-Received: from jaewan1.c.googlers.com ([fda3:e722:ac3:cc00:3:22c1:c0a8:e59]) (user=jaewan job=sendgmr) by 2002:a25:9b86:0:b0:a8a:a652:2a69 with SMTP id v6-20020a259b86000000b00a8aa6522a69mr4618013ybo.10.1677773001493; Thu, 02 Mar 2023 08:03:21 -0800 (PST) Date: Thu, 2 Mar 2023 16:03:06 +0000 In-Reply-To: <20230302160310.923349-1-jaewan@google.com> Mime-Version: 1.0 References: <20230302160310.923349-1-jaewan@google.com> X-Mailer: git-send-email 2.39.2.722.g9855ee24e9-goog Message-ID: <20230302160310.923349-2-jaewan@google.com> Subject: [PATCH v8 1/5] mac80211_hwsim: add PMSR capability support From: Jaewan Kim To: gregkh@linuxfoundation.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Cc: kernel-team@android.com, adelva@google.com, Jaewan Kim Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org PMSR (a.k.a. peer measurement) is generalized measurement between two Wi-Fi devices. And currently FTM (a.k.a. fine time measurement or flight time measurement) is the one and only measurement. FTM is measured by RTT (a.k.a. round trip time) of packets between two Wi-Fi devices. Add necessary functionality to allow mac80211_hwsim to be configured with PMSR capability. The capability is mandatory to accept incoming PMSR request because nl80211_pmsr_start() ignores incoming the request without the PMSR capability. In detail, add new mac80211_hwsim attribute HWSIM_ATTR_PMSR_SUPPORT. HWSIM_ATTR_PMSR_SUPPORT is used to set PMSR capability when creating a new radio. To send extra capability details, HWSIM_ATTR_PMSR_SUPPORT can have nested PMSR capability attributes defined in the nl80211.h. Data format is the same as cfg80211_pmsr_capabilities. If HWSIM_ATTR_PMSR_SUPPORT is specified, mac80211_hwsim builds cfg80211_pmsr_capabilities and sets wiphy.pmsr_capa. Signed-off-by: Jaewan Kim --- V7 -> V8: Stop sending pmsr_capa when adding new radio to limit exporting cfg80211 function to driver. V6 -> V7: Added terms definitions. Removed pr_*() uses. V5 -> V6: Added per change patch history. V4 -> V5: Fixed style for commit messages. V3 -> V4: Added change details for new attribute, and fixed memory leak. V1 -> V3: Initial commit (includes resends). --- drivers/net/wireless/mac80211_hwsim.c | 128 +++++++++++++++++++++++++- drivers/net/wireless/mac80211_hwsim.h | 3 + 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 4cc4eaf80b14..79476d55c1ca 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -719,6 +719,9 @@ struct mac80211_hwsim_data { /* RSSI in rx status of the receiver */ int rx_rssi; + /* only used when pmsr capability is supplied */ + struct cfg80211_pmsr_capabilities pmsr_capa; + struct mac80211_hwsim_link_data link_data[IEEE80211_MLD_MAX_NUM_LINKS]; }; @@ -760,6 +763,34 @@ static const struct genl_multicast_group hwsim_mcgrps[] = { /* MAC80211_HWSIM netlink policy */ +static const struct nla_policy +hwsim_ftm_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_CAPA_ATTR_ASAP] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT] = NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST] = NLA_POLICY_MAX(NLA_U8, 31), + [NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG }, +}; + +static const struct nla_policy +hwsim_pmsr_capa_type_policy[NL80211_PMSR_TYPE_MAX + 1] = { + [NL80211_PMSR_TYPE_FTM] = NLA_POLICY_NESTED(hwsim_ftm_capa_policy), +}; + +static const struct nla_policy +hwsim_pmsr_capa_policy[NL80211_PMSR_ATTR_MAX + 1] = { + [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_U32 }, + [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_FLAG }, + [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_FLAG }, + [NL80211_PMSR_ATTR_TYPE_CAPA] = NLA_POLICY_NESTED(hwsim_pmsr_capa_type_policy), + [NL80211_PMSR_ATTR_PEERS] = { .type = NLA_REJECT }, // only for request. +}; + static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { [HWSIM_ATTR_ADDR_RECEIVER] = NLA_POLICY_ETH_ADDR_COMPAT, [HWSIM_ATTR_ADDR_TRANSMITTER] = NLA_POLICY_ETH_ADDR_COMPAT, @@ -788,6 +819,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { [HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 }, [HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY }, [HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, + [HWSIM_ATTR_PMSR_SUPPORT] = NLA_POLICY_NESTED(hwsim_pmsr_capa_policy), }; #if IS_REACHABLE(CONFIG_VIRTIO) @@ -3186,6 +3218,7 @@ struct hwsim_new_radio_params { u32 *ciphers; u8 n_ciphers; bool mlo; + const struct cfg80211_pmsr_capabilities *pmsr_capa; }; static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, @@ -3260,7 +3293,7 @@ static int append_radio_msg(struct sk_buff *skb, int id, return ret; } - return 0; + return ret; } static void hwsim_mcast_new_radio(int id, struct genl_info *info, @@ -4445,6 +4478,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); hw->wiphy->interface_modes = param->iftypes; @@ -4606,6 +4640,11 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, data->debugfs, data, &hwsim_simulate_radar); + if (param->pmsr_capa) { + data->pmsr_capa = *param->pmsr_capa; + hw->wiphy->pmsr_capa = &data->pmsr_capa; + } + spin_lock_bh(&hwsim_radio_lock); err = rhashtable_insert_fast(&hwsim_radios_rht, &data->rht, hwsim_rht_params); @@ -4715,6 +4754,7 @@ static int mac80211_hwsim_get_radio(struct sk_buff *skb, param.regd = data->regd; param.channels = data->channels; param.hwname = wiphy_name(data->hw->wiphy); + param.pmsr_capa = &data->pmsr_capa; res = append_radio_msg(skb, data->idx, ¶m); if (res < 0) @@ -5053,6 +5093,76 @@ static bool hwsim_known_ciphers(const u32 *ciphers, int n_ciphers) return true; } +static int parse_ftm_capa(const struct nlattr *ftm_capa, struct cfg80211_pmsr_capabilities *out, + struct genl_info *info) +{ + struct nlattr *tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1]; + int ret = nla_parse_nested(tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX, + ftm_capa, hwsim_ftm_capa_policy, NULL); + + if (ret) { + NL_SET_ERR_MSG_ATTR(info->extack, ftm_capa, "malformed FTM capability"); + return -EINVAL; + } + + out->ftm.supported = 1; + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES]) + out->ftm.preambles = nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES]); + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS]) + out->ftm.bandwidths = nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS]); + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT]) + out->ftm.max_bursts_exponent = + nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT]); + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST]) + out->ftm.max_ftms_per_burst = + nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST]); + out->ftm.asap = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_ASAP]; + out->ftm.non_asap = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP]; + out->ftm.request_lci = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI]; + out->ftm.request_civicloc = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC]; + out->ftm.trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED]; + out->ftm.non_trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED]; + + return 0; +} + +static int parse_pmsr_capa(const struct nlattr *pmsr_capa, struct cfg80211_pmsr_capabilities *out, + struct genl_info *info) +{ + struct nlattr *tb[NL80211_PMSR_ATTR_MAX + 1]; + struct nlattr *nla; + int size; + int ret = nla_parse_nested(tb, NL80211_PMSR_ATTR_MAX, pmsr_capa, + hwsim_pmsr_capa_policy, NULL); + + if (ret) { + NL_SET_ERR_MSG_ATTR(info->extack, pmsr_capa, "malformed PMSR capability"); + return -EINVAL; + } + + if (tb[NL80211_PMSR_ATTR_MAX_PEERS]) + out->max_peers = nla_get_u32(tb[NL80211_PMSR_ATTR_MAX_PEERS]); + out->report_ap_tsf = !!tb[NL80211_PMSR_ATTR_REPORT_AP_TSF]; + out->randomize_mac_addr = !!tb[NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR]; + + if (!tb[NL80211_PMSR_ATTR_TYPE_CAPA]) { + NL_SET_ERR_MSG_ATTR(info->extack, tb[NL80211_PMSR_ATTR_TYPE_CAPA], + "malformed PMSR type"); + return -EINVAL; + } + + nla_for_each_nested(nla, tb[NL80211_PMSR_ATTR_TYPE_CAPA], size) { + switch (nla_type(nla)) { + case NL80211_PMSR_TYPE_FTM: + parse_ftm_capa(nla, out, info); + break; + default: + WARN_ON(1); + } + } + return 0; +} + static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) { struct hwsim_new_radio_params param = { 0 }; @@ -5173,8 +5283,24 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) param.hwname = hwname; } + if (info->attrs[HWSIM_ATTR_PMSR_SUPPORT]) { + struct cfg80211_pmsr_capabilities *pmsr_capa = + kmalloc(sizeof(*pmsr_capa), GFP_KERNEL); + if (!pmsr_capa) { + ret = -ENOMEM; + goto out_free; + } + ret = parse_pmsr_capa(info->attrs[HWSIM_ATTR_PMSR_SUPPORT], pmsr_capa, info); + if (ret) + goto out_free; + param.pmsr_capa = pmsr_capa; + } + ret = mac80211_hwsim_new_radio(info, ¶m); + +out_free: kfree(hwname); + kfree(param.pmsr_capa); return ret; } diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index 527799b2de0f..d10fa7f4853b 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -142,6 +142,8 @@ enum { * @HWSIM_ATTR_CIPHER_SUPPORT: u32 array of supported cipher types * @HWSIM_ATTR_MLO_SUPPORT: claim MLO support (exact parameters TBD) for * the new radio + * @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_CREATE_RADIO + * to provide peer measurement capabilities. (nl80211_peer_measurement_attrs) * @__HWSIM_ATTR_MAX: enum limit */ @@ -173,6 +175,7 @@ enum { HWSIM_ATTR_IFTYPE_SUPPORT, HWSIM_ATTR_CIPHER_SUPPORT, HWSIM_ATTR_MLO_SUPPORT, + HWSIM_ATTR_PMSR_SUPPORT, __HWSIM_ATTR_MAX, }; #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) From patchwork Thu Mar 2 16:03:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaewan Kim X-Patchwork-Id: 13157488 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E0E3EC678D4 for ; Thu, 2 Mar 2023 16:03:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229679AbjCBQDc (ORCPT ); Thu, 2 Mar 2023 11:03:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229592AbjCBQD3 (ORCPT ); Thu, 2 Mar 2023 11:03:29 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A273418B33 for ; Thu, 2 Mar 2023 08:03:26 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-536bbaa701aso316367707b3.3 for ; Thu, 02 Mar 2023 08:03:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1677773006; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=UyTUdnNvjlSXrE9Kg/YR8WzgRJx0XjIVyXbmHCyAEw4=; b=NsSMk1fz/8llD6nvhDaBCiI3w+rn6L8PZdp7ZE3FTRqEIPk+ZdELA4hptxYTolkXop zczliQ3gRtlxYAt1cPtZGaUUWLGO8JtP8g72jx4jy3C4kyhWwHonq02fDOZFVmVtNKDr 7YbDb/Znu8ISfpDkDjDJGscAtmAtTuGQlOxZ36ZpqA8lYJ+M+ixCcFOj48bUrIhKqjYp H+MMdZkZQqFY3omizfQFFcTPPPlrTYHnICgpDgzbCJ9Cmsw0BuYDPf8AjnPJxeUHb29+ zil7p7EryjzwTEyWbFSASH9oLziCQYwZuqWfXO3NP3PfZQSNwrUKXvo703cnN5WqQfFs Ce3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677773006; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=UyTUdnNvjlSXrE9Kg/YR8WzgRJx0XjIVyXbmHCyAEw4=; b=HNxReu3yPzjXGZcAAXnO9p1NxWCT9n9D2zBivtmFdDK5Qz2enmHcZeaqkKTLACpmot /yJxFMD0KLENdB0hPDzFG9vh9jXNqCZkEOr83QWn36irHcsdVKweRmjmBMbHzg8FOLEX lgoVdTZygoLhaSVnyPcar0+ftV2PLQuTKonsDUTYOo+Ig9VmRXMrzR7Lv/b6TjYC3wSt 0ONr+NJgosvXITp+kylFwPOvpfBYwHK/Z0pzQr/QyFdq/GaXeCBZMb6lgJEqO0uSJd01 exIk2OSOzszbYe+eQk+OsgbJcmBKetazVrx7Q85023kiD3Y1jDSpUU6JOxLBUdHVml6n Bdmw== X-Gm-Message-State: AO0yUKUAVDbhb2sQQiAHXhXcqDMFQPKYU0agvzsOElaT162K5LvPWI+D qJv0ZAilw03I/GAyDBGZCC7PznOSAyw= X-Google-Smtp-Source: AK7set9nEFrwTcHZqdi1ssJMuZPy81qYZgcAPXHhcEHIGgwLIczbbc8sP5q81TiH5Wqt+GPMCrJzWU5NHeU= X-Received: from jaewan1.c.googlers.com ([fda3:e722:ac3:cc00:3:22c1:c0a8:e59]) (user=jaewan job=sendgmr) by 2002:a05:6902:101:b0:a4e:4575:f3ec with SMTP id o1-20020a056902010100b00a4e4575f3ecmr4841329ybh.0.1677773005908; Thu, 02 Mar 2023 08:03:25 -0800 (PST) Date: Thu, 2 Mar 2023 16:03:07 +0000 In-Reply-To: <20230302160310.923349-1-jaewan@google.com> Mime-Version: 1.0 References: <20230302160310.923349-1-jaewan@google.com> X-Mailer: git-send-email 2.39.2.722.g9855ee24e9-goog Message-ID: <20230302160310.923349-3-jaewan@google.com> Subject: [PATCH v8 2/5] wifi: nl80211: make nl80211_send_chandef non-static From: Jaewan Kim To: gregkh@linuxfoundation.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Cc: kernel-team@android.com, adelva@google.com, Jaewan Kim Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Expose nl80211_send_chandef functionality for mac80211_hwsim or vendor netlink can use it where needed. Signed-off-by: Jaewan Kim --- V8: Initial commit (split from other change) --- include/net/cfg80211.h | 9 +++++++++ net/wireless/nl80211.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f115b2550309..bcce8e9e2aba 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -938,6 +938,15 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef, enum nl80211_iftype iftype); +/** + * nl80211_send_chandef - sends the channel definition. + * @msg: the msg to send channel definition + * @chandef: the channel definition to check + * + * Returns: 0 if sent the channel definition to msg, < 0 on error + **/ +int nl80211_send_chandef(struct sk_buff *msg, const struct cfg80211_chan_def *chandef); + /** * ieee80211_chanwidth_rate_flags - return rate flags for channel width * @width: the channel width of the channel diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 112b4bb009c8..1fd9e6545225 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3756,8 +3756,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) return result; } -static int nl80211_send_chandef(struct sk_buff *msg, - const struct cfg80211_chan_def *chandef) +int nl80211_send_chandef(struct sk_buff *msg, const struct cfg80211_chan_def *chandef) { if (WARN_ON(!cfg80211_chandef_valid(chandef))) return -EINVAL; @@ -3788,6 +3787,7 @@ static int nl80211_send_chandef(struct sk_buff *msg, return -ENOBUFS; return 0; } +EXPORT_SYMBOL(nl80211_send_chandef); static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, struct cfg80211_registered_device *rdev, From patchwork Thu Mar 2 16:03:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaewan Kim X-Patchwork-Id: 13157489 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 66097C7EE2F for ; Thu, 2 Mar 2023 16:03:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229621AbjCBQDe (ORCPT ); Thu, 2 Mar 2023 11:03:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229658AbjCBQDd (ORCPT ); Thu, 2 Mar 2023 11:03:33 -0500 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A49782C642 for ; Thu, 2 Mar 2023 08:03:30 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-5395c8fc4a1so272413317b3.5 for ; Thu, 02 Mar 2023 08:03:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1677773010; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=w6TV6qbj19Dh9PF1pUdhjuWma2mC8eJ9x5dw31gF7bU=; b=NRzgn+/c4lhOaNH6wxDCRn2fYRhmn0cInVe6SE40v1Q8IaqDkCQwjflWhMUV6ljLy+ RkFZNLb4i/FY+HSGbnnBJt4vvnP+i1Mimv74S+/SfPR7GM0RjtFLpmkxgqkyzHHnmZJ0 PF8j/X4aBeMgi1nb+yRPLBCQ86gw3E5wKcHbJuNEdv6vRe4HUVdMpPuaM+NwxSHDZdqN dxYi2TmsCnYl4qur9F7V4KC1jT++b0gPJToOQ19q4FaCmE26Ci6FMse94WHlvEAV7Kyw rI5SO0hMlxPt0yhOEJ7dpipqVhWnZnsfR19w6IULYzeiRQWU+ipdew0yT8y8eS+qrZmI oshw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677773010; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=w6TV6qbj19Dh9PF1pUdhjuWma2mC8eJ9x5dw31gF7bU=; b=freaXVKHVgaO4v/y8xqYsnUmaKl0rVuUHjiU0SglacTJiEIRlTM5hNxoIu+g09i97S hqKdO/mK9027WTJ+JGjaoxIqhOQPtlli6klCajCv2nJ7/FkLnNAx4MKrvnmqjy+4QqrI 093iM7jRn5Zb+tFjfU4IHgQihjeV2v1YvoFKmvxsgmIbgSdqvHgsNw5IZZJkuQ59v7Hz LOZ7Eucvvxj5rG6KgOFtSuXehSWebquzdFaeuzQBRw9ipZKFWZ457o0+0l5XuaNRV7MC 9eOAFy8hpdqmuWtBQoJgrvPG3+VSHcExXdKIG/eFp4h6pxJAG+B4UzhhjYJXKl+85+Dt atJA== X-Gm-Message-State: AO0yUKU46M4gb/1+ktmWXLK48VeXmv8caxuTEFJewbVMDpfbHjbB65OR CKnaF7qIJNON7KS1Tz78Y7R8GdMFt+U= X-Google-Smtp-Source: AK7set/tW947DpdWPrxzVOolHTbfoMmP2EALIiTLcJumjpAgwAG44j0bLAejo8yAywN/6PfevNxBEqtlHfo= X-Received: from jaewan1.c.googlers.com ([fda3:e722:ac3:cc00:3:22c1:c0a8:e59]) (user=jaewan job=sendgmr) by 2002:a05:6902:101:b0:a4e:4575:f3ec with SMTP id o1-20020a056902010100b00a4e4575f3ecmr4841455ybh.0.1677773009959; Thu, 02 Mar 2023 08:03:29 -0800 (PST) Date: Thu, 2 Mar 2023 16:03:08 +0000 In-Reply-To: <20230302160310.923349-1-jaewan@google.com> Mime-Version: 1.0 References: <20230302160310.923349-1-jaewan@google.com> X-Mailer: git-send-email 2.39.2.722.g9855ee24e9-goog Message-ID: <20230302160310.923349-4-jaewan@google.com> Subject: [PATCH v8 3/5] mac80211_hwsim: add PMSR request support via virtio From: Jaewan Kim To: gregkh@linuxfoundation.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Cc: kernel-team@android.com, adelva@google.com, Jaewan Kim Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org PMSR (a.k.a. peer measurement) is generalized measurement between two Wi-Fi devices. And currently FTM (a.k.a. fine time measurement or flight time measurement) is the one and only measurement. FTM is measured by RTT (a.k.a. round trip time) of packets between two Wi-Fi devices. Add necessary functionalities for mac80211_hwsim to start PMSR request by passthrough the request to wmediumd via virtio. mac80211_hwsim can't measure RTT for real because mac80211_hwsim the software simulator and packets are sent almost immediately for real. This change expect wmediumd to have all the location information of devices, so passthrough requests to wmediumd. In detail, add new mac80211_hwsim command HWSIM_CMD_ABORT_PMSR. When mac80211_hwsim receives the PMSR start request via ieee80211_ops.start_pmsr, the received cfg80211_pmsr_request is resent to the wmediumd with command HWSIM_CMD_START_PMSR and attribute HWSIM_ATTR_PMSR_REQUEST. The attribute is formatted as the same way as nl80211_pmsr_start() expects. Signed-off-by: Jaewan Kim --- V7->V8: Export nl80211_send_chandef directly and instead of creating wrapper. V7: Initial commit (split from previously large patch) --- drivers/net/wireless/mac80211_hwsim.c | 207 +++++++++++++++++++++++++- drivers/net/wireless/mac80211_hwsim.h | 6 + 2 files changed, 212 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 79476d55c1ca..691b83140d57 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -721,6 +721,8 @@ struct mac80211_hwsim_data { /* only used when pmsr capability is supplied */ struct cfg80211_pmsr_capabilities pmsr_capa; + struct cfg80211_pmsr_request *pmsr_request; + struct wireless_dev *pmsr_request_wdev; struct mac80211_hwsim_link_data link_data[IEEE80211_MLD_MAX_NUM_LINKS]; }; @@ -3139,6 +3141,208 @@ static int mac80211_hwsim_change_sta_links(struct ieee80211_hw *hw, return 0; } +static int mac80211_hwsim_send_pmsr_ftm_request_peer(struct sk_buff *msg, + struct cfg80211_pmsr_ftm_request_peer *request) +{ + struct nlattr *ftm; + + if (!request->requested) + return -EINVAL; + + ftm = nla_nest_start(msg, NL80211_PMSR_TYPE_FTM); + if (!ftm) + return -ENOBUFS; + + if (nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE, request->preamble)) + return -ENOBUFS; + + if (nla_put_u16(msg, NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD, request->burst_period)) + return -ENOBUFS; + + if (request->asap && nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_ASAP)) + return -ENOBUFS; + + if (request->request_lci && nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI)) + return -ENOBUFS; + + if (request->request_civicloc && + nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC)) + return -ENOBUFS; + + if (request->trigger_based && nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED)) + return -ENOBUFS; + + if (request->non_trigger_based && + nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED)) + return -ENOBUFS; + + if (request->lmr_feedback && nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK)) + return -ENOBUFS; + + if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP, request->num_bursts_exp)) + return -ENOBUFS; + + if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION, request->burst_duration)) + return -ENOBUFS; + + if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST, request->ftms_per_burst)) + return -ENOBUFS; + + if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES, request->ftmr_retries)) + return -ENOBUFS; + + if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION, request->burst_duration)) + return -ENOBUFS; + + if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR, request->bss_color)) + return -ENOBUFS; + + nla_nest_end(msg, ftm); + + return 0; +} + +static int mac80211_hwsim_send_pmsr_request_peer(struct sk_buff *msg, + struct cfg80211_pmsr_request_peer *request) +{ + struct nlattr *peer, *chandef, *req, *data; + int err; + + peer = nla_nest_start(msg, NL80211_PMSR_ATTR_PEERS); + if (!peer) + return -ENOBUFS; + + if (nla_put(msg, NL80211_PMSR_PEER_ATTR_ADDR, ETH_ALEN, + request->addr)) + return -ENOBUFS; + + chandef = nla_nest_start(msg, NL80211_PMSR_PEER_ATTR_CHAN); + if (!chandef) + return -ENOBUFS; + + err = nl80211_send_chandef(msg, &request->chandef); + if (err) + return err; + + nla_nest_end(msg, chandef); + + req = nla_nest_start(msg, NL80211_PMSR_PEER_ATTR_REQ); + if (request->report_ap_tsf && nla_put_flag(msg, NL80211_PMSR_REQ_ATTR_GET_AP_TSF)) + return -ENOBUFS; + + data = nla_nest_start(msg, NL80211_PMSR_REQ_ATTR_DATA); + if (!data) + return -ENOBUFS; + + err = mac80211_hwsim_send_pmsr_ftm_request_peer(msg, &request->ftm); + if (err) + return err; + + nla_nest_end(msg, data); + nla_nest_end(msg, req); + nla_nest_end(msg, peer); + + return 0; +} + +static int mac80211_hwsim_send_pmsr_request(struct sk_buff *msg, + struct cfg80211_pmsr_request *request) +{ + int err; + struct nlattr *pmsr = nla_nest_start(msg, NL80211_ATTR_PEER_MEASUREMENTS); + + if (!pmsr) + return -ENOBUFS; + + if (nla_put_u32(msg, NL80211_ATTR_TIMEOUT, request->timeout)) + return -ENOBUFS; + + if (!is_zero_ether_addr(request->mac_addr)) { + if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, request->mac_addr)) + return -ENOBUFS; + if (nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN, request->mac_addr_mask)) + return -ENOBUFS; + } + + for (int i = 0; i < request->n_peers; i++) { + err = mac80211_hwsim_send_pmsr_request_peer(msg, &request->peers[i]); + if (err) + return err; + } + + nla_nest_end(msg, pmsr); + + return 0; +} + +static int mac80211_hwsim_start_pmsr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *request) +{ + struct mac80211_hwsim_data *data = hw->priv; + u32 _portid = READ_ONCE(data->wmediumd); + int err = 0; + struct sk_buff *skb = NULL; + void *msg_head; + struct nlattr *pmsr; + + if (!_portid && !hwsim_virtio_enabled) + return -EOPNOTSUPP; + + mutex_lock(&data->mutex); + + if (data->pmsr_request) { + err = -EBUSY; + goto out_err; + } + + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + + if (!skb) { + err = -ENOMEM; + goto out_err; + } + + msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, + HWSIM_CMD_START_PMSR); + + if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, + ETH_ALEN, data->addresses[1].addr)) { + err = -ENOMEM; + goto out_err; + } + + pmsr = nla_nest_start(skb, HWSIM_ATTR_PMSR_REQUEST); + if (!pmsr) { + err = -ENOMEM; + goto out_err; + } + + err = mac80211_hwsim_send_pmsr_request(skb, request); + if (err) + goto out_err; + + nla_nest_end(skb, pmsr); + + genlmsg_end(skb, msg_head); + if (hwsim_virtio_enabled) + hwsim_tx_virtio(data, skb); + else + hwsim_unicast_netgroup(data, skb, _portid); + +out_err: + if (err && skb) + nlmsg_free(skb); + + if (!err) { + data->pmsr_request = request; + data->pmsr_request_wdev = ieee80211_vif_to_wdev(vif); + } + + mutex_unlock(&data->mutex); + return err; +} + #define HWSIM_COMMON_OPS \ .tx = mac80211_hwsim_tx, \ .wake_tx_queue = ieee80211_handle_wake_tx_queue, \ @@ -3161,7 +3365,8 @@ static int mac80211_hwsim_change_sta_links(struct ieee80211_hw *hw, .flush = mac80211_hwsim_flush, \ .get_et_sset_count = mac80211_hwsim_get_et_sset_count, \ .get_et_stats = mac80211_hwsim_get_et_stats, \ - .get_et_strings = mac80211_hwsim_get_et_strings, + .get_et_strings = mac80211_hwsim_get_et_strings, \ + .start_pmsr = mac80211_hwsim_start_pmsr, \ #define HWSIM_NON_MLO_OPS \ .sta_add = mac80211_hwsim_sta_add, \ diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index d10fa7f4853b..98e586a56582 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -81,6 +81,8 @@ enum hwsim_tx_control_flags { * to this receiver address for a given station. * @HWSIM_CMD_DEL_MAC_ADDR: remove the MAC address again, the attributes * are the same as to @HWSIM_CMD_ADD_MAC_ADDR. + * @HWSIM_CMD_START_PMSR: request to start peer measurement with the + * %HWSIM_ATTR_PMSR_REQUEST. * @__HWSIM_CMD_MAX: enum limit */ enum { @@ -93,6 +95,7 @@ enum { HWSIM_CMD_GET_RADIO, HWSIM_CMD_ADD_MAC_ADDR, HWSIM_CMD_DEL_MAC_ADDR, + HWSIM_CMD_START_PMSR, __HWSIM_CMD_MAX, }; #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) @@ -144,6 +147,8 @@ enum { * the new radio * @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_CREATE_RADIO * to provide peer measurement capabilities. (nl80211_peer_measurement_attrs) + * @HWSIM_ATTR_PMSR_REQUEST: nested attribute used with %HWSIM_CMD_START_PMSR + * to provide details about peer measurement request (nl80211_peer_measurement_attrs) * @__HWSIM_ATTR_MAX: enum limit */ @@ -176,6 +181,7 @@ enum { HWSIM_ATTR_CIPHER_SUPPORT, HWSIM_ATTR_MLO_SUPPORT, HWSIM_ATTR_PMSR_SUPPORT, + HWSIM_ATTR_PMSR_REQUEST, __HWSIM_ATTR_MAX, }; #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) From patchwork Thu Mar 2 16:03:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaewan Kim X-Patchwork-Id: 13157490 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E44CAC6FA8E for ; Thu, 2 Mar 2023 16:03:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229691AbjCBQDk (ORCPT ); Thu, 2 Mar 2023 11:03:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33104 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229681AbjCBQDj (ORCPT ); Thu, 2 Mar 2023 11:03:39 -0500 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 118E5231ED for ; Thu, 2 Mar 2023 08:03:35 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-536cad819c7so317686897b3.6 for ; Thu, 02 Mar 2023 08:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1677773014; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=vLoDLuc62NhKk4/mKSLF7jhQKGozjf+HOSoQc+6IDzU=; b=TrheORYCMREjzOi2u5PwHTnUn2UXlkZ+yA+/asKzVte9SwkC27YYX6uqmPBabFgvIB vPWdEVSKTGsszBIfSbEQWVsoOoJ4zfunwBhIOSRg9FbZ3KHdQEz7I/0coTX/Nb487Qui 1KOZpYaSN5FvyljV6IW1Lf1bNbvEUi3/i9j4maMkMDRWKrPXyp6s46YDNdv+cJvfghfb lvvG60jYNbRU4hgOMP4u0uGwlVFcwsQVdRU9LaOzgqMbkYKy7Y70dJHsULnkufd54vwC C4wP+JuTKwzv5kIhZR5ZEtWxccW8368v0624lSMe/iermiSLvnCELINfJLRiru9w5BzR lBXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677773014; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vLoDLuc62NhKk4/mKSLF7jhQKGozjf+HOSoQc+6IDzU=; b=obn+JlLneqWZORAamJRBCCF9MEZD8PUHXnlTBEDJfIPjaneKbeMlQtKWcwd+h/kKdX KcznPr8uepMqG03lSnzgeKaEW9RP7H2+o6NPZio7L0Imwc43mRjwl1EV/sFPXAkoPyc6 +QIidP1JSSlskNS9bg1IbuGYo/hyXXBBmHoZ1gu38CMdqASO9ns4xnWwQJ0KDNG7DYhJ 21a5wiBZEEI/ms7XkAcABjqQbtkYurZZRpjzD6DVjqpjI/oqI8qjyAXRT7lrNbUET9j7 lSeprl6B5d/NP3dHNfxaC8m/Wx3Twkef/g9xl+5PSgDn5aWcOdldJ9CkPXpe0Wm1GHmF ebBQ== X-Gm-Message-State: AO0yUKUV09T5BJukE1N+XNg2uhOwe9ae8IrIyyVMsAusa1GhBlwkxkIR DBZD52Y6NjSrPPdOop7tC/MKDEAX+QQ= X-Google-Smtp-Source: AK7set8jMzUNvdps3utzYeykDEewPoBgaVPu3+NyW4dnW68IGpDMZVv/mtdAVb4/kiSWI8T4wiOlCAZ6rc0= X-Received: from jaewan1.c.googlers.com ([fda3:e722:ac3:cc00:3:22c1:c0a8:e59]) (user=jaewan job=sendgmr) by 2002:a05:6902:4b:b0:a09:314f:a3ef with SMTP id m11-20020a056902004b00b00a09314fa3efmr5719502ybh.12.1677773014299; Thu, 02 Mar 2023 08:03:34 -0800 (PST) Date: Thu, 2 Mar 2023 16:03:09 +0000 In-Reply-To: <20230302160310.923349-1-jaewan@google.com> Mime-Version: 1.0 References: <20230302160310.923349-1-jaewan@google.com> X-Mailer: git-send-email 2.39.2.722.g9855ee24e9-goog Message-ID: <20230302160310.923349-5-jaewan@google.com> Subject: [PATCH v8 4/5] mac80211_hwsim: add PMSR abort support via virtio From: Jaewan Kim To: gregkh@linuxfoundation.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Cc: kernel-team@android.com, adelva@google.com, Jaewan Kim Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org PMSR (a.k.a. peer measurement) is generalized measurement between two devices with Wi-Fi support. And currently FTM (a.k.a. fine time measurement or flight time measurement) is the one and only measurement. Add necessary functionalities for mac80211_hwsim to abort previous PMSR request. The abortion request is sent to the wmedium where the PMSR request is actually handled. In detail, add new mac80211_hwsim command HWSIM_CMD_ABORT_PMSR. When mac80211_hwsim receives the PMSR abortion request via ieee80211_ops.abort_pmsr, the received cfg80211_pmsr_request is resent to the wmediumd with command HWSIM_CMD_ABORT_PMSR and attribute HWSIM_ATTR_PMSR_REQUEST. The attribute is formatted as the same way as nl80211_pmsr_start() expects. Signed-off-by: Jaewan Kim --- V7->V8: Rewrote commit msg V7: Initial commit (split from previously large patch) --- drivers/net/wireless/mac80211_hwsim.c | 61 +++++++++++++++++++++++++++ drivers/net/wireless/mac80211_hwsim.h | 2 + 2 files changed, 63 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 691b83140d57..0d92a7e51057 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -3343,6 +3343,66 @@ static int mac80211_hwsim_start_pmsr(struct ieee80211_hw *hw, return err; } +static void mac80211_hwsim_abort_pmsr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *request) +{ + struct mac80211_hwsim_data *data = hw->priv; + u32 _portid = READ_ONCE(data->wmediumd); + struct sk_buff *skb = NULL; + int err = 0; + void *msg_head; + struct nlattr *pmsr; + + if (!_portid && !hwsim_virtio_enabled) + return; + + mutex_lock(&data->mutex); + + if (data->pmsr_request != request) { + err = -EINVAL; + goto out_err; + } + + if (err) + return; + + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb) + return; + + msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, HWSIM_CMD_ABORT_PMSR); + + if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, ETH_ALEN, data->addresses[1].addr)) + goto out_err; + + pmsr = nla_nest_start(skb, HWSIM_ATTR_PMSR_REQUEST); + if (!pmsr) { + err = -ENOMEM; + goto out_err; + } + + err = mac80211_hwsim_send_pmsr_request(skb, request); + if (err) + goto out_err; + + err = nla_nest_end(skb, pmsr); + if (err) + goto out_err; + + genlmsg_end(skb, msg_head); + if (hwsim_virtio_enabled) + hwsim_tx_virtio(data, skb); + else + hwsim_unicast_netgroup(data, skb, _portid); + +out_err: + if (err && skb) + nlmsg_free(skb); + + mutex_unlock(&data->mutex); +} + #define HWSIM_COMMON_OPS \ .tx = mac80211_hwsim_tx, \ .wake_tx_queue = ieee80211_handle_wake_tx_queue, \ @@ -3367,6 +3427,7 @@ static int mac80211_hwsim_start_pmsr(struct ieee80211_hw *hw, .get_et_stats = mac80211_hwsim_get_et_stats, \ .get_et_strings = mac80211_hwsim_get_et_strings, \ .start_pmsr = mac80211_hwsim_start_pmsr, \ + .abort_pmsr = mac80211_hwsim_abort_pmsr, #define HWSIM_NON_MLO_OPS \ .sta_add = mac80211_hwsim_sta_add, \ diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index 98e586a56582..383f3e39c911 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -83,6 +83,7 @@ enum hwsim_tx_control_flags { * are the same as to @HWSIM_CMD_ADD_MAC_ADDR. * @HWSIM_CMD_START_PMSR: request to start peer measurement with the * %HWSIM_ATTR_PMSR_REQUEST. + * @HWSIM_CMD_ABORT_PMSR: abort previously sent peer measurement * @__HWSIM_CMD_MAX: enum limit */ enum { @@ -96,6 +97,7 @@ enum { HWSIM_CMD_ADD_MAC_ADDR, HWSIM_CMD_DEL_MAC_ADDR, HWSIM_CMD_START_PMSR, + HWSIM_CMD_ABORT_PMSR, __HWSIM_CMD_MAX, }; #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) From patchwork Thu Mar 2 16:03:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaewan Kim X-Patchwork-Id: 13157491 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D0BFC678D4 for ; Thu, 2 Mar 2023 16:03:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229681AbjCBQDs (ORCPT ); Thu, 2 Mar 2023 11:03:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33254 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229695AbjCBQDr (ORCPT ); Thu, 2 Mar 2023 11:03:47 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E720D2820E for ; Thu, 2 Mar 2023 08:03:38 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-536bbaa701aso316375347b3.3 for ; Thu, 02 Mar 2023 08:03:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1677773018; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=7z2mQwup8/gR0OgPQE/3FqgLiWq8E3qDsgwW2p24hUo=; b=RqtWxu/vlOLpAGVO+L2Wqu10LB7ZUlqYeKTKHJthlEsA39H2sPge3Tz+wM9SwqMEUf kboKwXXxOAMRD9heqka0yedSG54LbZivTfNEsBvqIcttWUtR26krOkc7tYIHMimkpD5+ GHX7TskgE0sq0SPkMiLBJOD2NBDABYx43AFJGY8gnxddDkHkQ/QPC9YiuISbekyz2fdH zWe+ggxvlH72Sp8ir7Jcn6u+eGWJ4mdqPK4P2TVkH5YZgsB3N+HQSSJ3ronLO4W5Q36l yOm+DXSRBw5bY2G8OM2hVBuXF45mUpGaomtThEz/F+haCmnJpZKNwL42XSLyp6j2lDB1 vh1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677773018; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=7z2mQwup8/gR0OgPQE/3FqgLiWq8E3qDsgwW2p24hUo=; b=Be/JSmTBasCuU4O/9vY8KIO4jmvu2ObJbHkt5M4xS5dNew6R0fdeJkSDkKENTYyfQX Yn1QHKuTT/FBOrrVDr6I9XjRu5P86h0m/ENAeq15KTLGOvTPqGrt1tYm0Rd+wmB0BzDK 7KYV2aU2aWWGhRS0S3eDRqgAKqbc8UdWuBdRZiLnOo1nwWUCjCooRTIqoH0kKo5zrPXk Vqx0P3kXkszLPRHLm85VHmnZALvK4hBNArRTUi2P8xAXO2O5D2zCxf59tTY/6PF+uhYH sP0WvhefCT2r28nDsQEgLGeZdLumpN+i9tN+zw+7DspK7IiHWq/eDocR4X5uYDDTQUjg +Lzw== X-Gm-Message-State: AO0yUKVnmBBcyDKkZibQGqDLycbjQXJFif71PKeF7q9iOr5w47tb0ExK ls33O6eoVICqIWAvdvp1Fa6BcLtitdI= X-Google-Smtp-Source: AK7set/ZqfGJh6RUCwrBlNGtf3JCH1lpqiK4gssnBUTv8RaTDyhVj3DW1YmpuYLsRak5jfeuaBSAUJDBfQc= X-Received: from jaewan1.c.googlers.com ([fda3:e722:ac3:cc00:3:22c1:c0a8:e59]) (user=jaewan job=sendgmr) by 2002:a05:6902:101:b0:a4e:4575:f3ec with SMTP id o1-20020a056902010100b00a4e4575f3ecmr4841778ybh.0.1677773018551; Thu, 02 Mar 2023 08:03:38 -0800 (PST) Date: Thu, 2 Mar 2023 16:03:10 +0000 In-Reply-To: <20230302160310.923349-1-jaewan@google.com> Mime-Version: 1.0 References: <20230302160310.923349-1-jaewan@google.com> X-Mailer: git-send-email 2.39.2.722.g9855ee24e9-goog Message-ID: <20230302160310.923349-6-jaewan@google.com> Subject: [PATCH v8 5/5] mac80211_hwsim: add PMSR report support via virtio From: Jaewan Kim To: gregkh@linuxfoundation.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Cc: kernel-team@android.com, adelva@google.com, Jaewan Kim Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org PMSR (a.k.a. peer measurement) is generalized measurement between two devices with Wi-Fi support. And currently FTM (a.k.a. fine time measurement or flight time measurement) is the one and only measurement. Add the necessary functionality to allow mac80211_hwsim to report PMSR result. The result would come from the wmediumd, where other Wi-Fi devices' information are kept. mac80211_hwsim only need to deliver the result to the userspace. In detail, add new mac80211_hwsim attributes HWSIM_CMD_REPORT_PMSR, and HWSIM_ATTR_PMSR_RESULT. When mac80211_hwsim receives the PMSR result with command HWSIM_CMD_REPORT_PMSR and detail with attribute HWSIM_ATTR_PMSR_RESULT, received data is parsed to cfg80211_pmsr_result and resent to the userspace by cfg80211_pmsr_report(). To help receive the details of PMSR result, hwsim_rate_info_attributes is added to receive rate_info without complex bitrate calculation. (i.e. send rate_info without adding inverse of nl80211_put_sta_rate()). Signed-off-by: Jaewan Kim --- V7->V8: Specify calculated last HWSIM_CMD for resv_start_op instead of __HWSIM_CMD_MAX for adding new CMD more explicit. V7: Initial commit (split from previously large patch) --- drivers/net/wireless/mac80211_hwsim.c | 379 +++++++++++++++++++++++++- drivers/net/wireless/mac80211_hwsim.h | 51 +++- 2 files changed, 420 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 0d92a7e51057..2a664b7e50d5 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -752,6 +752,11 @@ struct hwsim_radiotap_ack_hdr { __le16 rt_chbitmask; } __packed; +static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr) +{ + return rhashtable_lookup_fast(&hwsim_radios_rht, addr, hwsim_rht_params); +} + /* MAC80211_HWSIM netlink family */ static struct genl_family hwsim_genl_family; @@ -765,6 +770,76 @@ static const struct genl_multicast_group hwsim_mcgrps[] = { /* MAC80211_HWSIM netlink policy */ +static const struct nla_policy +hwsim_rate_info_policy[HWSIM_RATE_INFO_ATTR_MAX + 1] = { + [HWSIM_RATE_INFO_ATTR_FLAGS] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_MCS] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_LEGACY] = { .type = NLA_U16 }, + [HWSIM_RATE_INFO_ATTR_NSS] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_BW] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_HE_GI] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_HE_DCM] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_EHT_GI] = { .type = NLA_U8 }, + [HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC] = { .type = NLA_U8 }, +}; + +static const struct nla_policy +hwsim_ftm_result_policy[NL80211_PMSR_FTM_RESP_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX] = { .type = NLA_U16 }, + [NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_TX_RATE] = NLA_POLICY_NESTED(hwsim_rate_info_policy), + [NL80211_PMSR_FTM_RESP_ATTR_RX_RATE] = NLA_POLICY_NESTED(hwsim_rate_info_policy), + [NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG] = { .type = NLA_U64 }, + [NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE] = { .type = NLA_U64 }, + [NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD] = { .type = NLA_U64 }, + [NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG] = { .type = NLA_U64 }, + [NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE] = { .type = NLA_U64 }, + [NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD] = { .type = NLA_U64 }, + [NL80211_PMSR_FTM_RESP_ATTR_LCI] = { .type = NLA_STRING }, + [NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_STRING }, +}; + +static const struct nla_policy +hwsim_pmsr_resp_type_policy[NL80211_PMSR_TYPE_MAX + 1] = { + [NL80211_PMSR_TYPE_FTM] = NLA_POLICY_NESTED(hwsim_ftm_result_policy), +}; + +static const struct nla_policy +hwsim_pmsr_resp_policy[NL80211_PMSR_RESP_ATTR_MAX + 1] = { + [NL80211_PMSR_RESP_ATTR_STATUS] = { .type = NLA_U32 }, + [NL80211_PMSR_RESP_ATTR_HOST_TIME] = { .type = NLA_U64 }, + [NL80211_PMSR_RESP_ATTR_AP_TSF] = { .type = NLA_U64 }, + [NL80211_PMSR_RESP_ATTR_FINAL] = { .type = NLA_FLAG }, + [NL80211_PMSR_RESP_ATTR_DATA] = NLA_POLICY_NESTED(hwsim_pmsr_resp_type_policy), +}; + +static const struct nla_policy +hwsim_pmsr_peer_result_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = { + [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR_COMPAT, + [NL80211_PMSR_PEER_ATTR_CHAN] = { .type = NLA_REJECT }, + [NL80211_PMSR_PEER_ATTR_REQ] = { .type = NLA_REJECT }, + [NL80211_PMSR_PEER_ATTR_RESP] = NLA_POLICY_NESTED(hwsim_pmsr_resp_policy), +}; + +static const struct nla_policy +hwsim_pmsr_peers_result_policy[NL80211_PMSR_ATTR_MAX + 1] = { + [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT }, + [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT }, + [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT }, + [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT }, + [NL80211_PMSR_ATTR_PEERS] = NLA_POLICY_NESTED_ARRAY(hwsim_pmsr_peer_result_policy), +}; + static const struct nla_policy hwsim_ftm_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = { [NL80211_PMSR_FTM_CAPA_ATTR_ASAP] = { .type = NLA_FLAG }, @@ -822,6 +897,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { [HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY }, [HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, [HWSIM_ATTR_PMSR_SUPPORT] = NLA_POLICY_NESTED(hwsim_pmsr_capa_policy), + [HWSIM_ATTR_PMSR_RESULT] = NLA_POLICY_NESTED(hwsim_pmsr_peers_result_policy), }; #if IS_REACHABLE(CONFIG_VIRTIO) @@ -3403,6 +3479,292 @@ static void mac80211_hwsim_abort_pmsr(struct ieee80211_hw *hw, mutex_unlock(&data->mutex); } +static int mac80211_hwsim_parse_rate_info(struct nlattr *rateattr, + struct rate_info *rate_info, + struct genl_info *info) +{ + struct nlattr *tb[HWSIM_RATE_INFO_ATTR_MAX + 1]; + int ret; + + ret = nla_parse_nested(tb, HWSIM_RATE_INFO_ATTR_MAX, + rateattr, hwsim_rate_info_policy, info->extack); + if (ret) + return ret; + + if (tb[HWSIM_RATE_INFO_ATTR_FLAGS]) + rate_info->flags = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_FLAGS]); + + if (tb[HWSIM_RATE_INFO_ATTR_MCS]) + rate_info->mcs = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_MCS]); + + if (tb[HWSIM_RATE_INFO_ATTR_LEGACY]) + rate_info->legacy = nla_get_u16(tb[HWSIM_RATE_INFO_ATTR_LEGACY]); + + if (tb[HWSIM_RATE_INFO_ATTR_NSS]) + rate_info->nss = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_NSS]); + + if (tb[HWSIM_RATE_INFO_ATTR_BW]) + rate_info->bw = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_BW]); + + if (tb[HWSIM_RATE_INFO_ATTR_HE_GI]) + rate_info->he_gi = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_HE_GI]); + + if (tb[HWSIM_RATE_INFO_ATTR_HE_DCM]) + rate_info->he_dcm = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_HE_DCM]); + + if (tb[HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC]) + rate_info->he_ru_alloc = + nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC]); + + if (tb[HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH]) + rate_info->n_bonded_ch = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH]); + + if (tb[HWSIM_RATE_INFO_ATTR_EHT_GI]) + rate_info->eht_gi = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_EHT_GI]); + + if (tb[HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC]) + rate_info->eht_ru_alloc = nla_get_u8(tb[HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC]); + + return 0; +} + +static int mac80211_hwsim_parse_ftm_result(struct nlattr *ftm, + struct cfg80211_pmsr_ftm_result *result, + struct genl_info *info) +{ + struct nlattr *tb[NL80211_PMSR_FTM_RESP_ATTR_MAX + 1]; + int ret; + + ret = nla_parse_nested(tb, NL80211_PMSR_FTM_RESP_ATTR_MAX, + ftm, hwsim_ftm_result_policy, info->extack); + if (ret) + return ret; + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON]) + result->failure_reason = nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON]); + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX]) + result->burst_index = nla_get_u16(tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX]); + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS]) { + result->num_ftmr_attempts_valid = 1; + result->num_ftmr_attempts = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES]) { + result->num_ftmr_successes_valid = 1; + result->num_ftmr_successes = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME]) + result->busy_retry_time = + nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME]); + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP]) + result->num_bursts_exp = nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP]); + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION]) + result->burst_duration = nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION]); + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST]) + result->ftms_per_burst = nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST]); + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG]) { + result->rssi_avg_valid = 1; + result->rssi_avg = nla_get_s32(tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG]); + } + if (tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD]) { + result->rssi_spread_valid = 1; + result->rssi_spread = + nla_get_s32(tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_TX_RATE]) { + result->tx_rate_valid = 1; + ret = mac80211_hwsim_parse_rate_info(tb[NL80211_PMSR_FTM_RESP_ATTR_TX_RATE], + &result->tx_rate, info); + if (ret) + return ret; + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_RX_RATE]) { + result->rx_rate_valid = 1; + ret = mac80211_hwsim_parse_rate_info(tb[NL80211_PMSR_FTM_RESP_ATTR_RX_RATE], + &result->rx_rate, info); + if (ret) + return ret; + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG]) { + result->rtt_avg_valid = 1; + result->rtt_avg = + nla_get_u64(tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG]); + } + if (tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE]) { + result->rtt_variance_valid = 1; + result->rtt_variance = + nla_get_u64(tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE]); + } + if (tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD]) { + result->rtt_spread_valid = 1; + result->rtt_spread = + nla_get_u64(tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD]); + } + if (tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG]) { + result->dist_avg_valid = 1; + result->dist_avg = + nla_get_u64(tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG]); + } + if (tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE]) { + result->dist_variance_valid = 1; + result->dist_variance = + nla_get_u64(tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE]); + } + if (tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD]) { + result->dist_spread_valid = 1; + result->dist_spread = + nla_get_u64(tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_LCI]) { + result->lci = nla_data(tb[NL80211_PMSR_FTM_RESP_ATTR_LCI]); + result->lci_len = nla_len(tb[NL80211_PMSR_FTM_RESP_ATTR_LCI]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]) { + result->civicloc = nla_data(tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]); + result->civicloc_len = nla_len(tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]); + } + + return 0; +} + +static int mac80211_hwsim_parse_pmsr_resp(struct nlattr *resp, + struct cfg80211_pmsr_result *result, + struct genl_info *info) +{ + struct nlattr *tb[NL80211_PMSR_RESP_ATTR_MAX + 1]; + struct nlattr *pmsr; + int rem; + int ret; + + ret = nla_parse_nested(tb, NL80211_PMSR_RESP_ATTR_MAX, resp, + hwsim_pmsr_resp_policy, info->extack); + + if (tb[NL80211_PMSR_RESP_ATTR_STATUS]) + result->status = nla_get_u32(tb[NL80211_PMSR_RESP_ATTR_STATUS]); + + if (tb[NL80211_PMSR_RESP_ATTR_HOST_TIME]) + result->host_time = nla_get_u64(tb[NL80211_PMSR_RESP_ATTR_HOST_TIME]); + + if (tb[NL80211_PMSR_RESP_ATTR_AP_TSF]) { + result->ap_tsf_valid = 1; + result->ap_tsf = nla_get_u64(tb[NL80211_PMSR_RESP_ATTR_AP_TSF]); + } + + result->final = !!tb[NL80211_PMSR_RESP_ATTR_FINAL]; + + if (tb[NL80211_PMSR_RESP_ATTR_DATA]) { + nla_for_each_nested(pmsr, tb[NL80211_PMSR_RESP_ATTR_DATA], rem) { + switch (nla_type(pmsr)) { + case NL80211_PMSR_TYPE_FTM: + result->type = NL80211_PMSR_TYPE_FTM; + ret = mac80211_hwsim_parse_ftm_result(pmsr, &result->ftm, info); + if (ret) + return ret; + break; + default: + NL_SET_ERR_MSG_ATTR(info->extack, pmsr, "Unknown pmsr resp type"); + return -EINVAL; + } + } + } + + return 0; +} + +static int mac80211_hwsim_parse_pmsr_result(struct nlattr *peer, + struct cfg80211_pmsr_result *result, + struct genl_info *info) +{ + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + int ret; + + if (!peer) + return -EINVAL; + + ret = nla_parse_nested(tb, NL80211_PMSR_PEER_ATTR_MAX, peer, + hwsim_pmsr_peer_result_policy, info->extack); + if (ret) + return ret; + + if (tb[NL80211_PMSR_PEER_ATTR_ADDR]) + memcpy(result->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), + ETH_ALEN); + + if (tb[NL80211_PMSR_PEER_ATTR_RESP]) { + ret = mac80211_hwsim_parse_pmsr_resp(tb[NL80211_PMSR_PEER_ATTR_RESP], result, info); + if (ret) + return ret; + } + + return 0; +}; + +static int hwsim_pmsr_report_nl(struct sk_buff *msg, struct genl_info *info) +{ + struct nlattr *reqattr; + const u8 *src; + int err, rem; + struct nlattr *peers, *peer; + struct mac80211_hwsim_data *data; + + src = nla_data(info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]); + data = get_hwsim_data_ref_from_addr(src); + if (!data) + return -EINVAL; + + mutex_lock(&data->mutex); + if (!data->pmsr_request) { + err = -EINVAL; + goto out_err; + } + + reqattr = info->attrs[HWSIM_ATTR_PMSR_RESULT]; + if (!reqattr) { + err = -EINVAL; + goto out_err; + } + + peers = nla_find_nested(reqattr, NL80211_PMSR_ATTR_PEERS); + if (!peers) { + err = -EINVAL; + goto out_err; + } + + nla_for_each_nested(peer, peers, rem) { + struct cfg80211_pmsr_result result; + + err = mac80211_hwsim_parse_pmsr_result(peer, &result, info); + if (err) + goto out_err; + + cfg80211_pmsr_report(data->pmsr_request_wdev, + data->pmsr_request, &result, GFP_KERNEL); + } + + cfg80211_pmsr_complete(data->pmsr_request_wdev, data->pmsr_request, GFP_KERNEL); + +out_err: + data->pmsr_request = NULL; + data->pmsr_request_wdev = NULL; + + mutex_unlock(&data->mutex); + return err; +} + #define HWSIM_COMMON_OPS \ .tx = mac80211_hwsim_tx, \ .wake_tx_queue = ieee80211_handle_wake_tx_queue, \ @@ -5072,13 +5434,6 @@ static void hwsim_mon_setup(struct net_device *dev) eth_hw_addr_set(dev, addr); } -static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr) -{ - return rhashtable_lookup_fast(&hwsim_radios_rht, - addr, - hwsim_rht_params); -} - static void hwsim_register_wmediumd(struct net *net, u32 portid) { struct mac80211_hwsim_data *data; @@ -5745,6 +6100,11 @@ static const struct genl_small_ops hwsim_ops[] = { .doit = hwsim_get_radio_nl, .dumpit = hwsim_dump_radio_nl, }, + { + .cmd = HWSIM_CMD_REPORT_PMSR, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = hwsim_pmsr_report_nl, + }, }; static struct genl_family hwsim_genl_family __ro_after_init = { @@ -5756,7 +6116,7 @@ static struct genl_family hwsim_genl_family __ro_after_init = { .module = THIS_MODULE, .small_ops = hwsim_ops, .n_small_ops = ARRAY_SIZE(hwsim_ops), - .resv_start_op = HWSIM_CMD_DEL_MAC_ADDR + 1, + .resv_start_op = HWSIM_CMD_REPORT_PMSR + 1, // match with __HWSIM_CMD_MAX .mcgrps = hwsim_mcgrps, .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), }; @@ -5925,6 +6285,9 @@ static int hwsim_virtio_handle_cmd(struct sk_buff *skb) case HWSIM_CMD_TX_INFO_FRAME: hwsim_tx_info_frame_received_nl(skb, &info); break; + case HWSIM_CMD_REPORT_PMSR: + hwsim_pmsr_report_nl(skb, &info); + break; default: pr_err_ratelimited("hwsim: invalid cmd: %d\n", gnlh->cmd); return -EPROTO; diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index 383f3e39c911..92126f02c58f 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -82,8 +82,8 @@ enum hwsim_tx_control_flags { * @HWSIM_CMD_DEL_MAC_ADDR: remove the MAC address again, the attributes * are the same as to @HWSIM_CMD_ADD_MAC_ADDR. * @HWSIM_CMD_START_PMSR: request to start peer measurement with the - * %HWSIM_ATTR_PMSR_REQUEST. - * @HWSIM_CMD_ABORT_PMSR: abort previously sent peer measurement + * %HWSIM_ATTR_PMSR_REQUEST. Result will be sent back asynchronously + * with %HWSIM_CMD_REPORT_PMSR. * @__HWSIM_CMD_MAX: enum limit */ enum { @@ -98,6 +98,7 @@ enum { HWSIM_CMD_DEL_MAC_ADDR, HWSIM_CMD_START_PMSR, HWSIM_CMD_ABORT_PMSR, + HWSIM_CMD_REPORT_PMSR, __HWSIM_CMD_MAX, }; #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) @@ -151,6 +152,8 @@ enum { * to provide peer measurement capabilities. (nl80211_peer_measurement_attrs) * @HWSIM_ATTR_PMSR_REQUEST: nested attribute used with %HWSIM_CMD_START_PMSR * to provide details about peer measurement request (nl80211_peer_measurement_attrs) + * @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR + * to provide peer measurement result (nl80211_peer_measurement_attrs) * @__HWSIM_ATTR_MAX: enum limit */ @@ -184,6 +187,7 @@ enum { HWSIM_ATTR_MLO_SUPPORT, HWSIM_ATTR_PMSR_SUPPORT, HWSIM_ATTR_PMSR_REQUEST, + HWSIM_ATTR_PMSR_RESULT, __HWSIM_ATTR_MAX, }; #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) @@ -288,4 +292,47 @@ enum { HWSIM_VQ_RX, HWSIM_NUM_VQS, }; + +/** + * enum hwsim_rate_info -- bitrate information. + * + * Information about a receiving or transmitting bitrate + * that can be mapped to struct rate_info + * + * @HWSIM_RATE_INFO_ATTR_FLAGS: bitflag of flags from &enum rate_info_flags + * @HWSIM_RATE_INFO_ATTR_MCS: mcs index if struct describes an HT/VHT/HE rate + * @HWSIM_RATE_INFO_ATTR_LEGACY: bitrate in 100kbit/s for 802.11abg + * @HWSIM_RATE_INFO_ATTR_NSS: number of streams (VHT & HE only) + * @HWSIM_RATE_INFO_ATTR_BW: bandwidth (from &enum rate_info_bw) + * @HWSIM_RATE_INFO_ATTR_HE_GI: HE guard interval (from &enum nl80211_he_gi) + * @HWSIM_RATE_INFO_ATTR_HE_DCM: HE DCM value + * @HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC: HE RU allocation (from &enum nl80211_he_ru_alloc, + * only valid if bw is %RATE_INFO_BW_HE_RU) + * @HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH: In case of EDMG the number of bonded channels (1-4) + * @HWSIM_RATE_INFO_ATTR_EHT_GI: EHT guard interval (from &enum nl80211_eht_gi) + * @HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC: EHT RU allocation (from &enum nl80211_eht_ru_alloc, + * only valid if bw is %RATE_INFO_BW_EHT_RU) + * @NUM_HWSIM_RATE_INFO_ATTRS: internal + * @HWSIM_RATE_INFO_ATTR_MAX: highest attribute number + */ +enum hwsim_rate_info_attributes { + __HWSIM_RATE_INFO_ATTR_INVALID, + + HWSIM_RATE_INFO_ATTR_FLAGS, + HWSIM_RATE_INFO_ATTR_MCS, + HWSIM_RATE_INFO_ATTR_LEGACY, + HWSIM_RATE_INFO_ATTR_NSS, + HWSIM_RATE_INFO_ATTR_BW, + HWSIM_RATE_INFO_ATTR_HE_GI, + HWSIM_RATE_INFO_ATTR_HE_DCM, + HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC, + HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH, + HWSIM_RATE_INFO_ATTR_EHT_GI, + HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC, + + /* keep last */ + NUM_HWSIM_RATE_INFO_ATTRS, + HWSIM_RATE_INFO_ATTR_MAX = NUM_HWSIM_RATE_INFO_ATTRS - 1 +}; + #endif /* __MAC80211_HWSIM_H */