Commit 9bb7e0f2 authored by Johannes Berg's avatar Johannes Berg

cfg80211: add peer measurement with FTM initiator API

Add a new "peer measurement" API, that can be used to measure
certain things related to a peer. Right now, only implement
FTM (flight time measurement) over it, but the idea is that
it'll be extensible to also support measuring the necessary
things to calculate e.g. angle-of-arrival for WiGig.

The API is structured to have a generic list of peers and
channels to measure with/on, and then for each of those a
set of measurements (again, only FTM right now) to perform.

Results are sent to the requesting socket, including a final
complete message.

Closing the controlling netlink socket will abort a running
measurement.

v3:
 - add a bit to report "final" for partial results
 - remove list keeping etc. and just unicast out the results
   to the requester (big code reduction ...)
 - also send complete message unicast, and as a result
   remove the multicast group
 - separate out struct cfg80211_pmsr_ftm_request_peer
   from struct cfg80211_pmsr_request_peer
 - document timeout == 0 if no timeout
 - disallow setting timeout nl80211 attribute to 0,
   must not include attribute for no timeout
 - make MAC address randomization optional
 - change num bursts exponent default to 0 (1 burst, rather
   rather than the old default of 15==don't care)

v4:
 - clarify NL80211_ATTR_TIMEOUT documentation

v5:
 - remove unnecessary nl80211 multicast/family changes
 - remove partial results bit/flag, final is sufficient
 - add max_bursts_exponent, max_ftms_per_burst to capability
 - rename "frames per burst" -> "FTMs per burst"

v6:
 - rename cfg80211_pmsr_free_wdev() to cfg80211_pmsr_wdev_down()
   and call it in leave, so the device can't go down with any
   pending measurements

v7:
 - wording fixes (Lior)
 - fix ftm.max_bursts_exponent to allow having the limit of 0 (Lior)

v8:
 - copyright statements
 - minor coding style fixes
 - fix error path leak
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 801f8746
This diff is collapsed.
This diff is collapsed.
...@@ -12,6 +12,7 @@ obj-$(CONFIG_WEXT_PRIV) += wext-priv.o ...@@ -12,6 +12,7 @@ obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
cfg80211-y += pmsr.o
cfg80211-$(CONFIG_OF) += of.o cfg80211-$(CONFIG_OF) += of.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH * Copyright 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
...@@ -664,6 +665,34 @@ int wiphy_register(struct wiphy *wiphy) ...@@ -664,6 +665,34 @@ int wiphy_register(struct wiphy *wiphy)
return -EINVAL; return -EINVAL;
#endif #endif
if (WARN_ON(wiphy->pmsr_capa && !wiphy->pmsr_capa->ftm.supported))
return -EINVAL;
if (wiphy->pmsr_capa && wiphy->pmsr_capa->ftm.supported) {
if (WARN_ON(!wiphy->pmsr_capa->ftm.asap &&
!wiphy->pmsr_capa->ftm.non_asap))
return -EINVAL;
if (WARN_ON(!wiphy->pmsr_capa->ftm.preambles ||
!wiphy->pmsr_capa->ftm.bandwidths))
return -EINVAL;
if (WARN_ON(wiphy->pmsr_capa->ftm.preambles &
~(BIT(NL80211_PREAMBLE_LEGACY) |
BIT(NL80211_PREAMBLE_HT) |
BIT(NL80211_PREAMBLE_VHT) |
BIT(NL80211_PREAMBLE_DMG))))
return -EINVAL;
if (WARN_ON(wiphy->pmsr_capa->ftm.bandwidths &
~(BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_80P80) |
BIT(NL80211_CHAN_WIDTH_160) |
BIT(NL80211_CHAN_WIDTH_5) |
BIT(NL80211_CHAN_WIDTH_10))))
return -EINVAL;
}
/* /*
* if a wiphy has unsupported modes for regulatory channel enforcement, * if a wiphy has unsupported modes for regulatory channel enforcement,
* opt-out of enforcement checking * opt-out of enforcement checking
...@@ -1087,6 +1116,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, ...@@ -1087,6 +1116,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
ASSERT_RTNL(); ASSERT_RTNL();
ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev);
cfg80211_pmsr_wdev_down(wdev);
switch (wdev->iftype) { switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
__cfg80211_leave_ibss(rdev, dev, true); __cfg80211_leave_ibss(rdev, dev, true);
...@@ -1174,6 +1205,9 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev, ...@@ -1174,6 +1205,9 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
spin_lock_init(&wdev->event_lock); spin_lock_init(&wdev->event_lock);
INIT_LIST_HEAD(&wdev->mgmt_registrations); INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock); spin_lock_init(&wdev->mgmt_registrations_lock);
INIT_LIST_HEAD(&wdev->pmsr_list);
spin_lock_init(&wdev->pmsr_lock);
INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
/* /*
* We get here also when the interface changes network namespaces, * We get here also when the interface changes network namespaces,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Wireless configuration interface internals. * Wireless configuration interface internals.
* *
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright (C) 2018 Intel Corporation
*/ */
#ifndef __NET_WIRELESS_CORE_H #ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H
...@@ -530,4 +531,8 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, ...@@ -530,4 +531,8 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
void cfg80211_cqm_config_free(struct wireless_dev *wdev); void cfg80211_cqm_config_free(struct wireless_dev *wdev);
void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid);
void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
void cfg80211_pmsr_free_wk(struct work_struct *work);
#endif /* __NET_WIRELESS_CORE_H */ #endif /* __NET_WIRELESS_CORE_H */
...@@ -240,7 +240,63 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { ...@@ -240,7 +240,63 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
.len = U8_MAX }, .len = U8_MAX },
}; };
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { static const struct nla_policy
nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
NLA_POLICY_MAX(NLA_U8, 15),
[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
NLA_POLICY_MAX(NLA_U8, 15),
[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
NLA_POLICY_MAX(NLA_U8, 15),
[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
};
static const struct nla_policy
nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
[NL80211_PMSR_TYPE_FTM] =
NLA_POLICY_NESTED(NL80211_PMSR_FTM_REQ_ATTR_MAX,
nl80211_pmsr_ftm_req_attr_policy),
};
static const struct nla_policy
nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
[NL80211_PMSR_REQ_ATTR_DATA] =
NLA_POLICY_NESTED(NL80211_PMSR_TYPE_MAX,
nl80211_pmsr_req_data_policy),
[NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
};
static const struct nla_policy
nl80211_psmr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
[NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
/*
* we could specify this again to be the top-level policy,
* but that would open us up to recursion problems ...
*/
[NL80211_PMSR_PEER_ATTR_CHAN] = { .type = NLA_NESTED },
[NL80211_PMSR_PEER_ATTR_REQ] =
NLA_POLICY_NESTED(NL80211_PMSR_REQ_ATTR_MAX,
nl80211_pmsr_req_attr_policy),
[NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
};
static const struct nla_policy
nl80211_pmsr_attr_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(NL80211_PMSR_PEER_ATTR_MAX,
nl80211_psmr_peer_attr_policy),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
.len = 20-1 }, .len = 20-1 },
...@@ -497,6 +553,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { ...@@ -497,6 +553,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
.type = NLA_NESTED, .type = NLA_NESTED,
.validation_data = nl80211_ftm_responder_policy, .validation_data = nl80211_ftm_responder_policy,
}, },
[NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
[NL80211_ATTR_PEER_MEASUREMENTS] =
NLA_POLICY_NESTED(NL80211_PMSR_FTM_REQ_ATTR_MAX,
nl80211_pmsr_attr_policy),
}; };
/* policy for the key attributes */ /* policy for the key attributes */
...@@ -637,9 +697,9 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = { ...@@ -637,9 +697,9 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
[NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 }, [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
}; };
static int nl80211_prepare_wdev_dump(struct netlink_callback *cb, int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
struct cfg80211_registered_device **rdev, struct cfg80211_registered_device **rdev,
struct wireless_dev **wdev) struct wireless_dev **wdev)
{ {
int err; int err;
...@@ -684,8 +744,8 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb, ...@@ -684,8 +744,8 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
} }
/* message building helper */ /* message building helper */
static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
int flags, u8 cmd) int flags, u8 cmd)
{ {
/* since there is no private header just add the generic one */ /* since there is no private header just add the generic one */
return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd); return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
...@@ -1615,6 +1675,91 @@ static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev, ...@@ -1615,6 +1675,91 @@ static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
return -ENOBUFS; return -ENOBUFS;
} }
static int
nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
struct sk_buff *msg)
{
struct nlattr *ftm;
if (!cap->ftm.supported)
return 0;
ftm = nla_nest_start(msg, NL80211_PMSR_TYPE_FTM);
if (!ftm)
return -ENOBUFS;
if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
return -ENOBUFS;
if (cap->ftm.non_asap &&
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
return -ENOBUFS;
if (cap->ftm.request_lci &&
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
return -ENOBUFS;
if (cap->ftm.request_civicloc &&
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
return -ENOBUFS;
if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
cap->ftm.preambles))
return -ENOBUFS;
if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
cap->ftm.bandwidths))
return -ENOBUFS;
if (cap->ftm.max_bursts_exponent >= 0 &&
nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
cap->ftm.max_bursts_exponent))
return -ENOBUFS;
if (cap->ftm.max_ftms_per_burst &&
nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
cap->ftm.max_ftms_per_burst))
return -ENOBUFS;
nla_nest_end(msg, ftm);
return 0;
}
static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
struct sk_buff *msg)
{
const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
struct nlattr *pmsr, *caps;
if (!cap)
return 0;
/*
* we don't need to clean up anything here since the caller
* will genlmsg_cancel() if we fail
*/
pmsr = nla_nest_start(msg, NL80211_ATTR_PEER_MEASUREMENTS);
if (!pmsr)
return -ENOBUFS;
if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
return -ENOBUFS;
if (cap->report_ap_tsf &&
nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
return -ENOBUFS;
if (cap->randomize_mac_addr &&
nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
return -ENOBUFS;
caps = nla_nest_start(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
if (!caps)
return -ENOBUFS;
if (nl80211_send_pmsr_ftm_capa(cap, msg))
return -ENOBUFS;
nla_nest_end(msg, caps);
nla_nest_end(msg, pmsr);
return 0;
}
struct nl80211_dump_wiphy_state { struct nl80211_dump_wiphy_state {
s64 filter_wiphy; s64 filter_wiphy;
long start; long start;
...@@ -2118,6 +2263,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, ...@@ -2118,6 +2263,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
goto nla_put_failure; goto nla_put_failure;
} }
state->split_start++;
break;
case 14:
if (nl80211_send_pmsr_capa(rdev, msg))
goto nla_put_failure;
/* done */ /* done */
state->split_start = 0; state->split_start = 0;
break; break;
...@@ -2318,9 +2469,9 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) ...@@ -2318,9 +2469,9 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
wdev->iftype == NL80211_IFTYPE_P2P_GO; wdev->iftype == NL80211_IFTYPE_P2P_GO;
} }
static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
struct genl_info *info, struct genl_info *info,
struct cfg80211_chan_def *chandef) struct cfg80211_chan_def *chandef)
{ {
struct netlink_ext_ack *extack = info->extack; struct netlink_ext_ack *extack = info->extack;
struct nlattr **attrs = info->attrs; struct nlattr **attrs = info->attrs;
...@@ -2794,12 +2945,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2794,12 +2945,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
return 0; return 0;
} }
static inline u64 wdev_id(struct wireless_dev *wdev)
{
return (u64)wdev->identifier |
((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
}
static int nl80211_send_chandef(struct sk_buff *msg, static int nl80211_send_chandef(struct sk_buff *msg,
const struct cfg80211_chan_def *chandef) const struct cfg80211_chan_def *chandef)
{ {
...@@ -4521,8 +4666,7 @@ static int parse_station_flags(struct genl_info *info, ...@@ -4521,8 +4666,7 @@ static int parse_station_flags(struct genl_info *info,
return 0; return 0;
} }
static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
int attr)
{ {
struct nlattr *rate; struct nlattr *rate;
u32 bitrate; u32 bitrate;
...@@ -6855,8 +6999,8 @@ static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy, ...@@ -6855,8 +6999,8 @@ static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
return 0; return 0;
} }
static int nl80211_parse_random_mac(struct nlattr **attrs, int nl80211_parse_random_mac(struct nlattr **attrs,
u8 *mac_addr, u8 *mac_addr_mask) u8 *mac_addr, u8 *mac_addr_mask)
{ {
int i; int i;
...@@ -13898,6 +14042,14 @@ static const struct genl_ops nl80211_ops[] = { ...@@ -13898,6 +14042,14 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV | .internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL, NL80211_FLAG_NEED_RTNL,
}, },
{
.cmd = NL80211_CMD_PEER_MEASUREMENT_START,
.doit = nl80211_pmsr_start,
.policy = nl80211_policy,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
}; };
static struct genl_family nl80211_fam __ro_after_init = { static struct genl_family nl80211_fam __ro_after_init = {
...@@ -15881,6 +16033,8 @@ static int nl80211_netlink_notify(struct notifier_block * nb, ...@@ -15881,6 +16033,8 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
} else if (wdev->conn_owner_nlportid == notify->portid) { } else if (wdev->conn_owner_nlportid == notify->portid) {
schedule_work(&wdev->disconnect_wk); schedule_work(&wdev->disconnect_wk);
} }
cfg80211_release_pmsr(wdev, notify->portid);
} }
spin_lock_bh(&rdev->beacon_registrations_lock); spin_lock_bh(&rdev->beacon_registrations_lock);
......
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
/*
* Portions of this file
* Copyright (C) 2018 Intel Corporation
*/
#ifndef __NET_WIRELESS_NL80211_H #ifndef __NET_WIRELESS_NL80211_H
#define __NET_WIRELESS_NL80211_H #define __NET_WIRELESS_NL80211_H
...@@ -6,6 +10,30 @@ ...@@ -6,6 +10,30 @@
int nl80211_init(void); int nl80211_init(void);
void nl80211_exit(void); void nl80211_exit(void);
extern const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
int flags, u8 cmd);
bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
int attr);
static inline u64 wdev_id(struct wireless_dev *wdev)
{
return (u64)wdev->identifier |
((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
}
int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
struct cfg80211_registered_device **rdev,
struct wireless_dev **wdev);
int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
struct genl_info *info,
struct cfg80211_chan_def *chandef);
int nl80211_parse_random_mac(struct nlattr **attrs,
u8 *mac_addr, u8 *mac_addr_mask);
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
enum nl80211_commands cmd); enum nl80211_commands cmd);
void nl80211_notify_iface(struct cfg80211_registered_device *rdev, void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
...@@ -95,4 +123,8 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev); ...@@ -95,4 +123,8 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev);
void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
/* peer measurement */
int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info);
int nl80211_pmsr_dump_results(struct sk_buff *skb, struct netlink_callback *cb);
#endif /* __NET_WIRELESS_NL80211_H */ #endif /* __NET_WIRELESS_NL80211_H */
This diff is collapsed.
...@@ -1247,4 +1247,29 @@ rdev_get_ftm_responder_stats(struct cfg80211_registered_device *rdev, ...@@ -1247,4 +1247,29 @@ rdev_get_ftm_responder_stats(struct cfg80211_registered_device *rdev,
return ret; return ret;
} }
static inline int
rdev_start_pmsr(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct cfg80211_pmsr_request *request)
{
int ret = -EOPNOTSUPP;
trace_rdev_start_pmsr(&rdev->wiphy, wdev, request->cookie);
if (rdev->ops->start_pmsr)
ret = rdev->ops->start_pmsr(&rdev->wiphy, wdev, request);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
static inline void
rdev_abort_pmsr(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct cfg80211_pmsr_request *request)
{
trace_rdev_abort_pmsr(&rdev->wiphy, wdev, request->cookie);
if (rdev->ops->abort_pmsr)
rdev->ops->abort_pmsr(&rdev->wiphy, wdev, request);
trace_rdev_return_void(&rdev->wiphy);
}
#endif /* __CFG80211_RDEV_OPS */ #endif /* __CFG80211_RDEV_OPS */
...@@ -361,6 +361,24 @@ DECLARE_EVENT_CLASS(wiphy_wdev_evt, ...@@ -361,6 +361,24 @@ DECLARE_EVENT_CLASS(wiphy_wdev_evt,
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
); );
DECLARE_EVENT_CLASS(wiphy_wdev_cookie_evt,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
TP_ARGS(wiphy, wdev, cookie),
TP_STRUCT__entry(
WIPHY_ENTRY
WDEV_ENTRY
__field(u64, cookie)
),
TP_fast_assign(
WIPHY_ASSIGN;
WDEV_ASSIGN;
__entry->cookie = cookie;
),
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %lld",
WIPHY_PR_ARG, WDEV_PR_ARG,
(unsigned long long)__entry->cookie)
);
DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev, DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
TP_ARGS(wiphy, wdev) TP_ARGS(wiphy, wdev)
...@@ -2502,6 +2520,16 @@ TRACE_EVENT(rdev_get_ftm_responder_stats, ...@@ -2502,6 +2520,16 @@ TRACE_EVENT(rdev_get_ftm_responder_stats,
__entry->out_of_window) __entry->out_of_window)
); );
DEFINE_EVENT(wiphy_wdev_cookie_evt, rdev_start_pmsr,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
TP_ARGS(wiphy, wdev, cookie)
);
DEFINE_EVENT(wiphy_wdev_cookie_evt, rdev_abort_pmsr,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
TP_ARGS(wiphy, wdev, cookie)
);
/************************************************************* /*************************************************************
* cfg80211 exported functions traces * * cfg80211 exported functions traces *
*************************************************************/ *************************************************************/
...@@ -3294,6 +3322,46 @@ TRACE_EVENT(cfg80211_stop_iface, ...@@ -3294,6 +3322,46 @@ TRACE_EVENT(cfg80211_stop_iface,
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
WIPHY_PR_ARG, WDEV_PR_ARG) WIPHY_PR_ARG, WDEV_PR_ARG)
); );
TRACE_EVENT(cfg80211_pmsr_report,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
u64 cookie, const u8 *addr),
TP_ARGS(wiphy, wdev, cookie, addr),
TP_STRUCT__entry(
WIPHY_ENTRY
WDEV_ENTRY
__field(u64, cookie)
MAC_ENTRY(addr)
),
TP_fast_assign(
WIPHY_ASSIGN;
WDEV_ASSIGN;
__entry->cookie = cookie;
MAC_ASSIGN(addr, addr);
),
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie:%lld, " MAC_PR_FMT,
WIPHY_PR_ARG, WDEV_PR_ARG,
(unsigned long long)__entry->cookie,
MAC_PR_ARG(addr))
);
TRACE_EVENT(cfg80211_pmsr_complete,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
TP_ARGS(wiphy, wdev, cookie),
TP_STRUCT__entry(
WIPHY_ENTRY
WDEV_ENTRY
__field(u64, cookie)
),
TP_fast_assign(
WIPHY_ASSIGN;
WDEV_ASSIGN;
__entry->cookie = cookie;
),
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie:%lld",
WIPHY_PR_ARG, WDEV_PR_ARG,
(unsigned long long)__entry->cookie)
);
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH #undef TRACE_INCLUDE_PATH
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment