git: 9996e4df555c - stable/14 - LinuxKPI; 802.11: start filling rxrate statistics
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Apr 2025 14:37:29 UTC
The branch stable/14 has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=9996e4df555c7b7b4988526729fdf4230d796954
commit 9996e4df555c7b7b4988526729fdf4230d796954
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-04-13 23:05:46 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-04-18 14:36:03 +0000
LinuxKPI; 802.11: start filling rxrate statistics
Start collecting rxrate information from the RX statistics which are
passed per packet. Store them in the lsta and upon printing statistics,
if no RX_BIRATE is provided copy them over from the lsta.
This allows us to see rate information in both directions on modern
iwlwifi chipsets, which are doing [tx]rate handling in firmware.
Sponsored by: The FreeBSD Foundation
(cherry picked from commit a1adefb139b3c8f95e5255c67705fb92f4d9fc04)
---
sys/compat/linuxkpi/common/src/linux_80211.c | 72 +++++++++++++++++++++-------
sys/compat/linuxkpi/common/src/linux_80211.h | 2 +
2 files changed, 58 insertions(+), 16 deletions(-)
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 3dba41a4e547..98e0b28d9ef2 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -314,6 +314,13 @@ lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS)
continue;
}
+ /* If no RX_BITRATE is reported, try to fill it in from the lsta sinfo. */
+ if ((sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) == 0 &&
+ (lsta->sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) != 0) {
+ memcpy(&sinfo.rxrate, &lsta->sinfo.rxrate, sizeof(sinfo.rxrate));
+ sinfo.filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
+ }
+
lkpi_nl80211_sta_info_to_str(&s, " nl80211_sta_info (valid fields)", sinfo.filled);
sbuf_printf(&s, " connected_time %u inactive_time %u\n",
sinfo.connected_time, sinfo.inactive_time);
@@ -6276,15 +6283,17 @@ lkpi_80211_lhw_rxq_task(void *ctx, int pending)
}
static void
-lkpi_convert_rx_status(struct ieee80211_hw *hw,
+lkpi_convert_rx_status(struct ieee80211_hw *hw, struct lkpi_sta *lsta,
struct ieee80211_rx_status *rx_status,
struct ieee80211_rx_stats *rx_stats,
uint8_t *rssip)
{
struct ieee80211_supported_band *supband;
+ struct rate_info rxrate;
int i;
uint8_t rssi;
+ memset(&rxrate, 0, sizeof(rxrate));
memset(rx_stats, 0, sizeof(*rx_stats));
rx_stats->r_flags = IEEE80211_R_NF | IEEE80211_R_RSSI;
/* XXX-BZ correct hardcoded noise floor, survey data? */
@@ -6351,30 +6360,56 @@ lkpi_convert_rx_status(struct ieee80211_hw *hw,
switch (rx_status->encoding) {
case RX_ENC_LEGACY:
+ {
+ uint32_t legacy = 0;
+
supband = hw->wiphy->bands[rx_status->band];
if (supband != NULL)
- rx_stats->c_rate = supband->bitrates[rx_status->rate_idx].bitrate;
+ legacy = supband->bitrates[rx_status->rate_idx].bitrate;
+ rx_stats->c_rate = legacy;
+ rxrate.legacy = legacy;
/* Is there a LinuxKPI way of reporting IEEE80211_RX_F_CCK / _OFDM? */
break;
+ }
case RX_ENC_HT:
rx_stats->c_pktflags |= IEEE80211_RX_F_HT;
- if ((rx_status->enc_flags & RX_ENC_FLAG_SHORT_GI) != 0)
- rx_stats->c_pktflags |= IEEE80211_RX_F_SHORTGI;
rx_stats->c_rate = rx_status->rate_idx; /* mcs */
+ rxrate.flags |= RATE_INFO_FLAGS_MCS;
+ rxrate.mcs = rx_status->rate_idx;
+ if ((rx_status->enc_flags & RX_ENC_FLAG_SHORT_GI) != 0) {
+ rx_stats->c_pktflags |= IEEE80211_RX_F_SHORTGI;
+ rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ }
break;
case RX_ENC_VHT:
rx_stats->c_pktflags |= IEEE80211_RX_F_VHT;
- if ((rx_status->enc_flags & RX_ENC_FLAG_SHORT_GI) != 0)
- rx_stats->c_pktflags |= IEEE80211_RX_F_SHORTGI;
rx_stats->c_rate = rx_status->rate_idx; /* mcs */
rx_stats->c_vhtnss = rx_status->nss;
+ rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
+ rxrate.mcs = rx_status->rate_idx;
+ rxrate.nss = rx_status->nss;
+ if ((rx_status->enc_flags & RX_ENC_FLAG_SHORT_GI) != 0) {
+ rx_stats->c_pktflags |= IEEE80211_RX_F_SHORTGI;
+ rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ }
break;
case RX_ENC_HE:
+ rxrate.flags |= RATE_INFO_FLAGS_HE_MCS;
+ rxrate.mcs = rx_status->rate_idx;
+ rxrate.nss = rx_status->nss;
+ /* XXX TODO */
+ TODO("net80211 has not matching encoding for %u", rx_status->encoding);
+ break;
case RX_ENC_EHT:
+ rxrate.flags |= RATE_INFO_FLAGS_EHT_MCS;
+ rxrate.mcs = rx_status->rate_idx;
+ rxrate.nss = rx_status->nss;
+ /* XXX TODO */
TODO("net80211 has not matching encoding for %u", rx_status->encoding);
break;
}
+ rxrate.bw = rx_status->bw;
switch (rx_status->bw) {
case RATE_INFO_BW_20:
rx_stats->c_width = IEEE80211_RX_FW_20MHZ;
@@ -6425,6 +6460,11 @@ lkpi_convert_rx_status(struct ieee80211_hw *hw,
if (rx_status->flag & RX_FLAG_FAILED_FCS_CRC)
rx_stats->c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC;
#endif
+
+ if (lsta != NULL) {
+ memcpy(&lsta->sinfo.rxrate, &rxrate, sizeof(rxrate));
+ lsta->sinfo.filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
+ }
}
/* For %list see comment towards the end of the function. */
@@ -6527,16 +6567,6 @@ linuxkpi_ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
no_trace_beacons:
#endif
- rssi = 0;
- lkpi_convert_rx_status(hw, rx_status, &rx_stats, &rssi);
-
- ok = ieee80211_add_rx_params(m, &rx_stats);
- if (ok == 0) {
- m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
- goto err;
- }
-
lsta = NULL;
if (sta != NULL) {
lsta = STA_TO_LSTA(sta);
@@ -6550,6 +6580,16 @@ no_trace_beacons:
lsta = ni->ni_drv_data;
}
+ rssi = 0;
+ lkpi_convert_rx_status(hw, lsta, rx_status, &rx_stats, &rssi);
+
+ ok = ieee80211_add_rx_params(m, &rx_stats);
+ if (ok == 0) {
+ m_freem(m);
+ counter_u64_add(ic->ic_ierrors, 1);
+ goto err;
+ }
+
if (ni != NULL)
vap = ni->ni_vap;
else
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index ebf02994af47..e9c0d01af1bb 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -161,6 +161,8 @@ struct lkpi_sta {
bool added_to_drv; /* Driver knows; i.e. we called ...(). */
bool in_mgd; /* XXX-BZ should this be per-vif? */
+ struct station_info sinfo; /* statistics */
+
/* Must be last! */
struct ieee80211_sta sta __aligned(CACHE_LINE_SIZE);
};