[PATCH v2 1/2] wifi: cfg80211/mac80211: Add support to rx retry stats

Hari Chandrakanthan
2024-03-19T13:45:32Z

Add support to count station level rx retries.
It denotes the number of data frames(MPDUs) with rx retry bit set.

The rx retry stats helps in understanding the medium
during UL transmission.

The counting logic of rx retry stats in the mac80211 rx path accounts the
data frames for which decap is not offloaded.

Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
---
v2:
Added mac80211 support to count the rx retry stats
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 3 +++
net/mac80211/rx.c | 6 ++++++
net/mac80211/sta_info.c | 5 +++++
net/mac80211/sta_info.h | 1 +
net/wireless/nl80211.c | 1 +
6 files changed, 18 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2e2be4fd2bb6..21400bcc0646 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2049,6 +2049,7 @@ struct cfg80211_tid_stats {
* @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
+ * @rx_retries: number of rx packets(MPDUs) from this station with retry bit set.
* @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.
@@ -2129,6 +2130,7 @@ struct station_info {
struct rate_info rxrate;
u32 rx_packets;
u32 tx_packets;
+ u32 rx_retries;
u32 tx_retries;
u32 tx_failed;
u32 rx_dropped_misc;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f23ecbdd84a2..2e31909bf8af 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3885,6 +3885,8 @@ enum nl80211_sta_bss_param {
* of STA's association
* @NL80211_STA_INFO_CONNECTED_TO_AS: set to true if STA has a path to a
* authentication server (u8, 0 or 1)
+ * @NL80211_STA_INFO_RX_RETRIES: number of rx packets(MPDUs) from this station
+ * with retry bit set (u32)
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
@@ -3933,6 +3935,7 @@ enum nl80211_sta_info {
NL80211_STA_INFO_AIRTIME_LINK_METRIC,
NL80211_STA_INFO_ASSOC_AT_BOOTTIME,
NL80211_STA_INFO_CONNECTED_TO_AS,
+ NL80211_STA_INFO_RX_RETRIES,

/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c1f850138405..f8d408ac6742 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3191,6 +3191,9 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
if (!ieee80211_frame_allowed(rx, fc))
return RX_DROP_MONITOR;

+ if (ieee80211_has_retry(hdr->frame_control) && rx->sta)
+ rx->link_sta->rx_stats.rx_retries++;
+
/* directly handle TDLS channel switch requests/responses */
if (unlikely(((struct ethhdr *)rx->skb->data)->h_proto ==
cpu_to_be16(ETH_P_TDLS))) {
@@ -4976,6 +4979,9 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
goto drop;
}

+ if (ieee80211_has_retry(hdr->frame_control) && rx->sta)
+ rx->link_sta->rx_stats.rx_retries++;
+
ieee80211_rx_8023(rx, fast_rx, orig_len);

return true;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index da5fdd6f5c85..b04092b6ea64 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2653,6 +2653,11 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
}

+ if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_RETRIES))) {
+ sinfo->rx_retries = sta->deflink.rx_stats.rx_retries;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_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);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index a52fb76386d0..a4c47e3f0d5a 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -436,6 +436,7 @@ struct ieee80211_sta_rx_stats {
struct u64_stats_sync syncp;
u64 bytes;
u64 msdu[IEEE80211_NUM_TIDS + 1];
+ u32 rx_retries;
};

/*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b4edba6b0b7b..fb643d3061c5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6626,6 +6626,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,

PUT_SINFO(RX_PACKETS, rx_packets, u32);
PUT_SINFO(TX_PACKETS, tx_packets, u32);
+ PUT_SINFO(RX_RETRIES, rx_retries, u32);
PUT_SINFO(TX_RETRIES, tx_retries, u32);
PUT_SINFO(TX_FAILED, tx_failed, u32);
PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
--
2.34.1