[PATCH 5/8] AP: Support SPP A-MSDU negotiation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Daniel Gabay <daniel.gabay@xxxxxxxxx>

Implement SPP (Signaling and Payload Protected) A-MSDU negotiation.
AP advertise support in beacon/probe response RSNXE whenever:
 - The driver supports SPP A-MSDU.
 - Advertising CCMP/GCMP ciphers in RSN element.
 - The spp_amsdu conf option is not explicitly disabled (if the above
   is true, it is enabled by default).

Indicate to the driver to enable SPP A-MSDU when associating station
advertised SPP A-MSDU support in association request RSNXE.

Signed-off-by: Daniel Gabay <daniel.gabay@xxxxxxxxx>
---
 src/ap/ap_drv_ops.c        |  2 ++
 src/ap/drv_callbacks.c     |  5 +++++
 src/ap/ieee802_11.c        |  5 +++++
 src/ap/ieee802_11_shared.c |  3 +++
 src/ap/sta_info.c          |  5 +++--
 src/ap/sta_info.h          |  1 +
 src/ap/wpa_auth.h          |  3 +++
 src/ap/wpa_auth_glue.c     |  3 +++
 src/ap/wpa_auth_i.h        |  1 +
 src/ap/wpa_auth_ie.c       | 15 +++++++++++++++
 10 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 65e83f468b..8e9c41e41d 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -39,6 +39,8 @@ u32 hostapd_sta_flags_to_drv(u32 flags)
 		res |= WPA_STA_AUTHENTICATED;
 	if (flags & WLAN_STA_ASSOC)
 		res |= WPA_STA_ASSOCIATED;
+	if (flags & WLAN_STA_SPP_AMSDU)
+		res |= WPA_STA_SPP_AMSDU;
 	return res;
 }
 
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index d660beefcf..7234a3b478 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -649,6 +649,11 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
 		else
 			sta->flags &= ~WLAN_STA_MFP;
 
+		if (wpa_auth_uses_spp_amsdu(sta->wpa_sm))
+			sta->flags |= WLAN_STA_SPP_AMSDU;
+		else
+			sta->flags &= ~WLAN_STA_SPP_AMSDU;
+
 #ifdef CONFIG_IEEE80211R_AP
 		if (sta->auth_alg == WLAN_AUTH_FT) {
 			status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index a9ed6eb0fa..73e92e408c 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -4222,6 +4222,11 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
 		else
 			sta->flags &= ~WLAN_STA_MFP;
 
+		if (wpa_auth_uses_spp_amsdu(sta->wpa_sm))
+			sta->flags |= WLAN_STA_SPP_AMSDU;
+		else
+			sta->flags &= ~WLAN_STA_SPP_AMSDU;
+
 #ifdef CONFIG_IEEE80211R_AP
 		if (sta->auth_alg == WLAN_AUTH_FT) {
 			if (!reassoc) {
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 5e67216de6..32bdd49742 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -1136,6 +1136,9 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
 	if (hapd->conf->ssid_protection)
 		capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
+	if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU &&
+	    hapd->conf->spp_amsdu)
+		capab |= BIT(WLAN_RSNX_CAPAB_SPP_A_MSDU);
 
 	if (!capab)
 		return eid; /* no supported extended RSN capabilities */
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 5a7677905d..4023b75708 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -1766,7 +1766,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
 
 	buf[0] = '\0';
 	res = os_snprintf(buf, buflen,
-			  "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+			  "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
 			  (flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
 			  (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
 			  (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
@@ -1790,7 +1790,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
 			  (flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""),
 			  (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
 			  (flags & WLAN_STA_WNM_SLEEP_MODE ?
-			   "[WNM_SLEEP_MODE]" : ""));
+			   "[WNM_SLEEP_MODE]" : ""),
+			  (flags & WLAN_STA_SPP_AMSDU ? "[SPP-A-MSDU]" : ""));
 	if (os_snprintf_error(buflen, res))
 		res = -1;
 
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index d22e86d451..0bcb1d17f9 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -22,6 +22,7 @@
 /* STA flags */
 #define WLAN_STA_AUTH BIT(0)
 #define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_SPP_AMSDU BIT(2)
 #define WLAN_STA_AUTHORIZED BIT(5)
 #define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
 #define WLAN_STA_SHORT_PREAMBLE BIT(7)
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 9514e55b7f..7354314b81 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -319,6 +319,8 @@ struct wpa_auth_config {
 	bool ssid_protection;
 
 	int rsn_override_omit_rsnxe;
+
+	bool spp_amsdu;
 };
 
 typedef enum {
@@ -459,6 +461,7 @@ int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
 		      struct wpa_state_machine *sm,
 		      const u8 *osen_ie, size_t osen_ie_len);
 int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
+int wpa_auth_uses_spp_amsdu(struct wpa_state_machine *sm);
 void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv);
 int wpa_auth_uses_ocv(struct wpa_state_machine *sm);
 struct wpa_state_machine *
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 9fa9f19b7b..6b66f38188 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -277,6 +277,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
 		conf->no_disconnect_on_group_keyerror;
 
 	wconf->rsn_override_omit_rsnxe = conf->rsn_override_omit_rsnxe;
+	wconf->spp_amsdu = conf->spp_amsdu;
 }
 
 
@@ -1755,6 +1756,8 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
 	_conf.prot_range_neg =
 		!!(hapd->iface->drv_flags2 &
 		   WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP);
+	_conf.spp_amsdu = hapd->conf->spp_amsdu &&
+			  hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU;
 
 #ifdef CONFIG_IEEE80211BE
 	_conf.mld_addr = NULL;
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index cb902e42b9..188f51eb84 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -97,6 +97,7 @@ struct wpa_state_machine {
 #endif /* CONFIG_IEEE80211R_AP */
 	unsigned int is_wnmsleep:1;
 	unsigned int pmkid_set:1;
+	unsigned int spp_amsdu:1;
 
 	unsigned int ptkstart_without_success;
 
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index ce7f90aff2..3e7a08421a 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -507,6 +507,8 @@ static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt)
 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
 	if (conf->ssid_protection)
 		capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
+	if (conf->spp_amsdu)
+		capab |= BIT(WLAN_RSNX_CAPAB_SPP_A_MSDU);
 
 	return capab;
 }
@@ -1169,6 +1171,14 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 		    return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
 	}
 
+	if (wpa_auth->conf.spp_amsdu &&
+	    ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SPP_A_MSDU) &&
+	    (ciphers & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
+			WPA_CIPHER_GCMP_256 | WPA_CIPHER_GCMP)))
+		sm->spp_amsdu = 1;
+	else
+		sm->spp_amsdu = 0;
+
 #ifdef CONFIG_IEEE80211R_AP
 	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
 		if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
@@ -1412,6 +1422,11 @@ int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
 }
 
 
+int wpa_auth_uses_spp_amsdu(struct wpa_state_machine *sm)
+{
+	return sm ? sm->spp_amsdu : 0;
+}
+
 #ifdef CONFIG_OCV
 
 void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv)
-- 
2.43.0


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux