]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Add initial support for 6 GHz band
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Wed, 19 Jun 2019 12:49:11 +0000 (15:49 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 15 Oct 2019 12:39:22 +0000 (15:39 +0300)
Add support for new hardware mode for 6 GHz band. 6 GHz operation is
defined in IEEE P802.11ax/D4.3. 6 GHz band adds global operating classes
131-135 that define channels in frequency range from 5940 MHz to 7105
MHz.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
- Remove HOSTAPD_MODE_IEEE80211AX mode
- Replace check for HOSTAPD_MODE_IEEE80211AX with is_6ghz_freq()
- Move center_idx_to_bw_6ghz() to ieee802_11_common.c file

Signed-off-by: Vamsi Krishna <vamsin@codeaurora.org>
hostapd/hostapd.conf
src/common/hw_features_common.c
src/common/ieee802_11_common.c
src/common/ieee802_11_common.h

index b8a54457b0e7cf4eafbdaebbd9f742fe6d724933..4cbe45190a4951afb0a813870058626f24456a8f 100644 (file)
@@ -146,7 +146,8 @@ ssid=test
 # Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz),
 # g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used
 # with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this
-# needs to be set to hw_mode=a. When using ACS (see channel parameter), a
+# needs to be set to hw_mode=a. For IEEE 802.11ax (HE) on 6 GHz this needs
+# to be set to hw_mode=a. When using ACS (see channel parameter), a
 # special value "any" can be used to indicate that any support band can be used.
 # This special case is currently supported only with drivers with which
 # offloaded ACS is used.
@@ -805,6 +806,11 @@ wmm_ac_vo_acm=0
 #he_rts_threshold=0
 
 # HE operating channel information; see matching vht_* parameters for details.
+# On the 6 GHz band the center freq calculation starts from 5.940 GHz offset.
+# For example idx=3 would result in 5955 MHz center frequency. In addition,
+# he_oper_chwidth is ignored, and the channel width is derived from the
+# configured operating class or center frequency indexes (see
+# IEEE P802.11ax/D4.3 Annex E, Table E-4).
 #he_oper_chwidth
 #he_oper_centr_freq_seg0_idx
 #he_oper_centr_freq_seg1_idx
index 57f5e39811bb8310f5d3a9012b23983ed6bafd19..1ad8d7c3e921bd044ba77d6b509005bd6d7a3a3f 100644 (file)
@@ -385,6 +385,71 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
        hostapd_encode_edmg_chan(enable_edmg, edmg_channel, channel,
                                 &data->edmg);
 
+       if (is_6ghz_freq(freq)) {
+               if (!data->he_enabled) {
+                       wpa_printf(MSG_ERROR,
+                                  "Can't set 6 GHz mode - HE isn't enabled");
+                       return -1;
+               }
+
+               if (center_idx_to_bw_6ghz(channel) != 0) {
+                       wpa_printf(MSG_ERROR,
+                                  "Invalid control channel for 6 GHz band");
+                       return -1;
+               }
+
+               if (!center_segment0) {
+                       if (center_segment1) {
+                               wpa_printf(MSG_ERROR,
+                                          "Segment 0 center frequency isn't set");
+                               return -1;
+                       }
+
+                       data->center_freq1 = data->freq;
+                       data->bandwidth = 20;
+               } else {
+                       int freq1, freq2 = 0;
+                       int bw = center_idx_to_bw_6ghz(center_segment0);
+
+                       if (bw < 0) {
+                               wpa_printf(MSG_ERROR,
+                                          "Invalid center frequency index for 6 GHz");
+                               return -1;
+                       }
+
+                       freq1 = ieee80211_chan_to_freq(NULL, 131,
+                                                      center_segment0);
+                       if (freq1 < 0) {
+                               wpa_printf(MSG_ERROR,
+                                          "Invalid segment 0 center frequency for 6 GHz");
+                               return -1;
+                       }
+
+                       if (center_segment1) {
+                               if (center_idx_to_bw_6ghz(center_segment1) != 2 ||
+                                   bw != 2) {
+                                       wpa_printf(MSG_ERROR,
+                                                  "6 GHz 80+80 MHz configuration doesn't use valid 80 MHz channels");
+                                       return -1;
+                               }
+
+                               freq2 = ieee80211_chan_to_freq(NULL, 131,
+                                                              center_segment1);
+                               if (freq2 < 0) {
+                                       wpa_printf(MSG_ERROR,
+                                                  "Invalid segment 1 center frequency for UHB");
+                                       return -1;
+                               }
+                       }
+
+                       data->bandwidth = (1 << (u8) bw) * 20;
+                       data->center_freq1 = freq1;
+                       data->center_freq2 = freq2;
+               }
+
+               return 0;
+       }
+
        if (data->vht_enabled) switch (oper_chwidth) {
        case CHANWIDTH_USE_HT:
                if (center_segment1 ||
index 6bb5e4313be279c900f6b59a1274698a2cab41a5..f75ce1e30f2efc4e670a3464c2e6a1ee43c4bde9 100644 (file)
@@ -882,6 +882,19 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
                return HOSTAPD_MODE_IEEE80211AD;
        }
 
+       if (freq > 5940 && freq <= 7105) {
+               int bw;
+               u8 idx = (freq - 5940) / 5;
+
+               bw = center_idx_to_bw_6ghz(idx);
+               if (bw < 0)
+                       return NUM_HOSTAPD_MODES;
+
+               *channel = idx;
+               *op_class = 131 + bw;
+               return HOSTAPD_MODE_IEEE80211A;
+       }
+
        return NUM_HOSTAPD_MODES;
 }
 
@@ -1161,6 +1174,14 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
                if (chan < 36 || chan > 128)
                        return -1;
                return 5000 + 5 * chan;
+       case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
+       case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
+       case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
+       case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
+       case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
+               if (chan < 1 || chan > 233)
+                       return -1;
+               return 5940 + chan * 5;
        case 180: /* 60 GHz band, channels 1..6 */
                if (chan < 1 || chan > 6)
                        return -1;
@@ -1591,6 +1612,7 @@ const struct oper_class_map global_op_class[] = {
        { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
+       { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
        { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
 };
@@ -1905,6 +1927,37 @@ int oper_class_bw_to_int(const struct oper_class_map *map)
 }
 
 
+int center_idx_to_bw_6ghz(u8 idx)
+{
+       /* channels: 1, 5, 9, 13... */
+       if ((idx & 0x3) == 0x1)
+               return 0; /* 20 MHz */
+       /* channels 3, 11, 19... */
+       if ((idx & 0x7) == 0x3)
+               return 1; /* 40 MHz */
+       /* channels 7, 23, 39.. */
+       if ((idx & 0xf) == 0x7)
+               return 2; /* 80 MHz */
+       /* channels 15, 47, 79...*/
+       if ((idx & 0x1f) == 0xf)
+               return 3; /* 160 MHz */
+
+       return -1;
+}
+
+
+int is_6ghz_freq(int freq)
+{
+       if (freq < 5940 || freq > 7105)
+               return 0;
+
+       if (center_idx_to_bw_6ghz((freq - 5940) / 5) < 0)
+               return 0;
+
+       return 1;
+}
+
+
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
                                    size_t nei_rep_len)
 {
index 2452b82b96c7238bb27325e81b7c6f0ca01e53db..d8b6fa216fc36a8387dc664eb155e6a59fb6714e 100644 (file)
@@ -220,6 +220,8 @@ u8 country_to_global_op_class(const char *country, u8 op_class);
 
 const struct oper_class_map * get_oper_class(const char *country, u8 op_class);
 int oper_class_bw_to_int(const struct oper_class_map *map);
+int center_idx_to_bw_6ghz(u8 idx);
+int is_6ghz_freq(int freq);
 
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
                                    size_t nei_rep_len);