[PATCH wireless-next v3 06/21] wifi: ieee80211: define APIs for UHR Link Reconfiguration frame checks

From: Pooventhiran G

Date: Thu Nov 05 2026 - 15:02:02 EST


Add APIs necessary to check whether the frame is a UHR Link
Reconfiguration Request/Response/Notify frame and subtypes to invoke
necessary SMD BSS Transition handling on the AP MLD.

Signed-off-by: Pooventhiran G <pooventhiran.g@xxxxxxxxxxxxxxxx>
---
include/linux/ieee80211-uhr.h | 125 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 125 insertions(+)

diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h
index c6c89e4562f4..9274fa146f01 100644
--- a/include/linux/ieee80211-uhr.h
+++ b/include/linux/ieee80211-uhr.h
@@ -699,6 +699,131 @@ ieee80211_uhr_mode_change_tuple_next(const struct ieee80211_uhr_mode_change_tupl
return (const void *)((const u8 *)tuple + needed);
}

+/**
+ * ieee80211_is_uhr_link_reconf_req - check if frame is UHR Link Reconf Request
+ * @skb: the SKB to check
+ * Return: whether or not the frame is a UHR Link Reconf Request frame
+ */
+static inline bool ieee80211_is_uhr_link_reconf_req(struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 category, action;
+
+ if (!ieee80211_is_action(mgmt->frame_control))
+ return false;
+
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(uhr_link_reconf_req))
+ return false;
+
+ category = mgmt->u.action.category;
+ action = mgmt->u.action.action_code;
+
+ return category == WLAN_CATEGORY_PROTECTED_UHR &&
+ action == IEEE80211_PROTECTED_UHR_ACTION_LINK_RECONFIG_REQUEST;
+}
+
+/**
+ * ieee80211_is_uhr_link_reconf_resp - check if frame is UHR Link Reconf
+ * Response
+ * @skb: the SKB to check
+ * Return: whether or not the frame is a UHR Link Reconf Response frame
+ */
+static inline bool ieee80211_is_uhr_link_reconf_resp(struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 category, action;
+
+ if (!ieee80211_is_action(mgmt->frame_control))
+ return false;
+
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(uhr_link_reconf_resp))
+ return false;
+
+ category = mgmt->u.action.category;
+ action = mgmt->u.action.action_code;
+
+ return category == WLAN_CATEGORY_PROTECTED_UHR &&
+ action == IEEE80211_PROTECTED_UHR_ACTION_LINK_RECONFIG_RESPONSE;
+}
+
+/**
+ * ieee80211_is_st_prep_req - check if frame is ST Preparation Request
+ * @skb: the SKB to check
+ * Return: whether or not the frame is an ST Prep request frame
+ */
+static inline bool ieee80211_is_st_prep_req(struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 type;
+
+ if (!ieee80211_is_uhr_link_reconf_req(skb))
+ return false;
+
+ type = mgmt->u.action.uhr_link_reconf_req.type;
+
+ return type == IEEE80211_UHR_LINK_RECONFIG_REQUEST_ST_PREP;
+}
+
+/**
+ * ieee80211_is_st_exec_req - check if frame is ST Execution Request
+ * @skb: the SKB to check
+ * Return: whether or not the frame is an ST Exec request frame
+ */
+static inline bool ieee80211_is_st_exec_req(struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 type;
+
+ if (!ieee80211_is_uhr_link_reconf_req(skb))
+ return false;
+
+ type = mgmt->u.action.uhr_link_reconf_req.type;
+
+ return type == IEEE80211_UHR_LINK_RECONFIG_REQUEST_ST_EXEC;
+}
+
+/**
+ * ieee80211_is_st_exec_resp - check if frame is ST Execution Response
+ * @skb: the SKB to check
+ * Return: whether or not the frame is an ST Exec response frame
+ */
+static inline bool ieee80211_is_st_exec_resp(struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 type;
+
+ if (!ieee80211_is_uhr_link_reconf_resp(skb))
+ return false;
+
+ type = mgmt->u.action.uhr_link_reconf_resp.type;
+
+ return type == IEEE80211_UHR_LINK_RECONFIG_REQUEST_ST_EXEC;
+}
+
+/**
+ * ieee80211_is_uhr_link_reconf_notify - check if frame is UHR Link Reconf
+ * Notify
+ * @skb: the SKB to check
+ * Return: whether or not the frame is a UHR Link Reconf Notify frame
+ */
+static inline bool ieee80211_is_uhr_link_reconf_notify(struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 category, action;
+
+ if (!ieee80211_is_action(mgmt->frame_control))
+ return false;
+
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE(uhr_link_reconf_notif))
+ return false;
+
+ category = mgmt->u.action.category;
+ action = mgmt->u.action.action_code;
+
+ return category == WLAN_CATEGORY_PROTECTED_UHR &&
+ action == IEEE80211_PROTECTED_UHR_ACTION_LINK_RECONFIG_NOTIFY;
+}
+
#define for_each_uhr_mode_change_tuple(data, len, tuple) \
for (tuple = (const void *)(data); \
ieee80211_uhr_mode_change_tuple_next( \

--
2.34.1