git: 912a05670ed9 - main - net80211: add helper functions for VHT transmit

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Thu, 09 Jan 2025 00:59:11 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=912a05670ed9545a1d1b010eedafb819e14eb1b8

commit 912a05670ed9545a1d1b010eedafb819e14eb1b8
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2024-12-16 02:29:33 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2025-01-09 00:51:51 +0000

    net80211: add helper functions for VHT transmit
    
    * Add static helper functions for VHT TX for 20MHz, 40MHz and 80MHz.
    * Add a public function to check if the given VHT width is available
      for transmit.
    
    Differential Revision:  https://reviews.freebsd.org/D48101
---
 sys/net80211/ieee80211_vht.c | 137 +++++++++++++++++++++++++++++++++++++++++++
 sys/net80211/ieee80211_vht.h |   4 ++
 2 files changed, 141 insertions(+)

diff --git a/sys/net80211/ieee80211_vht.c b/sys/net80211/ieee80211_vht.c
index a05beb91216f..82879f90c67b 100644
--- a/sys/net80211/ieee80211_vht.c
+++ b/sys/net80211/ieee80211_vht.c
@@ -873,3 +873,140 @@ ieee80211_vht_get_vhtinfo_ie(struct ieee80211_node *ni,
 {
 	printf("%s: called; TODO!\n", __func__);
 }
+
+/*
+ * Return true if VHT rates can be used for the given node.
+ */
+bool
+ieee80211_vht_check_tx_vht(const struct ieee80211_node *ni)
+{
+	const struct ieee80211vap *vap;
+	const struct ieee80211_channel *bss_chan;
+
+	if (ni == NULL || ni->ni_chan == IEEE80211_CHAN_ANYC ||
+	    ni->ni_vap == NULL || ni->ni_vap->iv_bss == NULL)
+		return (false);
+
+	vap = ni->ni_vap;
+	bss_chan = vap->iv_bss->ni_chan;
+
+	if (bss_chan == IEEE80211_CHAN_ANYC)
+		return (false);
+
+	return (IEEE80211_IS_CHAN_VHT(ni->ni_chan));
+}
+
+/*
+ * Return true if VHT40 rates can be transmitted to the given node.
+ *
+ * This verifies that the BSS is VHT40 capable and the current
+ * node channel width is 40MHz.
+ */
+static bool
+ieee80211_vht_check_tx_vht40(const struct ieee80211_node *ni)
+{
+	struct ieee80211vap *vap;
+	struct ieee80211_channel *bss_chan;
+
+	if (!ieee80211_vht_check_tx_vht(ni))
+		return (false);
+
+	vap = ni->ni_vap;
+	bss_chan = vap->iv_bss->ni_chan;
+
+	return (IEEE80211_IS_CHAN_VHT40(bss_chan) &&
+	    IEEE80211_IS_CHAN_VHT40(ni->ni_chan) &&
+	    (ni->ni_chw == IEEE80211_STA_RX_BW_40));
+}
+
+/*
+ * Return true if VHT80 rates can be transmitted to the given node.
+ *
+ * This verifies that the BSS is VHT80 capable and the current
+ * node channel width is 80MHz.
+ */
+static bool
+ieee80211_vht_check_tx_vht80(const struct ieee80211_node *ni)
+{
+	struct ieee80211vap *vap;
+	struct ieee80211_channel *bss_chan;
+
+	if (!ieee80211_vht_check_tx_vht(ni))
+		return (false);
+
+	vap = ni->ni_vap;
+	bss_chan = vap->iv_bss->ni_chan;
+
+	return (IEEE80211_IS_CHAN_VHT80(bss_chan) &&
+	    IEEE80211_IS_CHAN_VHT80(ni->ni_chan) &&
+	    (ni->ni_chw == IEEE80211_STA_RX_BW_80));
+}
+
+/*
+ * Return true if VHT 160 rates can be transmitted to the given node.
+ *
+ * This verifies that the BSS is VHT80+80 or VHT160 capable and the current
+ * node channel width is 80+80MHz or 160MHz.
+ */
+static bool
+ieee80211_vht_check_tx_vht160(const struct ieee80211_node *ni)
+{
+	struct ieee80211vap *vap;
+	struct ieee80211_channel *bss_chan;
+
+	if (!ieee80211_vht_check_tx_vht(ni))
+		return (false);
+
+	vap = ni->ni_vap;
+	bss_chan = vap->iv_bss->ni_chan;
+
+	if (ni->ni_chw != IEEE80211_STA_RX_BW_160)
+		return (false);
+
+	if (IEEE80211_IS_CHAN_VHT160(bss_chan) &&
+	    IEEE80211_IS_CHAN_VHT160(ni->ni_chan))
+		return (true);
+
+	if (IEEE80211_IS_CHAN_VHT80P80(bss_chan) &&
+	    IEEE80211_IS_CHAN_VHT80P80(ni->ni_chan))
+		return (true);
+
+	return (false);
+}
+
+/**
+ * @brief Check if the given transmit bandwidth is available to the given node
+ *
+ * This checks that the node and BSS both allow the given bandwidth,
+ * and that the current node bandwidth (which can dynamically change)
+ * also allows said bandwidth.
+ *
+ * This relies on the channels having the flags for the narrower
+ * channels as well - eg a VHT160 channel will have the CHAN_VHT80,
+ * CHAN_VHT40, CHAN_VHT flags also set.
+ *
+ * @param ni		the ieee80211_node to check
+ * @param bw		the required bandwidth to check
+ *
+ * @returns true if it is allowed, false otherwise
+ */
+bool
+ieee80211_vht_check_tx_bw(const struct ieee80211_node *ni,
+    enum ieee80211_sta_rx_bw bw)
+{
+
+	switch (bw) {
+	case IEEE80211_STA_RX_BW_20:
+		return (ieee80211_vht_check_tx_vht(ni));
+	case IEEE80211_STA_RX_BW_40:
+		return (ieee80211_vht_check_tx_vht40(ni));
+	case IEEE80211_STA_RX_BW_80:
+		return (ieee80211_vht_check_tx_vht80(ni));
+	case IEEE80211_STA_RX_BW_160:
+		return (ieee80211_vht_check_tx_vht160(ni));
+	case IEEE80211_STA_RX_BW_320:
+		return (false);
+	default:
+		return (false);
+	}
+}
diff --git a/sys/net80211/ieee80211_vht.h b/sys/net80211/ieee80211_vht.h
index f2d1706ea0f2..bcb61020c5a1 100644
--- a/sys/net80211/ieee80211_vht.h
+++ b/sys/net80211/ieee80211_vht.h
@@ -65,4 +65,8 @@ void	ieee80211_vht_get_vhtcap_ie(struct ieee80211_node *ni,
 void	ieee80211_vht_get_vhtinfo_ie(struct ieee80211_node *ni,
 	    struct ieee80211_vht_operation *, int);
 
+bool	ieee80211_vht_check_tx_vht(const struct ieee80211_node *);
+bool	ieee80211_vht_check_tx_bw(const struct ieee80211_node *,
+	    enum ieee80211_sta_rx_bw);
+
 #endif	/* _NET80211_IEEE80211_VHT_H_ */