]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Enable multiple channel widths for P2P in 6 GHz band
authorSreeramya Soratkal <ssramya@codeaurora.org>
Thu, 22 Jul 2021 12:41:00 +0000 (18:11 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 2 Sep 2021 15:41:12 +0000 (18:41 +0300)
Enable support for P2P connection in 6 GHz with the channel width of 40
MHz, 80 MHz, and 160 MHz. The flag max_oper_chwidth is used to configure
the maximum channel width for P2P connection in 6 GHz with the commands
P2P_CONNECT, P2P_INVITE, and P2P_GROUP_ADD.

Signed-off-by: Sreeramya Soratkal <ssramya@codeaurora.org>
src/common/hw_features_common.c
src/common/ieee802_11_common.c
src/common/ieee802_11_defs.h
wpa_supplicant/ap.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/op_classes.c
wpa_supplicant/p2p_supplicant.c

index 8e7aa0b69ac2dbc12ae6cd9442d2ce2b5429c53b..8a897fddc9461007928cc571e10f49a2684cb9cf 100644 (file)
@@ -417,7 +417,16 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
        data->sec_channel_offset = sec_channel_offset;
        data->center_freq1 = freq + sec_channel_offset * 10;
        data->center_freq2 = 0;
-       data->bandwidth = sec_channel_offset ? 40 : 20;
+       if (oper_chwidth == CHANWIDTH_80MHZ)
+               data->bandwidth = 80;
+       else if (oper_chwidth == CHANWIDTH_160MHZ ||
+                oper_chwidth == CHANWIDTH_80P80MHZ)
+               data->bandwidth = 160;
+       else if (sec_channel_offset)
+               data->bandwidth = 40;
+       else
+               data->bandwidth = 20;
+
 
        hostapd_encode_edmg_chan(enable_edmg, edmg_channel, channel,
                                 &data->edmg);
@@ -441,9 +450,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
                                           "Segment 0 center frequency isn't set");
                                return -1;
                        }
