[PATCH wireless-next 10/18] wifi: mac80211: Define SMD BSS Transition context for transport
From: Pooventhiran G
Date: Mon Sep 07 2026 - 16:42:03 EST
IEEE P802.11bn/D2.0, Aug 2026, subclause 37.16.9, defines the context
data to be transported during SMD BSS Transition (ST) laid out in
subclause 37.16. The station's context data is attached to the ST
Preparation or Execution management frame using SKB extensions so that
userspace receives the context along with the relevant frame.
Define the context data - per-TID sequence numbers in downlink (DL) and
uplink (UL) directions, packet number in DL, per-TID packet numbers in
UL, and per-TID BlockAck session parameters in DL and UL, plus a
variable-length driver context - to be used by the driver to attach the
context to the frame SKB. Additionally, define a helper that attaches
the SMD context to the SKB extension so that the initialization
operations (container allocation, reference tracking, and context
linking) are properly handled.
Signed-off-by: Pooventhiran G <pooventhiran.g@xxxxxxxxxxxxxxxx>
---
include/linux/ieee80211-uhr.h | 86 +++++++++++++++++++++++++++++++++++++++++++
include/net/mac80211.h | 50 +++++++++++++++++++++++++
2 files changed, 136 insertions(+)
diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h
index c3f87d4c8bec..f904b1e65f10 100644
--- a/include/linux/ieee80211-uhr.h
+++ b/include/linux/ieee80211-uhr.h
@@ -649,6 +649,92 @@ struct ieee80211_uhr_mode_change_tuple {
u8 variable[];
} __packed;
+/*
+ * Context information carried in SMD BSS Transition (refer IEEE P802.11bn/D2.0,
+ * Aug 2026, subclause 37.16.9.
+ */
+#define IEEE80211_SMD_CTX_NUM_VALID_CTX 8
+
+#define IEEE80211_SMD_CTX_VALID_DL_SN 0
+#define IEEE80211_SMD_CTX_VALID_UL_SN 1
+#define IEEE80211_SMD_CTX_VALID_PN 2
+#define IEEE80211_SMD_CTX_VALID_BA_PARAMS 3
+/* Positions 4 to 7 are reserved */
+
+/*
+ * Data TIDs transported in the context, IEEE P802.11bn/D2.0, Aug 2026,
+ * subclause 9.4.2.364.
+ */
+#define IEEE80211_SMD_CTX_NUM_TIDS 8
+
+#define IEEE80211_SMD_CTX_MAX_PN_LEN 16
+
+/**
+ * struct ieee80211_smd_ctx_ba - BlockAck parameters for DL and UL
+ *
+ * @amsdu_supported: Peer's capability to support A-MSDU within A-MPDU.
+ * @ba_policy: BlockAck policy (0 = delayed BlockAck, 1 = immediate BlockAck)
+ * @buffer_size: Reorder buffer size from ADDBA Request (10-bit, max 1023)
+ * @timeout: BlockAck session timeout
+ * @ext_no_frag: ADDBA Extension fragmentation support
+ * @extfrag_level: ADDBA Extension HE fragmentation level
+ * @ext_buffer_size: ADDBA Extension buffer size; combined with @buffer_size as
+ * (@ext_buffer_size << 10 | @buffer_size) to get the full reorder
+ * buffer size
+ */
+struct ieee80211_smd_ctx_ba {
+ bool amsdu_supported;
+ u8 ba_policy;
+ u16 buffer_size;
+ u16 timeout;
+ bool ext_no_frag;
+ u8 extfrag_level;
+ u16 ext_buffer_size;
+};
+
+/**
+ * struct ieee80211_smd_ctx - IEEE 802.11bn SMD Roaming Context (refer
+ * IEEE P802.11bn/D2.0, Aug 2026, subclause 37.16.9)
+ *
+ * @valid_ctx_bmap: Bitmap indicating which context fields are valid;
+ * bit positions defined by IEEE80211_SMD_CTX_VALID_* constants
+ * @pn_len: Length of PN in bytes; varies by cipher type
+ * (e.g. CCMP (6), GCMP-256 (16))
+ * @dl: Down-link context data
+ * @dl.valid_tid_bmap: valid DL TIDs for which context is present
+ * @dl.sn: DL SN per-TID to be assigned next
+ * @dl.pn: DL PN to be assigned next
+ * @dl.ba: DL BlockAck parameters per-TID for the BlockAck session
+ * @ul: Up-link context data
+ * @ul.valid_tid_bmap: valid UL TIDs for which context is present
+ * @ul.sn: UL SN per-TID to be checked next
+ * @ul.pn: UL PN per-TID to be checked next
+ * @ul.ba: UL BlockAck parameters per-TID for the BlockAck session
+ * @drv_ctx_size: Number of valid bytes in @drv_ctx.
+ * @drv_ctx: Variable-sized array of driver-specific context, counted by
+ * @drv_ctx_size. Opaque to the wireless core; interpreted by the drivers.
+ */
+struct ieee80211_smd_ctx {
+ DECLARE_BITMAP(valid_ctx_bmap, IEEE80211_SMD_CTX_NUM_VALID_CTX);
+ u8 pn_len;
+
+ struct {
+ DECLARE_BITMAP(valid_tid_bmap, IEEE80211_SMD_CTX_NUM_TIDS);
+ u16 sn[IEEE80211_SMD_CTX_NUM_TIDS];
+ u8 pn[IEEE80211_SMD_CTX_MAX_PN_LEN];
+ struct ieee80211_smd_ctx_ba ba[IEEE80211_SMD_CTX_NUM_TIDS];
+ } dl;
+ struct {
+ DECLARE_BITMAP(valid_tid_bmap, IEEE80211_SMD_CTX_NUM_TIDS);
+ u16 sn[IEEE80211_SMD_CTX_NUM_TIDS];
+ u8 pn[IEEE80211_SMD_CTX_NUM_TIDS][IEEE80211_SMD_CTX_MAX_PN_LEN];
+ struct ieee80211_smd_ctx_ba ba[IEEE80211_SMD_CTX_NUM_TIDS];
+ } ul;
+
+ size_t drv_ctx_size;
+ u8 drv_ctx[] ____cacheline_aligned __counted_by(drv_ctx_size);
+};
+
static inline int
ieee80211_uhr_mode_change_tuple_size(const struct ieee80211_uhr_mode_change_tuple *tuple)
{
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 32b9b7cd1685..b4b1d3db9b19 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
+#include <linux/skbuff_wireless.h>
#include <linux/ieee80211.h>
#include <linux/lockdep.h>
#include <net/cfg80211.h>
@@ -8246,4 +8247,53 @@ bool ieee80211_vif_nan_started(struct ieee80211_vif *vif);
* Return: 0 if success and non-zero on error
*/
int ieee80211_encrypt_tx_skb(struct sk_buff *skb);
+
+/**
+ * ieee80211_skb_ext_add_uhr - attach or replace a UHR SMD context on
+ * SKB_EXT_WIRELESS
+ * @skb: the SKB to attach the extension to
+ * @ctx: the SMD context; must be a kmalloc-ed buffer by the caller
+ *
+ * Allocates a &struct wireless_skb_ext_smd_ctx container, sets @ctx to it with
+ * @refcnt initialized to 1, and attaches it to @skb on SKB_EXT_WIRELESS.
+ * If SKB_EXT_WIRELESS is already active, the existing @container is released
+ * before the new one is attached.
+ *
+ * Ownership of @ctx transfers to @container on success - the core will
+ * kfree() both when the last reference is released.
+ * Upon error, @ctx ownership is not transferred from the caller; old @container
+ * may get freed.
+ *
+ * Drivers must use this helper to attach SKB_EXT_WIRELESS extension to
+ * properly handle clone and COW copies.
+ *
+ * Returns 0 on success; -ENOMEM on allocation failure.
+ */
+static inline int ieee80211_skb_ext_add_uhr(struct sk_buff *skb,
+ struct ieee80211_smd_ctx *ctx)
+{
+ struct wireless_skb_ext_smd_ctx *container;
+ struct wireless_skb_ext *ext;
+
+ container = kzalloc_obj(*container, GFP_ATOMIC);
+ if (!container)
+ return -ENOMEM;
+
+ refcount_set(&container->refcnt, 1);
+ container->smd_ctx = ctx;
+
+ skb_ext_del(skb, SKB_EXT_WIRELESS);
+
+ ext = skb_ext_add(skb, SKB_EXT_WIRELESS);
+ if (!ext) {
+ kfree(container);
+ return -ENOMEM;
+ }
+
+ ext->uhr_smd_ctx = container;
+ ext->type = WIRELESS_SKB_EXT_UHR_SMD;
+
+ return 0;
+}
+
#endif /* MAC80211_H */
--
2.34.1