git: 44ec60a4290b - main - net80211: fix ff_approx_txtime() to handle VHT rates

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Sat, 03 May 2025 15:39:14 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=44ec60a4290b1b4dd4842889038c399a7bed17bd

commit 44ec60a4290b1b4dd4842889038c399a7bed17bd
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2025-04-10 20:27:14 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2025-05-03 15:38:51 +0000

    net80211: fix ff_approx_txtime() to handle VHT rates
    
    The fast frames / A-MSDU aggregation code is calculating whether to
    aggregate frames based on transmit time, which requires a frame length
    calculation.  Unfortunately this is another place where VHT rates
    started showing up but weren't being handled.
    
    This only shows up if IEEE80211_SUPPORT_SUPERG is enabled, which
    isn't enabled by default (which means there's also no net80211
    software driven A-MSDU assembly.)
    
    So:
    
    * Fetch the rate type
    * Handle HT, LEGACY, VHT and UNDEFINED
    * default UNDEFINED to 4ms, which should avoid the FF/A-MSDU aggregation
    * default VHT to 1ms, to allow SOME possible A-MSDU aggregation where
      possible.
    
    There needs to be a bit more work done on HT/VHT for doing A-MSDU
    with and without A-MPDU running, as that drastically changes the
    math.
    
    Differential Revision:  https://reviews.freebsd.org/D49766
---
 sys/net80211/ieee80211_superg.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/sys/net80211/ieee80211_superg.c b/sys/net80211/ieee80211_superg.c
index ee3b70d5ed9f..fcf0c614b0a0 100644
--- a/sys/net80211/ieee80211_superg.c
+++ b/sys/net80211/ieee80211_superg.c
@@ -721,6 +721,7 @@ static uint32_t
 ff_approx_txtime(struct ieee80211_node *ni,
 	const struct mbuf *m1, const struct mbuf *m2)
 {
+	struct ieee80211_node_txrate txr;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211vap *vap = ni->ni_vap;
 	uint32_t framelen;
@@ -743,20 +744,33 @@ ff_approx_txtime(struct ieee80211_node *ni,
 	if (m2 != NULL)
 		framelen += m2->m_pkthdr.len;
 
-	/*
-	 * For now, we assume non-shortgi, 20MHz, just because I want to
-	 * at least test 802.11n.
-	 */
-	dot11rate = ieee80211_node_get_txrate_dot11rate(ni);
-	if (dot11rate & IEEE80211_RATE_MCS)
+	ieee80211_node_get_txrate(ni, &txr);
+
+	switch (txr.type) {
+	case IEEE80211_NODE_TXRATE_LEGACY:
+		dot11rate = ieee80211_node_get_txrate_dot11rate(ni);
+		frame_time = ieee80211_compute_duration(ic->ic_rt, framelen,
+			    dot11rate, 0);
+		break;
+	case IEEE80211_NODE_TXRATE_HT:
+		/* TODO: check ht40/shortgi */
+		dot11rate = ieee80211_node_get_txrate_dot11rate(ni);
 		frame_time = ieee80211_compute_duration_ht(framelen,
 		    dot11rate,
 		    IEEE80211_HT_RC_2_STREAMS(dot11rate),
 		    0, /* isht40 */
 		    0); /* isshortgi */
-	else
-		frame_time = ieee80211_compute_duration(ic->ic_rt, framelen,
-			    dot11rate, 0);
+		break;
+	case IEEE80211_NODE_TXRATE_VHT:
+		/* TODO: there's no VHT frame length calculation just yet */
+		frame_time = 1000;	/* 1ms */
+		break;
+	case IEEE80211_NODE_TXRATE_UNDEFINED:
+		/* TODO: proper error handling */
+		frame_time = 4000; /* 4ms */
+		break;
+	}
+
 	return (frame_time);
 }