@@ -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)
{
@@ -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
@@ -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;
@@ -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 */
@@ -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;
@@ -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);
@@ -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;
@@ -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)) {
@@ -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;