diff mbox series

[3/3] mesh: add support for HE mode

Message ID 20190614144921.13069-4-sven@narfation.org
State Accepted
Headers show
Series HE: add support for mesh mode | expand

Commit Message

Sven Eckelmann June 14, 2019, 2:49 p.m. UTC
From: Sven Eckelmann <seckelmann@datto.com>

Mesh points can partially support HE features (when requiring no
controlling STA/AP) as long as hardware supports it. The kernel just
requires support for HE mesh and wpa_supplicant can forward the peer
capabilities to the kernel for further processing.

Signed-off-by: Sven Eckelmann <seckelmann@datto.com>
---
 src/drivers/driver.h              |  3 ++-
 wpa_supplicant/ap.c               |  6 ++++++
 wpa_supplicant/mesh.c             |  3 +++
 wpa_supplicant/mesh_mpm.c         | 32 +++++++++++++++++++++++++++++++
 wpa_supplicant/wpa_supplicant.c   |  9 +++++++--
 wpa_supplicant/wpa_supplicant_i.h | 20 +++++++++++++++++++
 6 files changed, 70 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 6a9dfefc9..ce5da5863 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -185,6 +185,7 @@  struct hostapd_channel_data {
 #define HE_MAX_MAC_CAPAB_SIZE	6
 #define HE_MAX_PHY_CAPAB_SIZE	11
 #define HE_MAX_MCS_CAPAB_SIZE	12
+#define HE_MAX_PPET_CAPAB_SIZE	25
 
 /**
  * struct he_capabilities - IEEE 802.11ax HE capabilities
@@ -194,7 +195,7 @@  struct he_capabilities {
 	u8 phy_cap[HE_MAX_PHY_CAPAB_SIZE];
 	u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE];
 	u8 mcs[HE_MAX_MCS_CAPAB_SIZE];
-	u8 ppet[25];
+	u8 ppet[HE_MAX_PPET_CAPAB_SIZE];
 };
 
 #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index eea5b4e59..f58176a46 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -137,6 +137,8 @@  int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
 			      struct wpa_ssid *ssid,
 			      struct hostapd_config *conf)
 {
+	int ieee80211_mode = wpas_mode_to_iee80211_mode(ssid->mode);
+
 	conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
 					       &conf->channel);
 
@@ -239,6 +241,10 @@  int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
 				conf->vht_capab |= mode->vht_capab;
 				wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
 			}
+
+			if (mode->he_capab[ieee80211_mode].he_supported &&
+			    ssid->he)
+				conf->ieee80211ax = 1;
 		}
 	}
 
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 1068a5598..7354c1b79 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -456,6 +456,7 @@  int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 	ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
 	wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
 	wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
+	wpa_s->mesh_he_enabled = !!params->freq.he_enabled;
 	if (params->freq.ht_enabled && params->freq.sec_channel_offset)
 		ssid->ht40 = params->freq.sec_channel_offset;
 
@@ -480,6 +481,8 @@  int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 			break;
 		}
 	}
+	if (wpa_s->mesh_he_enabled)
+		ssid->he = 1;
 	if (ssid->beacon_int > 0)
 		params->beacon_int = ssid->beacon_int;
 	else if (wpa_s->conf->beacon_int > 0)
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 9d6ab8da1..4a163b6eb 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -245,6 +245,16 @@  static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
 			   2 + 5;  /* VHT Operation */
 	}
 #endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_IEEE80211AX
+	if (type != PLINK_CLOSE && wpa_s->mesh_he_enabled) {
+		buf_len += 3 +
+			   HE_MAX_MAC_CAPAB_SIZE +
+			   HE_MAX_PHY_CAPAB_SIZE +
+			   HE_MAX_MCS_CAPAB_SIZE +
+			   HE_MAX_PPET_CAPAB_SIZE;
+		buf_len += 3 + sizeof(struct ieee80211_he_operation);
+	}
+#endif /* CONFIG_IEEE80211AX */
 	if (type != PLINK_CLOSE)
 		buf_len += conf->rsn_ie_len; /* RSN IE */
 #ifdef CONFIG_OCV
@@ -362,6 +372,21 @@  static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
 		wpabuf_put_data(buf, vht_capa_oper, pos - vht_capa_oper);
 	}
 #endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_IEEE80211AX
