Implement SPP (Signaling and Payload Protected) A-MSDU negotiation.
Station advertise support in the RSNXE in the (Re)Association Request
frame whenever:
- The driver supports SPP A-MSDU.
- AP advertises SPP A-MSDU support in the RSNXE.
- CCMP/GCMP cipher is used as the pairwise cipher in the connection.
Indicate to the driver to enable SPP A-MSDU in association parameters
when AP also advertised support in its RSNXE.
Signed-off-by: Daniel Gabay <daniel.gabay@intel.com>
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;
}
+bool wpa_sm_uses_spp_amsdu(struct wpa_sm *sm)
+{
+ return sm ? sm->spp_amsdu : false;
+}
+
+
struct rsn_pmksa_cache * wpa_sm_get_pmksa_cache(struct wpa_sm *sm)
{
return sm ? sm->pmksa : NULL;
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 {
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);
+bool wpa_sm_uses_spp_amsdu(struct wpa_sm *sm);
#else /* CONFIG_NO_WPA */
{
}
+static inline bool wpa_sm_uses_spp_amsdu(struct wpa_sm *sm)
+{
+ return false;
+}
+
#endif /* CONFIG_NO_WPA */
#ifdef CONFIG_IEEE80211R
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;
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 */
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;
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) &&
+ ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SPP_A_MSDU))
+ 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);
}
}
+ wpa_s->sme.spp_amsdu = wpa_sm_uses_spp_amsdu(wpa_s->wpa);
+
#ifdef CONFIG_P2P
if (wpa_s->global->p2p) {
u8 *pos;
#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;
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)) {
u8 sched_obss_scan;
u16 obss_scan_int;
u16 bss_max_idle_period;
+ bool spp_amsdu;
#ifdef CONFIG_SAE
struct sae_data sae;
struct wpabuf *sae_token;