Skip to content

Commit 82d7f84

Browse files
Sarika Sharmajmberg-intel
authored andcommitted
wifi: cfg80211: extend to embed link level statistics in NL message
Currently, statistics is supported at deflink( or one of the links) level for station. This has problems when applied to multi-link(ML) connections. Hence, add changes to support link level statistics to embed NL message with link related information if valid links are present. This will be helpful to check the link related statistics during MLO. The statistics will be embedded into NL message as below: For non-ML: cmd-> NL80211_ATTR_IFINDEX NL80211_ATTR_MAC NL80211_ATTR_GENERATION ....etc NL80211_ATTR_STA_INFO | nested NL80211_STA_INFO_CONNECTED_TIME, NL80211_STA_INFO_STA_FLAGS, NL80211_STA_INFO_RX_BYTES, NL80211_STA_INFO_TX_BYTES, .........etc For MLO: cmd -> NL80211_ATTR_IFINDEX NL80211_ATTR_MAC NL80211_ATTR_GENERATION .......etc NL80211_ATTR_STA_INFO | nested 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_MAC, NL80211_ATTR_STA_INFO | nested NL80211_STA_INFO_RX_BYTES, NL80211_STA_INFO_TX_BYTES, NL80211_STA_INFO_CONNECTED_TIME, ..........etc. link_id-2 | nested NL80211_ATTR_MLO_LINK_ID, NL80211_ATTR_MAC, NL80211_ATTR_STA_INFO | nested NL80211_STA_INFO_RX_BYTES, NL80211_STA_INFO_TX_BYTES, NL80211_STA_INFO_CONNECTED_TIME, .........etc Signed-off-by: Sarika Sharma <quic_sarishar@quicinc.com> Link: https://patch.msgid.link/20250528054420.3050133-4-quic_sarishar@quicinc.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent d2329ff commit 82d7f84

File tree

1 file changed

+216
-0
lines changed

1 file changed

+216
-0
lines changed

net/wireless/nl80211.c

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6728,6 +6728,185 @@ static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
67286728
return true;
67296729
}
67306730

