[PATCH 7/8] wpa_supplicant: Support SPP A-MSDUs negotiation

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Jan 7 04:51:48 PST 2025


From: Daniel Gabay <daniel.gabay at intel.com>

Implement SPP (Signaling and Payload Protected) A-MSDU negotiation.
Station advertise support in (Re)association RSNXE whenever:
 - The driver supports SPP A-MSDU.
 - AP advertises SPP A-MSDU support in the RSNXE.
 - Using CCMP/GCMP cipher in the connection.

Indicate to the driver to enable SPP A-MSDU in association params
when AP also advertised support in it's beacon/probe response RSNXE.

Signed-off-by: Daniel Gabay <daniel.gabay at intel.com>
---
 src/rsn_supp/wpa.c                |  7 +++++++
 src/rsn_supp/wpa.h                |  7 +++++++
 src/rsn_supp/wpa_i.h              |  1 +
 src/rsn_supp/wpa_ie.c             |  2 ++
 wpa_supplicant/ctrl_iface.c       |  2 ++
 wpa_supplicant/pasn_supplicant.c  |  3 +++
 wpa_supplicant/sme.c              |  3 +++
 wpa_supplicant/wpa_supplicant.c   | 10 ++++++++++
 wpa_supplicant/wpa_supplicant_i.h |  1 +
 9 files changed, 36 insertions(+)

diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 9e4b0b219e..ba576d2413 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -4953,6 +4953,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
 	case WPA_PARAM_USE_EXT_KEY_ID:
 		sm->use_ext_key_id = value;
 		break;
+	case WPA_PARAM_SPP_AMSDU:
+		sm->spp_amsdu = value;
+		break;
 #ifdef CONFIG_TESTING_OPTIONS
 	case WPA_PARAM_FT_RSNXE_USED:
 		sm->ft_rsnxe_used = value;
@@ -7183,6 +7186,10 @@ void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm)
 		pmksa_cache_reconfig(sm->pmksa);
 }
 
+int wpa_sm_uses_spp_amsdu(struct wpa_sm *sm)
+{
+	return sm ? sm->spp_amsdu : 0;
+}
 
 struct rsn_pmksa_cache * wpa_sm_get_pmksa_cache(struct wpa_sm *sm)
 {
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 9783feef2b..3f6d7e9648 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -140,6 +140,7 @@ enum wpa_sm_conf_params {
 	WPA_PARAM_RSN_OVERRIDE,
 	WPA_PARAM_RSN_OVERRIDE_SUPPORT,
 	WPA_PARAM_EAPOL_2_KEY_INFO_SET_MASK,
+	WPA_PARAM_SPP_AMSDU,
 };
 
 enum wpa_rsn_override {
@@ -279,6 +280,7 @@ void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm);
 int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo);
 void wpa_sm_set_driver_bss_selection(struct wpa_sm *sm,
 				     bool driver_bss_selection);
+int wpa_sm_uses_spp_amsdu(struct wpa_sm *sm);
 
 #else /* CONFIG_NO_WPA */
 
@@ -527,6 +529,11 @@ static inline void wpa_sm_set_driver_bss_selection(struct wpa_sm *sm,
 {
 }
 
+static inline int wpa_sm_uses_spp_amsdu(struct wpa_sm *sm)
+{
+	return 0;
+}
+
 #endif /* CONFIG_NO_WPA */
 
 #ifdef CONFIG_IEEE80211R
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 2fd08b0f23..b1b6729097 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -113,6 +113,7 @@ struct wpa_sm {
 	unsigned int secure_rtt:1;
 	unsigned int prot_range_neg:1;
 	unsigned int ssid_protection:1;
+	unsigned int spp_amsdu:1;
 
 	u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
 	size_t assoc_wpa_ie_len;
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 515f1b0275..d07f5b367f 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -394,6 +394,8 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
 	if (sm->ssid_protection)
 		capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
+	if (sm->spp_amsdu)
+		capab |= BIT(WLAN_RSNX_CAPAB_SPP_A_MSDU);
 
 	if (!capab)
 		return 0; /* no supported extended RSN capabilities */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 76012955be..7d5cd329cd 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -10504,6 +10504,8 @@ static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
 	params.key_mgmt_suite = wpa_s->key_mgmt;
 	params.wpa_proto = wpa_s->wpa_proto;
 	params.mgmt_frame_protection = wpa_s->sme.mfp;
+	params.spp_amsdu = wpa_s->sme.spp_amsdu;
+
 	params.rrm_used = wpa_s->rrm.rrm_used;
 	if (wpa_s->sme.prev_bssid_set)
 		params.prev_bssid = wpa_s->sme.prev_bssid;
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index a46fe46b1f..8f095e8afd 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -583,6 +583,9 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
 	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA)
 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
+	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU)
+		capab |= BIT(WLAN_RSNX_CAPAB_SPP_A_MSDU);
+
 	pasn_set_rsnxe_caps(pasn, capab);
 	pasn_register_callbacks(pasn, wpa_s, wpas_pasn_send_mlme, NULL);
 	ssid = wpa_config_get_network(wpa_s->conf, awork->network_id);
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 2b758939d3..b74664ecbd 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -854,6 +854,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
 		}
 	}
 
+	wpa_s->sme.spp_amsdu = wpa_sm_uses_spp_amsdu(wpa_s->wpa);
+
 #ifdef CONFIG_P2P
 	if (wpa_s->global->p2p) {
 		u8 *pos;
@@ -2660,6 +2662,7 @@ mscs_fail:
 #endif /* CONFIG_IEEE80211R */
 	params.mode = mode;
 	params.mgmt_frame_protection = wpa_s->sme.mfp;
+	params.spp_amsdu = wpa_s->sme.spp_amsdu;
 	params.rrm_used = wpa_s->rrm.rrm_used;
 	if (wpa_s->sme.prev_bssid_set)
 		params.prev_bssid = wpa_s->sme.prev_bssid;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 132d91598f..8f45a5c726 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2272,6 +2272,16 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SSID_PROTECTION, false);
 	}
 
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SPP_AMSDU,
+			 wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU &&
+			 ieee802_11_rsnx_capab(bss_rsnx,
+					       WLAN_RSNX_CAPAB_SPP_A_MSDU) &&
+			 wpa_s->pairwise_cipher & (WPA_CIPHER_CCMP_256 |
+						   WPA_CIPHER_GCMP_256 |
+						   WPA_CIPHER_CCMP |
+						   WPA_CIPHER_GCMP) &&
+			 wpa_s->wpa_proto & WPA_PROTO_RSN);
+
 	if (!skip_default_rsne) {
 		if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
 						    wpa_ie_len)) {
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 93592a1377..9d64f12e1b 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1035,6 +1035,7 @@ struct wpa_supplicant {
 		u8 sched_obss_scan;
 		u16 obss_scan_int;
 		u16 bss_max_idle_period;
+		unsigned int spp_amsdu:1;
 #ifdef CONFIG_SAE
 		struct sae_data sae;
 		struct wpabuf *sae_token;
-- 
2.43.0




More information about the Hostap mailing list