* [PATCH RFC 1/7] wifi: cfg80211: reorg sinfo structure elements for mesh
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
@ 2025-01-10 4:24 ` Sarika Sharma
2025-01-10 9:15 ` Johannes Berg
2025-01-10 4:24 ` [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO Sarika Sharma
` (7 subsequent siblings)
8 siblings, 1 reply; 28+ messages in thread
From: Sarika Sharma @ 2025-01-10 4:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sarika Sharma
Currently, as multi-link operation(MLO) is not supported for mesh,
reorganize the sinfo structure for mesh-specific fields and
introduce the sta_set_mesh_sinfo() API to populate these fields.
This will allow for the simplified reorganization of sinfo structure
for link level in a subsequent patch to add support for MLO station
statistics.
No functionality changes added.
Pahole summary before the reorg of sinfo structure:
- size: 256, cachelines: 4, members: 50
- sum members: 239, holes: 4, sum holes: 17
- paddings: 2, sum paddings: 2
- forced alignments: 1, forced holes: 1, sum forced holes: 1
Pahole summary after the reorg of sinfo structure:
- size: 248, cachelines: 4, members: 50
- sum members: 239, holes: 4, sum holes: 9
- paddings: 2, sum paddings: 2
- forced alignments: 1, last cacheline: 56 bytes
Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
---
include/net/cfg80211.h | 43 ++++++++++++++-------------
net/mac80211/sta_info.c | 64 ++++++++++++++++++++++-------------------
net/wireless/nl80211.c | 11 +++----
3 files changed, 62 insertions(+), 56 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7790af534b7f..77f72a46ce42 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2045,9 +2045,6 @@ struct cfg80211_tid_stats {
* @assoc_at: bootime (ns) of the last association
* @rx_bytes: bytes (size of MPDUs) received from this station
* @tx_bytes: bytes (size of MPDUs) transmitted to this station
- * @llid: mesh local link id
- * @plid: mesh peer link id
- * @plink_state: mesh peer link state
* @signal: The signal strength, type depends on the wiphy's signal_type.
* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
@@ -2067,14 +2064,20 @@ struct cfg80211_tid_stats {
* This number should increase every time the list of stations
* changes, i.e. when a station is added or removed, so that
* userspace can tell whether it got a consistent snapshot.
+ * @beacon_loss_count: Number of times beacon loss event has triggered.
* @assoc_req_ies: IEs from (Re)Association Request.
* This is used only when in AP mode with drivers that do not use
* user space MLME/SME implementation. The information is provided for
* the cfg80211_new_sta() calls to notify user space of the IEs.
* @assoc_req_ies_len: Length of assoc_req_ies buffer in octets.
* @sta_flags: station flags mask & values
- * @beacon_loss_count: Number of times beacon loss event has triggered.
* @t_offset: Time offset of the station relative to this host.
+ * @llid: mesh local link id
+ * @plid: mesh peer link id
+ * @plink_state: mesh peer link state
+ * @connected_to_gate: true if mesh STA has a path to mesh gate
+ * @connected_to_as: true if mesh STA has a path to authentication server
+ * @airtime_link_metric: mesh airtime link metric.
* @local_pm: local mesh STA power save mode
* @peer_pm: peer mesh STA power save mode
* @nonpeer_pm: non-peer mesh STA power save mode
@@ -2083,7 +2086,6 @@ struct cfg80211_tid_stats {
* @rx_beacon: number of beacons received from this peer
* @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received
* from this peer
- * @connected_to_gate: true if mesh STA has a path to mesh gate
* @rx_duration: aggregate PPDU duration(usecs) for all the frames from a peer
* @tx_duration: aggregate PPDU duration(usecs) for all the frames to a peer
* @airtime_weight: current airtime scheduling weight
@@ -2097,8 +2099,6 @@ struct cfg80211_tid_stats {
* @fcs_err_count: number of packets (MPDUs) received from this station with
* an FCS error. This counter should be incremented only when TA of the
* received packet with an FCS error matches the peer MAC address.
- * @airtime_link_metric: mesh airtime link metric.
- * @connected_to_as: true if mesh STA has a path to authentication server
* @mlo_params_valid: Indicates @assoc_link_id and @mld_addr fields are filled
* by driver. Drivers use this only in cfg80211_new_sta() calls when AP
* MLD's MLME/SME is offload to driver. Drivers won't fill this
@@ -2125,9 +2125,6 @@ struct station_info {
u64 assoc_at;
u64 rx_bytes;
u64 tx_bytes;
- u16 llid;
- u16 plid;
- u8 plink_state;
s8 signal;
s8 signal_avg;
@@ -2147,36 +2144,38 @@ struct station_info {
int generation;
+ u32 beacon_loss_count;
+
const u8 *assoc_req_ies;
size_t assoc_req_ies_len;
- u32 beacon_loss_count;
s64 t_offset;
+ u16 llid;
+ u16 plid;
+ u8 plink_state;
+ u8 connected_to_gate;
+ u8 connected_to_as;
+ u32 airtime_link_metric;
enum nl80211_mesh_power_mode local_pm;
enum nl80211_mesh_power_mode peer_pm;
enum nl80211_mesh_power_mode nonpeer_pm;
u32 expected_throughput;
- u64 tx_duration;
- u64 rx_duration;
- u64 rx_beacon;
- u8 rx_beacon_signal_avg;
- u8 connected_to_gate;
+ u16 airtime_weight;
- struct cfg80211_tid_stats *pertid;
s8 ack_signal;
s8 avg_ack_signal;
+ struct cfg80211_tid_stats *pertid;
- u16 airtime_weight;
+ u64 tx_duration;
+ u64 rx_duration;
+ u64 rx_beacon;
+ u8 rx_beacon_signal_avg;
u32 rx_mpdu_count;
u32 fcs_err_count;
- u32 airtime_link_metric;
-
- u8 connected_to_as;
-
bool mlo_params_valid;
u8 assoc_link_id;
u8 mld_addr[ETH_ALEN] __aligned(2);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aa22f09e6d14..53f8da74fb99 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2563,6 +2563,39 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
return value;
}
+#ifdef CONFIG_MAC80211_MESH
+static void sta_set_mesh_sinfo(struct sta_info *sta,
+ struct station_info *sinfo)
+{
+ struct ieee80211_local *local = sta->sdata->local;
+
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_LLID) |
+ BIT_ULL(NL80211_STA_INFO_PLID) |
+ BIT_ULL(NL80211_STA_INFO_PLINK_STATE) |
+ BIT_ULL(NL80211_STA_INFO_LOCAL_PM) |
+ BIT_ULL(NL80211_STA_INFO_PEER_PM) |
+ BIT_ULL(NL80211_STA_INFO_NONPEER_PM) |
+ BIT_ULL(NL80211_STA_INFO_CONNECTED_TO_GATE) |
+ BIT_ULL(NL80211_STA_INFO_CONNECTED_TO_AS);
+
+ sinfo->llid = sta->mesh->llid;
+ sinfo->plid = sta->mesh->plid;
+ sinfo->plink_state = sta->mesh->plink_state;
+ if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_T_OFFSET);
+ sinfo->t_offset = sta->mesh->t_offset;
+ }
+ sinfo->local_pm = sta->mesh->local_pm;
+ sinfo->peer_pm = sta->mesh->peer_pm;
+ sinfo->nonpeer_pm = sta->mesh->nonpeer_pm;
+ sinfo->connected_to_gate = sta->mesh->connected_to_gate;
+ sinfo->connected_to_as = sta->mesh->connected_to_as;
+
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_LINK_METRIC);
+ sinfo->airtime_link_metric = airtime_link_metric_get(local, sta);
+}
+#endif
+
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
bool tidstats)
{
@@ -2747,31 +2780,10 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sta_set_tidstats(sta, &sinfo->pertid[i], i);
}
- if (ieee80211_vif_is_mesh(&sdata->vif)) {
#ifdef CONFIG_MAC80211_MESH
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_LLID) |
- BIT_ULL(NL80211_STA_INFO_PLID) |
- BIT_ULL(NL80211_STA_INFO_PLINK_STATE) |
- BIT_ULL(NL80211_STA_INFO_LOCAL_PM) |
- BIT_ULL(NL80211_STA_INFO_PEER_PM) |
- BIT_ULL(NL80211_STA_INFO_NONPEER_PM) |
- BIT_ULL(NL80211_STA_INFO_CONNECTED_TO_GATE) |
- BIT_ULL(NL80211_STA_INFO_CONNECTED_TO_AS);
-
- sinfo->llid = sta->mesh->llid;
- sinfo->plid = sta->mesh->plid;
- sinfo->plink_state = sta->mesh->plink_state;
- if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_T_OFFSET);
- sinfo->t_offset = sta->mesh->t_offset;
- }
- sinfo->local_pm = sta->mesh->local_pm;
- sinfo->peer_pm = sta->mesh->peer_pm;
- sinfo->nonpeer_pm = sta->mesh->nonpeer_pm;
- sinfo->connected_to_gate = sta->mesh->connected_to_gate;
- sinfo->connected_to_as = sta->mesh->connected_to_as;
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ sta_set_mesh_sinfo(sta, sinfo);
#endif
- }
sinfo->bss_param.flags = 0;
if (sdata->vif.bss_conf.use_cts_prot)
@@ -2827,12 +2839,6 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sinfo->filled |=
BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
}
-
- if (ieee80211_vif_is_mesh(&sdata->vif)) {
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_LINK_METRIC);
- sinfo->airtime_link_metric =
- airtime_link_metric_get(local, sta);
- }
}
u32 sta_get_expected_throughput(struct sta_info *sta)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8789d8b73f0f..d90033e03dd6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6726,9 +6726,6 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
PUT_SINFO_U64(RX_BYTES64, rx_bytes);
PUT_SINFO_U64(TX_BYTES64, tx_bytes);
- PUT_SINFO(LLID, llid, u16);
- PUT_SINFO(PLID, plid, u16);
- PUT_SINFO(PLINK_STATE, plink_state, u8);
PUT_SINFO_U64(RX_DURATION, rx_duration);
PUT_SINFO_U64(TX_DURATION, tx_duration);
@@ -6772,13 +6769,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
PUT_SINFO(TX_RETRIES, tx_retries, u32);
PUT_SINFO(TX_FAILED, tx_failed, u32);
PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
- PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
+
+ PUT_SINFO(LLID, llid, u16);
+ PUT_SINFO(PLID, plid, u16);
+ PUT_SINFO(PLINK_STATE, plink_state, u8);
+ PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
PUT_SINFO(LOCAL_PM, local_pm, u32);
PUT_SINFO(PEER_PM, peer_pm, u32);
PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
+ PUT_SINFO_U64(T_OFFSET, t_offset);
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
bss_param = nla_nest_start_noflag(msg,
@@ -6806,7 +6808,6 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
&sinfo->sta_flags))
goto nla_put_failure;
- PUT_SINFO_U64(T_OFFSET, t_offset);
PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
PUT_SINFO_U64(BEACON_RX, rx_beacon);
PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
--
2.34.1
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
2025-01-10 4:24 ` [PATCH RFC 1/7] wifi: cfg80211: reorg sinfo structure elements for mesh Sarika Sharma
@ 2025-01-10 4:24 ` Sarika Sharma
2025-01-10 9:19 ` Johannes Berg
` (2 more replies)
2025-01-10 4:24 ` [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo Sarika Sharma
` (6 subsequent siblings)
8 siblings, 3 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-10 4:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sarika Sharma
Current implementation of NL80211_GET_STATION does not work for
multi-link operation(MLO) since in case of MLO only deflink (or one
of the links) is considered and not all links.
Therefore to support for MLO, start reorganizing sinfo structure
related data elements and add link_sinfo structure for link-level
statistics and keep station related data at sinfo structure.
Currently, changes are done at the deflink level. Actual link-level
changes will be added in subsequent changes.
Also currently, mac80211 ops .sta_statistics() is mapped to fill sinfo
structure. But to add support for station statistics at link level,
change the ops to .link_sta_statistics() to fill link_sinfo structure.
NOTE:
- Currently this patch is not-bisectable, once RFC patches are
approved could add other required driver changes.
- Have included ath12k driver changes as an example that could be
used as reference for other drivers.
Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 42 ++--
include/net/cfg80211.h | 165 +++++++++-------
include/net/mac80211.h | 18 +-
net/mac80211/driver-ops.h | 14 +-
net/mac80211/ethtool.c | 30 +--
net/mac80211/sta_info.c | 251 ++++++++++++-----------
net/mac80211/trace.h | 2 +-
net/wireless/nl80211.c | 273 +++++++++++++++-----------
net/wireless/trace.h | 33 ++--
net/wireless/util.c | 10 +-
net/wireless/wext-compat.c | 22 +--
11 files changed, 469 insertions(+), 391 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index c4eab4c1c10e..ebde8a604eec 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <net/mac80211.h>
@@ -9896,10 +9896,10 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
return 0;
}
-static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct station_info *sinfo)
+static void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct link_station_info *link_sinfo)
{
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k_link_sta *arsta;
@@ -9908,31 +9908,31 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
arsta = &ahsta->deflink;
- sinfo->rx_duration = arsta->rx_duration;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
+ link_sinfo->rx_duration = arsta->rx_duration;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
- sinfo->tx_duration = arsta->tx_duration;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
+ link_sinfo->tx_duration = arsta->tx_duration;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
if (!arsta->txrate.legacy && !arsta->txrate.nss)
return;
if (arsta->txrate.legacy) {
- sinfo->txrate.legacy = arsta->txrate.legacy;
+ link_sinfo->txrate.legacy = arsta->txrate.legacy;
} else {
- sinfo->txrate.mcs = arsta->txrate.mcs;
- sinfo->txrate.nss = arsta->txrate.nss;
- sinfo->txrate.bw = arsta->txrate.bw;
- sinfo->txrate.he_gi = arsta->txrate.he_gi;
- sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
- sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
+ link_sinfo->txrate.mcs = arsta->txrate.mcs;
+ link_sinfo->txrate.nss = arsta->txrate.nss;
+ link_sinfo->txrate.bw = arsta->txrate.bw;
+ link_sinfo->txrate.he_gi = arsta->txrate.he_gi;
+ link_sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
+ link_sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
}
- sinfo->txrate.flags = arsta->txrate.flags;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+ link_sinfo->txrate.flags = arsta->txrate.flags;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
/* TODO: Use real NF instead of default one. */
- sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+ link_sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
}
static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
@@ -10177,7 +10177,7 @@ static const struct ieee80211_ops ath12k_ops = {
.set_bitrate_mask = ath12k_mac_op_set_bitrate_mask,
.get_survey = ath12k_mac_op_get_survey,
.flush = ath12k_mac_op_flush,
- .sta_statistics = ath12k_mac_op_sta_statistics,
+ .link_sta_statistics = ath12k_mac_op_link_sta_statistics,
.remain_on_channel = ath12k_mac_op_remain_on_channel,
.cancel_remain_on_channel = ath12k_mac_op_cancel_remain_on_channel,
.change_sta_links = ath12k_mac_op_change_sta_links,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 77f72a46ce42..ba3e7e72ab5d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2034,17 +2034,18 @@ struct cfg80211_tid_stats {
#define IEEE80211_MAX_CHAINS 4
/**
- * struct station_info - station information
+ * struct link_station_info - link station information
*
- * Station information filled by driver for get_station() and dump_station.
+ * Link station information filled by driver for get_station() and dump_station.
*
+ * @link_id: Link ID uniquely identifying the link STA. This is -1 for non-ML
* @filled: bitflag of flags using the bits of &enum nl80211_sta_info to
* indicate the relevant values in this struct for them
- * @connected_time: time(in secs) since a station is last connected
- * @inactive_time: time since last station activity (tx/rx) in milliseconds
- * @assoc_at: bootime (ns) of the last association
- * @rx_bytes: bytes (size of MPDUs) received from this station
- * @tx_bytes: bytes (size of MPDUs) transmitted to this station
+ * @connected_time: time(in secs) since a link station is last connected
+ * @inactive_time: time since last link station activity (tx/rx) in milliseconds
+ * @assoc_at: bootime (ns) of the last link station association
+ * @rx_bytes: bytes (size of MPDUs) received from this link station
+ * @tx_bytes: bytes (size of MPDUs) transmitted to this link station
* @signal: The signal strength, type depends on the wiphy's signal_type.
* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
@@ -2052,19 +2053,95 @@ struct cfg80211_tid_stats {
* @chains: bitmask for filled values in @chain_signal, @chain_signal_avg
* @chain_signal: per-chain signal strength of last received packet in dBm
* @chain_signal_avg: per-chain signal strength average in dBm
- * @txrate: current unicast bitrate from this station
- * @rxrate: current unicast bitrate to this station
- * @rx_packets: packets (MSDUs & MMPDUs) received from this station
- * @tx_packets: packets (MSDUs & MMPDUs) transmitted to this station
+ * @txrate: current unicast bitrate from this link station
+ * @rxrate: current unicast bitrate to this link station
+ * @rx_packets: packets (MSDUs & MMPDUs) received from this link station
+ * @tx_packets: packets (MSDUs & MMPDUs) transmitted to thislink station
* @tx_retries: cumulative retry counts (MPDUs)
* @tx_failed: number of failed transmissions (MPDUs) (retries exceeded, no ACK)
* @rx_dropped_misc: Dropped for un-specified reason.
* @bss_param: current BSS parameters
+ * @beacon_loss_count: Number of times beacon loss event has triggered.
+ * @expected_throughput: expected throughput in kbps (including 802.11 headers)
+ * towards this link station.
+ * @rx_beacon: number of beacons received from this peer
+ * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received
+ * from this peer
+ * @rx_duration: aggregate PPDU duration(usecs) for all the frames from a peer
+ * @tx_duration: aggregate PPDU duration(usecs) for all the frames to a peer
+ * @airtime_weight: current airtime scheduling weight
+ * @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last
+ * (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs.
+ * Note that this doesn't use the @filled bit, but is used if non-NULL.
+ * @ack_signal: signal strength (in dBm) of the last ACK frame.
+ * @avg_ack_signal: average rssi value of ack packet for the no of msdu's has
+ * been sent.
+ * @rx_mpdu_count: number of MPDUs received from this link station
+ * @fcs_err_count: number of packets (MPDUs) received from this link station with
+ * an FCS error. This counter should be incremented only when TA of the
+ * received packet with an FCS error matches the peer MAC address.
+ * @addr: For MLO STA connection, filled with address of the link station.
+ * For non-MLO STA connection, filled with all zeros.
+ */
+struct link_station_info {
+ int link_id;
+ u64 filled;
+ u32 connected_time;
+ u32 inactive_time;
+ u64 assoc_at;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ s8 signal;
+ s8 signal_avg;
+
+ u8 chains;
+ s8 chain_signal[IEEE80211_MAX_CHAINS];
+ s8 chain_signal_avg[IEEE80211_MAX_CHAINS];
+
+ struct rate_info txrate;
+ struct rate_info rxrate;
+ u32 rx_packets;
+ u32 tx_packets;
+ u32 tx_retries;
+ u32 tx_failed;
+ u32 rx_dropped_misc;
+ struct sta_bss_parameters bss_param;
+
+ u32 beacon_loss_count;
+
+ u32 expected_throughput;
+
+ u64 tx_duration;
+ u64 rx_duration;
+ u64 rx_beacon;
+ u8 rx_beacon_signal_avg;
+
+ u16 airtime_weight;
+
+ s8 ack_signal;
+ s8 avg_ack_signal;
+ struct cfg80211_tid_stats *pertid;
+
+ u32 rx_mpdu_count;
+ u32 fcs_err_count;
+
+ u8 addr[ETH_ALEN] __aligned(2);
+};
+
+/**
+ * struct station_info - station information
+ *
+ * Station information filled by driver for get_station() and dump_station.
+ *
+ * @filled: bitflag of flags using the bits of &enum nl80211_sta_info to
+ * indicate the relevant values in this struct for them
+ * @connected_time: time(in secs) since a station is last connected
+ * @assoc_at: bootime (ns) of the last association
+ * @sta_flags: station flags mask & values
* @generation: generation number for nl80211 dumps.
* This number should increase every time the list of stations
* changes, i.e. when a station is added or removed, so that
* userspace can tell whether it got a consistent snapshot.
- * @beacon_loss_count: Number of times beacon loss event has triggered.
* @assoc_req_ies: IEs from (Re)Association Request.
* This is used only when in AP mode with drivers that do not use
* user space MLME/SME implementation. The information is provided for
@@ -2081,24 +2158,6 @@ struct cfg80211_tid_stats {
* @local_pm: local mesh STA power save mode
* @peer_pm: peer mesh STA power save mode
* @nonpeer_pm: non-peer mesh STA power save mode
- * @expected_throughput: expected throughput in kbps (including 802.11 headers)
- * towards this station.
- * @rx_beacon: number of beacons received from this peer
- * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received
- * from this peer
- * @rx_duration: aggregate PPDU duration(usecs) for all the frames from a peer
- * @tx_duration: aggregate PPDU duration(usecs) for all the frames to a peer
- * @airtime_weight: current airtime scheduling weight
- * @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last
- * (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs.
- * Note that this doesn't use the @filled bit, but is used if non-NULL.
- * @ack_signal: signal strength (in dBm) of the last ACK frame.
- * @avg_ack_signal: average rssi value of ack packet for the no of msdu's has
- * been sent.
- * @rx_mpdu_count: number of MPDUs received from this station
- * @fcs_err_count: number of packets (MPDUs) received from this station with
- * an FCS error. This counter should be incremented only when TA of the
- * received packet with an FCS error matches the peer MAC address.
* @mlo_params_valid: Indicates @assoc_link_id and @mld_addr fields are filled
* by driver. Drivers use this only in cfg80211_new_sta() calls when AP
* MLD's MLME/SME is offload to driver. Drivers won't fill this
@@ -2117,35 +2176,17 @@ struct cfg80211_tid_stats {
* dump_station() callbacks. User space needs this information to determine
* the accepted and rejected affiliated links of the connected station.
* @assoc_resp_ies_len: Length of @assoc_resp_ies buffer in octets.
+ * @deflink: This holds the default link STA information, for non MLO STA
+ * all link specific STA information is accessed through @deflink.
*/
struct station_info {
u64 filled;
u32 connected_time;
- u32 inactive_time;
u64 assoc_at;
- u64 rx_bytes;
- u64 tx_bytes;
- s8 signal;
- s8 signal_avg;
-
- u8 chains;
- s8 chain_signal[IEEE80211_MAX_CHAINS];
- s8 chain_signal_avg[IEEE80211_MAX_CHAINS];
-
- struct rate_info txrate;
- struct rate_info rxrate;
- u32 rx_packets;
- u32 tx_packets;
- u32 tx_retries;
- u32 tx_failed;
- u32 rx_dropped_misc;
- struct sta_bss_parameters bss_param;
struct nl80211_sta_flag_update sta_flags;
int generation;
- u32 beacon_loss_count;
-
const u8 *assoc_req_ies;
size_t assoc_req_ies_len;
@@ -2160,27 +2201,13 @@ struct station_info {
enum nl80211_mesh_power_mode peer_pm;
enum nl80211_mesh_power_mode nonpeer_pm;
- u32 expected_throughput;
-
- u16 airtime_weight;
-
- s8 ack_signal;
- s8 avg_ack_signal;
- struct cfg80211_tid_stats *pertid;
-
- u64 tx_duration;
- u64 rx_duration;
- u64 rx_beacon;
- u8 rx_beacon_signal_avg;
-
- u32 rx_mpdu_count;
- u32 fcs_err_count;
-
bool mlo_params_valid;
u8 assoc_link_id;
u8 mld_addr[ETH_ALEN] __aligned(2);
const u8 *assoc_resp_ies;
size_t assoc_resp_ies_len;
+
+ struct link_station_info deflink;
};
/**
@@ -8429,12 +8456,12 @@ void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
/**
* cfg80211_sinfo_alloc_tid_stats - allocate per-tid statistics.
*
- * @sinfo: the station information
+ * @link_sinfo: the station information
* @gfp: allocation flags
*
* Return: 0 on success. Non-zero on error.
*/
-int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp);
+int cfg80211_sinfo_alloc_tid_stats(struct link_station_info *link_sinfo, gfp_t gfp);
/**
* cfg80211_sinfo_release_content - release contents of station info
@@ -8446,7 +8473,7 @@ int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp);
*/
static inline void cfg80211_sinfo_release_content(struct station_info *sinfo)
{
- kfree(sinfo->pertid);
+ kfree(sinfo->deflink.pertid);
}
/**
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9320d4bc22ee..ea62d223a0e4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4106,11 +4106,11 @@ struct ieee80211_prep_tx_info {
* is only used if the configured rate control algorithm actually uses
* the new rate table API, and is therefore optional. Must be atomic.
*
- * @sta_statistics: Get statistics for this station. For example with beacon
- * filtering, the statistics kept by mac80211 might not be accurate, so
- * let the driver pre-fill the statistics. The driver can fill most of
- * the values (indicating which by setting the filled bitmap), but not
- * all of them make sense - see the source for which ones are possible.
+ * @link_sta_statistics: Get statistics for this link station. For example
+ * with beacon filtering, the statistics kept by mac80211 might not be
+ * accurate, so let the driver pre-fill the statistics. The driver can
+ * fill most of the values (indicating which by setting the filled bitmap),
+ * but not all of them make sense - see the source for which ones are possible.
* Statistics that the driver doesn't fill will be filled by mac80211.
* The callback can sleep.
*
@@ -4593,10 +4593,10 @@ struct ieee80211_ops {
void (*sta_rate_tbl_update)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
- void (*sta_statistics)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct station_info *sinfo);
+ void (*link_sta_statistics)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct link_station_info *link_sinfo);
int (*conf_tx)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id, u16 ac,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index c64531e0a60e..33365870ce86 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -613,10 +613,10 @@ static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local,
trace_drv_return_void(local);
}
-static inline void drv_sta_statistics(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta,
- struct station_info *sinfo)
+static inline void drv_link_sta_statistics(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct link_station_info *link_sinfo)
{
might_sleep();
lockdep_assert_wiphy(local->hw.wiphy);
@@ -625,9 +625,9 @@ static inline void drv_sta_statistics(struct ieee80211_local *local,
if (!check_sdata_in_driver(sdata))
return;
- trace_drv_sta_statistics(local, sdata, sta);
- if (local->ops->sta_statistics)
- local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo);
+ trace_drv_link_sta_statistics(local, sdata, sta);
+ if (local->ops->link_sta_statistics)
+ local->ops->link_sta_statistics(&local->hw, &sdata->vif, sta, link_sinfo);
trace_drv_return_void(local);
}
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c
index 42f7ee142ce3..172e0c4659de 100644
--- a/net/mac80211/ethtool.c
+++ b/net/mac80211/ethtool.c
@@ -79,6 +79,7 @@ static void ieee80211_get_stats(struct net_device *dev,
struct sta_info *sta;
struct ieee80211_local *local = sdata->local;
struct station_info sinfo;
+ struct link_station_info *link_sinfo;
struct survey_info survey;
int i, q;
#define STA_STATS_SURVEY_LEN 7
@@ -87,17 +88,16 @@ static void ieee80211_get_stats(struct net_device *dev,
#define ADD_STA_STATS(sta) \
do { \
- data[i++] += sinfo.rx_packets; \
- data[i++] += sinfo.rx_bytes; \
+ data[i++] += link_sinfo->rx_packets; \
+ data[i++] += link_sinfo->rx_bytes; \
data[i++] += (sta)->rx_stats.num_duplicates; \
data[i++] += (sta)->rx_stats.fragments; \
- data[i++] += sinfo.rx_dropped_misc; \
- \
- data[i++] += sinfo.tx_packets; \
- data[i++] += sinfo.tx_bytes; \
+ data[i++] += link_sinfo->rx_dropped_misc; \
+ data[i++] += link_sinfo->tx_packets; \
+ data[i++] += link_sinfo->tx_bytes; \
data[i++] += (sta)->status_stats.filtered; \
- data[i++] += sinfo.tx_failed; \
- data[i++] += sinfo.tx_retries; \
+ data[i++] += link_sinfo->tx_failed; \
+ data[i++] += link_sinfo->tx_retries; \
} while (0)
/* For Managed stations, find the single station based on BSSID
@@ -117,23 +117,24 @@ static void ieee80211_get_stats(struct net_device *dev,
memset(&sinfo, 0, sizeof(sinfo));
sta_set_sinfo(sta, &sinfo, false);
+ link_sinfo = &sinfo.deflink;
i = 0;
ADD_STA_STATS(&sta->deflink);
data[i++] = sta->sta_state;
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))
data[i] = 100000ULL *
- cfg80211_calculate_bitrate(&sinfo.txrate);
+ cfg80211_calculate_bitrate(&link_sinfo->txrate);
i++;
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE))
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE))
data[i] = 100000ULL *
- cfg80211_calculate_bitrate(&sinfo.rxrate);
+ cfg80211_calculate_bitrate(&link_sinfo->rxrate);
i++;
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))
- data[i] = (u8)sinfo.signal_avg;
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))
+ data[i] = (u8)link_sinfo->signal_avg;
i++;
} else {
list_for_each_entry(sta, &local->sta_list, list) {
@@ -143,6 +144,7 @@ static void ieee80211_get_stats(struct net_device *dev,
memset(&sinfo, 0, sizeof(sinfo));
sta_set_sinfo(sta, &sinfo, false);
+ link_sinfo = &sinfo.deflink;
i = 0;
ADD_STA_STATS(&sta->deflink);
}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 53f8da74fb99..985e53bf04bc 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2596,204 +2596,231 @@ static void sta_set_mesh_sinfo(struct sta_info *sta,
}
#endif
-void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
- bool tidstats)
+static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *link_sinfo,
+ struct ieee80211_link_data *link_sdata, bool tidstats)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
u32 thr = 0;
int i, ac, cpu;
struct ieee80211_sta_rx_stats *last_rxstats;
+ struct link_sta_info *link_sta_info = &sta->deflink;
last_rxstats = sta_get_last_rx_stats(sta);
- sinfo->generation = sdata->local->sta_generation;
/* do before driver, so beacon filtering drivers have a
* chance to e.g. just add the number of filtered beacons
* (or just modify the value entirely, of course)
*/
if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sinfo->rx_beacon = sdata->deflink.u.mgd.count_beacon_signal;
+ link_sinfo->rx_beacon = link_sdata->u.mgd.count_beacon_signal;
- drv_sta_statistics(local, sdata, &sta->sta, sinfo);
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) |
- BIT_ULL(NL80211_STA_INFO_STA_FLAGS) |
+ drv_link_sta_statistics(local, sdata, &sta->sta, link_sinfo);
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) |
BIT_ULL(NL80211_STA_INFO_BSS_PARAM) |
- BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME) |
- BIT_ULL(NL80211_STA_INFO_ASSOC_AT_BOOTTIME) |
BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC);
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- sinfo->beacon_loss_count =
- sdata->deflink.u.mgd.beacon_loss_count;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_LOSS);
+ link_sinfo->beacon_loss_count =
+ link_sdata->u.mgd.beacon_loss_count;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_LOSS);
}
- sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
- sinfo->assoc_at = sta->assoc_at;
- sinfo->inactive_time =
+ link_sinfo->inactive_time =
jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta));
- if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
+ if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
- sinfo->tx_bytes = 0;
+ link_sinfo->tx_bytes = 0;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- sinfo->tx_bytes += sta->deflink.tx_stats.bytes[ac];
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
+ link_sinfo->tx_bytes += link_sta_info->tx_stats.bytes[ac];
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_PACKETS))) {
- sinfo->tx_packets = 0;
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_PACKETS))) {
+ link_sinfo->tx_packets = 0;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- sinfo->tx_packets += sta->deflink.tx_stats.packets[ac];
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+ link_sinfo->tx_packets += link_sta_info->tx_stats.packets[ac];
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
}
- if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) |
+ if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) |
BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) {
- sinfo->rx_bytes += sta_get_stats_bytes(&sta->deflink.rx_stats);
+ link_sinfo->rx_bytes += sta_get_stats_bytes(&link_sta_info->rx_stats);
- if (sta->deflink.pcpu_rx_stats) {
+ if (link_sta_info->pcpu_rx_stats) {
for_each_possible_cpu(cpu) {
struct ieee80211_sta_rx_stats *cpurxs;
- cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats,
+ cpurxs = per_cpu_ptr(link_sta_info->pcpu_rx_stats,
cpu);
- sinfo->rx_bytes += sta_get_stats_bytes(cpurxs);
+ link_sinfo->rx_bytes += sta_get_stats_bytes(cpurxs);
}
}
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_PACKETS))) {
- sinfo->rx_packets = sta->deflink.rx_stats.packets;
- if (sta->deflink.pcpu_rx_stats) {
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_PACKETS))) {
+ link_sinfo->rx_packets = link_sta_info->rx_stats.packets;
+ if (link_sta_info->pcpu_rx_stats) {
for_each_possible_cpu(cpu) {
struct ieee80211_sta_rx_stats *cpurxs;
- cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats,
+ cpurxs = per_cpu_ptr(link_sta_info->pcpu_rx_stats,
cpu);
- sinfo->rx_packets += cpurxs->packets;
+ link_sinfo->rx_packets += cpurxs->packets;
}
}
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_RETRIES))) {
- sinfo->tx_retries = sta->deflink.status_stats.retry_count;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_RETRIES))) {
+ link_sinfo->tx_retries = link_sta_info->status_stats.retry_count;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))) {
- sinfo->tx_failed = sta->deflink.status_stats.retry_failed;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))) {
+ link_sinfo->tx_failed = link_sta_info->status_stats.retry_failed;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_DURATION))) {
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_DURATION))) {
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- sinfo->rx_duration += sta->airtime[ac].rx_airtime;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
+ link_sinfo->rx_duration += sta->airtime[ac].rx_airtime;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_DURATION))) {
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_DURATION))) {
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- sinfo->tx_duration += sta->airtime[ac].tx_airtime;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
+ link_sinfo->tx_duration += sta->airtime[ac].tx_airtime;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT))) {
- sinfo->airtime_weight = sta->airtime_weight;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT);
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT))) {
+ link_sinfo->airtime_weight = sta->airtime_weight;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT);
}
- sinfo->rx_dropped_misc = sta->deflink.rx_stats.dropped;
- if (sta->deflink.pcpu_rx_stats) {
+ link_sinfo->rx_dropped_misc = link_sta_info->rx_stats.dropped;
+ if (link_sta_info->pcpu_rx_stats) {
for_each_possible_cpu(cpu) {
struct ieee80211_sta_rx_stats *cpurxs;
- cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats, cpu);
- sinfo->rx_dropped_misc += cpurxs->dropped;
+ cpurxs = per_cpu_ptr(link_sta_info->pcpu_rx_stats, cpu);
+ link_sinfo->rx_dropped_misc += cpurxs->dropped;
}
}
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
!(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) {
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) |
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) |
BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG);
- sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif);
+ link_sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif);
}
if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) ||
ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) {
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL))) {
- sinfo->signal = (s8)last_rxstats->last_signal;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL))) {
+ link_sinfo->signal = (s8)last_rxstats->last_signal;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
}
- if (!sta->deflink.pcpu_rx_stats &&
- !(sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))) {
- sinfo->signal_avg =
- -ewma_signal_read(&sta->deflink.rx_stats_avg.signal);
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
+ if (!link_sta_info->pcpu_rx_stats &&
+ !(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))) {
+ link_sinfo->signal_avg =
+ -ewma_signal_read(&link_sta_info->rx_stats_avg.signal);
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
}
}
/* for the average - if pcpu_rx_stats isn't set - rxstats must point to
- * the sta->rx_stats struct, so the check here is fine with and without
+ * the link_sta_info->rx_stats struct, so the check here is fine with and without
* pcpu statistics
*/
if (last_rxstats->chains &&
- !(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL) |
+ !(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL) |
BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) {
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
- if (!sta->deflink.pcpu_rx_stats)
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
+ if (!link_sta_info->pcpu_rx_stats)
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);
+ link_sinfo->chains = last_rxstats->chains;
- sinfo->chains = last_rxstats->chains;
-
- for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
- sinfo->chain_signal[i] =
+ for (i = 0; i < ARRAY_SIZE(link_sinfo->chain_signal); i++) {
+ link_sinfo->chain_signal[i] =
last_rxstats->chain_signal_last[i];
- sinfo->chain_signal_avg[i] =
- -ewma_signal_read(&sta->deflink.rx_stats_avg.chain_signal[i]);
+ link_sinfo->chain_signal_avg[i] =
+ -ewma_signal_read(&link_sta_info->rx_stats_avg.chain_signal[i]);
}
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
!sta->sta.valid_links &&
- ieee80211_rate_valid(&sta->deflink.tx_stats.last_rate)) {
- sta_set_rate_info_tx(sta, &sta->deflink.tx_stats.last_rate,
- &sinfo->txrate);
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+ ieee80211_rate_valid(&link_sta_info->tx_stats.last_rate)) {
+ sta_set_rate_info_tx(sta, &link_sta_info->tx_stats.last_rate,
+ &link_sinfo->txrate);
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) &&
- !sta->sta.valid_links) {
- if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0)
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) &&
+ !sta->sta.valid_links){
+ if (sta_set_rate_info_rx(sta, &link_sinfo->rxrate) == 0)
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
}
- if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
+ if (tidstats && !cfg80211_sinfo_alloc_tid_stats(link_sinfo, GFP_KERNEL)) {
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
- sta_set_tidstats(sta, &sinfo->pertid[i], i);
+ sta_set_tidstats(sta, &link_sinfo->pertid[i], i);
}
-#ifdef CONFIG_MAC80211_MESH
- if (ieee80211_vif_is_mesh(&sdata->vif))
- sta_set_mesh_sinfo(sta, sinfo);
-#endif
+ link_sinfo->bss_param.flags = 0;
+ if (link_sdata->conf->use_cts_prot)
+ link_sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
+ if (link_sdata->conf->use_short_preamble)
+ link_sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+ if (link_sdata->conf->use_short_slot)
+ link_sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+ link_sinfo->bss_param.dtim_period = link_sdata->conf->dtim_period;
+ link_sinfo->bss_param.beacon_interval = link_sdata->conf->beacon_int;
+
+ thr = sta_get_expected_throughput(sta);
+
+ if (thr != 0) {
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
+ link_sinfo->expected_throughput = thr;
+ }
+
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL)) &&
+ link_sta_info->status_stats.ack_signal_filled) {
+ link_sinfo->ack_signal = link_sta_info->status_stats.last_ack_signal;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
+ }
+
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG)) &&
+ link_sta_info->status_stats.ack_signal_filled) {
+ link_sinfo->avg_ack_signal =
+ -(s8)ewma_avg_signal_read(&link_sta_info->status_stats.avg_ack_signal);
+ link_sinfo->filled |=
+ BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
+ }
+}
- sinfo->bss_param.flags = 0;
- if (sdata->vif.bss_conf.use_cts_prot)
- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
- if (sdata->vif.bss_conf.use_short_preamble)
- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
- if (sdata->vif.bss_conf.use_short_slot)
- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
- sinfo->bss_param.dtim_period = sdata->vif.bss_conf.dtim_period;
- sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
+void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
+ bool tidstats)
+{
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct link_station_info *link_sinfo = &sinfo->deflink;
+ struct ieee80211_link_data *link_sdata = &sdata->deflink;
+
+ sinfo->generation = sdata->local->sta_generation;
+
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_STA_FLAGS) |
+ BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME) |
+ BIT_ULL(NL80211_STA_INFO_ASSOC_AT_BOOTTIME);
+
+ sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
+ sinfo->assoc_at = sta->assoc_at;
sinfo->sta_flags.set = 0;
sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
@@ -2803,6 +2830,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
BIT(NL80211_STA_FLAG_AUTHENTICATED) |
BIT(NL80211_STA_FLAG_ASSOCIATED) |
BIT(NL80211_STA_FLAG_TDLS_PEER);
+
if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
@@ -2818,27 +2846,12 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
- thr = sta_get_expected_throughput(sta);
-
- if (thr != 0) {
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
- sinfo->expected_throughput = thr;
- }
-
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL)) &&
- sta->deflink.status_stats.ack_signal_filled) {
- sinfo->ack_signal = sta->deflink.status_stats.last_ack_signal;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
- }
+#ifdef CONFIG_MAC80211_MESH
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ sta_set_mesh_sinfo(sta, sinfo);
+#endif
- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG)) &&
- sta->deflink.status_stats.ack_signal_filled) {
- sinfo->avg_ack_signal =
- -(s8)ewma_avg_signal_read(
- &sta->deflink.status_stats.avg_ack_signal);
- sinfo->filled |=
- BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
- }
+ sta_set_link_sinfo(sta, link_sinfo, link_sdata, tidstats);
}
u32 sta_get_expected_throughput(struct sta_info *sta)
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index dc35fed7e9b0..1477506c76d6 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -995,7 +995,7 @@ DECLARE_EVENT_CLASS(sta_event,
)
);
-DEFINE_EVENT(sta_event, drv_sta_statistics,
+DEFINE_EVENT(sta_event, drv_link_sta_statistics,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta),
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d90033e03dd6..7740ab5c778d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6670,185 +6670,151 @@ static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
return true;
}
-static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
- u32 seq, int flags,
- struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- const u8 *mac_addr, struct station_info *sinfo)
+static int nl80211_fill_link_station(struct sk_buff *msg,
+ struct cfg80211_registered_device *rdev,
+ struct link_station_info *link_sinfo)
{
- void *hdr;
- struct nlattr *sinfoattr, *bss_param;
+ struct nlattr *bss_param;
- hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
- if (!hdr) {
- cfg80211_sinfo_release_content(sinfo);
- return -1;
- }
-
- if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
- nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
- nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
- goto nla_put_failure;
-
- sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
- if (!sinfoattr)
- goto nla_put_failure;
-
-#define PUT_SINFO(attr, memb, type) do { \
+#define PUT_LINK_SINFO(attr, memb, type) do { \
BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
- if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
- sinfo->memb)) \
- goto nla_put_failure; \
+ link_sinfo->memb)) \
+ return -EMSGSIZE; \
} while (0)
-#define PUT_SINFO_U64(attr, memb) do { \
- if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
+#define PUT_LINK_SINFO_U64(attr, memb) do { \
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
- sinfo->memb, NL80211_STA_INFO_PAD)) \
- goto nla_put_failure; \
+ link_sinfo->memb, NL80211_STA_INFO_PAD)) \
+ return -EMSGSIZE; \
} while (0)
- PUT_SINFO(CONNECTED_TIME, connected_time, u32);
- PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
- PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
+ PUT_LINK_SINFO(CONNECTED_TIME, connected_time, u32);
+ PUT_LINK_SINFO(INACTIVE_TIME, inactive_time, u32);
+ PUT_LINK_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
- if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
- BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
+ if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
+ BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
- (u32)sinfo->rx_bytes))
- goto nla_put_failure;
+ (u32)link_sinfo->rx_bytes))
+ return -EMSGSIZE;
- if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
- BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
+ if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
+ BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
- (u32)sinfo->tx_bytes))
- goto nla_put_failure;
+ (u32)link_sinfo->tx_bytes))
+ return -EMSGSIZE;
- PUT_SINFO_U64(RX_BYTES64, rx_bytes);
- PUT_SINFO_U64(TX_BYTES64, tx_bytes);
- PUT_SINFO_U64(RX_DURATION, rx_duration);
- PUT_SINFO_U64(TX_DURATION, tx_duration);
+ PUT_LINK_SINFO_U64(RX_BYTES64, rx_bytes);
+ PUT_LINK_SINFO_U64(TX_BYTES64, tx_bytes);
+ PUT_LINK_SINFO_U64(RX_DURATION, rx_duration);
+ PUT_LINK_SINFO_U64(TX_DURATION, tx_duration);
if (wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
- PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
+ PUT_LINK_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
switch (rdev->wiphy.signal_type) {
case CFG80211_SIGNAL_TYPE_MBM:
- PUT_SINFO(SIGNAL, signal, u8);
- PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
+ PUT_LINK_SINFO(SIGNAL, signal, u8);
+ PUT_LINK_SINFO(SIGNAL_AVG, signal_avg, u8);
break;
default:
break;
}
- if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
- if (!nl80211_put_signal(msg, sinfo->chains,
- sinfo->chain_signal,
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
+ if (!nl80211_put_signal(msg, link_sinfo->chains,
+ link_sinfo->chain_signal,
NL80211_STA_INFO_CHAIN_SIGNAL))
- goto nla_put_failure;
+ return -EMSGSIZE;
}
- if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
- if (!nl80211_put_signal(msg, sinfo->chains,
- sinfo->chain_signal_avg,
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
+ if (!nl80211_put_signal(msg, link_sinfo->chains,
+ link_sinfo->chain_signal_avg,
NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
- goto nla_put_failure;
+ return -EMSGSIZE;
}
- if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
- if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
+ if (!nl80211_put_sta_rate(msg, &link_sinfo->txrate,
NL80211_STA_INFO_TX_BITRATE))
- goto nla_put_failure;
+ return -EMSGSIZE;
}
- if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
- if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
+ if (!nl80211_put_sta_rate(msg, &link_sinfo->rxrate,
NL80211_STA_INFO_RX_BITRATE))
- goto nla_put_failure;
+ return -EMSGSIZE;
}
- PUT_SINFO(RX_PACKETS, rx_packets, u32);
- PUT_SINFO(TX_PACKETS, tx_packets, u32);
- PUT_SINFO(TX_RETRIES, tx_retries, u32);
- PUT_SINFO(TX_FAILED, tx_failed, u32);
- PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
- PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
+ PUT_LINK_SINFO(RX_PACKETS, rx_packets, u32);
+ PUT_LINK_SINFO(TX_PACKETS, tx_packets, u32);
+ PUT_LINK_SINFO(TX_RETRIES, tx_retries, u32);
+ PUT_LINK_SINFO(TX_FAILED, tx_failed, u32);
+ PUT_LINK_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
+ PUT_LINK_SINFO(BEACON_LOSS, beacon_loss_count, u32);
- PUT_SINFO(LLID, llid, u16);
- PUT_SINFO(PLID, plid, u16);
- PUT_SINFO(PLINK_STATE, plink_state, u8);
- PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
- PUT_SINFO(LOCAL_PM, local_pm, u32);
- PUT_SINFO(PEER_PM, peer_pm, u32);
- PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
- PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
- PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
- PUT_SINFO_U64(T_OFFSET, t_offset);
-
- if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
bss_param = nla_nest_start_noflag(msg,
NL80211_STA_INFO_BSS_PARAM);
if (!bss_param)
- goto nla_put_failure;
+ return -EMSGSIZE;
- if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
+ if (((link_sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
- ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
+ ((link_sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
- ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
+ ((link_sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
- sinfo->bss_param.dtim_period) ||
+ link_sinfo->bss_param.dtim_period) ||
nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
- sinfo->bss_param.beacon_interval))
- goto nla_put_failure;
+ link_sinfo->bss_param.beacon_interval))
+ return -EMSGSIZE;
nla_nest_end(msg, bss_param);
}
- if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
- nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
- sizeof(struct nl80211_sta_flag_update),
- &sinfo->sta_flags))
- goto nla_put_failure;
- PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
- PUT_SINFO_U64(BEACON_RX, rx_beacon);
- PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
- PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
- PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
+ PUT_LINK_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
+ PUT_LINK_SINFO_U64(BEACON_RX, rx_beacon);
+ PUT_LINK_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
+ PUT_LINK_SINFO(RX_MPDUS, rx_mpdu_count, u32);
+ PUT_LINK_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
if (wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
- PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
- PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
+ PUT_LINK_SINFO(ACK_SIGNAL, ack_signal, u8);
+ PUT_LINK_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
}
-#undef PUT_SINFO
-#undef PUT_SINFO_U64
+#undef PUT_LINK_SINFO
+#undef PUT_LINK_SINFO_U64
- if (sinfo->pertid) {
+ if (link_sinfo->pertid) {
struct nlattr *tidsattr;
int tid;
tidsattr = nla_nest_start_noflag(msg,
NL80211_STA_INFO_TID_STATS);
if (!tidsattr)
- goto nla_put_failure;
+ return -EMSGSIZE;
for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
struct cfg80211_tid_stats *tidstats;
struct nlattr *tidattr;
- tidstats = &sinfo->pertid[tid];
+ tidstats = &link_sinfo->pertid[tid];
if (!tidstats->filled)
continue;
tidattr = nla_nest_start_noflag(msg, tid + 1);
if (!tidattr)
- goto nla_put_failure;
+ return -EMSGSIZE;
#define PUT_TIDVAL_U64(attr, memb) do { \
if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
tidstats->memb, NL80211_TID_STATS_PAD)) \
- goto nla_put_failure; \
+ return -EMSGSIZE; \
} while (0)
PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
@@ -6861,7 +6827,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
BIT(NL80211_TID_STATS_TXQ_STATS)) &&
!nl80211_put_txq_stats(msg, &tidstats->txq_stats,
NL80211_TID_STATS_TXQ_STATS))
- goto nla_put_failure;
+ return -EMSGSIZE;
nla_nest_end(msg, tidattr);
}
@@ -6869,16 +6835,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
nla_nest_end(msg, tidsattr);
}
- nla_nest_end(msg, sinfoattr);
+ return 0;
+}
- if (sinfo->assoc_req_ies_len &&
- nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
- sinfo->assoc_req_ies))
- goto nla_put_failure;
+static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
+ u32 seq, int flags,
+ struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ const u8 *mac_addr, struct station_info *sinfo)
+{
+ struct nlattr *sinfoattr;
+ void *hdr;
+ struct link_station_info *link_sinfo = &sinfo->deflink;
+ int ret = -1;
- if (sinfo->assoc_resp_ies_len &&
- nla_put(msg, NL80211_ATTR_RESP_IE, sinfo->assoc_resp_ies_len,
- sinfo->assoc_resp_ies))
+ hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
+ if (!hdr) {
+ cfg80211_sinfo_release_content(sinfo);
+ return ret;
+ }
+
+ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
+ nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
goto nla_put_failure;
if (sinfo->mlo_params_valid) {
@@ -6892,11 +6871,68 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
goto nla_put_failure;
}
+ if (sinfo->assoc_req_ies_len &&
+ nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
+ sinfo->assoc_req_ies))
+ goto nla_put_failure;
+
+ if (sinfo->assoc_resp_ies_len &&
+ nla_put(msg, NL80211_ATTR_RESP_IE, sinfo->assoc_resp_ies_len,
+ sinfo->assoc_resp_ies))
+ goto nla_put_failure;
+
+ sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
+ if (!sinfoattr)
+ goto nla_put_failure;
+
+ if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
+ nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
+ sizeof(struct nl80211_sta_flag_update),
+ &sinfo->sta_flags))
+ goto nla_put_failure;
+
+#define PUT_SINFO(attr, memb, type) do { \
+ BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
+ if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
+ nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
+ sinfo->memb)) \
+ goto nla_put_failure; \
+ } while (0)
+#define PUT_SINFO_U64(attr, memb) do { \
+ if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
+ nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
+ sinfo->memb, NL80211_STA_INFO_PAD)) \
+ goto nla_put_failure; \
+ } while (0)
+
+ PUT_SINFO(CONNECTED_TIME, connected_time, u32);
+ PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
+
+ PUT_SINFO(LLID, llid, u16);
+ PUT_SINFO(PLID, plid, u16);
+ PUT_SINFO(PLINK_STATE, plink_state, u8);
+ PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
+ PUT_SINFO(LOCAL_PM, local_pm, u32);
+ PUT_SINFO(PEER_PM, peer_pm, u32);
+ PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
+ PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
+ PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
+ PUT_SINFO_U64(T_OFFSET, t_offset);
+
+#undef PUT_SINFO
+#undef PUT_SINFO_U64
+
+ ret = nl80211_fill_link_station(msg, rdev, link_sinfo);
+ if (ret)
+ goto nla_put_failure;
+
+ nla_nest_end(msg, sinfoattr);
+
cfg80211_sinfo_release_content(sinfo);
genlmsg_end(msg, hdr);
return 0;
- nla_put_failure:
+nla_put_failure:
cfg80211_sinfo_release_content(sinfo);
genlmsg_cancel(msg, hdr);
return -EMSGSIZE;
@@ -13005,11 +13041,10 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
if (err)
return err;
-
cfg80211_sinfo_release_content(&sinfo);
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
+ if (sinfo.deflink.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
cqm_config->last_rssi_event_value =
- (s8) sinfo.rx_beacon_signal_avg;
+ (s8)sinfo.deflink.rx_beacon_signal_avg;
}
last = cqm_config->last_rssi_event_value;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a57210c8087c..69193fc3b040 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -200,22 +200,23 @@
__field(u16, llid) \
__field(u16, plid) \
__field(u8, plink_state)
-#define SINFO_ASSIGN \
- do { \
- __entry->generation = sinfo->generation; \
- __entry->connected_time = sinfo->connected_time; \
- __entry->inactive_time = sinfo->inactive_time; \
- __entry->rx_bytes = sinfo->rx_bytes; \
- __entry->tx_bytes = sinfo->tx_bytes; \
- __entry->rx_packets = sinfo->rx_packets; \
- __entry->tx_packets = sinfo->tx_packets; \
- __entry->tx_retries = sinfo->tx_retries; \
- __entry->tx_failed = sinfo->tx_failed; \
- __entry->rx_dropped_misc = sinfo->rx_dropped_misc; \
- __entry->beacon_loss_count = sinfo->beacon_loss_count; \
- __entry->llid = sinfo->llid; \
- __entry->plid = sinfo->plid; \
- __entry->plink_state = sinfo->plink_state; \
+#define SINFO_ASSIGN \
+ struct link_station_info *link_sinfo = &sinfo->deflink; \
+ do { \
+ __entry->generation = sinfo->generation; \
+ __entry->connected_time = link_sinfo->connected_time; \
+ __entry->inactive_time = link_sinfo->inactive_time; \
+ __entry->rx_bytes = link_sinfo->rx_bytes; \
+ __entry->tx_bytes = link_sinfo->tx_bytes; \
+ __entry->rx_packets = link_sinfo->rx_packets; \
+ __entry->tx_packets = link_sinfo->tx_packets; \
+ __entry->tx_retries = link_sinfo->tx_retries; \
+ __entry->tx_failed = link_sinfo->tx_failed; \
+ __entry->rx_dropped_misc = link_sinfo->rx_dropped_misc; \
+ __entry->beacon_loss_count = link_sinfo->beacon_loss_count; \
+ __entry->llid = sinfo->llid; \
+ __entry->plid = sinfo->plid; \
+ __entry->plink_state = sinfo->plink_state; \
} while (0)
#define BOOL_TO_STR(bo) (bo) ? "true" : "false"
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 60157943d351..dbb2313b6982 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2626,12 +2626,12 @@ bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
return false;
}
-int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp)
+int cfg80211_sinfo_alloc_tid_stats(struct link_station_info *link_sinfo, gfp_t gfp)
{
- sinfo->pertid = kcalloc(IEEE80211_NUM_TIDS + 1,
- sizeof(*(sinfo->pertid)),
- gfp);
- if (!sinfo->pertid)
+ link_sinfo->pertid = kcalloc(IEEE80211_NUM_TIDS + 1,
+ sizeof(*(link_sinfo->pertid)),
+ gfp);
+ if (!link_sinfo->pertid)
return -ENOMEM;
return 0;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index a74b1afc594e..a59510deffae 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -1267,12 +1267,12 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
if (err)
return err;
- if (!(sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) {
+ if (!(sinfo.deflink.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) {
err = -EOPNOTSUPP;
goto free;
}
- rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
+ rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.deflink.txrate);
free:
cfg80211_sinfo_release_content(&sinfo);
@@ -1316,8 +1316,8 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
switch (rdev->wiphy.signal_type) {
case CFG80211_SIGNAL_TYPE_MBM:
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
- int sig = sinfo.signal;
+ if (sinfo.deflink.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
+ int sig = sinfo.deflink.signal;
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
wstats.qual.updated |= IW_QUAL_DBM;
@@ -1331,11 +1331,11 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
}
fallthrough;
case CFG80211_SIGNAL_TYPE_UNSPEC:
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
+ if (sinfo.deflink.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
- wstats.qual.level = sinfo.signal;
- wstats.qual.qual = sinfo.signal;
+ wstats.qual.level = sinfo.deflink.signal;
+ wstats.qual.qual = sinfo.deflink.signal;
break;
}
fallthrough;
@@ -1345,10 +1345,10 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
}
wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC))
- wstats.discard.misc = sinfo.rx_dropped_misc;
- if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))
- wstats.discard.retries = sinfo.tx_failed;
+ if (sinfo.deflink.filled & BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC))
+ wstats.discard.misc = sinfo.deflink.rx_dropped_misc;
+ if (sinfo.deflink.filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))
+ wstats.discard.retries = sinfo.deflink.tx_failed;
cfg80211_sinfo_release_content(&sinfo);
--
2.34.1
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
2025-01-10 4:24 ` [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO Sarika Sharma
@ 2025-01-10 9:19 ` Johannes Berg
2025-01-12 8:10 ` Sarika Sharma
2025-01-11 6:51 ` kernel test robot
2025-01-11 7:25 ` kernel test robot
2 siblings, 1 reply; 28+ messages in thread
From: Johannes Berg @ 2025-01-10 9:19 UTC (permalink / raw)
To: Sarika Sharma; +Cc: linux-wireless
On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>
> struct station_info {
>
> + struct link_station_info deflink;
Having a deflink here seems kind of questionable?
Why not pass multiple pointers?
Also here I'd say you should split this better. Probably the whole
series needs some reorg for cfg80211/mac80211.
> - if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
> + if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
>
A little less renaming would probably also make this easier to review.
johannes
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
2025-01-10 9:19 ` Johannes Berg
@ 2025-01-12 8:10 ` Sarika Sharma
2025-01-14 11:19 ` Johannes Berg
0 siblings, 1 reply; 28+ messages in thread
From: Sarika Sharma @ 2025-01-12 8:10 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 1/10/2025 2:49 PM, Johannes Berg wrote:
> On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>>
>> struct station_info {
>>
>> + struct link_station_info deflink;
>
> Having a deflink here seems kind of questionable?
ohh! why so? In other structures like vif, sdata, sta, we did the same
way. So why can't we have the same way here as well?
>
> Why not pass multiple pointers?
Sorry, I didn't get you.
Did you mean keep the sinfo structure and call this for filling all link
level, non-mL, ML information?
>
> Also here I'd say you should split this better. Probably the whole
> series needs some reorg for cfg80211/mac80211.
Sure, let me check what I can do here.
>> - if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
>> + if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
>>
>
> A little less renaming would probably also make this easier to review.
Sure, but this is corresponding to filling link level data, that's why
just renaming sinfo to link_sinfo.
>
> johannes
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
2025-01-12 8:10 ` Sarika Sharma
@ 2025-01-14 11:19 ` Johannes Berg
2025-01-15 6:40 ` Sarika Sharma
0 siblings, 1 reply; 28+ messages in thread
From: Johannes Berg @ 2025-01-14 11:19 UTC (permalink / raw)
To: Sarika Sharma; +Cc: linux-wireless
On Sun, 2025-01-12 at 13:40 +0530, Sarika Sharma wrote:
> On 1/10/2025 2:49 PM, Johannes Berg wrote:
> > On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
> > >
> > > struct station_info {
> > >
> > > + struct link_station_info deflink;
> >
> > Having a deflink here seems kind of questionable?
>
> ohh! why so? In other structures like vif, sdata, sta, we did the same
> way. So why can't we have the same way here as well?
Well, (a) I tend to think in hindsight it was sort of a mistake, but (b)
we couldn't really do it differently due to all drivers. But here you're
already touching all the code anyway, and it's mostly cfg80211/mac80211,
so why bother?
> > Why not pass multiple pointers?
>
> Sorry, I didn't get you.
> Did you mean keep the sinfo structure and call this for filling all link
> level, non-mL, ML information?
I think I meant that we could have per link pointers passed to the
method, but we might as well just have them in the sinfo struct as you
introduce in later patches.
> > > - if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
> > > + if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
> > >
> >
> > A little less renaming would probably also make this easier to review.
>
> Sure, but this is corresponding to filling link level data, that's why
> just renaming sinfo to link_sinfo.
Yeah, but does it matter so much? :)
I guess the flipside is that this way it's easier to review that all
values fall into the right place, but I think the data structure
organisation you did mostly ensures that anyway? Not sure though.
johannes
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
2025-01-14 11:19 ` Johannes Berg
@ 2025-01-15 6:40 ` Sarika Sharma
0 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-15 6:40 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 1/14/2025 4:49 PM, Johannes Berg wrote:
> On Sun, 2025-01-12 at 13:40 +0530, Sarika Sharma wrote:
>> On 1/10/2025 2:49 PM, Johannes Berg wrote:
>>> On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>>>>
>>>> struct station_info {
>>>>
>>>> + struct link_station_info deflink;
>>>
>>> Having a deflink here seems kind of questionable?
>>
>> ohh! why so? In other structures like vif, sdata, sta, we did the same
>> way. So why can't we have the same way here as well?
>
> Well, (a) I tend to think in hindsight it was sort of a mistake, but (b)
> we couldn't really do it differently due to all drivers. But here you're
> already touching all the code anyway, and it's mostly cfg80211/mac80211,
> so why bother?
Sure, I will remove deflink and instead could use link pointer (link[0])
to fill statistics for non-ML stations.
>
>>> Why not pass multiple pointers?
>>
>> Sorry, I didn't get you.
>> Did you mean keep the sinfo structure and call this for filling all link
>> level, non-mL, ML information?
>
> I think I meant that we could have per link pointers passed to the
> method, but we might as well just have them in the sinfo struct as you
> introduce in later patches.
Sure, will introduce the link pointer here and use link[0] for non-ML
stations and corresponding link pointer for ML stations.
For drivers that offload link decisions and do not provide per-link
statistics, a flag could be used to indicate whether the per-link
statistics is filled from driver or not, if not can use link[0] to fill
the station information and if yes then can use the corresponding link
pointers to fill link level information.
>
>>>> - if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
>>>> + if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
>>>>
>>>
>>> A little less renaming would probably also make this easier to review.
>>
>> Sure, but this is corresponding to filling link level data, that's why
>> just renaming sinfo to link_sinfo.
>
> Yeah, but does it matter so much? :)
Not really, this is just done to differentiate the structures
used(station_info or link_station_info) and code readability purpose.
>
> I guess the flipside is that this way it's easier to review that all
> values fall into the right place, but I think the data structure
> organisation you did mostly ensures that anyway? Not sure though.
Yes from data structure organization it is taken care that it falls at
right place.
If it found to be difficult to review and required, I can rename to sinfo?
>
> johannes
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
2025-01-10 4:24 ` [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO Sarika Sharma
2025-01-10 9:19 ` Johannes Berg
@ 2025-01-11 6:51 ` kernel test robot
2025-01-11 7:25 ` kernel test robot
2 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2025-01-11 6:51 UTC (permalink / raw)
To: Sarika Sharma; +Cc: oe-kbuild-all
Hi Sarika,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on 7bf1659bad4e9413cdba132ef9cbd0caa9cabcc4]
url: https://github.com/intel-lab-lkp/linux/commits/Sarika-Sharma/wifi-cfg80211-reorg-sinfo-structure-elements-for-mesh/20250110-122824
base: 7bf1659bad4e9413cdba132ef9cbd0caa9cabcc4
patch link: https://lore.kernel.org/r/20250110042449.1158789-3-quic_sarishar%40quicinc.com
patch subject: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
config: csky-randconfig-001-20250111 (https://download.01.org/0day-ci/archive/20250111/202501111457.KNK3Pg5x-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250111/202501111457.KNK3Pg5x-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501111457.KNK3Pg5x-lkp@intel.com/
All errors (new ones prefixed by >>):
net/batman-adv/bat_v_elp.c: In function 'batadv_v_elp_get_throughput':
>> net/batman-adv/bat_v_elp.c:113:37: error: 'struct station_info' has no member named 'expected_throughput'
113 | return sinfo.expected_throughput / 100;
| ^
net/batman-adv/bat_v_elp.c:119:65: error: 'struct station_info' has no member named 'txrate'
119 | return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
| ^
vim +113 net/batman-adv/bat_v_elp.c
d6f94d91f766b4 Linus Lüssing 2016-01-16 58
c833484e5f3872 Antonio Quartulli 2015-11-10 59 /**
7e9a8c2ce7c5f8 Sven Eckelmann 2017-12-02 60 * batadv_v_elp_get_throughput() - get the throughput towards a neighbour
c833484e5f3872 Antonio Quartulli 2015-11-10 61 * @neigh: the neighbour for which the throughput has to be obtained
c833484e5f3872 Antonio Quartulli 2015-11-10 62 *
c833484e5f3872 Antonio Quartulli 2015-11-10 63 * Return: The throughput towards the given neighbour in multiples of 100kpbs
bccb48c89fe3c0 Sven Eckelmann 2020-06-01 64 * (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
c833484e5f3872 Antonio Quartulli 2015-11-10 65 */
c833484e5f3872 Antonio Quartulli 2015-11-10 66 static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
c833484e5f3872 Antonio Quartulli 2015-11-10 67 {
c833484e5f3872 Antonio Quartulli 2015-11-10 68 struct batadv_hard_iface *hard_iface = neigh->if_incoming;
c833484e5f3872 Antonio Quartulli 2015-11-10 69 struct ethtool_link_ksettings link_settings;
1942de1bbac301 Marek Lindner 2016-09-30 70 struct net_device *real_netdev;
c833484e5f3872 Antonio Quartulli 2015-11-10 71 struct station_info sinfo;
c833484e5f3872 Antonio Quartulli 2015-11-10 72 u32 throughput;
c833484e5f3872 Antonio Quartulli 2015-11-10 73 int ret;
c833484e5f3872 Antonio Quartulli 2015-11-10 74
c833484e5f3872 Antonio Quartulli 2015-11-10 75 /* if the user specified a customised value for this interface, then
c833484e5f3872 Antonio Quartulli 2015-11-10 76 * return it directly
c833484e5f3872 Antonio Quartulli 2015-11-10 77 */
c833484e5f3872 Antonio Quartulli 2015-11-10 78 throughput = atomic_read(&hard_iface->bat_v.throughput_override);
c833484e5f3872 Antonio Quartulli 2015-11-10 79 if (throughput != 0)
c833484e5f3872 Antonio Quartulli 2015-11-10 80 return throughput;
c833484e5f3872 Antonio Quartulli 2015-11-10 81
c833484e5f3872 Antonio Quartulli 2015-11-10 82 /* if this is a wireless device, then ask its throughput through
c833484e5f3872 Antonio Quartulli 2015-11-10 83 * cfg80211 API
c833484e5f3872 Antonio Quartulli 2015-11-10 84 */
10b1bbb46c6c8e Sven Eckelmann 2016-09-30 85 if (batadv_is_wifi_hardif(hard_iface)) {
10b1bbb46c6c8e Sven Eckelmann 2016-09-30 86 if (!batadv_is_cfg80211_hardif(hard_iface))
f44a3ae9a2811c Marek Lindner 2016-09-30 87 /* unsupported WiFi driver version */
f44a3ae9a2811c Marek Lindner 2016-09-30 88 goto default_throughput;
f44a3ae9a2811c Marek Lindner 2016-09-30 89
1942de1bbac301 Marek Lindner 2016-09-30 90 real_netdev = batadv_get_real_netdev(hard_iface->net_dev);
1942de1bbac301 Marek Lindner 2016-09-30 91 if (!real_netdev)
1942de1bbac301 Marek Lindner 2016-09-30 92 goto default_throughput;
1942de1bbac301 Marek Lindner 2016-09-30 93
1942de1bbac301 Marek Lindner 2016-09-30 94 ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
1942de1bbac301 Marek Lindner 2016-09-30 95
ca8c3b922e7032 Anders Roxell 2019-02-22 96 if (!ret) {
7d652669b61d70 Felix Fietkau 2019-01-25 97 /* free the TID stats immediately */
7d652669b61d70 Felix Fietkau 2019-01-25 98 cfg80211_sinfo_release_content(&sinfo);
ca8c3b922e7032 Anders Roxell 2019-02-22 99 }
7d652669b61d70 Felix Fietkau 2019-01-25 100
1942de1bbac301 Marek Lindner 2016-09-30 101 dev_put(real_netdev);
c833484e5f3872 Antonio Quartulli 2015-11-10 102 if (ret == -ENOENT) {
c833484e5f3872 Antonio Quartulli 2015-11-10 103 /* Node is not associated anymore! It would be
c833484e5f3872 Antonio Quartulli 2015-11-10 104 * possible to delete this neighbor. For now set
c833484e5f3872 Antonio Quartulli 2015-11-10 105 * the throughput metric to 0.
c833484e5f3872 Antonio Quartulli 2015-11-10 106 */
c833484e5f3872 Antonio Quartulli 2015-11-10 107 return 0;
c833484e5f3872 Antonio Quartulli 2015-11-10 108 }
3f3f87325dcb3c Sven Eckelmann 2017-06-09 109 if (ret)
3f3f87325dcb3c Sven Eckelmann 2017-06-09 110 goto default_throughput;
3f3f87325dcb3c Sven Eckelmann 2017-06-09 111
2b1aa5a4c654cc René Treffer 2019-11-26 112 if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
c833484e5f3872 Antonio Quartulli 2015-11-10 @113 return sinfo.expected_throughput / 100;
2b1aa5a4c654cc René Treffer 2019-11-26 114
2b1aa5a4c654cc René Treffer 2019-11-26 115 /* try to estimate the expected throughput based on reported tx
2b1aa5a4c654cc René Treffer 2019-11-26 116 * rates
2b1aa5a4c654cc René Treffer 2019-11-26 117 */
2b1aa5a4c654cc René Treffer 2019-11-26 118 if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
2b1aa5a4c654cc René Treffer 2019-11-26 119 return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
2b1aa5a4c654cc René Treffer 2019-11-26 120
2b1aa5a4c654cc René Treffer 2019-11-26 121 goto default_throughput;
c833484e5f3872 Antonio Quartulli 2015-11-10 122 }
c833484e5f3872 Antonio Quartulli 2015-11-10 123
c833484e5f3872 Antonio Quartulli 2015-11-10 124 /* if not a wifi interface, check if this device provides data via
c833484e5f3872 Antonio Quartulli 2015-11-10 125 * ethtool (e.g. an Ethernet adapter)
c833484e5f3872 Antonio Quartulli 2015-11-10 126 */
c833484e5f3872 Antonio Quartulli 2015-11-10 127 rtnl_lock();
c833484e5f3872 Antonio Quartulli 2015-11-10 128 ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings);
c833484e5f3872 Antonio Quartulli 2015-11-10 129 rtnl_unlock();
9ad346c90509eb Sven Eckelmann 2019-11-25 130 if (ret == 0) {
c833484e5f3872 Antonio Quartulli 2015-11-10 131 /* link characteristics might change over time */
c833484e5f3872 Antonio Quartulli 2015-11-10 132 if (link_settings.base.duplex == DUPLEX_FULL)
c833484e5f3872 Antonio Quartulli 2015-11-10 133 hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
c833484e5f3872 Antonio Quartulli 2015-11-10 134 else
c833484e5f3872 Antonio Quartulli 2015-11-10 135 hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
c833484e5f3872 Antonio Quartulli 2015-11-10 136
c833484e5f3872 Antonio Quartulli 2015-11-10 137 throughput = link_settings.base.speed;
825ffe1f7b8751 Sven Eckelmann 2017-08-23 138 if (throughput && throughput != SPEED_UNKNOWN)
c833484e5f3872 Antonio Quartulli 2015-11-10 139 return throughput * 10;
c833484e5f3872 Antonio Quartulli 2015-11-10 140 }
c833484e5f3872 Antonio Quartulli 2015-11-10 141
c833484e5f3872 Antonio Quartulli 2015-11-10 142 default_throughput:
c833484e5f3872 Antonio Quartulli 2015-11-10 143 if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
c833484e5f3872 Antonio Quartulli 2015-11-10 144 batadv_info(hard_iface->soft_iface,
c833484e5f3872 Antonio Quartulli 2015-11-10 145 "WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %u.%1u Mbps. Consider overriding the throughput manually or checking your driver.\n",
c833484e5f3872 Antonio Quartulli 2015-11-10 146 hard_iface->net_dev->name,
c833484e5f3872 Antonio Quartulli 2015-11-10 147 BATADV_THROUGHPUT_DEFAULT_VALUE / 10,
c833484e5f3872 Antonio Quartulli 2015-11-10 148 BATADV_THROUGHPUT_DEFAULT_VALUE % 10);
c833484e5f3872 Antonio Quartulli 2015-11-10 149 hard_iface->bat_v.flags |= BATADV_WARNING_DEFAULT;
c833484e5f3872 Antonio Quartulli 2015-11-10 150 }
c833484e5f3872 Antonio Quartulli 2015-11-10 151
c833484e5f3872 Antonio Quartulli 2015-11-10 152 /* if none of the above cases apply, return the base_throughput */
c833484e5f3872 Antonio Quartulli 2015-11-10 153 return BATADV_THROUGHPUT_DEFAULT_VALUE;
c833484e5f3872 Antonio Quartulli 2015-11-10 154 }
c833484e5f3872 Antonio Quartulli 2015-11-10 155
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
2025-01-10 4:24 ` [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO Sarika Sharma
2025-01-10 9:19 ` Johannes Berg
2025-01-11 6:51 ` kernel test robot
@ 2025-01-11 7:25 ` kernel test robot
2 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2025-01-11 7:25 UTC (permalink / raw)
To: Sarika Sharma; +Cc: oe-kbuild-all
Hi Sarika,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on 7bf1659bad4e9413cdba132ef9cbd0caa9cabcc4]
url: https://github.com/intel-lab-lkp/linux/commits/Sarika-Sharma/wifi-cfg80211-reorg-sinfo-structure-elements-for-mesh/20250110-122824
base: 7bf1659bad4e9413cdba132ef9cbd0caa9cabcc4
patch link: https://lore.kernel.org/r/20250110042449.1158789-3-quic_sarishar%40quicinc.com
patch subject: [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO
config: nios2-randconfig-002-20250111 (https://download.01.org/0day-ci/archive/20250111/202501111530.X3vZY0os-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250111/202501111530.X3vZY0os-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501111530.X3vZY0os-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from include/linux/kernel.h:16,
from include/net/mac80211.h:17,
from drivers/net/wireless/ath/ath11k/mac.c:7:
drivers/net/wireless/ath/ath11k/mac.c: In function 'ath11k_mac_put_chain_rssi':
>> drivers/net/wireless/ath/ath11k/mac.c:8920:41: error: 'struct station_info' has no member named 'chain_signal'
8920 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
| ^~
include/linux/array_size.h:11:33: note: in definition of macro 'ARRAY_SIZE'
11 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
| ^~~
>> drivers/net/wireless/ath/ath11k/mac.c:8920:41: error: 'struct station_info' has no member named 'chain_signal'
8920 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
| ^~
include/linux/array_size.h:11:48: note: in definition of macro 'ARRAY_SIZE'
11 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
| ^~~
In file included from include/asm-generic/bug.h:5,
from ./arch/nios2/include/generated/asm/bug.h:1,
from include/linux/bug.h:5,
from include/net/mac80211.h:16:
>> drivers/net/wireless/ath/ath11k/mac.c:8920:41: error: 'struct station_info' has no member named 'chain_signal'
8920 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
| ^~
include/linux/compiler.h:260:79: note: in definition of macro '__BUILD_BUG_ON_ZERO_MSG'
260 | #define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
| ^
include/linux/compiler.h:264:57: note: in expansion of macro '__same_type'
264 | #define __must_be_array(a) __BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
| ^~~~~~~~~~~
include/linux/array_size.h:11:59: note: in expansion of macro '__must_be_array'
11 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
| ^~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/mac.c:8920:25: note: in expansion of macro 'ARRAY_SIZE'
8920 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
| ^~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/mac.c:8920:41: error: 'struct station_info' has no member named 'chain_signal'
8920 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
| ^~
include/linux/compiler.h:260:79: note: in definition of macro '__BUILD_BUG_ON_ZERO_MSG'
260 | #define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
| ^
include/linux/compiler.h:264:57: note: in expansion of macro '__same_type'
264 | #define __must_be_array(a) __BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
| ^~~~~~~~~~~
include/linux/array_size.h:11:59: note: in expansion of macro '__must_be_array'
11 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
| ^~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/mac.c:8920:25: note: in expansion of macro 'ARRAY_SIZE'
8920 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
| ^~~~~~~~~~
include/linux/compiler.h:260:77: error: expression in static assertion is not an integer
260 | #define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
| ^
include/linux/compiler.h:264:33: note: in expansion of macro '__BUILD_BUG_ON_ZERO_MSG'
264 | #define __must_be_array(a) __BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/array_size.h:11:59: note: in expansion of macro '__must_be_array'
11 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
| ^~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/mac.c:8920:25: note: in expansion of macro 'ARRAY_SIZE'
8920 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
| ^~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/mac.c:8921:22: error: 'struct station_info' has no member named 'chains'
8921 | sinfo->chains &= ~BIT(i);
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8933:30: error: 'struct station_info' has no member named 'chain_signal'
8933 | sinfo->chain_signal[i] = rssi;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8934:30: error: 'struct station_info' has no member named 'chains'
8934 | sinfo->chains |= BIT(i);
| ^~
drivers/net/wireless/ath/ath11k/mac.c: In function 'ath11k_mac_op_sta_statistics':
>> drivers/net/wireless/ath/ath11k/mac.c:8951:14: error: 'struct station_info' has no member named 'rx_duration'
8951 | sinfo->rx_duration = arsta->rx_duration;
| ^~
>> drivers/net/wireless/ath/ath11k/mac.c:8954:14: error: 'struct station_info' has no member named 'tx_duration'
8954 | sinfo->tx_duration = arsta->tx_duration;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8959:30: error: 'struct station_info' has no member named 'txrate'
8959 | sinfo->txrate.legacy = arsta->txrate.legacy;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8961:30: error: 'struct station_info' has no member named 'txrate'
8961 | sinfo->txrate.mcs = arsta->txrate.mcs;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8962:30: error: 'struct station_info' has no member named 'txrate'
8962 | sinfo->txrate.nss = arsta->txrate.nss;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8963:30: error: 'struct station_info' has no member named 'txrate'
8963 | sinfo->txrate.bw = arsta->txrate.bw;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8964:30: error: 'struct station_info' has no member named 'txrate'
8964 | sinfo->txrate.he_gi = arsta->txrate.he_gi;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8965:30: error: 'struct station_info' has no member named 'txrate'
8965 | sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8966:30: error: 'struct station_info' has no member named 'txrate'
8966 | sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8968:22: error: 'struct station_info' has no member named 'txrate'
8968 | sinfo->txrate.flags = arsta->txrate.flags;
| ^~
drivers/net/wireless/ath/ath11k/mac.c:8995:22: error: 'struct station_info' has no member named 'signal'
8995 | sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR;
| ^~
>> drivers/net/wireless/ath/ath11k/mac.c:8999:14: error: 'struct station_info' has no member named 'signal_avg'
8999 | sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
| ^~
drivers/net/wireless/ath/ath11k/mac.c:9002:22: error: 'struct station_info' has no member named 'signal_avg'
9002 | sinfo->signal_avg += ATH11K_DEFAULT_NOISE_FLOOR;
| ^~
drivers/net/wireless/ath/ath11k/mac.c: At top level:
>> drivers/net/wireless/ath/ath11k/mac.c:9727:10: error: 'const struct ieee80211_ops' has no member named 'sta_statistics'; did you mean 'link_sta_statistics'?
9727 | .sta_statistics = ath11k_mac_op_sta_statistics,
| ^~~~~~~~~~~~~~
| link_sta_statistics
>> drivers/net/wireless/ath/ath11k/mac.c:9727:43: error: initialization of 'void (*)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *)' from incompatible pointer type 'void (*)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, struct station_info *)' [-Wincompatible-pointer-types]
9727 | .sta_statistics = ath11k_mac_op_sta_statistics,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/mac.c:9727:43: note: (near initialization for 'ath11k_ops.flush_sta')
vim +8920 drivers/net/wireless/ath/ath11k/mac.c
d5c65159f28953 Kalle Valo 2019-11-23 8910
b488c766442f7d Wen Gong 2021-12-17 8911 static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
b488c766442f7d Wen Gong 2021-12-17 8912 struct ath11k_sta *arsta,
b488c766442f7d Wen Gong 2021-12-17 8913 char *pre,
b488c766442f7d Wen Gong 2021-12-17 8914 bool clear)
b488c766442f7d Wen Gong 2021-12-17 8915 {
b488c766442f7d Wen Gong 2021-12-17 8916 struct ath11k *ar = arsta->arvif->ar;
b488c766442f7d Wen Gong 2021-12-17 8917 int i;
b488c766442f7d Wen Gong 2021-12-17 8918 s8 rssi;
b488c766442f7d Wen Gong 2021-12-17 8919
b488c766442f7d Wen Gong 2021-12-17 @8920 for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
b488c766442f7d Wen Gong 2021-12-17 @8921 sinfo->chains &= ~BIT(i);
b488c766442f7d Wen Gong 2021-12-17 8922 rssi = arsta->chain_signal[i];
b488c766442f7d Wen Gong 2021-12-17 8923 if (clear)
b488c766442f7d Wen Gong 2021-12-17 8924 arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL;
b488c766442f7d Wen Gong 2021-12-17 8925
b488c766442f7d Wen Gong 2021-12-17 8926 ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
fc3b984a7d99bc Kalle Valo 2023-06-09 8927 "sta statistics %s rssi[%d] %d\n", pre, i, rssi);
b488c766442f7d Wen Gong 2021-12-17 8928
b488c766442f7d Wen Gong 2021-12-17 8929 if (rssi != ATH11K_DEFAULT_NOISE_FLOOR &&
b488c766442f7d Wen Gong 2021-12-17 8930 rssi != ATH11K_INVALID_RSSI_FULL &&
b488c766442f7d Wen Gong 2021-12-17 8931 rssi != ATH11K_INVALID_RSSI_EMPTY &&
b488c766442f7d Wen Gong 2021-12-17 8932 rssi != 0) {
b488c766442f7d Wen Gong 2021-12-17 8933 sinfo->chain_signal[i] = rssi;
b488c766442f7d Wen Gong 2021-12-17 8934 sinfo->chains |= BIT(i);
b488c766442f7d Wen Gong 2021-12-17 8935 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
b488c766442f7d Wen Gong 2021-12-17 8936 }
b488c766442f7d Wen Gong 2021-12-17 8937 }
b488c766442f7d Wen Gong 2021-12-17 8938 }
b488c766442f7d Wen Gong 2021-12-17 8939
d5c65159f28953 Kalle Valo 2019-11-23 8940 static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
d5c65159f28953 Kalle Valo 2019-11-23 8941 struct ieee80211_vif *vif,
d5c65159f28953 Kalle Valo 2019-11-23 8942 struct ieee80211_sta *sta,
d5c65159f28953 Kalle Valo 2019-11-23 8943 struct station_info *sinfo)
d5c65159f28953 Kalle Valo 2019-11-23 8944 {
10c65f97b424fc Jeff Johnson 2023-10-09 8945 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
b488c766442f7d Wen Gong 2021-12-17 8946 struct ath11k *ar = arsta->arvif->ar;
c3b39553fc7712 Wen Gong 2021-12-17 8947 s8 signal;
c3b39553fc7712 Wen Gong 2021-12-17 8948 bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
c3b39553fc7712 Wen Gong 2021-12-17 8949 ar->ab->wmi_ab.svc_map);
d5c65159f28953 Kalle Valo 2019-11-23 8950
d5c65159f28953 Kalle Valo 2019-11-23 @8951 sinfo->rx_duration = arsta->rx_duration;
d5c65159f28953 Kalle Valo 2019-11-23 8952 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
d5c65159f28953 Kalle Valo 2019-11-23 8953
a9e945eadf1759 Venkateswara Naralasetty 2019-11-28 @8954 sinfo->tx_duration = arsta->tx_duration;
a9e945eadf1759 Venkateswara Naralasetty 2019-11-28 8955 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
a9e945eadf1759 Venkateswara Naralasetty 2019-11-28 8956
1d795645e1eef9 Wen Gong 2021-10-11 8957 if (arsta->txrate.legacy || arsta->txrate.nss) {
d5c65159f28953 Kalle Valo 2019-11-23 8958 if (arsta->txrate.legacy) {
d5c65159f28953 Kalle Valo 2019-11-23 8959 sinfo->txrate.legacy = arsta->txrate.legacy;
d5c65159f28953 Kalle Valo 2019-11-23 8960 } else {
d5c65159f28953 Kalle Valo 2019-11-23 8961 sinfo->txrate.mcs = arsta->txrate.mcs;
d5c65159f28953 Kalle Valo 2019-11-23 8962 sinfo->txrate.nss = arsta->txrate.nss;
d5c65159f28953 Kalle Valo 2019-11-23 8963 sinfo->txrate.bw = arsta->txrate.bw;
d5c65159f28953 Kalle Valo 2019-11-23 8964 sinfo->txrate.he_gi = arsta->txrate.he_gi;
d5c65159f28953 Kalle Valo 2019-11-23 8965 sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
d5c65159f28953 Kalle Valo 2019-11-23 8966 sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
d5c65159f28953 Kalle Valo 2019-11-23 8967 }
d5c65159f28953 Kalle Valo 2019-11-23 8968 sinfo->txrate.flags = arsta->txrate.flags;
d5c65159f28953 Kalle Valo 2019-11-23 8969 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
1d795645e1eef9 Wen Gong 2021-10-11 8970 }
d5c65159f28953 Kalle Valo 2019-11-23 8971
b488c766442f7d Wen Gong 2021-12-17 8972 ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false);
b488c766442f7d Wen Gong 2021-12-17 8973
b488c766442f7d Wen Gong 2021-12-17 8974 if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) &&
b488c766442f7d Wen Gong 2021-12-17 8975 arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
b488c766442f7d Wen Gong 2021-12-17 8976 ar->ab->hw_params.supports_rssi_stats &&
b488c766442f7d Wen Gong 2021-12-17 8977 !ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
b488c766442f7d Wen Gong 2021-12-17 8978 WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
b488c766442f7d Wen Gong 2021-12-17 8979 ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true);
b488c766442f7d Wen Gong 2021-12-17 8980 }
b488c766442f7d Wen Gong 2021-12-17 8981
c3b39553fc7712 Wen Gong 2021-12-17 8982 signal = arsta->rssi_comb;
c3b39553fc7712 Wen Gong 2021-12-17 8983 if (!signal &&
c3b39553fc7712 Wen Gong 2021-12-17 8984 arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
c3b39553fc7712 Wen Gong 2021-12-17 8985 ar->ab->hw_params.supports_rssi_stats &&
c3b39553fc7712 Wen Gong 2021-12-17 8986 !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
c3b39553fc7712 Wen Gong 2021-12-17 8987 WMI_REQUEST_VDEV_STAT)))
c3b39553fc7712 Wen Gong 2021-12-17 8988 signal = arsta->rssi_beacon;
c3b39553fc7712 Wen Gong 2021-12-17 8989
c3b39553fc7712 Wen Gong 2021-12-17 8990 ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
fc3b984a7d99bc Kalle Valo 2023-06-09 8991 "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
c3b39553fc7712 Wen Gong 2021-12-17 8992 db2dbm, arsta->rssi_comb, arsta->rssi_beacon);
c3b39553fc7712 Wen Gong 2021-12-17 8993
c3b39553fc7712 Wen Gong 2021-12-17 8994 if (signal) {
c3b39553fc7712 Wen Gong 2021-12-17 8995 sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR;
f277eb0500b4ee Sriram R 2021-02-24 8996 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
d5c65159f28953 Kalle Valo 2019-11-23 8997 }
b205ce4c266cd6 Thiraviyam Mariyappan 2022-05-19 8998
aadeee47e9d7ae Lingbo Kong 2024-03-09 @8999 sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
aadeee47e9d7ae Lingbo Kong 2024-03-09 9000
aadeee47e9d7ae Lingbo Kong 2024-03-09 9001 if (!db2dbm)
aadeee47e9d7ae Lingbo Kong 2024-03-09 9002 sinfo->signal_avg += ATH11K_DEFAULT_NOISE_FLOOR;
aadeee47e9d7ae Lingbo Kong 2024-03-09 9003
b205ce4c266cd6 Thiraviyam Mariyappan 2022-05-19 9004 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
c3b39553fc7712 Wen Gong 2021-12-17 9005 }
d5c65159f28953 Kalle Valo 2019-11-23 9006
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
2025-01-10 4:24 ` [PATCH RFC 1/7] wifi: cfg80211: reorg sinfo structure elements for mesh Sarika Sharma
2025-01-10 4:24 ` [PATCH RFC 2/7] wifi: cfg80211: reorg sinfo structure elements for MLO Sarika Sharma
@ 2025-01-10 4:24 ` Sarika Sharma
2025-01-10 9:20 ` Johannes Berg
` (2 more replies)
2025-01-10 4:24 ` [PATCH RFC 4/7] wifi: cfg80211: add accumulated statistics for MLO links Sarika Sharma
` (5 subsequent siblings)
8 siblings, 3 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-10 4:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sarika Sharma
Currently, statistics is supported at deflink level for station. This
has problems when applied to multi-link(ML) connections.
Hence, add changes to support link level statistics in sinfo structure.
Additionally, remove mlo_params_valid from the sinfo structure and
add valid_links to indicate bitmap of valid links for MLO.
This will be helpful to check the link related statistics during MLO.
The statistics could be embedded into NL message as below:
For MLO:
cmd ->
NL80211_ATTR_IFINDEX
NL80211_ATTR_MAC
NL80211_ATTR_GENERATION
.......etc
NL80211_ATTR_STA_INFO | nest flag
NL80211_STA_INFO_CONNECTED_TIME,
NL80211_STA_INFO_STA_FLAGS,
........etc
NL80211_ATTR_MLO_LINK_ID,
NL80211_ATTR_MLD_ADDR,
NL80211_ATTR_MLO_LINKS | nested
link_id-1 | nested
NL80211_ATTR_MLO_LINK_ID,
NL80211_ATTR_MLD_ADDR,
NL80211_ATTR_STA_INFO | nest flag
NL80211_STA_INFO_RX_BYTES,
NL80211_STA_INFO_TX_BYTES,
..........etc.
link_id-2 | nested
NL80211_ATTR_MLO_LINK_ID,
NL80211_ATTR_MLD_ADDR,
NL80211_ATTR_STA_INFO | nest flag
NL80211_STA_INFO_RX_BYTES,
NL80211_STA_INFO_TX_BYTES,
.........etc
For non-ML:
cmd->
NL80211_ATTR_IFINDEX
NL80211_ATTR_MAC
NL80211_ATTR_GENERATION
....
NL80211_ATTR_STA_INFO | nest flag
NL80211_STA_INFO_CONNECTED_TIME,
NL80211_STA_INFO_STA_FLAGS,
NL80211_STA_INFO_RX_BYTES,
NL80211_STA_INFO_TX_BYTES,
.........etc
The output of iw dev wlan0 station dump for MLO could look like below:
Station 00:03:7f:04:31:78 (on wlan0)
authorized: yes
authenticated: yes
associated: yes
preamble: long
WMM/WME: yes
MFP: yes
TDLS peer: no
connected time: 383 seconds
associated at [boottime]: 93.740s
associated at: 93685 ms
current time: 340046 ms
MLD address: 00:03:7f:04:31:78
Link 0:
Address: 00:03:7f:04:31:78
inactive time: 330120 ms
rx bytes: 116
rx packets: 3
tx bytes: 0
tx packets: 0
tx retries: 0
tx failed: 0
rx drop misc: 0
signal: -95 dBm
tx bitrate: 6.0 MBit/s
tx duration: 2669 us
rx duration: 0 us
DTIM period: 2
beacon interval:100
Link 1:
Address: 00:03:7f:04:31:79
inactive time: 81268 ms
rx bytes: 1323
rx packets: 12
tx bytes: 1538
tx packets: 8
tx retries: 0
tx failed: 0
rx drop misc: 0
signal: -95 dBm
tx bitrate: 6.0 MBit/s
tx duration: 2669 us
rx bitrate: 6.0 MBit/s
rx duration: 0 us
DTIM period: 2
beacon interval:100
Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
---
include/net/cfg80211.h | 24 +++++---
include/net/mac80211.h | 3 +-
net/mac80211/ibss.c | 4 +-
net/mac80211/sta_info.c | 132 ++++++++++++++++++++++++++++++----------
net/mac80211/sta_info.h | 2 +-
net/mac80211/util.c | 18 +++++-
net/wireless/nl80211.c | 78 ++++++++++++++++++------
7 files changed, 198 insertions(+), 63 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ba3e7e72ab5d..5b0ec0394715 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2158,11 +2158,6 @@ struct link_station_info {
* @local_pm: local mesh STA power save mode
* @peer_pm: peer mesh STA power save mode
* @nonpeer_pm: non-peer mesh STA power save mode
- * @mlo_params_valid: Indicates @assoc_link_id and @mld_addr fields are filled
- * by driver. Drivers use this only in cfg80211_new_sta() calls when AP
- * MLD's MLME/SME is offload to driver. Drivers won't fill this
- * information in cfg80211_del_sta_sinfo(), get_station() and
- * dump_station() callbacks.
* @assoc_link_id: Indicates MLO link ID of the AP, with which the station
* completed (re)association. This information filled for both MLO
* and non-MLO STA connections when the AP affiliated with an MLD.
@@ -2176,8 +2171,12 @@ struct link_station_info {
* dump_station() callbacks. User space needs this information to determine
* the accepted and rejected affiliated links of the connected station.
* @assoc_resp_ies_len: Length of @assoc_resp_ies buffer in octets.
+ * @valid_links: bitmap of valid links, or 0 for non-MLO. Drivers fill this
+ * information in cfg80211_new_sta(), cfg80211_del_sta_sinfo(),
+ * get_station() and dump_station() callbacks.
* @deflink: This holds the default link STA information, for non MLO STA
* all link specific STA information is accessed through @deflink.
+ * @links: reference to Link sta entries for MLO.
*/
struct station_info {
u64 filled;
@@ -2201,13 +2200,15 @@ struct station_info {
enum nl80211_mesh_power_mode peer_pm;
enum nl80211_mesh_power_mode nonpeer_pm;
- bool mlo_params_valid;
u8 assoc_link_id;
u8 mld_addr[ETH_ALEN] __aligned(2);
const u8 *assoc_resp_ies;
size_t assoc_resp_ies_len;
+ u16 valid_links;
struct link_station_info deflink;
+ /* TODO: Need to check and add protection access to links memory */
+ struct link_station_info *links[IEEE80211_MLD_MAX_NUM_LINKS];
};
/**
@@ -8473,7 +8474,16 @@ int cfg80211_sinfo_alloc_tid_stats(struct link_station_info *link_sinfo, gfp_t g
*/
static inline void cfg80211_sinfo_release_content(struct station_info *sinfo)
{
- kfree(sinfo->deflink.pertid);
+ int link_id;
+
+ if (sinfo->valid_links) {
+ for_each_valid_link(sinfo, link_id) {
+ kfree(sinfo->links[link_id]->pertid);
+ kfree(sinfo->links[link_id]);
+ }
+ } else {
+ kfree(sinfo->deflink.pertid);
+ }
}
/**
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ea62d223a0e4..c1e88761b5e8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -7214,13 +7214,14 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
* ieee80211_ave_rssi - report the average RSSI for the specified interface
*
* @vif: the specified virtual interface
+ * @link_id: the link ID for MLO, or -1 for non-MLO
*
* Note: This function assumes that the given vif is valid.
*
* Return: The average RSSI value for the requested interface, or 0 if not
* applicable.
*/
-int ieee80211_ave_rssi(struct ieee80211_vif *vif);
+int ieee80211_ave_rssi(struct ieee80211_vif *vif, int link_id);
/**
* ieee80211_report_wowlan_wakeup - report WoWLAN wakeup
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index a1b4178deccf..0848fbda65f9 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -642,7 +642,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list) {
- unsigned long last_active = ieee80211_sta_last_active(sta);
+ unsigned long last_active = ieee80211_sta_last_active(sta, -1);
if (sta->sdata == sdata &&
time_is_after_jiffies(last_active +
@@ -1235,7 +1235,7 @@ static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata)
lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
- unsigned long last_active = ieee80211_sta_last_active(sta);
+ unsigned long last_active = ieee80211_sta_last_active(sta, -1);
if (sdata != sta->sdata)
continue;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 985e53bf04bc..6be5c05b686a 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1622,7 +1622,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
- unsigned long last_active = ieee80211_sta_last_active(sta);
+ unsigned long last_active = ieee80211_sta_last_active(sta, -1);
if (sdata != sta->sdata)
continue;
@@ -2391,18 +2391,28 @@ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
}
static struct ieee80211_sta_rx_stats *
-sta_get_last_rx_stats(struct sta_info *sta)
+sta_get_last_rx_stats(struct sta_info *sta, int link_id)
{
- struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats;
+ struct ieee80211_sta_rx_stats *stats;
+ struct link_sta_info *link_sta_info;
int cpu;
- if (!sta->deflink.pcpu_rx_stats)
+ if (link_id < 0)
+ link_sta_info = &sta->deflink;
+ else
+ link_sta_info =
+ rcu_dereference_protected(sta->link[link_id],
+ lockdep_is_held(&sta->local->hw.wiphy->mtx));
+
+ stats = &link_sta_info->rx_stats;
+
+ if (!link_sta_info->pcpu_rx_stats)
return stats;
for_each_possible_cpu(cpu) {
struct ieee80211_sta_rx_stats *cpustats;
- cpustats = per_cpu_ptr(sta->deflink.pcpu_rx_stats, cpu);
+ cpustats = per_cpu_ptr(link_sta_info->pcpu_rx_stats, cpu);
if (time_after(cpustats->last_rx, stats->last_rx))
stats = cpustats;
@@ -2470,9 +2480,10 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate,
}
}
-static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
+static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo,
+ int link_id)
{
- u32 rate = READ_ONCE(sta_get_last_rx_stats(sta)->last_rate);
+ u32 rate = READ_ONCE(sta_get_last_rx_stats(sta, link_id)->last_rate);
if (rate == STA_STATS_RATE_INVALID)
return -EINVAL;
@@ -2497,20 +2508,28 @@ static inline u64 sta_get_tidstats_msdu(struct ieee80211_sta_rx_stats *rxstats,
static void sta_set_tidstats(struct sta_info *sta,
struct cfg80211_tid_stats *tidstats,
- int tid)
+ int link_id, int tid)
{
struct ieee80211_local *local = sta->local;
+ struct link_sta_info *link_sta_info;
int cpu;
+ if (link_id < 0)
+ link_sta_info = &sta->deflink;
+ else
+ link_sta_info =
+ rcu_dereference_protected(sta->link[link_id],
+ lockdep_is_held(&local->hw.wiphy->mtx));
+
if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
- tidstats->rx_msdu += sta_get_tidstats_msdu(&sta->deflink.rx_stats,
+ tidstats->rx_msdu += sta_get_tidstats_msdu(&link_sta_info->rx_stats,
tid);
- if (sta->deflink.pcpu_rx_stats) {
+ if (link_sta_info->pcpu_rx_stats) {
for_each_possible_cpu(cpu) {
struct ieee80211_sta_rx_stats *cpurxs;
- cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats,
+ cpurxs = per_cpu_ptr(link_sta_info->pcpu_rx_stats,
cpu);
tidstats->rx_msdu +=
sta_get_tidstats_msdu(cpurxs, tid);
@@ -2522,19 +2541,19 @@ static void sta_set_tidstats(struct sta_info *sta,
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
- tidstats->tx_msdu = sta->deflink.tx_stats.msdu[tid];
+ tidstats->tx_msdu = link_sta_info->tx_stats.msdu[tid];
}
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
- tidstats->tx_msdu_retries = sta->deflink.status_stats.msdu_retries[tid];
+ tidstats->tx_msdu_retries = link_sta_info->status_stats.msdu_retries[tid];
}
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
- tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid];
+ tidstats->tx_msdu_failed = link_sta_info->status_stats.msdu_failed[tid];
}
if (tid < IEEE80211_NUM_TIDS) {
@@ -2602,11 +2621,20 @@ static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *l
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
u32 thr = 0;
- int i, ac, cpu;
+ int i, ac, cpu, link_id;
struct ieee80211_sta_rx_stats *last_rxstats;
- struct link_sta_info *link_sta_info = &sta->deflink;
+ struct link_sta_info *link_sta_info;
- last_rxstats = sta_get_last_rx_stats(sta);
+ link_id = link_sinfo->link_id;
+
+ if (link_id < 0)
+ link_sta_info = &sta->deflink;
+ else
+ link_sta_info =
+ rcu_dereference_protected(sta->link[link_id],
+ lockdep_is_held(&local->hw.wiphy->mtx));
+
+ last_rxstats = sta_get_last_rx_stats(sta, link_id);
/* do before driver, so beacon filtering drivers have a
@@ -2617,6 +2645,9 @@ static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *l
link_sinfo->rx_beacon = link_sdata->u.mgd.count_beacon_signal;
drv_link_sta_statistics(local, sdata, &sta->sta, link_sinfo);
+
+ memcpy(link_sinfo->addr, link_sta_info->addr, ETH_ALEN);
+
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) |
BIT_ULL(NL80211_STA_INFO_BSS_PARAM) |
BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC);
@@ -2628,7 +2659,7 @@ static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *l
}
link_sinfo->inactive_time =
- jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta));
+ jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, link_id));
if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
@@ -2717,7 +2748,8 @@ static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *l
!(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) {
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) |
BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG);
- link_sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif);
+ link_sinfo->rx_beacon_signal_avg =
+ ieee80211_ave_rssi(&sdata->vif, link_id);
}
if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) ||
@@ -2756,22 +2788,20 @@ static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *l
}
if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) &&
- !sta->sta.valid_links &&
ieee80211_rate_valid(&link_sta_info->tx_stats.last_rate)) {
sta_set_rate_info_tx(sta, &link_sta_info->tx_stats.last_rate,
&link_sinfo->txrate);
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
- if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) &&
- !sta->sta.valid_links){
- if (sta_set_rate_info_rx(sta, &link_sinfo->rxrate) == 0)
+ if (!(link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE))) {
+ if (sta_set_rate_info_rx(sta, &link_sinfo->rxrate, link_id) == 0)
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
}
if (tidstats && !cfg80211_sinfo_alloc_tid_stats(link_sinfo, GFP_KERNEL)) {
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
- sta_set_tidstats(sta, &link_sinfo->pertid[i], i);
+ sta_set_tidstats(sta, &link_sinfo->pertid[i], link_id, i);
}
link_sinfo->bss_param.flags = 0;
@@ -2810,10 +2840,13 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
bool tidstats)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
- struct link_station_info *link_sinfo = &sinfo->deflink;
- struct ieee80211_link_data *link_sdata = &sdata->deflink;
+ struct ieee80211_link_data *link_sdata;
+ struct link_station_info *link_sinfo;
+ struct link_sta_info *link_sta;
+ int link_id;
sinfo->generation = sdata->local->sta_generation;
+ sinfo->valid_links = sta->sta.valid_links;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_STA_FLAGS) |
BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME) |
@@ -2851,7 +2884,33 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sta_set_mesh_sinfo(sta, sinfo);
#endif
- sta_set_link_sinfo(sta, link_sinfo, link_sdata, tidstats);
+ if (sinfo->valid_links) {
+ memcpy(sinfo->mld_addr, sta->addr, ETH_ALEN);
+
+ for_each_valid_link(sinfo, link_id) {
+ link_sta =
+ rcu_dereference_protected(sta->link[link_id],
+ lockdep_is_held(&sta->local->hw.wiphy->mtx));
+ if (!link_sta)
+ continue;
+
+ link_sinfo = kzalloc(sizeof(*link_sinfo), GFP_KERNEL);
+ if (!link_sinfo)
+ return;
+
+ link_sinfo->link_id = link_id;
+ link_sdata =
+ rcu_dereference_protected(sdata->link[link_id],
+ lockdep_is_held(&sdata->local->hw.wiphy->mtx));
+ sta_set_link_sinfo(sta, link_sinfo, link_sdata, tidstats);
+ sinfo->links[link_id] = link_sinfo;
+ }
+ } else {
+ link_sinfo = &sinfo->deflink;
+ link_sinfo->link_id = -1;
+ link_sdata = &sdata->deflink;
+ sta_set_link_sinfo(sta, link_sinfo, link_sdata, tidstats);
+ }
}
u32 sta_get_expected_throughput(struct sta_info *sta)
@@ -2873,14 +2932,23 @@ u32 sta_get_expected_throughput(struct sta_info *sta)
return thr;
}
-unsigned long ieee80211_sta_last_active(struct sta_info *sta)
+unsigned long ieee80211_sta_last_active(struct sta_info *sta, int link_id)
{
- struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);
+ struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta, link_id);
+ struct link_sta_info *link_sta_info;
- if (!sta->deflink.status_stats.last_ack ||
- time_after(stats->last_rx, sta->deflink.status_stats.last_ack))
+ if (link_id < 0)
+ link_sta_info = &sta->deflink;
+ else
+ link_sta_info =
+ rcu_dereference_protected(sta->link[link_id],
+ lockdep_is_held(&sta->local->hw.wiphy->mtx));
+
+ if (!link_sta_info->status_stats.last_ack ||
+ time_after(stats->last_rx, link_sta_info->status_stats.last_ack))
return stats->last_rx;
- return sta->deflink.status_stats.last_ack;
+
+ return link_sta_info->status_stats.last_ack;
}
static void sta_update_codel_params(struct sta_info *sta, u32 thr)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 9f89fb5bee37..1d82519319fe 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -939,7 +939,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
-unsigned long ieee80211_sta_last_active(struct sta_info *sta);
+unsigned long ieee80211_sta_last_active(struct sta_info *sta, int link_id);
void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
const u8 *ext_capab,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7b656326e68a..f8ae7726eede 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3274,14 +3274,28 @@ int ieee80211_put_srates_elem(struct sk_buff *skb,
return 0;
}
-int ieee80211_ave_rssi(struct ieee80211_vif *vif)
+int ieee80211_ave_rssi(struct ieee80211_vif *vif, int link_id)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_link_data *link_data;
+ int rssi;
if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
return 0;
- return -ewma_beacon_signal_read(&sdata->deflink.u.mgd.ave_beacon_signal);
+ if (link_id < 0)
+ link_data = &sdata->deflink;
+ else
+ link_data =
+ rcu_dereference_protected(sdata->link[link_id],
+ lockdep_is_held(&sdata->local->hw.wiphy->mtx));
+
+ if (WARN_ON(!link_data))
+ return -99;
+
+ rssi = -ewma_beacon_signal_read(&link_data->u.mgd.ave_beacon_signal);
+
+ return rssi;
}
EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7740ab5c778d..37a8cbb1022a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6844,10 +6844,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
struct net_device *dev,
const u8 *mac_addr, struct station_info *sinfo)
{
- struct nlattr *sinfoattr;
+ struct nlattr *sinfoattr, *link_sinfoattr, *links, *link;
void *hdr;
- struct link_station_info *link_sinfo = &sinfo->deflink;
- int ret = -1;
+ struct link_station_info *link_sinfo;
+ int ret = -1, link_id;
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
if (!hdr) {
@@ -6860,17 +6860,6 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
goto nla_put_failure;
- if (sinfo->mlo_params_valid) {
- if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
- sinfo->assoc_link_id))
- goto nla_put_failure;
-
- if (!is_zero_ether_addr(sinfo->mld_addr) &&
- nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
- sinfo->mld_addr))
- goto nla_put_failure;
- }
-
if (sinfo->assoc_req_ies_len &&
nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
sinfo->assoc_req_ies))
@@ -6922,11 +6911,64 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
#undef PUT_SINFO
#undef PUT_SINFO_U64
- ret = nl80211_fill_link_station(msg, rdev, link_sinfo);
- if (ret)
- goto nla_put_failure;
+ if (sinfo->valid_links) {
+ /* TODO: Add accumulated stats for packets, bytes for
+ * better representation at MLO level.
+ */
+
+ /* Closing nested STA_INFO as MLO links ATTR should not
+ * be in nested STA_INFO
+ */
+ nla_nest_end(msg, sinfoattr);
+
+ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+ sinfo->assoc_link_id))
+ goto nla_put_failure;
+
+ if (!is_zero_ether_addr(sinfo->mld_addr) &&
+ nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
+ sinfo->mld_addr))
+ goto nla_put_failure;
+
+ links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
+ if (!links)
+ goto nla_put_failure;
+
+ for_each_valid_link(sinfo, link_id) {
+ link_sinfo = sinfo->links[link_id];
+ link = nla_nest_start(msg, link_id + 1);
+ if (!link)
+ goto nla_put_failure;
+
+ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+ link_id))
+ goto nla_put_failure;
- nla_nest_end(msg, sinfoattr);
+ if (!is_zero_ether_addr(link_sinfo->addr) &&
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
+ link_sinfo->addr))
+ goto nla_put_failure;
+
+ link_sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
+ if (!link_sinfoattr)
+ goto nla_put_failure;
+
+ ret = nl80211_fill_link_station(msg, rdev, link_sinfo);
+ if (ret)
+ goto nla_put_failure;
+
+ nla_nest_end(msg, link_sinfoattr);
+ nla_nest_end(msg, link);
+ }
+ nla_nest_end(msg, links);
+ } else {
+ link_sinfo = &sinfo->deflink;
+ ret = nl80211_fill_link_station(msg, rdev, link_sinfo);
+ if (ret)
+ goto nla_put_failure;
+
+ nla_nest_end(msg, sinfoattr);
+ }
cfg80211_sinfo_release_content(sinfo);
genlmsg_end(msg, hdr);
--
2.34.1
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo
2025-01-10 4:24 ` [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo Sarika Sharma
@ 2025-01-10 9:20 ` Johannes Berg
2025-01-12 8:10 ` Sarika Sharma
2025-01-10 9:21 ` Johannes Berg
2025-01-11 9:49 ` kernel test robot
2 siblings, 1 reply; 28+ messages in thread
From: Johannes Berg @ 2025-01-10 9:20 UTC (permalink / raw)
To: Sarika Sharma; +Cc: linux-wireless
On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>
> -int ieee80211_ave_rssi(struct ieee80211_vif *vif);
> +int ieee80211_ave_rssi(struct ieee80211_vif *vif, int link_id);
>
You really should get these kinds of things out of the way before the
real patches.
johannes
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo
2025-01-10 9:20 ` Johannes Berg
@ 2025-01-12 8:10 ` Sarika Sharma
0 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-12 8:10 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 1/10/2025 2:50 PM, Johannes Berg wrote:
> On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>>
>> -int ieee80211_ave_rssi(struct ieee80211_vif *vif);
>> +int ieee80211_ave_rssi(struct ieee80211_vif *vif, int link_id);
>>
>
> You really should get these kinds of things out of the way before the
> real patches.
Sure, will add these type of changes as a separate patch at the starting
of this series.
>
> johannes
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo
2025-01-10 4:24 ` [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo Sarika Sharma
2025-01-10 9:20 ` Johannes Berg
@ 2025-01-10 9:21 ` Johannes Berg
2025-01-12 8:14 ` Sarika Sharma
2025-01-11 9:49 ` kernel test robot
2 siblings, 1 reply; 28+ messages in thread
From: Johannes Berg @ 2025-01-10 9:21 UTC (permalink / raw)
To: Sarika Sharma; +Cc: linux-wireless
On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>
> The statistics could be embedded into NL message as below:
> For MLO:
> cmd ->
> NL80211_ATTR_IFINDEX
> NL80211_ATTR_MAC
> NL80211_ATTR_GENERATION
> .......etc
> NL80211_ATTR_STA_INFO | nest flag
> NL80211_STA_INFO_CONNECTED_TIME,
> NL80211_STA_INFO_STA_FLAGS,
> ........etc
> NL80211_ATTR_MLO_LINK_ID,
> NL80211_ATTR_MLD_ADDR,
> NL80211_ATTR_MLO_LINKS | nested
> link_id-1 | nested
> NL80211_ATTR_MLO_LINK_ID,
> NL80211_ATTR_MLD_ADDR,
Using the MLD_ADDR attribute here seems really odd?
Also I think you got the indentation wrong.
> NL80211_ATTR_STA_INFO | nest flag
> NL80211_STA_INFO_RX_BYTES,
> NL80211_STA_INFO_TX_BYTES,
> ..........etc.
johannes
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo
2025-01-10 9:21 ` Johannes Berg
@ 2025-01-12 8:14 ` Sarika Sharma
0 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-12 8:14 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 1/10/2025 2:51 PM, Johannes Berg wrote:
> On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>>
>> The statistics could be embedded into NL message as below:
>> For MLO:
>> cmd ->
>> NL80211_ATTR_IFINDEX
>> NL80211_ATTR_MAC
>> NL80211_ATTR_GENERATION
>> .......etc
>> NL80211_ATTR_STA_INFO | nest flag
>> NL80211_STA_INFO_CONNECTED_TIME,
>> NL80211_STA_INFO_STA_FLAGS,
>> ........etc
>> NL80211_ATTR_MLO_LINK_ID,
>> NL80211_ATTR_MLD_ADDR,
>> NL80211_ATTR_MLO_LINKS | nested
>> link_id-1 | nested
>> NL80211_ATTR_MLO_LINK_ID,
>> NL80211_ATTR_MLD_ADDR,
>
> Using the MLD_ADDR attribute here seems really odd?
Oops! looks here I keep it as MLD_ADDR by mistake, it is
NL80211_ATTR_MAC attribute that is filled in code.
Thankyou for pointing out, will correct it here.
>
> Also I think you got the indentation wrong.
>
>> NL80211_ATTR_STA_INFO | nest flag
>> NL80211_STA_INFO_RX_BYTES,
>> NL80211_STA_INFO_TX_BYTES,
>> ..........etc.
>
> johannes
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo
2025-01-10 4:24 ` [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo Sarika Sharma
2025-01-10 9:20 ` Johannes Berg
2025-01-10 9:21 ` Johannes Berg
@ 2025-01-11 9:49 ` kernel test robot
2 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2025-01-11 9:49 UTC (permalink / raw)
To: Sarika Sharma; +Cc: oe-kbuild-all
Hi Sarika,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on 7bf1659bad4e9413cdba132ef9cbd0caa9cabcc4]
url: https://github.com/intel-lab-lkp/linux/commits/Sarika-Sharma/wifi-cfg80211-reorg-sinfo-structure-elements-for-mesh/20250110-122824
base: 7bf1659bad4e9413cdba132ef9cbd0caa9cabcc4
patch link: https://lore.kernel.org/r/20250110042449.1158789-4-quic_sarishar%40quicinc.com
patch subject: [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo
config: sparc-allmodconfig (https://download.01.org/0day-ci/archive/20250111/202501111737.RNr9aH6Z-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250111/202501111737.RNr9aH6Z-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501111737.RNr9aH6Z-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/wireless/intel/iwlwifi/dvm/lib.c: In function 'iwlagn_fill_txpower_mode':
>> drivers/net/wireless/intel/iwlwifi/dvm/lib.c:589:20: error: too few arguments to function 'ieee80211_ave_rssi'
589 | ave_rssi = ieee80211_ave_rssi(ctx->vif);
| ^~~~~~~~~~~~~~~~~~
In file included from drivers/net/wireless/intel/iwlwifi/dvm/lib.c:10:
include/net/mac80211.h:7224:5: note: declared here
7224 | int ieee80211_ave_rssi(struct ieee80211_vif *vif, int link_id);
| ^~~~~~~~~~~~~~~~~~
vim +/ieee80211_ave_rssi +589 drivers/net/wireless/intel/iwlwifi/dvm/lib.c
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 567
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 568 /*
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 569 * Upon RSSI changes, sends a bt config command with following changes
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 570 * 1. enable/disable "reduced control frames tx power
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 571 * 2. update the "kill)ack_mask" and "kill_cts_mask"
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 572 *
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 573 * If "reduced tx power" is enabled, uCode shall
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 574 * 1. ACK/Back/CTS rate shall reduced to 6Mbps
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 575 * 2. not use duplciate 20/40MHz mode
83ce21de686a67 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 576 */
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 577 static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 578 struct iwl_bt_uart_msg *uart_msg)
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 579 {
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 580 bool need_update = false;
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 581 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 582 int ave_rssi;
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 583
e19ebcab01cc13 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Ilan Peer 2012-05-10 584 if (!ctx->vif || (ctx->vif->type != NL80211_IFTYPE_STATION)) {
e19ebcab01cc13 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Ilan Peer 2012-05-10 585 IWL_DEBUG_INFO(priv, "BSS ctx not active or not in sta mode\n");
e19ebcab01cc13 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Ilan Peer 2012-05-10 586 return false;
e19ebcab01cc13 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Ilan Peer 2012-05-10 587 }
e19ebcab01cc13 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Ilan Peer 2012-05-10 588
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 @589 ave_rssi = ieee80211_ave_rssi(ctx->vif);
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 590 if (!ave_rssi) {
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 591 /* no rssi data, no changes to reduce tx power */
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 592 IWL_DEBUG_COEX(priv, "no rssi data available\n");
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 593 return need_update;
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 594 }
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 595 if (!priv->reduced_txpower &&
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 596 !iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 597 (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) &&
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 598 (uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 599 BT_UART_MSG_FRAME3OBEX_MSK)) &&
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 600 !(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 601 BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK))) {
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 602 /* enabling reduced tx power */
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 603 priv->reduced_txpower = true;
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 604 priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR;
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 605 need_update = true;
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 606 } else if (priv->reduced_txpower &&
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 607 (iwl_is_associated(priv, IWL_RXON_CTX_PAN) ||
dd551ab7b47ace drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 608 (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) ||
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 609 (uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 610 BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) ||
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 611 !(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 612 BT_UART_MSG_FRAME3OBEX_MSK)))) {
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 613 /* disable reduced tx power */
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 614 priv->reduced_txpower = false;
f6be8b7845434a drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-05-03 615 priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR;
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 616 need_update = true;
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 617 }
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 618
354ce4a4ca613f drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2012-04-19 619 return need_update;
b6e116e8bf7d74 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2010-08-23 620 }
b6e116e8bf7d74 drivers/net/wireless/iwlwifi/iwl-agn-lib.c Wey-Yi Guy 2010-08-23 621
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH RFC 4/7] wifi: cfg80211: add accumulated statistics for MLO links
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
` (2 preceding siblings ...)
2025-01-10 4:24 ` [PATCH RFC 3/7] wifi: cfg80211: extend statistics for link level in sinfo Sarika Sharma
@ 2025-01-10 4:24 ` Sarika Sharma
2025-01-10 4:24 ` [PATCH RFC 5/7] wifi: mac80211: add support to accumulate removed link statistics Sarika Sharma
` (4 subsequent siblings)
8 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-10 4:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sarika Sharma
Currently statistics are handled at link level for multi-link
operation(MLO). There is no provision to check accumulated statistics
for a multi-link(ML) station. Accumulated statistics are useful to
provide comprehensive overview for the ML stations.
Statistics such as packets and bytes are useful for observing the
total packets sent and received at the station level. However,
MLO statistics for rates and signal can not be accumulated since it
won't make much sense. Hence, a subsequent change will handle signal
and rates bit differently at MLO level.
Hence, add accumulated statistics for MLO station. Also, for non-ML
station accumulated statistics make no sense.
The statistics could be embedded into NL message as below:
For MLO:
cmd ->
NL80211_ATTR_IFINDEX
NL80211_ATTR_MAC
NL80211_ATTR_GENERATION
......etc
NL80211_ATTR_STA_INFO | nest flag
NL80211_STA_INFO_CONNECTED_TIME,
NL80211_STA_INFO_STA_FLAGS,
NL80211_STA_INFO_RX_BYTES, //accumulated data
NL80211_STA_INFO_TX_BYTES,
......etc
NL80211_ATTR_MLO_LINK_ID,
NL80211_ATTR_MLD_ADDR,
NL80211_ATTR_MLO_LINKS | nested
link_id-1 | nested
NL80211_ATTR_MLO_LINK_ID,
NL80211_ATTR_MLD_ADDR,
NL80211_ATTR_STA_INFO | nest flag
NL80211_STA_INFO_RX_BYTES,
NL80211_STA_INFO_TX_BYTES,
..........etc.
link_id-2 | nested
NL80211_ATTR_MLO_LINK_ID,
NL80211_ATTR_MLD_ADDR,
NL80211_ATTR_STA_INFO | nest flag
NL80211_STA_INFO_RX_BYTES,
NL80211_STA_INFO_TX_BYTES,
.........etc
The output of iw dev wlan0 station dump for MLO could look like below:
Station 00:03:7f:04:31:78 (on wlan0)
authorized: yes
authenticated: yes
associated: yes
preamble: long
WMM/WME: yes
MFP: yes
TDLS peer: no
connected time: 383 seconds
associated at [boottime]: 93.740s
associated at: 93685 ms
rx bytes: 1439
rx packets: 15
tx bytes: 1538
tx packets: 8
tx retries: 0
tx failed: 0
current time: 474340 ms
MLD address: 00:03:7f:04:31:78
Link 0:
Address: 00:03:7f:04:31:78
inactive time: 330120 ms
rx bytes: 116
rx packets: 3
tx bytes: 0
tx packets: 0
tx retries: 0
tx failed: 0
rx drop misc: 0
signal: -95 dBm
tx bitrate: 6.0 MBit/s
tx duration: 2669 us
rx duration: 0 us
DTIM period: 2
beacon interval:100
Link 1:
Address: 00:03:7f:04:31:79
inactive time: 81268 ms
rx bytes: 1323
rx packets: 12
tx bytes: 1538
tx packets: 8
tx retries: 0
tx failed: 0
rx drop misc: 0
signal: -95 dBm
tx bitrate: 6.0 MBit/s
tx duration: 2669 us
rx bitrate: 6.0 MBit/s
rx duration: 0 us
DTIM period: 2
beacon interval:100
Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
---
include/net/cfg80211.h | 13 +++++++++++
net/mac80211/sta_info.c | 50 +++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 36 ++++++++++++++++++++++++++---
3 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5b0ec0394715..ac038903d53e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2174,6 +2174,12 @@ struct link_station_info {
* @valid_links: bitmap of valid links, or 0 for non-MLO. Drivers fill this
* information in cfg80211_new_sta(), cfg80211_del_sta_sinfo(),
* get_station() and dump_station() callbacks.
+ * @rx_packets: packets (MSDUs & MMPDUs) received from this station
+ * @tx_packets: packets (MSDUs & MMPDUs) transmitted to this station
+ * @rx_bytes: bytes (size of MPDUs) received from this station
+ * @tx_bytes: bytes (size of MPDUs) transmitted to this station
+ * @tx_retries: cumulative retry counts (MPDUs)
+ * @tx_failed: number of failed transmissions (MPDUs) (retries exceeded, no ACK)
* @deflink: This holds the default link STA information, for non MLO STA
* all link specific STA information is accessed through @deflink.
* @links: reference to Link sta entries for MLO.
@@ -2206,6 +2212,13 @@ struct station_info {
size_t assoc_resp_ies_len;
u16 valid_links;
+ u32 rx_packets;
+ u32 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ u32 tx_retries;
+ u32 tx_failed;
+
struct link_station_info deflink;
/* TODO: Need to check and add protection access to links memory */
struct link_station_info *links[IEEE80211_MLD_MAX_NUM_LINKS];
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 6be5c05b686a..f4492174d2c4 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2836,6 +2836,55 @@ static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *l
}
}
+static void sta_set_mld_sinfo(struct station_info *sinfo, struct sta_info *sta)
+{
+ struct link_station_info *link_sinfo;
+ struct link_sta_info *link_sta;
+ int link_id;
+
+ for_each_valid_link(sinfo, link_id) {
+ link_sta =
+ rcu_dereference_protected(sta->link[link_id],
+ lockdep_is_held(&sta->local->hw.wiphy->mtx));
+ if (!link_sta)
+ continue;
+
+ link_sinfo = sinfo->links[link_id];
+
+ if ((link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_PACKETS))) {
+ sinfo->tx_packets += link_sinfo->tx_packets;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+ }
+
+ if ((link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_PACKETS))) {
+ sinfo->rx_packets += link_sinfo->rx_packets;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
+ }
+
+ if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
+ BIT_ULL(NL80211_STA_INFO_TX_BYTES64))) {
+ sinfo->tx_bytes += link_sinfo->tx_bytes;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
+ }
+
+ if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
+ BIT_ULL(NL80211_STA_INFO_TX_BYTES64))) {
+ sinfo->rx_bytes += link_sinfo->rx_bytes;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
+ }
+
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_RETRIES)) {
+ sinfo->tx_retries += link_sinfo->tx_retries;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
+ }
+
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED)) {
+ sinfo->tx_failed += link_sinfo->tx_failed;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+ }
+ }
+}
+
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
bool tidstats)
{
@@ -2905,6 +2954,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sta_set_link_sinfo(sta, link_sinfo, link_sdata, tidstats);
sinfo->links[link_id] = link_sinfo;
}
+ sta_set_mld_sinfo(sinfo, sta);
} else {
link_sinfo = &sinfo->deflink;
link_sinfo->link_id = -1;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 37a8cbb1022a..06688aa1780f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6838,6 +6838,36 @@ static int nl80211_fill_link_station(struct sk_buff *msg,
return 0;
}
+static int nl80211_fill_mld_station(struct sk_buff *msg,
+ struct station_info *sinfo)
+{
+#define PUT_SINFO(attr, memb, type) do { \
+ BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
+ if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
+ nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
+ sinfo->memb)) \
+ return -EMSGSIZE; \
+ } while (0)
+#define PUT_SINFO_U64(attr, memb) do { \
+ if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
+ nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
+ sinfo->memb, NL80211_STA_INFO_PAD)) \
+ return -EMSGSIZE; \
+ } while (0)
+
+ PUT_SINFO(RX_PACKETS, rx_packets, u32);
+ PUT_SINFO(TX_PACKETS, tx_packets, u32);
+ PUT_SINFO_U64(RX_BYTES, rx_bytes);
+ PUT_SINFO_U64(TX_BYTES, tx_bytes);
+ PUT_SINFO(TX_RETRIES, tx_retries, u32);
+ PUT_SINFO(TX_FAILED, tx_failed, u32);
+
+#undef PUT_SINFO
+#undef PUT_SINFO_U64
+
+ return 0;
+}
+
static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
@@ -6912,9 +6942,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
#undef PUT_SINFO_U64
if (sinfo->valid_links) {
- /* TODO: Add accumulated stats for packets, bytes for
- * better representation at MLO level.
- */
+ ret = nl80211_fill_mld_station(msg, sinfo);
+ if (ret)
+ goto nla_put_failure;
/* Closing nested STA_INFO as MLO links ATTR should not
* be in nested STA_INFO
--
2.34.1
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH RFC 5/7] wifi: mac80211: add support to accumulate removed link statistics
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
` (3 preceding siblings ...)
2025-01-10 4:24 ` [PATCH RFC 4/7] wifi: cfg80211: add accumulated statistics for MLO links Sarika Sharma
@ 2025-01-10 4:24 ` Sarika Sharma
2025-01-10 9:22 ` Johannes Berg
2025-01-10 4:24 ` [PATCH RFC 6/7] wifi: cfg80211: add additional MLO statistics Sarika Sharma
` (3 subsequent siblings)
8 siblings, 1 reply; 28+ messages in thread
From: Sarika Sharma @ 2025-01-10 4:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sarika Sharma
Currently, if a link gets removed in between for a station then
directly accumulated data will fall down to sum of other active links.
This will bring inconsistency in station dump statistics.
For instance, let's take Tx packets
- at t=0-> link-0:2 link-1:3 Tx packets => accumulated = 5
- at t=1-> link-0:4 link-1:6 Tx packets => accumulated = 10
let say at t=2, link-0 went down => link-0:0 link-1:7 => accumulated = 7
Here, suddenly accumulated Tx packets will come down to 7 from 10.
This is showing inconsistency.
Therefore, store link-0 data when it went down and add to accumulated
Tx packet = 11.
Hence, store the removed link statistics data in sta structure and
add it in accumulated statistics for consistency.
Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
---
net/mac80211/sta_info.c | 30 ++++++++++++++++++++++++++++++
net/mac80211/sta_info.h | 28 ++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index f4492174d2c4..4b78b03b1047 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -356,6 +356,24 @@ static void sta_info_free_link(struct link_sta_info *link_sta)
free_percpu(link_sta->pcpu_rx_stats);
}
+static void sta_accumulate_removed_link_stats(struct sta_info *sta, int link_id)
+{
+ struct link_sta_info *link_sta =
+ rcu_dereference_protected(sta->link[link_id],
+ lockdep_is_held(&sta->local->hw.wiphy->mtx));
+ int ac;
+
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ sta->rem_link_stats.tx_packets += link_sta->tx_stats.packets[ac];
+ sta->rem_link_stats.tx_bytes += link_sta->tx_stats.bytes[ac];
+ }
+
+ sta->rem_link_stats.rx_packets += link_sta->rx_stats.packets;
+ sta->rem_link_stats.rx_bytes += link_sta->rx_stats.bytes;
+ sta->rem_link_stats.tx_retries += link_sta->status_stats.retry_count;
+ sta->rem_link_stats.tx_failed += link_sta->status_stats.retry_failed;
+}
+
static void sta_remove_link(struct sta_info *sta, unsigned int link_id,
bool unhash)
{
@@ -378,6 +396,10 @@ static void sta_remove_link(struct sta_info *sta, unsigned int link_id,
alloc = container_of(link_sta, typeof(*alloc), info);
sta->sta.valid_links &= ~BIT(link_id);
+
+ /* store removed link info for accumulated stats consistency */
+ sta_accumulate_removed_link_stats(sta, link_id);
+
RCU_INIT_POINTER(sta->link[link_id], NULL);
RCU_INIT_POINTER(sta->sta.link[link_id], NULL);
if (alloc) {
@@ -2883,6 +2905,14 @@ static void sta_set_mld_sinfo(struct station_info *sinfo, struct sta_info *sta)
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
}
}
+
+ /* Add accumulated removed link data to sinfo data for consistency */
+ sinfo->tx_packets += sta->rem_link_stats.tx_packets;
+ sinfo->rx_packets += sta->rem_link_stats.rx_packets;
+ sinfo->tx_bytes += sta->rem_link_stats.tx_bytes;
+ sinfo->rx_bytes += sta->rem_link_stats.rx_bytes;
+ sinfo->tx_retries += sta->rem_link_stats.tx_retries;
+ sinfo->tx_failed += sta->rem_link_stats.tx_failed;
}
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 1d82519319fe..2ddea966d500 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -569,6 +569,32 @@ struct link_sta_info {
struct ieee80211_link_sta *pub;
};
+/**
+ * struct ieee80211_sta_removed_link_stats - Removed link sta data
+ *
+ * keep required accumulated removed link data for stats
+ *
+ * @rx_packets: accumulated packets (MSDUs & MMPDUs) received from
+ * this station for removed links
+ * @tx_packets: accumulated packets (MSDUs & MMPDUs) transmitted to
+ * this station for removed links
+ * @rx_bytes: accumulated bytes (size of MPDUs) received from this
+ * station for removed links
+ * @tx_bytes: accumulated bytes (size of MPDUs) transmitted to this
+ * station for removed links
+ * @tx_retries: cumulative retry counts (MPDUs) for removed links
+ * @tx_failed: accumulated number of failed transmissions (MPDUs)
+ * (retries exceeded, no ACK) for removed links
+ */
+struct ieee80211_sta_removed_link_stats {
+ u32 rx_packets;
+ u32 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ u32 tx_retries;
+ u32 tx_failed;
+};
+
/**
* struct sta_info - STA information
*
@@ -646,6 +672,7 @@ struct link_sta_info {
* @deflink address and remaining would be allocated and the address
* would be assigned to link[link_id] where link_id is the id assigned
* by the AP.
+ * @rem_link_stats: accumulated removed link stats
*/
struct sta_info {
/* General information, mostly static */
@@ -722,6 +749,7 @@ struct sta_info {
struct ieee80211_sta_aggregates cur;
struct link_sta_info deflink;
struct link_sta_info __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+ struct ieee80211_sta_removed_link_stats rem_link_stats;
/* keep last! */
struct ieee80211_sta sta;
--
2.34.1
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH RFC 5/7] wifi: mac80211: add support to accumulate removed link statistics
2025-01-10 4:24 ` [PATCH RFC 5/7] wifi: mac80211: add support to accumulate removed link statistics Sarika Sharma
@ 2025-01-10 9:22 ` Johannes Berg
2025-01-12 8:15 ` Sarika Sharma
0 siblings, 1 reply; 28+ messages in thread
From: Johannes Berg @ 2025-01-10 9:22 UTC (permalink / raw)
To: Sarika Sharma; +Cc: linux-wireless
On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
> Currently, if a link gets removed in between for a station then
> directly accumulated data will fall down to sum of other active links.
> This will bring inconsistency in station dump statistics.
>
What if a link is removed and then re-added? Should it go back to that
link? That would require keeping statistics per link rather than
accumulating removed.
johannes
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 5/7] wifi: mac80211: add support to accumulate removed link statistics
2025-01-10 9:22 ` Johannes Berg
@ 2025-01-12 8:15 ` Sarika Sharma
0 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-12 8:15 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 1/10/2025 2:52 PM, Johannes Berg wrote:
> On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>> Currently, if a link gets removed in between for a station then
>> directly accumulated data will fall down to sum of other active links.
>> This will bring inconsistency in station dump statistics.
>>
>
> What if a link is removed and then re-added? Should it go back to that
> link? That would require keeping statistics per link rather than
> accumulating removed.
>
> johannes
When a link is removed, its corresponding data will be set to NULL. If
it reconnects, its statistics will start from zero. The link might not
reconnect to the same link again. Therefore, retaining data for a
removed link per link may not be useful, as the link is being removed
and connected. It's better to start with zero rather than using previous
data.
Also, if really link level storing of stats is required will add it, but
currently I am not seeing it much useful here.
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH RFC 6/7] wifi: cfg80211: add additional MLO statistics
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
` (4 preceding siblings ...)
2025-01-10 4:24 ` [PATCH RFC 5/7] wifi: mac80211: add support to accumulate removed link statistics Sarika Sharma
@ 2025-01-10 4:24 ` Sarika Sharma
2025-01-10 4:24 ` [PATCH RFC 7/7] wifi: ath12k: correctly fetch arsta for MLO Sarika Sharma
` (2 subsequent siblings)
8 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-10 4:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sarika Sharma
Currently, the accumulable statistics for multi-link operation(MLO)
are handled. Other statistics, such as signal and rates, are managed at
the link level. Therefore, add signal and rates at the MLO level to
provide an comprehensive overview of the station.
The signal could be the best of all links-
e.g. if Link 1 has a signal strength of -70 dBm and Link 2 has -65 dBm,
the signal for MLO will be -65 dBm.
The rate could be determined based on the most recently updated link-
e.g. if link 1 has a rate of 300 Mbps and link 2 has a rate of 450 Mbps,
the MLO rate can be calculated based on the inactivity of each link.
If the inactive time for link 1 is 20 seconds and for link 2 is 10 seconds,
the MLO rate will be the most recently updated rate, which is link 2's
rate of 450 Mbps.
NOTE:
- Currently using one of the link to fill rate and signal. Could add
the last updated for rate and best of signal for MLO with actual
patches.
Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
---
include/net/cfg80211.h | 7 +++++++
net/mac80211/sta_info.c | 44 +++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 25 +++++++++++++++++++++--
3 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ac038903d53e..30231855be1f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2180,6 +2180,10 @@ struct link_station_info {
* @tx_bytes: bytes (size of MPDUs) transmitted to this station
* @tx_retries: cumulative retry counts (MPDUs)
* @tx_failed: number of failed transmissions (MPDUs) (retries exceeded, no ACK)
+ * @signal: The signal strength, type depends on the wiphy's signal_type.
+ * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @txrate: last updated unicast bitrate from this station
+ * @rxrate: last updated unicast bitrate to this station
* @deflink: This holds the default link STA information, for non MLO STA
* all link specific STA information is accessed through @deflink.
* @links: reference to Link sta entries for MLO.
@@ -2218,6 +2222,9 @@ struct station_info {
u64 tx_bytes;
u32 tx_retries;
u32 tx_failed;
+ s8 signal;
+ struct rate_info txrate;
+ struct rate_info rxrate;
struct link_station_info deflink;
/* TODO: Need to check and add protection access to links memory */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 4b78b03b1047..2cad17cb64d7 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2858,6 +2858,33 @@ static void sta_set_link_sinfo(struct sta_info *sta, struct link_station_info *l
}
}
+static void sta_set_mld_rate_info(struct rate_info *sinfo_rate,
+ struct rate_info *link_sinfo_rate)
+{
+ if (link_sinfo_rate->flags)
+ sinfo_rate->flags = link_sinfo_rate->flags;
+ if (link_sinfo_rate->legacy)
+ sinfo_rate->legacy = link_sinfo_rate->legacy;
+ if (link_sinfo_rate->mcs)
+ sinfo_rate->mcs = link_sinfo_rate->mcs;
+ if (link_sinfo_rate->nss)
+ sinfo_rate->nss = link_sinfo_rate->nss;
+ if (link_sinfo_rate->bw)
+ sinfo_rate->bw = link_sinfo_rate->bw;
+ if (link_sinfo_rate->he_gi)
+ sinfo_rate->he_gi = link_sinfo_rate->he_gi;
+ if (link_sinfo_rate->he_dcm)
+ sinfo_rate->he_dcm = link_sinfo_rate->he_dcm;
+ if (link_sinfo_rate->he_ru_alloc)
+ sinfo_rate->he_ru_alloc = link_sinfo_rate->he_ru_alloc;
+ if (link_sinfo_rate->n_bonded_ch)
+ sinfo_rate->n_bonded_ch = link_sinfo_rate->n_bonded_ch;
+ if (link_sinfo_rate->eht_gi)
+ sinfo_rate->eht_gi = link_sinfo_rate->eht_gi;
+ if (link_sinfo_rate->eht_ru_alloc)
+ sinfo_rate->eht_ru_alloc = link_sinfo_rate->eht_ru_alloc;
+}
+
static void sta_set_mld_sinfo(struct station_info *sinfo, struct sta_info *sta)
{
struct link_station_info *link_sinfo;
@@ -2913,6 +2940,23 @@ static void sta_set_mld_sinfo(struct station_info *sinfo, struct sta_info *sta)
sinfo->rx_bytes += sta->rem_link_stats.rx_bytes;
sinfo->tx_retries += sta->rem_link_stats.tx_retries;
sinfo->tx_failed += sta->rem_link_stats.tx_failed;
+
+ /*TODO: set mld stats for signal based on best values and signal
+ * for last updated, currently using one of the link to fill stats
+ */
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
+ sinfo->signal = link_sinfo->signal;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+ }
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
+ sta_set_mld_rate_info(&sinfo->txrate, &link_sinfo->txrate);
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+ }
+
+ if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
+ sta_set_mld_rate_info(&sinfo->rxrate, &link_sinfo->rxrate);
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
+ }
}
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 06688aa1780f..99d74f67b1a2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6839,7 +6839,8 @@ static int nl80211_fill_link_station(struct sk_buff *msg,
}
static int nl80211_fill_mld_station(struct sk_buff *msg,
- struct station_info *sinfo)
+ struct station_info *sinfo,
+ struct cfg80211_registered_device *rdev)
{
#define PUT_SINFO(attr, memb, type) do { \
BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
@@ -6862,9 +6863,29 @@ static int nl80211_fill_mld_station(struct sk_buff *msg,
PUT_SINFO(TX_RETRIES, tx_retries, u32);
PUT_SINFO(TX_FAILED, tx_failed, u32);
+ switch (rdev->wiphy.signal_type) {
+ case CFG80211_SIGNAL_TYPE_MBM:
+ PUT_SINFO(SIGNAL, signal, u8);
+ break;
+ default:
+ break;
+ }
+
#undef PUT_SINFO
#undef PUT_SINFO_U64
+ if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
+ if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
+ NL80211_STA_INFO_TX_BITRATE))
+ return -EMSGSIZE;
+ }
+
+ if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
+ if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
+ NL80211_STA_INFO_RX_BITRATE))
+ return -EMSGSIZE;
+ }
+
return 0;
}
@@ -6942,7 +6963,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
#undef PUT_SINFO_U64
if (sinfo->valid_links) {
- ret = nl80211_fill_mld_station(msg, sinfo);
+ ret = nl80211_fill_mld_station(msg, sinfo, rdev);
if (ret)
goto nla_put_failure;
--
2.34.1
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH RFC 7/7] wifi: ath12k: correctly fetch arsta for MLO
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
` (5 preceding siblings ...)
2025-01-10 4:24 ` [PATCH RFC 6/7] wifi: cfg80211: add additional MLO statistics Sarika Sharma
@ 2025-01-10 4:24 ` Sarika Sharma
2025-01-10 9:45 ` [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Johannes Berg
2025-01-10 16:53 ` Ben Greear
8 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-10 4:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sarika Sharma
Currently in ath12k_mac_op_link_sta_statistics(), link sinfo structure
is filled from arsta structure and arsta is fetched from ahsta->deflink.
For both non-ML and multi-link operation (MLO), deflink is used. While
this is correct for non-ML, but the corresponding link_id should be
used for MLO.
Therefore, add support for MLO by taking the link_id from the
link_sinfo structure, fetching arsta from ahsta->link[link_id], and
filling the link_sinfo structure if valid_links.
NOTE:
- Currently ath12k changes are only included as an reference to other
drivers.
Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index ebde8a604eec..1bafda3c83aa 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -9902,11 +9902,18 @@ static void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
struct link_station_info *link_sinfo)
{
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ int link_id = link_sinfo->link_id;
struct ath12k_link_sta *arsta;
lockdep_assert_wiphy(hw->wiphy);
- arsta = &ahsta->deflink;
+ if (link_id < 0)
+ arsta = &ahsta->deflink;
+ else
+ arsta = wiphy_dereference(hw->wiphy, ahsta->link[link_id]);
+
+ if (!arsta)
+ return;
link_sinfo->rx_duration = arsta->rx_duration;
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
--
2.34.1
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
` (6 preceding siblings ...)
2025-01-10 4:24 ` [PATCH RFC 7/7] wifi: ath12k: correctly fetch arsta for MLO Sarika Sharma
@ 2025-01-10 9:45 ` Johannes Berg
2025-01-12 8:17 ` Sarika Sharma
2025-01-10 16:53 ` Ben Greear
8 siblings, 1 reply; 28+ messages in thread
From: Johannes Berg @ 2025-01-10 9:45 UTC (permalink / raw)
To: Sarika Sharma; +Cc: linux-wireless
On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>
> Current flow:
FWIW, I really would have preferred to see this discussion separately in
terms of cfg80211 and mac80211. Yes, the design phase obviously requires
both to be addressed, but once you have that I tend to think it's easier
to reason about them individually.
> Proposed flow: (Changes in last block)
Which kind of implies that cfg80211 didn't really change in terms of the
high-level overview, but I'm not sure that's really true?
> +----------------------------------------------------------+
> | sta_set_sinfo() |
> | 1. fill sinfo structure- info related to station |
> | 2. if MLO |
> | a. call sta_set_link_sinfo() for each valid link |
> | i. Call mac80211 ops- .link_sta_statistics() |
> | to fill link_sinfo structure |
> | ii. fill remaining link_sinfo structure |
> | b. call sta_set_mld_info()- to fill accumulated |
> | stats at MLO level |
> | 3. if non-ML |
> | a. call sta_set_link_sinfo() for deflink |
> | i. Call mac80211 ops - .link_sta_statistics() |
> | to fill deflink link_sinfo structure |
> | ii. fill remaining link_sinfo structure |
And that's simply too much detail. The ASCII art is also a distraction
rather than an aid if you ask me ;-)
>
> Alternate approach:
> - Keep sinfo structure as it is and use this for non-ML or
> accumulated statistics for ML station.
> - Add link sinfo for links with only certain link specific statistics.
> - Keep mac_op_sta_statistics at MLD level and let driver fill the
> MLO and link level data, if driver not filling let mac80211 fill
> the data.
> - Corresponding changes done to embed statistics into the NL message
> based on the sinfo/link_sinfo.
And this kind of data-structure based discussion is actually completely
missing for the proposed solution?
What about drivers that might offload link decisions and not really tell
you per-link statistics? I mean, I don't even know if such a thing
exists, but with a data structure like that you could still have it?
Should mac80211 even accumulate? Why not cfg80211 accumulate over the
links? And if mac80211 keeps the removed links per link then nothing
else is even needed? Or it could pre-fill the MLD level info?
johannes
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station
2025-01-10 9:45 ` [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Johannes Berg
@ 2025-01-12 8:17 ` Sarika Sharma
0 siblings, 0 replies; 28+ messages in thread
From: Sarika Sharma @ 2025-01-12 8:17 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 1/10/2025 3:15 PM, Johannes Berg wrote:
> On Fri, 2025-01-10 at 09:54 +0530, Sarika Sharma wrote:
>>
>> Current flow:
>
> FWIW, I really would have preferred to see this discussion separately in
> terms of cfg80211 and mac80211. Yes, the design phase obviously requires
> both to be addressed, but once you have that I tend to think it's easier
> to reason about them individually.
Sure, let me check what I can do here.
>
>> Proposed flow: (Changes in last block)
>
> Which kind of implies that cfg80211 didn't really change in terms of the
> high-level overview, but I'm not sure that's really true?
>
From cfg80211 still sta_set_sinfo() is called, sinfo structure is
getting changed. Sure, will add about the structure change in proposed
design.
>> +----------------------------------------------------------+
>> | sta_set_sinfo() |
>> | 1. fill sinfo structure- info related to station |
>> | 2. if MLO |
>> | a. call sta_set_link_sinfo() for each valid link |
>> | i. Call mac80211 ops- .link_sta_statistics() |
>> | to fill link_sinfo structure |
>> | ii. fill remaining link_sinfo structure |
>> | b. call sta_set_mld_info()- to fill accumulated |
>> | stats at MLO level |
>> | 3. if non-ML |
>> | a. call sta_set_link_sinfo() for deflink |
>> | i. Call mac80211 ops - .link_sta_statistics() |
>> | to fill deflink link_sinfo structure |
>> | ii. fill remaining link_sinfo structure |
>
> And that's simply too much detail. The ASCII art is also a distraction
> rather than an aid if you ask me ;-)
Sure, will move to points about the design proposed.
>>
>> Alternate approach:
>> - Keep sinfo structure as it is and use this for non-ML or
>> accumulated statistics for ML station.
>> - Add link sinfo for links with only certain link specific statistics.
>> - Keep mac_op_sta_statistics at MLD level and let driver fill the
>> MLO and link level data, if driver not filling let mac80211 fill
>> the data.
>> - Corresponding changes done to embed statistics into the NL message
>> based on the sinfo/link_sinfo.
>
> And this kind of data-structure based discussion is actually completely
> missing for the proposed solution?
Sure, let me add about the structural change as well in design flow.
>
> What about drivers that might offload link decisions and not really tell
> you per-link statistics? I mean, I don't even know if such a thing
> exists, but with a data structure like that you could still have it?
That is taken care, if driver is not filling the link info, mac80211
will check if it filled, if not it will be filled by mac80211.
>
> Should mac80211 even accumulate? Why not cfg80211 accumulate over the
> links? And if mac80211 keeps the removed links per link then nothing
> else is even needed? Or it could pre-fill the MLD level info?
Sure, we can do the accumulation in cfg80211 instead of mac80211.
>
> johannes
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station
2025-01-10 4:24 [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Sarika Sharma
` (7 preceding siblings ...)
2025-01-10 9:45 ` [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station Johannes Berg
@ 2025-01-10 16:53 ` Ben Greear
2025-01-15 5:11 ` Sarika Sharma
8 siblings, 1 reply; 28+ messages in thread
From: Ben Greear @ 2025-01-10 16:53 UTC (permalink / raw)
To: Sarika Sharma, johannes; +Cc: linux-wireless
On 1/9/25 20:24, Sarika Sharma wrote:
> Current implementation of NL80211_CMD_GET_STATION does not work
> for multi-link operation(MLO) since in case of MLO only deflink
> (or one of the links) is considered and not all links.
>
> Hence, add the link_sinfo structure to provide infrastructure
> for link-level station statistics for multi-link operation(MLO).
>
> Additionally, accumulated stats for MLO are included in a concise
> manner to provide a comprehensive overview of the ML stations.
>
> NOTE:
> 1. Current code changes are done to get an early feedback on design.
> 2. Once RFC patches are approved will add the required driver changes.
> 3. Ath12k changes are included in this series for reference to other
> driver changes.
> Alternate approach:
> - Keep sinfo structure as it is and use this for non-ML or
> accumulated statistics for ML station.
> - Add link sinfo for links with only certain link specific statistics.
> - Keep mac_op_sta_statistics at MLD level and let driver fill the
> MLO and link level data, if driver not filling let mac80211 fill
> the data.
> - Corresponding changes done to embed statistics into the NL message
> based on the sinfo/link_sinfo.
My suggestions for general approach to this:
1) current sinfo stats should report totals for all links,
but it should not sum them up at query time because links come
and go. So driver/firmware/mac80211 or whatever is keeping count
of the stats needs to count the total tx/rx/ packets/bytes/whatever
as it happens.
2) Per-link stats can be over duration of the link object.
3) For sinfo logic that currently reports tx/rx mcs rate and such that cannot
be summed, use 'best' link's for those values. Effectively, this probably means highest
frequency is 'best' link.
4) Add per-link stats data that looks very much like 'sinfo' data struct and user-space
that can support that could then get detailed per-link stats at same time it is getting
per netdev 'sinfo' stats.
5) Assuming there will never be more than 3 links for any radios supported by Linux in the near future,
embed the 3 link's 'sinfo-like' stats data structure in the per-netdev sinfo stats struct
so that we can get all 3 link's data at same time that we are getting the other stats.
That should save calls into the driver and ensure that per-links stats can be gathered
at exactly the same time.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station
2025-01-10 16:53 ` Ben Greear
@ 2025-01-15 5:11 ` Sarika Sharma
2025-01-15 17:02 ` Ben Greear
0 siblings, 1 reply; 28+ messages in thread
From: Sarika Sharma @ 2025-01-15 5:11 UTC (permalink / raw)
To: Ben Greear, johannes; +Cc: linux-wireless
On 1/10/2025 10:23 PM, Ben Greear wrote:
> On 1/9/25 20:24, Sarika Sharma wrote:
>> Current implementation of NL80211_CMD_GET_STATION does not work
>> for multi-link operation(MLO) since in case of MLO only deflink
>> (or one of the links) is considered and not all links.
>>
>> Hence, add the link_sinfo structure to provide infrastructure
>> for link-level station statistics for multi-link operation(MLO).
>>
>> Additionally, accumulated stats for MLO are included in a concise
>> manner to provide a comprehensive overview of the ML stations.
>>
>> NOTE:
>> 1. Current code changes are done to get an early feedback on design.
>> 2. Once RFC patches are approved will add the required driver
>> changes.
>> 3. Ath12k changes are included in this series for reference to other
>> driver changes.
>
>> Alternate approach:
>> - Keep sinfo structure as it is and use this for non-ML or
>> accumulated statistics for ML station.
>> - Add link sinfo for links with only certain link specific
>> statistics.
>> - Keep mac_op_sta_statistics at MLD level and let driver fill the
>> MLO and link level data, if driver not filling let mac80211 fill
>> the data.
>> - Corresponding changes done to embed statistics into the NL message
>> based on the sinfo/link_sinfo.
>
> My suggestions for general approach to this:
>
> 1) current sinfo stats should report totals for all links,
> but it should not sum them up at query time because links come
> and go. So driver/firmware/mac80211 or whatever is keeping count
> of the stats needs to count the total tx/rx/ packets/bytes/whatever
> as it happens.
Alternate approach is not considered here, because some fields at
station level could not be much meaningful like rx_beacon, pertid ,etc.
I believe the total count is better to do from links data in
cfg80211/mac80211, as if link's data is provided it is easy to aggregate
them, during query time.
Also removed link_data is maintained in implemented approach, so that
could be helpful if any link go down.
>
> 2) Per-link stats can be over duration of the link object.
>
> 3) For sinfo logic that currently reports tx/rx mcs rate and such that
> cannot
> be summed, use 'best' link's for those values. Effectively, this
> probably means highest
> frequency is 'best' link.
Every fields have it's own way of best, so based on field need to check
what is best for this field value? but some parameters not have much
meaning at MLO level like rx_beacon, pertid, etc. So keeping best of it,
will be useful here?
or you mean need to check for best frequency link and take this link
data as MLO data? if yes? will it be useful here?
>
> 4) Add per-link stats data that looks very much like 'sinfo' data struct
> and user-space
> that can support that could then get detailed per-link stats at same
> time it is getting
> per netdev 'sinfo' stats.
Again, some fields that are in sinfo structure could not be very useful
at link level like generation, sta_info, etc. So keeping same structure
for station level and link level is not very useful, instead better to
split the structure, fields for station level and some fields at link level.
>
> 5) Assuming there will never be more than 3 links for any radios
> supported by Linux in the near future,
> embed the 3 link's 'sinfo-like' stats data structure in the per-netdev
> sinfo stats struct
> so that we can get all 3 link's data at same time that we are getting
> the other stats.
> That should save calls into the driver and ensure that per-links stats
> can be gathered
> at exactly the same time.
Yes, I agree currently it's 3 only, but everywhere we are using max-15,
so explicitly keeping it 3 here isn't questionable? In future also it
will not be useful.
>
> Thanks,
> Ben
>
Currently, addressing the comments on current implemented approach.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH RFC 0/7] wifi: cfg80211/mac80211: add support to handle per link statistics of multi-link station
2025-01-15 5:11 ` Sarika Sharma
@ 2025-01-15 17:02 ` Ben Greear
0 siblings, 0 replies; 28+ messages in thread
From: Ben Greear @ 2025-01-15 17:02 UTC (permalink / raw)
To: Sarika Sharma, johannes; +Cc: linux-wireless
On 1/14/25 21:11, Sarika Sharma wrote:
> On 1/10/2025 10:23 PM, Ben Greear wrote:
>> On 1/9/25 20:24, Sarika Sharma wrote:
>>> Current implementation of NL80211_CMD_GET_STATION does not work
>>> for multi-link operation(MLO) since in case of MLO only deflink
>>> (or one of the links) is considered and not all links.
>>>
>>> Hence, add the link_sinfo structure to provide infrastructure
>>> for link-level station statistics for multi-link operation(MLO).
>>>
>>> Additionally, accumulated stats for MLO are included in a concise
>>> manner to provide a comprehensive overview of the ML stations.
>>>
>>> NOTE:
>>> 1. Current code changes are done to get an early feedback on design.
>>> 2. Once RFC patches are approved will add the required driver changes.
>>> 3. Ath12k changes are included in this series for reference to other
>>> driver changes.
>>
>>> Alternate approach:
>>> - Keep sinfo structure as it is and use this for non-ML or
>>> accumulated statistics for ML station.
>>> - Add link sinfo for links with only certain link specific statistics.
>>> - Keep mac_op_sta_statistics at MLD level and let driver fill the
>>> MLO and link level data, if driver not filling let mac80211 fill
>>> the data.
>>> - Corresponding changes done to embed statistics into the NL message
>>> based on the sinfo/link_sinfo.
>>
>> My suggestions for general approach to this:
>>
>> 1) current sinfo stats should report totals for all links,
>> but it should not sum them up at query time because links come
>> and go. So driver/firmware/mac80211 or whatever is keeping count
>> of the stats needs to count the total tx/rx/ packets/bytes/whatever
>> as it happens.
>
> Alternate approach is not considered here, because some fields at station level could not be much meaningful like rx_beacon, pertid ,etc.
> I believe the total count is better to do from links data in cfg80211/mac80211, as if link's data is provided it is easy to aggregate them, during query time.
>
> Also removed link_data is maintained in implemented approach, so that could be helpful if any link go down.
>
>>
>> 2) Per-link stats can be over duration of the link object.
>>
>> 3) For sinfo logic that currently reports tx/rx mcs rate and such that cannot
>> be summed, use 'best' link's for those values. Effectively, this probably means highest
>> frequency is 'best' link.
>
> Every fields have it's own way of best, so based on field need to check what is best for this field value? but some parameters not have much meaning at MLO
> level like rx_beacon, pertid, etc. So keeping best of it, will be useful here?
>
> or you mean need to check for best frequency link and take this link data as MLO data? if yes? will it be useful here?
My goal is to allow legacy user-space to report something useful for MLO netdevs, and in my opinion, reporting
tx/rx mcs rates in this case should use the highest frequency link that is active.
>> 4) Add per-link stats data that looks very much like 'sinfo' data struct and user-space
>> that can support that could then get detailed per-link stats at same time it is getting
>> per netdev 'sinfo' stats.
>
> Again, some fields that are in sinfo structure could not be very useful at link level like generation, sta_info, etc. So keeping same structure for station
> level and link level is not very useful, instead better to split the structure, fields for station level and some fields at link level.
>
>>
>> 5) Assuming there will never be more than 3 links for any radios supported by Linux in the near future,
>> embed the 3 link's 'sinfo-like' stats data structure in the per-netdev sinfo stats struct
>> so that we can get all 3 link's data at same time that we are getting the other stats.
>> That should save calls into the driver and ensure that per-links stats can be gathered
>> at exactly the same time.
>
> Yes, I agree currently it's 3 only, but everywhere we are using max-15, so explicitly keeping it 3 here isn't questionable? In future also it will not be useful.
Changing a 3 to a 4 is easy future change, and should not affect user-space API one
way or another. If we can simplify code and stats memory allocation by using a smaller
link count for stats gathering, I think we should do that. As soon as something supporting
more than 3 links exists, we can increase it.
But, it is not a big deal to me, so if you like the other approach, I'll not
argue further.
Thanks,
Ben
>
>>
>> Thanks,
>> Ben
>>
>
> Currently, addressing the comments on current implemented approach.
>
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 28+ messages in thread