wifi: cfg80211/nl80211: add STA-mode peer probing

Add NL80211_EXT_FEATURE_PROBE_AP to allow drivers to advertise
support for probing the associated AP from STA/P2P-client mode.

Extend nl80211_probe_peer() to accept STA/P2P-client interfaces
when the driver advertises NL80211_EXT_FEATURE_PROBE_AP; in that
case the MAC attribute must be omitted (the peer is implied by
the association).

Update cfg80211_probe_status() to accept an optional peer address
and a link_id parameter (-1 for non-MLO), and include
NL80211_ATTR_MLO_LINK_ID in the event when link_id >= 0.
Update all callers.

Signed-off-by: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
Link: https://patch.msgid.link/20260611062225.2144241-3-pritiwa@qti.qualcomm.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Priyansha Tiwari
2026-06-11 11:52:23 +05:30
committed by Johannes Berg
parent 4ab9b637b9
commit 010e955c20
5 changed files with 59 additions and 31 deletions

View File

@@ -2326,7 +2326,7 @@ static void wil_probe_client_handle(struct wil6210_priv *wil,
*/
bool alive = (sta->status == wil_sta_connected);
cfg80211_probe_status(ndev, sta->addr, req->cookie, alive,
cfg80211_probe_status(ndev, sta->addr, req->cookie, -1, alive,
0, false, GFP_KERNEL);
}

View File

@@ -5086,8 +5086,8 @@ struct mgmt_frame_regs {
* @tdls_mgmt: Transmit a TDLS management frame.
* @tdls_oper: Perform a high-level TDLS operation (e.g. TDLS link setup).
*
* @probe_peer: probe an associated client, must return a cookie that it
* later passes to cfg80211_probe_status().
* @probe_peer: probe a connected peer (AP: STA MAC required; STA: no MAC),
* must return a cookie that is later passed to cfg80211_probe_status().
*
* @set_noack_map: Set the NoAck Map for the TIDs.
*
@@ -9846,15 +9846,17 @@ bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, const u8 *addr,
/**
* cfg80211_probe_status - notify userspace about probe status
* @dev: the device the probe was sent on
* @addr: the address of the peer
* @cookie: the cookie filled in @probe_client previously
* @peer: The peer MAC address (or MLD address for MLO) or %NULL if not
* applicable (e.g. for STA/P2P-client)
* @cookie: the cookie filled in @probe_peer previously
* @link_id: The link ID on which the probe was sent (or -1 for non-MLO)
* @acked: indicates whether probe was acked or not
* @ack_signal: signal strength (in dBm) of the ACK frame.
* @is_valid_ack_signal: indicates the ack_signal is valid or not.
* @gfp: allocation flags
*/
void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
u64 cookie, bool acked, s32 ack_signal,
void cfg80211_probe_status(struct net_device *dev, const u8 *peer, u64 cookie,
int link_id, bool acked, s32 ack_signal,
bool is_valid_ack_signal, gfp_t gfp);
/**

View File

@@ -922,13 +922,15 @@
* and wasn't already in a 4-addr VLAN. The event will be sent similarly
* to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener.
*
* @NL80211_CMD_PROBE_PEER: Probe an associated station on an AP interface
* by sending a null data frame to it and reporting when the frame is
* acknowledged. This is used to allow timing out inactive clients. Uses
* %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a
* direct reply with an %NL80211_ATTR_COOKIE that is later used to match
* up the event with the request. The event includes the same data and
* has %NL80211_ATTR_ACK set if the frame was ACKed.
* @NL80211_CMD_PROBE_PEER: Probe a connected peer by sending a null data
* frame and reporting when the frame is acknowledged.
* In AP/GO mode, %NL80211_ATTR_MAC is required to identify the client.
* In STA/P2P-client mode, %NL80211_ATTR_MAC must be omitted (the AP is
* implied); the driver must advertise %NL80211_EXT_FEATURE_PROBE_AP.
* The command returns a direct reply with an %NL80211_ATTR_COOKIE that
* is later used to match up the event with the request. The event
* includes the same data and has %NL80211_ATTR_ACK set if the frame
* was ACKed.
*
* @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from
* other BSSes when any interfaces are in AP mode. This helps implement
@@ -7086,6 +7088,9 @@ enum nl80211_feature_flags {
* LTF key seed via %NL80211_KEY_LTF_SEED. The seed is used to generate
* secure LTF keys for secure LTF measurement sessions.
*
* @NL80211_EXT_FEATURE_PROBE_AP: Driver supports probing the associated AP
* in STA mode using @NL80211_CMD_PROBE_PEER.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -7167,6 +7172,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_IEEE8021X_AUTH,
NL80211_EXT_FEATURE_ROC_ADDR_FILTER,
NL80211_EXT_FEATURE_SET_KEY_LTF_SEED,
NL80211_EXT_FEATURE_PROBE_AP,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,

View File

@@ -655,7 +655,7 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
GFP_ATOMIC);
else if (ieee80211_is_any_nullfunc(hdr->frame_control))
cfg80211_probe_status(sdata->dev, hdr->addr1,
cookie, acked,
cookie, -1, acked,
info->status.ack_signal,
is_valid_ack_signal,
GFP_ATOMIC);

View File

@@ -16157,16 +16157,32 @@ static int nl80211_probe_peer(struct sk_buff *skb, struct genl_info *info)
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct sk_buff *msg;
void *hdr;
const u8 *addr;
const u8 *addr = NULL;
u64 cookie;
int err;
if (wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO)
/* Allow in AP, STA, and their P2P counterparts */
switch (wdev->iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL;
addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
if (!wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_PROBE_AP))
return -EOPNOTSUPP;
if (!wdev->connected)
return -ENOLINK;
/* STA/P2P-client probes the currently associated AP/GO. */
if (info->attrs[NL80211_ATTR_MAC])
return -EINVAL;
break;
default:
return -EOPNOTSUPP;
if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL;
}
if (!rdev->ops->probe_peer)
return -EOPNOTSUPP;
@@ -16182,8 +16198,6 @@ static int nl80211_probe_peer(struct sk_buff *skb, struct genl_info *info)
goto free_msg;
}
addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
err = rdev_probe_peer(rdev, dev, addr, &cookie);
if (err)
goto free_msg;
@@ -22597,8 +22611,8 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
}
EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
u64 cookie, bool acked, s32 ack_signal,
void cfg80211_probe_status(struct net_device *dev, const u8 *peer, u64 cookie,
int link_id, bool acked, s32 ack_signal,
bool is_valid_ack_signal, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -22606,7 +22620,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
struct sk_buff *msg;
void *hdr;
trace_cfg80211_probe_status(dev, addr, cookie, acked);
trace_cfg80211_probe_status(dev, peer, cookie, acked);
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
@@ -22621,12 +22635,18 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
(peer && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) ||
nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
NL80211_ATTR_PAD) ||
(acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
(is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
ack_signal)))
NL80211_ATTR_PAD))
goto nla_put_failure;
if (link_id >= 0 &&
nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
goto nla_put_failure;
if ((acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
(is_valid_ack_signal &&
nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL, ack_signal)))
goto nla_put_failure;
genlmsg_end(msg, hdr);