-
-                       data->center_freq1 = data->freq;
-                       data->bandwidth = 20;
+                       if (!sec_channel_offset)
+                               data->center_freq1 = data->freq;
                } else {
                        int freq1, freq2 = 0;
                        int bw = center_idx_to_bw_6ghz(center_segment0);
index ef68abacd4354c7ea07628be57e7317654dee29c..b516956458ec0b67839f438dad7eae355382c3cb 100644 (file)
@@ -1895,9 +1895,9 @@ const struct oper_class_map global_op_class[] = {
        { HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
-       { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP },
-       { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP },
-       { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP },
+       { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
+       { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
+       { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
 
index 519a13b1d0647fd09f9b9b9fcd9005915b40ea17..2ed2d37b0e8ce4d163fda6fc393c1190764330b9 100644 (file)
@@ -1337,6 +1337,7 @@ struct ieee80211_ampe_ie {
 #define CHANWIDTH_4320MHZ      5
 #define CHANWIDTH_6480MHZ      6
 #define CHANWIDTH_8640MHZ      7
+#define CHANWIDTH_40MHZ_6GHZ   8
 
 #define HE_NSS_MAX_STREAMS                         8
 
index d3fb239c8a4c20361ea838d51d8ba7c7794d0825..415f08789fd3225cd1eeabc48b249d3fc55cecfe 100644 (file)
@@ -84,6 +84,11 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
        /* Use the maximum oper channel width if it's given. */
        if (ssid->max_oper_chwidth)
                hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
+       if (hostapd_get_oper_chwidth(conf))
+               ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+                                             hostapd_get_oper_chwidth(conf),
+                                             &conf->op_class,
+                                             &conf->channel);
 
        if (hostapd_get_oper_chwidth(conf) == CHANWIDTH_80P80MHZ) {
                ieee80211_freq_to_chan(ssid->vht_center_freq2,
@@ -191,19 +196,75 @@ wpa_supplicant_find_hw_mode(struct wpa_supplicant *wpa_s,
 }
 
 
+static int get_max_oper_chwidth_6ghz(int chwidth)
+{
+       switch (chwidth) {
+       case CHANWIDTH_USE_HT:
+               return 20;
+       case CHANWIDTH_40MHZ_6GHZ:
+               return 40;
+       case CHANWIDTH_80MHZ:
+               return 80;
+       case CHANWIDTH_80P80MHZ:
+       case CHANWIDTH_160MHZ:
+               return 160;
+       default:
+               return 0;
+       }
+}
+
+
+static void wpas_conf_ap_he_6ghz(struct wpa_supplicant *wpa_s,
+                                struct hostapd_hw_modes *mode,
+                                struct wpa_ssid *ssid,
+                                struct hostapd_config *conf)
+{
+       bool is_chanwidth_40_80, is_chanwidth_160;
+       int he_chanwidth;
+
+       he_chanwidth =
+               mode->he_capab[wpas_mode_to_ieee80211_mode(
+                       ssid->mode)].phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
+       is_chanwidth_40_80 = he_chanwidth &
+               HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
+       is_chanwidth_160 = he_chanwidth &
+               HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+
+       wpa_printf(MSG_DEBUG,
+                  "Enable HE support (p2p_group=%d he_chwidth_cap=%d)",
+                  ssid->p2p_group, he_chanwidth);
+
+       if (mode->he_capab[wpas_mode_to_ieee80211_mode(
+                           ssid->mode)].he_supported &&
+           ssid->he)
+               conf->ieee80211ax = 1;
+
+       if (is_chanwidth_40_80 && ssid->p2p_group &&
+           get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 40) {
+               conf->secondary_channel =
+                       wpas_p2p_get_sec_channel_offset_40mhz(
+                               wpa_s, mode, conf->channel);
+               wpa_printf(MSG_DEBUG,
+                          "Secondary channel offset %d for P2P group",
+                          conf->secondary_channel);
+               if (ssid->max_oper_chwidth == CHANWIDTH_40MHZ_6GHZ)
+                       ssid->max_oper_chwidth = CHANWIDTH_USE_HT;
+       }
+
+       if ((is_chanwidth_40_80 || is_chanwidth_160) && ssid->p2p_group &&
+           get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 80)
+               wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
+}
+
+
 int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
                              struct wpa_ssid *ssid,
                              struct hostapd_config *conf)
 {
        conf->hw_mode = ieee80211_freq_to_channel_ext(ssid->frequency, 0,
-                                                     ssid->max_oper_chwidth,
+                                                     CHANWIDTH_USE_HT,
                                                      &conf->op_class,
                                                      &conf->channel);
-       /* ssid->max_oper_chwidth is not valid in all cases, so fall back to the
-        * less specific mechanism, if needed, at least for now */
-       if (conf->hw_mode == NUM_HOSTAPD_MODES)
-               conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
-                                                      &conf->channel);
        if (conf->hw_mode == NUM_HOSTAPD_MODES) {
                wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
                           ssid->frequency);
@@ -256,7 +317,10 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
                        no_ht = 1;
                }
 
-               if (!no_ht && mode && mode->ht_capab) {
+               if (mode && is_6ghz_freq(ssid->frequency) &&
+                   conf->hw_mode == HOSTAPD_MODE_IEEE80211A) {
+                       wpas_conf_ap_he_6ghz(wpa_s, mode, ssid, conf);
+               } else if (!no_ht && mode && mode->ht_capab) {
                        wpa_printf(MSG_DEBUG,
                                   "Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)",
                                   ssid->p2p_group,
index 08b19a3a92d070d82e039809acb4671008a39b51..c4f54ae889027e87dba78c9a2425b7038c43be15 100644 (file)
@@ -6126,6 +6126,9 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
        if (max_oper_chwidth < 0)
                return -1;
 
+       if (allow_6ghz && chwidth == 40)
+               max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
+
        pos2 = os_strstr(pos, " ssid=");
        if (pos2) {
                char *end;
@@ -6779,6 +6782,9 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
 
        allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
 
+       if (allow_6ghz && chwidth == 40)
+               max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
+
        return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
                               max_oper_chwidth, pref_freq, he, edmg,
                               allow_6ghz);
@@ -6922,6 +6928,9 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
        if (max_oper_chwidth < 0)
                return -1;
 
+       if (allow_6ghz && chwidth == 40)
+               max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
+
        if (group_id >= 0)
                return p2p_ctrl_group_add_persistent(wpa_s, group_id,
                                                     freq, freq2, ht40, vht,
index a0ad0c2ff5725ef04892695560494a25b838c378..bd53c5ceceafe2eeccc6d53902ccae4f18237a77 100644 (file)
@@ -207,11 +207,15 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
                if (!(flag & HOSTAPD_CHAN_HT40MINUS))
                        return NOT_ALLOWED;
                res2 = allow_channel(mode, op_class, channel - 4, NULL);
-       } else if (bw == BW40PLUS ||
-                  (bw == BW40 && !(((channel - 1) / 4) % 2))) {
+       } else if (bw == BW40PLUS) {
                if (!(flag & HOSTAPD_CHAN_HT40PLUS))
                        return NOT_ALLOWED;
                res2 = allow_channel(mode, op_class, channel + 4, NULL);
+       } else if (is_6ghz_op_class(op_class) && bw == BW40) {
+               if (get_6ghz_sec_channel(channel) < 0)
+                       res2 = allow_channel(mode, op_class, channel - 4, NULL);
+               else
+                       res2 = allow_channel(mode, op_class, channel + 4, NULL);
        } else if (bw == BW80) {
                /*
                 * channel is a center channel and as such, not necessarily a
index 51d351a482797fbcd2c6f7a4b4da9ff3a501ce9d..8864d7a848b9b75c66a7fcc4df417b0f28bd614a 100644 (file)
@@ -164,6 +164,17 @@ wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
 static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx);
 
 
+static int wpas_get_6ghz_he_chwidth_capab(struct hostapd_hw_modes *mode)
+{
+       int he_capab = 0;
+
+       if (mode)
+               he_capab = mode->he_capab[WPAS_MODE_INFRA].phy_cap[
+                       HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
+       return he_capab;
+}
+
+
 /*
  * Get the number of concurrent channels that the HW can operate, but that are
  * currently not in use by any of the wpa_supplicant interfaces.
@@ -3652,15 +3663,20 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
                        return NOT_ALLOWED;
                if (res == NO_IR)
                        ret = NO_IR;
-
-               if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
-                       return NOT_ALLOWED;
-               if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
-                       return NOT_ALLOWED;
-               if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30))
-                       return NOT_ALLOWED;
-               if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
+               if (!is_6ghz) {
+                       if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
+                               return NOT_ALLOWED;
+                       if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
+                               return NOT_ALLOWED;
+                       if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30))
+                               return NOT_ALLOWED;
+                       if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
+                               return NOT_ALLOWED;
+               } else if (is_6ghz &&
+                          (!(wpas_get_6ghz_he_chwidth_capab(mode) &
+                             HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))) {
                        return NOT_ALLOWED;
+               }
        }
 
        return ret;
@@ -3729,22 +3745,28 @@ static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
                if (res == NO_IR)
                        ret = NO_IR;
 
-               if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
-                       return NOT_ALLOWED;
-               if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
-                       return NOT_ALLOWED;
-               if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110))
-                       return NOT_ALLOWED;
-               if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90))
-                       return NOT_ALLOWED;
-               if (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70))
-                       return NOT_ALLOWED;
-               if (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50))
-                       return NOT_ALLOWED;
-               if (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30))
-                       return NOT_ALLOWED;
-               if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
+               if (!is_6ghz_op_class(op_class)) {
+                       if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
+                               return NOT_ALLOWED;
+                       if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
+                               return NOT_ALLOWED;
+                       if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110))
+                               return NOT_ALLOWED;
+                       if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90))
+                               return NOT_ALLOWED;
+                       if (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70))
+                               return NOT_ALLOWED;
+                       if (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50))
+                               return NOT_ALLOWED;
+                       if (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30))
+                               return NOT_ALLOWED;
+                       if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
+                               return NOT_ALLOWED;
+               } else if (is_6ghz_op_class(op_class) &&
+                          (!(wpas_get_6ghz_he_chwidth_capab(mode) &
+                             HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G))) {
                        return NOT_ALLOWED;
+               }
        }
 
        return ret;
@@ -3783,6 +3805,15 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
                        return NOT_ALLOWED;
                res2 = has_channel(wpa_s->global, mode, op_class, channel + 4,
                                   NULL);
+       } else if (is_6ghz_op_class(op_class) && bw == BW40) {
+               if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+                       return NOT_ALLOWED;
+               if (get_6ghz_sec_channel(channel) < 0)
+                       res2 = has_channel(wpa_s->global, mode, op_class,
+                                          channel - 4, NULL);
+               else
+                       res2 = has_channel(wpa_s->global, mode, op_class,
+                                          channel + 4, NULL);
        } else if (bw == BW80) {
                res2 = wpas_p2p_verify_80mhz(wpa_s, mode, op_class, channel,
                                             bw);