+	if (type != PLINK_CLOSE && wpa_s->mesh_he_enabled) {
+		u8 he_capa_oper[3 +
+				HE_MAX_MAC_CAPAB_SIZE +
+				HE_MAX_PHY_CAPAB_SIZE +
+				HE_MAX_MCS_CAPAB_SIZE +
+				HE_MAX_PPET_CAPAB_SIZE +
+				3 + sizeof(struct ieee80211_he_operation)];
+
+		pos = hostapd_eid_he_capab(bss, he_capa_oper,
+					   IEEE80211_MODE_MESH);
+		pos = hostapd_eid_he_operation(bss, pos);
+		wpabuf_put_data(buf, he_capa_oper, pos - he_capa_oper);
+	}
+#endif /* CONFIG_IEEE80211AX */
 
 #ifdef CONFIG_OCV
 	if (type != PLINK_CLOSE && conf->ocv) {
@@ -725,6 +750,11 @@  static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
 	set_sta_vht_opmode(data, sta, elems->vht_opmode_notif);
 #endif /* CONFIG_IEEE80211AC */
 
+#ifdef CONFIG_IEEE80211AX
+	copy_sta_he_capab(data, sta, IEEE80211_MODE_MESH,
+			  elems->he_capabilities, elems->he_capabilities_len);
+#endif /* CONFIG_IEEE80211AX */
+
 	if (hostapd_get_aid(data, sta) < 0) {
 		wpa_msg(wpa_s, MSG_ERROR, "No AIDs available");
 		ap_free_sta(data, sta);
@@ -742,6 +772,8 @@  static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
 	params.listen_interval = 100;
 	params.ht_capabilities = sta->ht_capabilities;
 	params.vht_capabilities = sta->vht_capabilities;
+	params.he_capab = sta->he_capab;
+	params.he_capab_len = sta->he_capab_len;
 	params.flags |= WPA_STA_WMM;
 	params.flags_mask |= WPA_STA_AUTHENTICATED;
 	if (conf->security == MESH_CONF_SEC_NONE) {
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 97ea7a721..de71764f6 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2139,6 +2139,7 @@  void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
 			  const struct wpa_ssid *ssid,
 			  struct hostapd_freq_params *freq)
 {
+	int ieee80211_mode = wpas_mode_to_iee80211_mode(ssid->mode);
 	enum hostapd_hw_mode hw_mode;
 	struct hostapd_hw_modes *mode = NULL;
 	int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
@@ -2202,6 +2203,9 @@  void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
 	if (!mode)
 		return;
 
+	/* HE can work without HT + VHT */
+	freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
+
 #ifdef CONFIG_HT_OVERRIDES
 	if (ssid->disable_ht) {
 		freq->ht_enabled = 0;
@@ -2408,9 +2412,10 @@  skip_ht40:
 
 	if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
 				    freq->channel, freq->ht_enabled,
-				    vht_freq.vht_enabled, 0,
+				    vht_freq.vht_enabled, freq->he_enabled,
 				    freq->sec_channel_offset,
-				    chwidth, seg0, seg1, vht_caps, NULL) != 0)
+				    chwidth, seg0, seg1, vht_caps,
+				    &mode->he_capab[ieee80211_mode]) != 0)
 		return;
 
 	*freq = vht_freq;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index b51390ba3..5a5739234 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -823,6 +823,7 @@  struct wpa_supplicant {
 	unsigned int mesh_if_created:1;
 	unsigned int mesh_ht_enabled:1;
 	unsigned int mesh_vht_enabled:1;
+	unsigned int mesh_he_enabled:1;
 	struct wpa_driver_mesh_join_params *mesh_params;
 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
 	/* struct external_pmksa_cache::list */
@@ -1464,6 +1465,25 @@  static inline int network_is_persistent_group(struct wpa_ssid *ssid)
 	return ssid->disabled == 2 && ssid->p2p_persistent_group;
 }
 
+
+static inline int wpas_mode_to_iee80211_mode(enum wpas_mode mode)
+{
+	switch (mode) {
+	default:
+	case WPAS_MODE_INFRA:
+		return IEEE80211_MODE_INFRA;
+	case WPAS_MODE_IBSS:
+		return IEEE80211_MODE_IBSS;
+	case WPAS_MODE_AP:
+	case WPAS_MODE_P2P_GO:
+	case WPAS_MODE_P2P_GROUP_FORMATION:
+		return IEEE80211_MODE_AP;
+	case WPAS_MODE_MESH:
+		return IEEE80211_MODE_MESH;
+	}
+}
+
+
 int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
 int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);