6731+
static int nl80211_fill_link_station(struct sk_buff *msg,
6732+
struct cfg80211_registered_device *rdev,
6733+
struct link_station_info *link_sinfo)
6734+
{
6735+
struct nlattr *bss_param, *link_sinfoattr;
6736+
6737+
#define PUT_LINK_SINFO(attr, memb, type) do { \
6738+
BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
6739+
if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
6740+
nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
6741+
link_sinfo->memb)) \
6742+
goto nla_put_failure; \
6743+
} while (0)
6744+
#define PUT_LINK_SINFO_U64(attr, memb) do { \
6745+
if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
6746+
nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
6747+
link_sinfo->memb, NL80211_STA_INFO_PAD)) \
6748+
goto nla_put_failure; \
6749+
} while (0)
6750+
6751+
link_sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
6752+
if (!link_sinfoattr)
6753+
goto nla_put_failure;
6754+
6755+
PUT_LINK_SINFO(INACTIVE_TIME, inactive_time, u32);
6756+
6757+
if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
6758+
BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
6759+
nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
6760+
(u32)link_sinfo->rx_bytes))
6761+
goto nla_put_failure;
6762+
6763+
if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
6764+
BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
6765+
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
6766+
(u32)link_sinfo->tx_bytes))
6767+
goto nla_put_failure;
6768+
6769+
PUT_LINK_SINFO_U64(RX_BYTES64, rx_bytes);
6770+
PUT_LINK_SINFO_U64(TX_BYTES64, tx_bytes);
6771+
PUT_LINK_SINFO_U64(RX_DURATION, rx_duration);
6772+
PUT_LINK_SINFO_U64(TX_DURATION, tx_duration);
6773+
6774+
if (wiphy_ext_feature_isset(&rdev->wiphy,
6775+
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6776+
PUT_LINK_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
6777+
6778+
switch (rdev->wiphy.signal_type) {
6779+
case CFG80211_SIGNAL_TYPE_MBM:
6780+
PUT_LINK_SINFO(SIGNAL, signal, u8);
6781+
PUT_LINK_SINFO(SIGNAL_AVG, signal_avg, u8);
6782+
break;
6783+
default:
6784+
break;
6785+
}
6786+
if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
6787+
if (!nl80211_put_signal(msg, link_sinfo->chains,
6788+
link_sinfo->chain_signal,
6789+
NL80211_STA_INFO_CHAIN_SIGNAL))
6790+
goto nla_put_failure;
6791+
}
6792+
if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
6793+
if (!nl80211_put_signal(msg, link_sinfo->chains,
6794+
link_sinfo->chain_signal_avg,
6795+
NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
6796+
goto nla_put_failure;
6797+
}
6798+
if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
6799+
if (!nl80211_put_sta_rate(msg, &link_sinfo->txrate,
6800+
NL80211_STA_INFO_TX_BITRATE))
6801+
goto nla_put_failure;
6802+
}
6803+
if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
6804+
if (!nl80211_put_sta_rate(msg, &link_sinfo->rxrate,
6805+
NL80211_STA_INFO_RX_BITRATE))
6806+
goto nla_put_failure;
6807+
}
6808+
6809+
PUT_LINK_SINFO(RX_PACKETS, rx_packets, u32);
6810+
PUT_LINK_SINFO(TX_PACKETS, tx_packets, u32);
6811+
PUT_LINK_SINFO(TX_RETRIES, tx_retries, u32);
6812+
PUT_LINK_SINFO(TX_FAILED, tx_failed, u32);
6813+
PUT_LINK_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
6814+
PUT_LINK_SINFO(BEACON_LOSS, beacon_loss_count, u32);
6815+
6816+
if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
6817+
bss_param = nla_nest_start_noflag(msg,
6818+
NL80211_STA_INFO_BSS_PARAM);
6819+
if (!bss_param)
6820+
goto nla_put_failure;
6821+
6822+
if (((link_sinfo->bss_param.flags &
6823+
BSS_PARAM_FLAGS_CTS_PROT) &&
6824+
nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
6825+
((link_sinfo->bss_param.flags &
6826+
BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
6827+
nla_put_flag(msg,
6828+
NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
6829+
((link_sinfo->bss_param.flags &
6830+
BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
6831+
nla_put_flag(msg,
6832+
NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
6833+
nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
6834+
link_sinfo->bss_param.dtim_period) ||
6835+
nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
6836+
link_sinfo->bss_param.beacon_interval))
6837+
goto nla_put_failure;
6838+
6839+
nla_nest_end(msg, bss_param);
6840+
}
6841+
6842+
PUT_LINK_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
6843+
PUT_LINK_SINFO_U64(BEACON_RX, rx_beacon);
6844+
PUT_LINK_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
6845+
PUT_LINK_SINFO(RX_MPDUS, rx_mpdu_count, u32);
6846+
PUT_LINK_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
6847+
if (wiphy_ext_feature_isset(&rdev->wiphy,
6848+
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
6849+
PUT_LINK_SINFO(ACK_SIGNAL, ack_signal, u8);
6850+
PUT_LINK_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
6851+
}
6852+
6853+
#undef PUT_LINK_SINFO
6854+
#undef PUT_LINK_SINFO_U64
6855+
6856+
if (link_sinfo->pertid) {
6857+
struct nlattr *tidsattr;
6858+
int tid;
6859+
6860+
tidsattr = nla_nest_start_noflag(msg,
6861+
NL80211_STA_INFO_TID_STATS);
6862+
if (!tidsattr)
6863+
goto nla_put_failure;
6864+
6865+
for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
6866+
struct cfg80211_tid_stats *tidstats;
6867+
struct nlattr *tidattr;
6868+
6869+
tidstats = &link_sinfo->pertid[tid];
6870+
6871+
if (!tidstats->filled)
6872+
continue;
6873+
6874+
tidattr = nla_nest_start_noflag(msg, tid + 1);
6875+
if (!tidattr)
6876+
goto nla_put_failure;
6877+
6878+
#define PUT_TIDVAL_U64(attr, memb) do { \
6879+
if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
6880+
nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
6881+
tidstats->memb, NL80211_TID_STATS_PAD)) \
6882+
goto nla_put_failure; \
6883+
} while (0)
6884+
6885+
PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
6886+
PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
6887+
PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
6888+
PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6889+
6890+
#undef PUT_TIDVAL_U64
6891+
if ((tidstats->filled &
6892+
BIT(NL80211_TID_STATS_TXQ_STATS)) &&
6893+
!nl80211_put_txq_stats(msg, &tidstats->txq_stats,
6894+
NL80211_TID_STATS_TXQ_STATS))
6895+
goto nla_put_failure;
6896+
6897+
nla_nest_end(msg, tidattr);
6898+
}
6899+
6900+
nla_nest_end(msg, tidsattr);
6901+
}
6902+
6903+
nla_nest_end(msg, link_sinfoattr);
6904+
return 0;
6905+
6906+
nla_put_failure:
6907+
return -EMSGSIZE;
6908+
}
6909+
67316910
static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
67326911
u32 seq, int flags,
67336912
struct cfg80211_registered_device *rdev,
@@ -6736,6 +6915,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
67366915
{
67376916
void *hdr;
67386917
struct nlattr *sinfoattr, *bss_param;
6918+
struct link_station_info *link_sinfo;
6919+
struct nlattr *links, *link;
6920+
int link_id;
67396921

67406922
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
67416923
if (!hdr) {
@@ -6950,6 +7132,40 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
69507132
goto nla_put_failure;
69517133
}
69527134

7135+
if (sinfo->valid_links) {
7136+
links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
7137+
if (!links)
7138+
goto nla_put_failure;
7139+
7140+
for_each_valid_link(sinfo, link_id) {
7141+
link_sinfo = sinfo->links[link_id];
7142+
7143+
if (WARN_ON_ONCE(!link_sinfo))
7144+
continue;
7145+
7146+
if (!is_valid_ether_addr(link_sinfo->addr))
7147+
continue;
7148+
7149+
link = nla_nest_start(msg, link_id + 1);
7150+
if (!link)
7151+
goto nla_put_failure;
7152+
7153+
if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
7154+
link_id))
7155+
goto nla_put_failure;
7156+
7157+
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
7158+
link_sinfo->addr))
7159+
goto nla_put_failure;
7160+
7161+
if (nl80211_fill_link_station(msg, rdev, link_sinfo))
7162+
goto nla_put_failure;
7163+
7164+
nla_nest_end(msg, link);
7165+
}
7166+
nla_nest_end(msg, links);
7167+
}
7168+
69537169
cfg80211_sinfo_release_content(sinfo);
69547170
genlmsg_end(msg, hdr);
69557171
return 0;

0 commit comments

Comments
 (0)