* [PATCH wireless-next v1 0/4] wifi: nl80211: introduce PROBE_PEER for AP and STA with MLO support
@ 2026-04-15 9:43 Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support Priyansha Tiwari
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Priyansha Tiwari @ 2026-04-15 9:43 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, quic_drohan
From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
This series introduces a unified mechanism to probe connected peers.
It generalizes the legacy AP-only PROBE_CLIENT functionality by adding
NL80211_CMD_PROBE_PEER and enabling (feature-gated) STA-side probing.
With this, AP/GO continues to probe associated stations as before, and
STA/P2P-client can probe the connected AP for faster link health checks.
For MLO connections, mac80211 supports per-link STA probing to obtain
link-specific ACK and RSSI information.
Patch 1 adds NL80211_CMD_PROBE_PEER (keeping PROBE_CLIENT as a
compatibility alias) and introduces NL80211_EXT_FEATURE_PROBE_AP to
advertise STA-side support in drivers/firmware.
Patch 2 renames the cfg80211 driver op from probe_client() to probe_peer(),
extends cfg80211_probe_status() to carry (peer address, link_id), updates the
nl80211 handler to NL80211_CMD_PROBE_PEER with proper validation (AP/GO:
MAC required; STA: MAC omitted, feature-gated), and adjusts all in-tree
users (wil6210, mwifiex, mac80211) so the tree builds after this patch.
Patch 3 adds per-link PROBE_PEER support in mac80211 for STA/P2P-client
mode. For MLO STA/P2P-client, it uses IEEE80211_LINK_UNSPECIFIED with
MLD addresses and lets the driver select the link. For non-MLO
STA/P2P-client, it uses link 0 with the per-link BSSID and link
address. In the TX status path, the peer address is omitted for
STA/P2P-client mode and the transmitted link is reported through the
link_valid/link_id bitfields in struct ieee80211_tx_info.status, which
drivers fill before calling ieee80211_tx_status_ext(). AP/GO behavior
is unchanged.
Patch 4 makes mac80211_hwsim populate link_valid/link_id in TX status
for both the direct TX status path and the wmediumd/netlink TX status
path.
Priyansha Tiwari (4):
wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side
probing support
wifi: cfg80211/nl80211: rename to probe_peer(), extend probe status,
and update in-tree users
wifi: mac80211: add per-link PROBE_PEER support
wifi: mac80211_hwsim: report TX status link_id
drivers/net/wireless/ath/wil6210/cfg80211.c | 11 +-
.../net/wireless/marvell/mwifiex/cfg80211.c | 8 +-
drivers/net/wireless/virtual/mac80211_hwsim.c | 46 +++-
include/net/cfg80211.h | 16 +-
include/net/mac80211.h | 2 +-
include/uapi/linux/nl80211.h | 27 ++-
net/mac80211/cfg.c | 199 ++++++++++++------
net/mac80211/status.c | 30 ++-
net/wireless/nl80211.c | 93 +++++---
net/wireless/rdev-ops.h | 10 +-
net/wireless/trace.h | 2 +-
11 files changed, 315 insertions(+), 129 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support
2026-04-15 9:43 [PATCH wireless-next v1 0/4] wifi: nl80211: introduce PROBE_PEER for AP and STA with MLO support Priyansha Tiwari
@ 2026-04-15 9:43 ` Priyansha Tiwari
2026-04-15 9:53 ` Johannes Berg
2026-04-15 9:43 ` [PATCH wireless-next v1 2/4] wifi: cfg80211/nl80211: rename to probe_peer(), extend probe status, and update in-tree users Priyansha Tiwari
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Priyansha Tiwari @ 2026-04-15 9:43 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, quic_drohan
From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
Rename NL80211_CMD_PROBE_CLIENT to NL80211_CMD_PROBE_PEER to generalize
peer probing, AP/GO continue to probe associated STAs (legacy PROBE_CLIENT
behavior) while, when the driver advertises NL80211_EXT_FEATURE_PROBE_AP,
a STA/P2P-client may probe its currently associated AP to quickly verify link
responsiveness without waiting for traffic or long timeouts.
Userspace and cfg80211 rely on this feature flag to determine whether
STA-mode probing is supported. The command returns a cookie in the direct
reply and delivers an event that indicates ACK (and, if available,
signed-dBm ACK_SIGNAL).
For MLO connections the event carries MLO_LINK_ID identifying the link on
which the probe was ACKed. In AP/GO mode the peer MAC is required, while in
STA/P2P-client mode the MAC is omitted (AP implied).
NL80211_CMD_PROBE_CLIENT is retained as a compatibility alias.
Signed-off-by: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
---
include/uapi/linux/nl80211.h | 27 +++++++++++++++++++++------
net/wireless/nl80211.c | 6 +++---
2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 3d55bf4be36f..5c1b00bf8161 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -920,13 +920,23 @@
* 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_CLIENT: Probe an associated station on an AP interface
+ * @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_ATTR_IFINDEX and %NL80211_ATTR_MAC (required in AP/GO mode).
+ * This command can also be used on a STA/P2P-client interface to probe
+ * the currently associated AP/GO, when the driver indicates
+ * %NL80211_EXT_FEATURE_PROBE_AP; in that case %NL80211_ATTR_MAC must
+ * be omitted (the peer is implied by the association).
+ *
+ * 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.
+ *
+ * In case of an MLO connection, the event includes
+ * %NL80211_ATTR_MLO_LINK_ID to indicate the link on which the null data
+ * frame was transmitted and ACKed.
*
* @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from
* other BSSes when any interfaces are in AP mode. This helps implement
@@ -1548,7 +1558,7 @@ enum nl80211_commands {
NL80211_CMD_UNEXPECTED_FRAME,
- NL80211_CMD_PROBE_CLIENT,
+ NL80211_CMD_PROBE_PEER,
NL80211_CMD_REGISTER_BEACONS,
@@ -1716,6 +1726,7 @@ enum nl80211_commands {
#define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG
#define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG
#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE
+#define NL80211_CMD_PROBE_CLIENT NL80211_CMD_PROBE_PEER
/**
* enum nl80211_attrs - nl80211 netlink attributes
@@ -7029,6 +7040,9 @@ enum nl80211_feature_flags {
* (NL80211_CMD_AUTHENTICATE) in non-AP STA mode, as specified in
* "IEEE P802.11bi/D4.0, 12.16.5".
*
+ * @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.
*/
@@ -7108,6 +7122,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_EPPKE,
NL80211_EXT_FEATURE_ASSOC_FRAME_ENCRYPTION,
NL80211_EXT_FEATURE_IEEE8021X_AUTH,
+ NL80211_EXT_FEATURE_PROBE_AP,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f334cdef8958..e7be43f023b6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15817,7 +15817,7 @@ static int nl80211_probe_client(struct sk_buff *skb,
return -ENOMEM;
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
- NL80211_CMD_PROBE_CLIENT);
+ NL80211_CMD_PROBE_PEER);
if (!hdr) {
err = -ENOBUFS;
goto free_msg;
@@ -19627,7 +19627,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
- .cmd = NL80211_CMD_PROBE_CLIENT,
+ .cmd = NL80211_CMD_PROBE_PEER,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_probe_client,
.flags = GENL_UNS_ADMIN_PERM,
@@ -22181,7 +22181,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
if (!msg)
return;
- hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_PEER);
if (!hdr) {
nlmsg_free(msg);
return;
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH wireless-next v1 2/4] wifi: cfg80211/nl80211: rename to probe_peer(), extend probe status, and update in-tree users
2026-04-15 9:43 [PATCH wireless-next v1 0/4] wifi: nl80211: introduce PROBE_PEER for AP and STA with MLO support Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support Priyansha Tiwari
@ 2026-04-15 9:43 ` Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 3/4] wifi: mac80211: add per-link PROBE_PEER support Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 4/4] wifi: mac80211_hwsim: report TX status link_id Priyansha Tiwari
3 siblings, 0 replies; 8+ messages in thread
From: Priyansha Tiwari @ 2026-04-15 9:43 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, quic_drohan
From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
Rename probe_client() to probe_peer() to reflect that probing is no longer
limited to AP clients and may be used for any connected peer.
Extend cfg80211_probe_status() to include peer and link_id so drivers can
report per-link results.
Update nl80211 handler to NL80211_CMD_PROBE_PEER with AP/GO requiring MAC
and STA/P2P-client omitting MAC (AP implied), and gate STA-mode probing via
NL80211_EXT_FEATURE_PROBE_AP.
Update in-tree users (wil6210, mwifiex) and mac80211 so the tree continues
to build after this change.
mac80211 switches cfg80211_ops to .probe_peer and passes link_id = -1
at the probe status callsite to preserve existing behavior.
This change is otherwise behavior-neutral, per-link STA reporting will
follow in a subsequent patch.
Signed-off-by: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 11 +--
.../net/wireless/marvell/mwifiex/cfg80211.c | 8 +-
include/net/cfg80211.h | 16 ++--
net/mac80211/cfg.c | 6 +-
net/mac80211/status.c | 2 +-
net/wireless/nl80211.c | 87 +++++++++++++------
net/wireless/rdev-ops.h | 10 +--
net/wireless/trace.h | 2 +-
8 files changed, 89 insertions(+), 53 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 3d6e5aad48b1..7d04594e974f 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/etherdevice.h>
@@ -2325,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);
}
@@ -2378,9 +2379,9 @@ void wil_probe_client_flush(struct wil6210_vif *vif)
mutex_unlock(&vif->probe_client_mutex);
}
-static int wil_cfg80211_probe_client(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *peer, u64 *cookie)
+static int wil_cfg80211_probe_peer(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer, u64 *cookie)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
struct wil6210_vif *vif = ndev_to_vif(dev);
@@ -2659,7 +2660,7 @@ static const struct cfg80211_ops wil_cfg80211_ops = {
.add_station = wil_cfg80211_add_station,
.del_station = wil_cfg80211_del_station,
.change_station = wil_cfg80211_change_station,
- .probe_client = wil_cfg80211_probe_client,
+ .probe_peer = wil_cfg80211_probe_peer,
.change_bss = wil_cfg80211_change_bss,
/* P2P device */
.start_p2p_device = wil_cfg80211_start_p2p_device,
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index c9a651bdf882..dae10236f460 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4557,9 +4557,9 @@ mwifiex_cfg80211_disassociate(struct wiphy *wiphy,
}
static int
-mwifiex_cfg80211_probe_client(struct wiphy *wiphy,
- struct net_device *dev, const u8 *peer,
- u64 *cookie)
+mwifiex_cfg80211_probe_peer(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *peer,
+ u64 *cookie)
{
/* hostapd looks for NL80211_CMD_PROBE_CLIENT support; otherwise,
* it requires monitor-mode support (which mwifiex doesn't support).
@@ -4725,7 +4725,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
ops->disassoc = mwifiex_cfg80211_disassociate;
ops->disconnect = NULL;
ops->connect = NULL;
- ops->probe_client = mwifiex_cfg80211_probe_client;
+ ops->probe_peer = mwifiex_cfg80211_probe_peer;
}
wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9d3639ff9c28..6675c6021fa5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4921,8 +4921,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_client: 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.
*
@@ -5320,8 +5320,8 @@ struct cfg80211_ops {
int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, enum nl80211_tdls_operation oper);
- int (*probe_client)(struct wiphy *wiphy, struct net_device *dev,
- const u8 *peer, u64 *cookie);
+ int (*probe_peer)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, u64 *cookie);
int (*set_noack_map)(struct wiphy *wiphy,
struct net_device *dev,
@@ -9602,15 +9602,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
+ * @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_client 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);
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7b77d57c9f96..abd0ac20f0da 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4746,8 +4746,8 @@ static int ieee80211_set_rekey_data(struct wiphy *wiphy,
return 0;
}
-static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
- const u8 *peer, u64 *cookie)
+static int ieee80211_probe_peer(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, u64 *cookie)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
@@ -5835,7 +5835,7 @@ const struct cfg80211_ops mac80211_config_ops = {
.tdls_mgmt = ieee80211_tdls_mgmt,
.tdls_channel_switch = ieee80211_tdls_channel_switch,
.tdls_cancel_channel_switch = ieee80211_tdls_cancel_channel_switch,
- .probe_client = ieee80211_probe_client,
+ .probe_peer = ieee80211_probe_peer,
.set_noack_map = ieee80211_set_noack_map,
#ifdef CONFIG_PM
.set_wakeup = ieee80211_set_wakeup,
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 4b38aa0e902a..4a64ac6d1451 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -654,7 +654,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);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e7be43f023b6..a7623200d9cb 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2400,7 +2400,7 @@ static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
}
if (rdev->wiphy.max_sched_scan_reqs)
CMD(sched_scan_start, START_SCHED_SCAN);
- CMD(probe_client, PROBE_CLIENT);
+ CMD(probe_peer, PROBE_PEER);
CMD(set_noack_map, SET_NOACK_MAP);
if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
i++;
@@ -15790,26 +15790,44 @@ static int nl80211_register_unexpected_frame(struct sk_buff *skb,
return 0;
}
-static int nl80211_probe_client(struct sk_buff *skb,
- struct genl_info *info)
+static int nl80211_probe_peer(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
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)
- return -EOPNOTSUPP;
+ /* Allow in AP, STA, and their P2P counterparts (and MLO) */
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ if (!info->attrs[NL80211_ATTR_MAC])
+ return -EINVAL;
- 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 (!rdev->ops->probe_client)
+ 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 (!rdev->ops->probe_peer)
return -EOPNOTSUPP;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -15823,9 +15841,8 @@ static int nl80211_probe_client(struct sk_buff *skb,
goto free_msg;
}
- addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- err = rdev_probe_client(rdev, dev, addr, &cookie);
+ err = rdev_probe_peer(rdev, dev, addr, &cookie);
if (err)
goto free_msg;
@@ -19629,7 +19646,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
{
.cmd = NL80211_CMD_PROBE_PEER,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
- .doit = nl80211_probe_client,
+ .doit = nl80211_probe_peer,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
@@ -22165,8 +22182,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;
@@ -22174,31 +22191,47 @@ 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);
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ if (WARN_ON(peer))
+ return;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ if (WARN_ON(!peer))
+ return;
+ break;
+ default:
+ break;
+ }
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_PEER);
- if (!hdr) {
- nlmsg_free(msg);
- return;
- }
+ if (!hdr)
+ goto nla_put_failure;
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;
- genlmsg_end(msg, hdr);
+ 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);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
NL80211_MCGRP_MLME, gfp);
return;
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index bba239a068f6..f821411e6721 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -947,13 +947,13 @@ static inline int rdev_tdls_oper(struct cfg80211_registered_device *rdev,
return ret;
}
-static inline int rdev_probe_client(struct cfg80211_registered_device *rdev,
- struct net_device *dev, const u8 *peer,
- u64 *cookie)
+static inline int rdev_probe_peer(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *peer,
+ u64 *cookie)
{
int ret;
- trace_rdev_probe_client(&rdev->wiphy, dev, peer);
- ret = rdev->ops->probe_client(&rdev->wiphy, dev, peer, cookie);
+ trace_rdev_probe_peer(&rdev->wiphy, dev, peer);
+ ret = rdev->ops->probe_peer(&rdev->wiphy, dev, peer, cookie);
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
return ret;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index eb5bedf9c92a..9635f53fa358 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2122,7 +2122,7 @@ DECLARE_EVENT_CLASS(rdev_pmksa,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid)
);
-TRACE_EVENT(rdev_probe_client,
+TRACE_EVENT(rdev_probe_peer,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
const u8 *peer),
TP_ARGS(wiphy, netdev, peer),
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH wireless-next v1 3/4] wifi: mac80211: add per-link PROBE_PEER support
2026-04-15 9:43 [PATCH wireless-next v1 0/4] wifi: nl80211: introduce PROBE_PEER for AP and STA with MLO support Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 2/4] wifi: cfg80211/nl80211: rename to probe_peer(), extend probe status, and update in-tree users Priyansha Tiwari
@ 2026-04-15 9:43 ` Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 4/4] wifi: mac80211_hwsim: report TX status link_id Priyansha Tiwari
3 siblings, 0 replies; 8+ messages in thread
From: Priyansha Tiwari @ 2026-04-15 9:43 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, quic_drohan
From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
Extend ieee80211_probe_peer() to support STA/P2P-client mode. Reject the
request if a peer MAC address is provided or if the interface is not
associated.
For MLO STA/P2P-client, construct the nullfunc using MLD addresses and
set IEEE80211_LINK_UNSPECIFIED in the TX control flags so the driver can
choose the link. For non-MLO STA/P2P-client, use link 0 together with
the corresponding per-link BSSID and link address.
In the TX status path, report probe status for STA/P2P-client mode
without a peer address and include the transmitted link in
cfg80211_probe_status(). Add link_valid/link_id bitfields to
struct ieee80211_tx_info.status so drivers can report the link used
for the completed TX.
Signed-off-by: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
---
include/net/mac80211.h | 2 +-
net/mac80211/cfg.c | 193 ++++++++++++++++++++++++++++-------------
net/mac80211/status.c | 30 ++++++-
3 files changed, 158 insertions(+), 67 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 40cb20d9309c..f93d15c61a52 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1364,7 +1364,7 @@ struct ieee80211_tx_info {
u8 pad;
u16 tx_time;
u8 flags;
- u8 pad2;
+ u8 link_valid:1, link_id:4, pad2:3;
void *status_driver_data[16 / sizeof(void *)];
} status;
struct {
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index abd0ac20f0da..f5b3c9bd67f8 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4753,101 +4753,174 @@ static int ieee80211_probe_peer(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_local *local = sdata->local;
struct ieee80211_qos_hdr *nullfunc;
struct sk_buff *skb;
- int size = sizeof(*nullfunc);
__le16 fc;
bool qos;
+ struct ieee80211_bss_conf *conf;
struct ieee80211_tx_info *info;
struct sta_info *sta;
struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_bss_conf *conf;
enum nl80211_band band;
- u8 link_id;
+ const u8 *peer_addr = peer;
+ const u8 *src_addr;
+ int link_id;
+ int size;
int ret;
/* the lock is needed to assign the cookie later */
lockdep_assert_wiphy(local->hw.wiphy);
- rcu_read_lock();
- sta = sta_info_get_bss(sdata, peer);
- if (!sta) {
- ret = -ENOLINK;
- goto unlock;
+ /* STA/P2P: userspace must NOT provide peer MAC, AP is implied. */
+ if (sdata->vif.type == NL80211_IFTYPE_STATION ||
+ sdata->vif.type == NL80211_IFTYPE_P2P_CLIENT) {
+ if (peer)
+ return -EINVAL;
+
+ if (!sdata->u.mgd.associated)
+ return -ENOTCONN;
+ } else if (!peer) {
+ /* AP/GO: must have a peer MAC. */
+ return -EINVAL;
}
- qos = sta->sta.wme;
+ guard(rcu)();
- if (ieee80211_vif_is_mld(&sdata->vif)) {
- if (sta->sta.mlo) {
- link_id = IEEE80211_LINK_UNSPECIFIED;
- } else {
- /*
- * For non-MLO clients connected to an AP MLD, band
- * information is not used; instead, sta->deflink is
- * used to send packets.
- */
- link_id = sta->deflink.link_id;
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_P2P_GO) {
+ sta = sta_info_get_bss(sdata, peer);
+ if (!sta)
+ return -ENOLINK;
- conf = rcu_dereference(sdata->vif.link_conf[link_id]);
+ qos = sta->sta.wme;
- if (unlikely(!conf)) {
- ret = -ENOLINK;
- goto unlock;
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
+ if (sta->sta.mlo) {
+ link_id = IEEE80211_LINK_UNSPECIFIED;
+ } else {
+ /*
+ * For non-MLO clients connected to an AP MLD,
+ * use the link address for the client's link.
+ */
+ link_id = sta->deflink.link_id;
+ conf = rcu_dereference(sdata->vif.link_conf[link_id]);
+ if (unlikely(!conf))
+ return -ENOLINK;
}
+ /* MLD transmissions must not rely on the band */
+ band = 0;
+ } else {
+ chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+ if (WARN_ON(!chanctx_conf))
+ return -EINVAL;
+ band = chanctx_conf->def.chan->band;
+ link_id = 0;
+ }
+
+ size = sizeof(*nullfunc);
+ fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ (qos ? IEEE80211_STYPE_QOS_NULLFUNC
+ : IEEE80211_STYPE_NULLFUNC) |
+ IEEE80211_FCTL_FROMDS);
+ if (!qos)
+ size -= 2;
+
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
+ if (!skb)
+ return -ENOMEM;
+
+ skb->dev = dev;
+ skb_reserve(skb, local->hw.extra_tx_headroom);
+
+ nullfunc = skb_put(skb, size);
+ memset(nullfunc, 0, size);
+ nullfunc->frame_control = fc;
+
+ memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
+ if (ieee80211_vif_is_mld(&sdata->vif) && !sta->sta.mlo) {
+ memcpy(nullfunc->addr2, conf->addr, ETH_ALEN);
+ memcpy(nullfunc->addr3, conf->addr, ETH_ALEN);
+ } else {
+ memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
+ memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
+ }
+
+ info = IEEE80211_SKB_CB(skb);
+ info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
+ IEEE80211_TX_INTFL_NL80211_FRAME_TX;
+ info->band = band;
+ info->control.flags |= u32_encode_bits(link_id,
+ IEEE80211_TX_CTRL_MLO_LINK);
+
+ skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+ skb->priority = 7;
+ if (qos)
+ nullfunc->qos_ctrl = cpu_to_le16(7);
+
+ ret = ieee80211_attach_ack_skb(local, skb, cookie, GFP_ATOMIC);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
}
- /* MLD transmissions must not rely on the band */
+
+ local_bh_disable();
+ ieee80211_xmit(sdata, sta, skb);
+ local_bh_enable();
+
+ return 0;
+ }
+
+ /*
+ * STA/P2P: send a nullfunc to probe the AP/peer.
+ * For MLO, let the driver/firmware decide which link to use.
+ */
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
+ link_id = IEEE80211_LINK_UNSPECIFIED;
+ peer_addr = sdata->vif.cfg.ap_addr;
+ src_addr = sdata->vif.addr;
band = 0;
+ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
} else {
- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
- if (WARN_ON(!chanctx_conf)) {
- ret = -EINVAL;
- goto unlock;
- }
- band = chanctx_conf->def.chan->band;
link_id = 0;
+ conf = rcu_dereference(sdata->vif.link_conf[0]);
+ if (!conf)
+ return -ENOLINK;
+ band = conf->chanreq.oper.chan->band;
+ peer_addr = conf->bssid;
+ src_addr = conf->addr;
+ sta = sta_info_get_bss(sdata, peer_addr);
}
- if (qos) {
- fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
- IEEE80211_STYPE_QOS_NULLFUNC |
- IEEE80211_FCTL_FROMDS);
- } else {
+ qos = sta ? sta->sta.wme : false;
+
+ size = sizeof(*nullfunc);
+ fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ (qos ? IEEE80211_STYPE_QOS_NULLFUNC
+ : IEEE80211_STYPE_NULLFUNC) |
+ IEEE80211_FCTL_TODS);
+ if (!qos)
size -= 2;
- fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
- IEEE80211_STYPE_NULLFUNC |
- IEEE80211_FCTL_FROMDS);
- }
skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
- if (!skb) {
- ret = -ENOMEM;
- goto unlock;
- }
+ if (!skb)
+ return -ENOMEM;
skb->dev = dev;
-
skb_reserve(skb, local->hw.extra_tx_headroom);
nullfunc = skb_put(skb, size);
+ memset(nullfunc, 0, size);
nullfunc->frame_control = fc;
- nullfunc->duration_id = 0;
- memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
- if (ieee80211_vif_is_mld(&sdata->vif) && !sta->sta.mlo) {
- memcpy(nullfunc->addr2, conf->addr, ETH_ALEN);
- memcpy(nullfunc->addr3, conf->addr, ETH_ALEN);
- } else {
- memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
- memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
- }
- nullfunc->seq_ctrl = 0;
- info = IEEE80211_SKB_CB(skb);
+ memcpy(nullfunc->addr1, peer_addr, ETH_ALEN);
+ memcpy(nullfunc->addr2, src_addr, ETH_ALEN);
+ memcpy(nullfunc->addr3, peer_addr, ETH_ALEN);
+ info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_INTFL_NL80211_FRAME_TX;
info->band = band;
-
info->control.flags |= u32_encode_bits(link_id,
IEEE80211_TX_CTRL_MLO_LINK);
+
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
skb->priority = 7;
if (qos)
@@ -4856,18 +4929,14 @@ static int ieee80211_probe_peer(struct wiphy *wiphy, struct net_device *dev,
ret = ieee80211_attach_ack_skb(local, skb, cookie, GFP_ATOMIC);
if (ret) {
kfree_skb(skb);
- goto unlock;
+ return ret;
}
local_bh_disable();
ieee80211_xmit(sdata, sta, skb);
local_bh_enable();
- ret = 0;
-unlock:
- rcu_read_unlock();
-
- return ret;
+ return 0;
}
static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 4a64ac6d1451..e049ab946e7b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -622,7 +622,8 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
return;
if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
- u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
+ struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
+ u64 cookie = skb_info->ack.cookie;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr = (void *)skb->data;
bool is_valid_ack_signal =
@@ -652,12 +653,33 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
skb->len,
acked,
GFP_ATOMIC);
- else if (ieee80211_is_any_nullfunc(hdr->frame_control))
- cfg80211_probe_status(sdata->dev, hdr->addr1,
- cookie, -1, acked,
+ else if (ieee80211_is_any_nullfunc(hdr->frame_control)) {
+ const u8 *peer_addr;
+ int link_id = -1;
+
+ /*
+ * STA/P2P client: peer_addr omitted;
+ * AP/GO: report RA
+ */
+ if (sdata->vif.type ==
+ NL80211_IFTYPE_STATION ||
+ sdata->vif.type ==
+ NL80211_IFTYPE_P2P_CLIENT) {
+ peer_addr = NULL;
+
+ if (ieee80211_vif_is_mld(&sdata->vif) &&
+ info->status.link_valid)
+ link_id = info->status.link_id;
+ } else {
+ peer_addr = hdr->addr1;
+ }
+
+ cfg80211_probe_status(sdata->dev, peer_addr,
+ cookie, link_id, acked,
info->status.ack_signal,
is_valid_ack_signal,
GFP_ATOMIC);
+ }
else if (ieee80211_is_mgmt(hdr->frame_control))
cfg80211_mgmt_tx_status_ext(&sdata->wdev,
&status,
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH wireless-next v1 4/4] wifi: mac80211_hwsim: report TX status link_id
2026-04-15 9:43 [PATCH wireless-next v1 0/4] wifi: nl80211: introduce PROBE_PEER for AP and STA with MLO support Priyansha Tiwari
` (2 preceding siblings ...)
2026-04-15 9:43 ` [PATCH wireless-next v1 3/4] wifi: mac80211: add per-link PROBE_PEER support Priyansha Tiwari
@ 2026-04-15 9:43 ` Priyansha Tiwari
2026-04-15 9:48 ` Johannes Berg
3 siblings, 1 reply; 8+ messages in thread
From: Priyansha Tiwari @ 2026-04-15 9:43 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, quic_drohan
From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
Populate link_valid/link_id in mac80211_hwsim TX status so the
transmitted link is reported to mac80211.
Set the link information in both the direct TX status path and the
wmediumd/netlink TX status path.
Signed-off-by: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 46 ++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 1fcf5d0d2e13..2a3df3e81f54 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -2074,6 +2074,27 @@ static int mac80211_hwsim_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return 0;
}
+static int mac80211_hwsim_get_link_id(struct ieee80211_vif *vif,
+ struct ieee80211_hdr *hdr)
+{
+ int i;
+
+ if (!vif || !ieee80211_vif_is_mld(vif))
+ return -1;
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ struct ieee80211_bss_conf *link_conf;
+
+ link_conf = rcu_dereference(vif->link_conf[i]);
+ if (!link_conf)
+ continue;
+ if (ether_addr_equal(link_conf->addr, hdr->addr2))
+ return i;
+ }
+
+ return -1;
+}
+
static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
@@ -2087,6 +2108,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
bool ack, unicast_data;
enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT;
u32 _portid, i;
+ int tx_link_id = -1;
if (WARN_ON(skb->len < 10)) {
/* Should not happen; just a sanity check for addr1 use */
@@ -2147,6 +2169,9 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
hdr, &link_sta);
}
+ if (bss_conf)
+ tx_link_id = bss_conf->link_id;
+
if (unlikely(!bss_conf)) {
/* if it's an MLO STA, it might have deactivated all
* links temporarily - but we don't handle real PS in
@@ -2279,6 +2304,18 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack)
txi->flags |= IEEE80211_TX_STAT_ACK;
+
+ /* Simulate ACK RSSI in perfect medium (no wmediumd) */
+ if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) {
+ txi->status.ack_signal = data->rx_rssi;
+ txi->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
+ }
+
+ if (tx_link_id >= 0) {
+ txi->status.link_valid = 1;
+ txi->status.link_id = tx_link_id;
+ }
+
ieee80211_tx_status_irqsafe(hw, skb);
}
@@ -6009,6 +6046,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_PUNCT);
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_PROBE_AP);
for (i = 0; i < ARRAY_SIZE(data->link_data); i++) {
hrtimer_setup(&data->link_data[i].beacon_timer, mac80211_hwsim_beacon,
@@ -6312,10 +6350,16 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
+ hdr = (struct ieee80211_hdr *)skb->data;
+ i = mac80211_hwsim_get_link_id(txi->control.vif, hdr);
+ if (i >= 0) {
+ txi->status.link_valid = 1;
+ txi->status.link_id = i;
+ }
+
if (!(hwsim_flags & HWSIM_TX_CTL_NO_ACK) &&
(hwsim_flags & HWSIM_TX_STAT_ACK)) {
if (skb->len >= 16) {
- hdr = (struct ieee80211_hdr *) skb->data;
mac80211_hwsim_monitor_ack(data2->channel,
hdr->addr2);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH wireless-next v1 4/4] wifi: mac80211_hwsim: report TX status link_id
2026-04-15 9:43 ` [PATCH wireless-next v1 4/4] wifi: mac80211_hwsim: report TX status link_id Priyansha Tiwari
@ 2026-04-15 9:48 ` Johannes Berg
0 siblings, 0 replies; 8+ messages in thread
From: Johannes Berg @ 2026-04-15 9:48 UTC (permalink / raw)
To: Priyansha Tiwari; +Cc: linux-wireless, quic_drohan
On Wed, 2026-04-15 at 15:13 +0530, Priyansha Tiwari wrote:
> From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
>
> Populate link_valid/link_id in mac80211_hwsim TX status so the
> transmitted link is reported to mac80211.
>
> Set the link information in both the direct TX status path and the
> wmediumd/netlink TX status path.
>
> Signed-off-by: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
> ---
> drivers/net/wireless/virtual/mac80211_hwsim.c | 46 ++++++++++++++++++-
> 1 file changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
> index 1fcf5d0d2e13..2a3df3e81f54 100644
> --- a/drivers/net/wireless/virtual/mac80211_hwsim.c
> +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
> @@ -2074,6 +2074,27 @@ static int mac80211_hwsim_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
> return 0;
> }
>
> +static int mac80211_hwsim_get_link_id(struct ieee80211_vif *vif,
> + struct ieee80211_hdr *hdr)
nit: maybe move this down closer to where it's needed? I did wonder for
a second why you need this at all, until I realized it's only for the
netlink case.
> + /* Simulate ACK RSSI in perfect medium (no wmediumd) */
> + if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) {
> + txi->status.ack_signal = data->rx_rssi;
> + txi->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
> + }
No objection to this change itself, but it's unrelated?
> @@ -6009,6 +6046,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
>
> wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
> wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_PUNCT);
> + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_PROBE_AP);
Also not related to reporting TX status link ID?
> if (skb->len >= 16) {
> - hdr = (struct ieee80211_hdr *) skb->data;
> mac80211_hwsim_monitor_ack(data2->channel,
> hdr->addr2);
> }
nit: remove braces now.
johannes
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support
2026-04-15 9:43 ` [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support Priyansha Tiwari
@ 2026-04-15 9:53 ` Johannes Berg
2026-04-17 13:28 ` Priyansha Tiwari
0 siblings, 1 reply; 8+ messages in thread
From: Johannes Berg @ 2026-04-15 9:53 UTC (permalink / raw)
To: Priyansha Tiwari; +Cc: linux-wireless, quic_drohan
On Wed, 2026-04-15 at 15:13 +0530, Priyansha Tiwari wrote:
> From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
>
> Rename NL80211_CMD_PROBE_CLIENT to NL80211_CMD_PROBE_PEER to generalize
> peer probing, AP/GO continue to probe associated STAs (legacy PROBE_CLIENT
> behavior) while, when the driver advertises NL80211_EXT_FEATURE_PROBE_AP,
> a STA/P2P-client may probe its currently associated AP to quickly verify link
> responsiveness without waiting for traffic or long timeouts.
Why though? Link management etc. is totally up to the driver/mac80211...
Also I'm sure this isn't going to work for all devices, e.g. Intel
devices can't send NDPs from the host (this is probably wrong in the
iwlmld driver for AP side though.)
johannes
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support
2026-04-15 9:53 ` Johannes Berg
@ 2026-04-17 13:28 ` Priyansha Tiwari
0 siblings, 0 replies; 8+ messages in thread
From: Priyansha Tiwari @ 2026-04-17 13:28 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, quic_drohan
On 4/15/2026 3:23 PM, Johannes Berg wrote:
> On Wed, 2026-04-15 at 15:13 +0530, Priyansha Tiwari wrote:
>> From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
>>
>> Rename NL80211_CMD_PROBE_CLIENT to NL80211_CMD_PROBE_PEER to generalize
>> peer probing, AP/GO continue to probe associated STAs (legacy PROBE_CLIENT
>> behavior) while, when the driver advertises NL80211_EXT_FEATURE_PROBE_AP,
>> a STA/P2P-client may probe its currently associated AP to quickly verify link
>> responsiveness without waiting for traffic or long timeouts.
> Why though? Link management etc. is totally up to the driver/mac80211...
>
> Also I'm sure this isn't going to work for all devices, e.g. Intel
> devices can't send NDPs from the host (this is probably wrong in the
> iwlmld driver for AP side though.)
>
> johannes
The intent is not link management, it is to let userspace explicitly
verify AP reachability on demand, without waiting for mac80211's
internal probe timer.
No change has been made to the AP/GO side.
The NL80211_EXT_FEATURE_PROBE_AP flag gates this feature: only drivers
that can handle host-initiated nullfunc frames in STA mode will
advertise it.
Drivers like iwlmld that handle this in firmware would not set the flag,
so userspace would not use the feature on those devices.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-04-17 13:28 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-15 9:43 [PATCH wireless-next v1 0/4] wifi: nl80211: introduce PROBE_PEER for AP and STA with MLO support Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support Priyansha Tiwari
2026-04-15 9:53 ` Johannes Berg
2026-04-17 13:28 ` Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 2/4] wifi: cfg80211/nl80211: rename to probe_peer(), extend probe status, and update in-tree users Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 3/4] wifi: mac80211: add per-link PROBE_PEER support Priyansha Tiwari
2026-04-15 9:43 ` [PATCH wireless-next v1 4/4] wifi: mac80211_hwsim: report TX status link_id Priyansha Tiwari
2026-04-15 9:48 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox