]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
mesh: Add support for HE mode
authorSven Eckelmann <seckelmann@datto.com>
Fri, 14 Jun 2019 14:49:21 +0000 (16:49 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 23 Jun 2019 15:03:51 +0000 (18:03 +0300)
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
wpa_supplicant/ap.c
wpa_supplicant/mesh.c
wpa_supplicant/mesh_mpm.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index ee11387e9bfea163fd25bb26eceb5e8dba4c64d8..8a5cdb8e95a87d1dfc2affb7b394b6993949de05 100644 (file)
@@ -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)
index eea5b4e599dadd3ce7246c43f0d592af9ded1f25..4e3c2814d0f3273416a67256b9543a0752233dc4 100644 (file)
@@ -239,6 +239,11 @@ 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[wpas_mode_to_ieee80211_mode(
+                                           ssid->mode)].he_supported &&
+                           ssid->he)
+                               conf->ieee80211ax = 1;
                }
        }
 
index 1068a559885270060a189c9be5e49a3cd0657d8e..7354c1b791612f103f00bad346fd5abf38a0aaa7 100644 (file)
@@ -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)
index 9d6ab8da1ebeb000cd6dcca333afb86efe9be527..4a163b6eb6d80e42c14b5a4ea425c6fe3175e85d 100644 (file)
@@ -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) {
index 1e11234741e7388c47597e5c828a2cb2f4cca1ca..be45f2e38fdb1202edfff81669e72e2ec1a728d8 100644 (file)
@@ -2140,6 +2140,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_ieee80211_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,
@@ -2203,6 +2204,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;
@@ -2409,9 +2413,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;
index b51390ba3b2488e3fb7b1a30d717e4be3f8a0bd6..204cf60f311611f16615b8e29cb5b0dc2857a162 100644 (file)
@@ -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_ieee80211_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);