]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EHT: Add 320 channel width support
authorVeerendranath Jakkam <quic_vjakkam@quicinc.com>
Fri, 13 May 2022 16:17:41 +0000 (21:47 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 20 Jun 2022 11:39:26 +0000 (14:39 +0300)
Add initial changes to support 320 MHz channel width.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
16 files changed:
hostapd/ctrl_iface.c
src/ap/ap_config.h
src/ap/ap_drv_ops.c
src/ap/drv_callbacks.c
src/ap/hostapd.c
src/ap/hw_features.c
src/ap/ieee802_11_eht.c
src/ap/ieee802_11_he.c
src/common/defs.h
src/common/hw_features_common.c
src/common/ieee802_11_common.c
src/drivers/driver.h
src/drivers/driver_common.c
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211_event.c
wpa_supplicant/ctrl_iface.c

index 664c59df7c8a0c8f18f9e1aee7c968d81c6c75db..4e464da73870215822fa65114769528d83153ad2 100644 (file)
@@ -2527,6 +2527,9 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
        case 160:
                bandwidth = CHAN_WIDTH_160;
                break;
+       case 320:
+               bandwidth = CHAN_WIDTH_320;
+               break;
        default:
                bandwidth = CHAN_WIDTH_20;
                break;
index 876a1bbd9310b020d6c95e97d8b2c0c807dd85ee..9b9212feb7a48a5fa53abd2758044813bfff32af 100644 (file)
@@ -1163,6 +1163,8 @@ hostapd_set_oper_chwidth(struct hostapd_config *conf,
 #ifdef CONFIG_IEEE80211BE
        if (conf->ieee80211be)
                conf->eht_oper_chwidth = oper_chwidth;
+       if (oper_chwidth == CONF_OPER_CHWIDTH_320MHZ)
+               oper_chwidth = CONF_OPER_CHWIDTH_160MHZ;
 #endif /* CONFIG_IEEE80211BE */
 #ifdef CONFIG_IEEE80211AX
        if (conf->ieee80211ax)
@@ -1192,6 +1194,9 @@ hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf,
 #ifdef CONFIG_IEEE80211BE
        if (conf->ieee80211be)
                conf->eht_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
+       if (center_idx_to_bw_6ghz(oper_centr_freq_seg0_idx) == 4)
+               oper_centr_freq_seg0_idx +=
+                       conf->channel > oper_centr_freq_seg0_idx ? 16 : -16;
 #endif /* CONFIG_IEEE80211BE */
 #ifdef CONFIG_IEEE80211AX
        if (conf->ieee80211ax)
index a7079f6abfc44daa445415d6eed2b6654e95ce86..87c3b9006191f59742c070e078abec906f9e4efa 100644 (file)
@@ -986,6 +986,8 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
                else if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ ||
                         oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
                        params.ch_width = 160;
+               else if (oper_chwidth == CONF_OPER_CHWIDTH_320MHZ)
+                       params.ch_width = 320;
        }
 
        if (hapd->iface->conf->op_class)
index 4b321a9b929e889058e81e5f67ad0a6a9b4a5e73..a673fae09c93a0fc831b5e4458f179c43c861a85 100644 (file)
@@ -838,6 +838,9 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
        case CHAN_WIDTH_160:
                txt = "160";
                break;
+       case CHAN_WIDTH_320:
+               txt = "320";
+               break;
        default:
                txt = NULL;
                break;
@@ -899,6 +902,9 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
        case CHAN_WIDTH_160:
                chwidth = CONF_OPER_CHWIDTH_160MHZ;
                break;
+       case CHAN_WIDTH_320:
+               chwidth = CONF_OPER_CHWIDTH_320MHZ;
+               break;
        case CHAN_WIDTH_20_NOHT:
        case CHAN_WIDTH_20:
        case CHAN_WIDTH_40:
@@ -1173,6 +1179,15 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
                }
        }
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iface->conf->ieee80211be && acs_res->ch_width == 320) {
+               hostapd_set_oper_chwidth(hapd->iconf, CONF_OPER_CHWIDTH_320MHZ);
+               hostapd_set_oper_centr_freq_seg0_idx(
+                       hapd->iconf, acs_res->vht_seg1_center_ch);
+               hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
+       }
+#endif /* CONFIG_IEEE80211BE */
+
 out:
        ret = hostapd_acs_completed(hapd->iface, err);
        if (ret) {
index f6e45274b2b8ee06f4c3a17f3c9213deabedb508..05faa0f143d58b51cf01f4e1f50116783d805306 100644 (file)
@@ -3516,6 +3516,9 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
        case 160:
                hostapd_set_oper_chwidth(conf, CONF_OPER_CHWIDTH_160MHZ);
                break;
+       case 320:
+               hostapd_set_oper_chwidth(conf, CONF_OPER_CHWIDTH_320MHZ);
+               break;
        default:
                return -1;
        }
@@ -3715,6 +3718,9 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
        case 160:
                bw = CONF_OPER_CHWIDTH_160MHZ;
                break;
+       case 320:
+               bw = CONF_OPER_CHWIDTH_320MHZ;
+               break;
        default:
                wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
                           freq_params->bandwidth);
index cbd65921997026500d08e6f4d1f6bd1e32267124..ed5ff41d3b41e147a37befe10f502a798980284f 100644 (file)
@@ -1087,13 +1087,14 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
 
        if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G ||
             iface->conf->ieee80211n || iface->conf->ieee80211ac ||
-            iface->conf->ieee80211ax) &&
+            iface->conf->ieee80211ax || iface->conf->ieee80211be) &&
            iface->conf->channel == 14) {
-               wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE on channel 14");
+               wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE/EHT on channel 14");
                iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
                iface->conf->ieee80211n = 0;
                iface->conf->ieee80211ac = 0;
                iface->conf->ieee80211ax = 0;
+               iface->conf->ieee80211be = 0;
        }
 
        iface->current_mode = NULL;
index 547ccd3296f5f57b49e232bc6455318e093163cc..ec36a9e7ad3240297c80f040eeadc9121e9725f7 100644 (file)
@@ -197,9 +197,7 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
        seg0 = hostapd_get_oper_centr_freq_seg0_idx(conf);
 
        switch (chwidth) {
-#if 0 /* FIX: Need to clean up CHANWIDTH_* use for protocol vs. internal
-       * needs to be able to define this. */
-       case CHANWIDTH_320MHZ:
+       case CONF_OPER_CHWIDTH_320MHZ:
                oper->oper_info.control |= EHT_OPER_CHANNEL_WIDTH_320MHZ;
                seg1 = seg0;
                if (hapd->iconf->channel < seg0)
@@ -207,7 +205,6 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
                else
                        seg0 += 16;
                break;
-#endif
        case CONF_OPER_CHWIDTH_160MHZ:
                oper->oper_info.control |= EHT_OPER_CHANNEL_WIDTH_160MHZ;
                seg1 = seg0;
@@ -286,10 +283,12 @@ static bool check_valid_eht_mcs(struct hostapd_data *hapd,
                        EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY);
 
        switch (hapd->iface->conf->eht_oper_chwidth) {
-       /* TODO: CHANWIDTH_320MHZ */
+       case CONF_OPER_CHWIDTH_320MHZ:
+               mcs_count++;
+               /* fall through */
        case CONF_OPER_CHWIDTH_80P80MHZ:
        case CONF_OPER_CHWIDTH_160MHZ:
-               mcs_count = 2;
+               mcs_count++;
                break;
        default:
                break;
index e9be2d3ede989e04bddc25813c089debac1db0a4..b5b7e5d462a0b0bf6ce5dd8886514dc1a11acb3c 100644 (file)
@@ -219,7 +219,7 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
        pos += 6; /* skip the fixed part */
 
        if (is_6ghz_op_class(hapd->iconf->op_class)) {
-               u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
+               u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
                u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
                u8 control;
 
index ce748798823bd809027d012b55ea5b3ab21d4a3d..4e6305382a498550f9ba0d02f64400e0d5da6de1 100644 (file)
@@ -429,6 +429,7 @@ enum chan_width {
        CHAN_WIDTH_4320,
        CHAN_WIDTH_6480,
        CHAN_WIDTH_8640,
+       CHAN_WIDTH_320,
        CHAN_WIDTH_UNKNOWN
 };
 
@@ -445,6 +446,7 @@ enum oper_chan_width {
        CONF_OPER_CHWIDTH_6480MHZ,
        CONF_OPER_CHWIDTH_8640MHZ,
        CONF_OPER_CHWIDTH_40MHZ_6GHZ,
+       CONF_OPER_CHWIDTH_320MHZ,
 };
 
 enum key_flag {
index e2bf3afc6830583ef4455883305a39acb9452fce..6646301dfb1ded90bc1492e3dcacd1a4e5c24288 100644 (file)
@@ -392,6 +392,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
 {
        if (!he_cap || !he_cap->he_supported)
                he_enabled = 0;
+       if (!eht_cap || !eht_cap->eht_supported)
+               eht_enabled = 0;
        os_memset(data, 0, sizeof(*data));
        data->mode = mode;
        data->freq = freq;
@@ -408,6 +410,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
        else if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ ||
                 oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
                data->bandwidth = 160;
+       else if (oper_chwidth == CONF_OPER_CHWIDTH_320MHZ)
+               data->bandwidth = 320;
        else if (sec_channel_offset)
                data->bandwidth = 40;
        else
@@ -483,9 +487,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
                return 0;
        }
 
-#if 0 /* FIX: Figure out how to handle CHANWIDTH_320MHZ */
        if (data->eht_enabled) switch (oper_chwidth) {
-       case CHANWIDTH_320MHZ:
+       case CONF_OPER_CHWIDTH_320MHZ:
                if (!(eht_cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
                      EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)) {
                        wpa_printf(MSG_ERROR,
@@ -493,8 +496,9 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
                        return -1;
                }
                break;
+       default:
+               break;
        }
-#endif
 
        if (data->he_enabled || data->eht_enabled) switch (oper_chwidth) {
        case CONF_OPER_CHWIDTH_USE_HT:
@@ -673,6 +677,41 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
                        return -1;
                }
                break;
+       case CONF_OPER_CHWIDTH_320MHZ:
+               data->bandwidth = 320;
+               if (!data->eht_enabled || !is_6ghz_freq(freq)) {
+                       wpa_printf(MSG_ERROR,
+                                  "320 MHz: EHT not enabled or not a 6 GHz channel");
+                       return -1;
+               }
+               if (center_segment1) {
+                       wpa_printf(MSG_ERROR,
+                                  "320 MHz: center segment 1 should not be set");
+                       return -1;
+               }
+               if (center_segment0 == channel + 30 ||
+                   center_segment0 == channel + 26 ||
+                   center_segment0 == channel + 22 ||
+                   center_segment0 == channel + 18 ||
+                   center_segment0 == channel + 14 ||
+                   center_segment0 == channel + 10 ||
+                   center_segment0 == channel + 6 ||
+                   center_segment0 == channel + 2 ||
+                   center_segment0 == channel - 2 ||
+                   center_segment0 == channel - 6 ||
+                   center_segment0 == channel - 10 ||
+                   center_segment0 == channel - 14 ||
+                   center_segment0 == channel - 18 ||
+                   center_segment0 == channel - 22 ||
+                   center_segment0 == channel - 26 ||
+                   center_segment0 == channel - 30)
+                       data->center_freq1 = 5000 + center_segment0 * 5;
+               else {
+                       wpa_printf(MSG_ERROR,
+                                  "320 MHz: wrong center segment 0");
+                       return -1;
+               }
+               break;
        default:
                break;
        }
@@ -785,6 +824,7 @@ u32 num_chan_to_bw(int num_chans)
        case 2:
        case 4:
        case 8:
+       case 16:
                return num_chans * 20;
        default:
                return 20;
@@ -818,6 +858,9 @@ int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
        case 160:
                bw_mask = HOSTAPD_CHAN_WIDTH_160;
                break;
+       case 320:
+               bw_mask = HOSTAPD_CHAN_WIDTH_320;
+               break;
        default:
                bw_mask = 0;
                break;
index dfc035df781c09b9a3a01807e483e128f7f0c36d..c8ee90cd7c6f3138643d984fe4b145ec1a233d8e 100644 (file)
@@ -1060,6 +1060,9 @@ ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel,
                case CONF_OPER_CHWIDTH_80P80MHZ:
                        *op_class = 135;
                        break;
+               case CONF_OPER_CHWIDTH_320MHZ:
+                       *op_class = 137;
+                       break;
                default:
                        if (sec_channel)
                                *op_class = 132;
@@ -1157,6 +1160,9 @@ int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
        case CHAN_WIDTH_8640:
                cw = CONF_OPER_CHWIDTH_8640MHZ;
                break;
+       case CHAN_WIDTH_320:
+               cw = CONF_OPER_CHWIDTH_320MHZ;
+               break;
        }
 
        if (ieee80211_freq_to_channel_ext(freq, sec_channel, cw, op_class,
@@ -1452,6 +1458,7 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
        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.. */
+       case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
                if (chan < 1 || chan > 233)
                        return -1;
                return 5950 + chan * 5;
@@ -2265,6 +2272,9 @@ int center_idx_to_bw_6ghz(u8 idx)
        /* channels 15, 47, 79...*/
        if ((idx & 0x1f) == 0xf)
                return 3; /* 160 MHz */
+       /* channels 31, 63, 95, 127, 159, 191 */
+       if ((idx & 0x1f) == 0x1f && idx < 192)
+               return 4; /* 320 MHz */
 
        return -1;
 }
@@ -2287,7 +2297,7 @@ bool is_6ghz_freq(int freq)
 
 bool is_6ghz_op_class(u8 op_class)
 {
-       return op_class >= 131 && op_class <= 136;
+       return op_class >= 131 && op_class <= 137;
 }
 
 
@@ -2593,6 +2603,8 @@ int op_class_to_bandwidth(u8 op_class)
                return 160;
        case 136: /* UHB channels, 20 MHz: 2 */
                return 20;
+       case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
+               return 320;
        case 180: /* 60 GHz band, channels 1..8 */
                return 2160;
        case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
@@ -2655,6 +2667,8 @@ enum oper_chan_width op_class_to_ch_width(u8 op_class)
                return CONF_OPER_CHWIDTH_80P80MHZ;
        case 136: /* UHB channels, 20 MHz: 2 */
                return CONF_OPER_CHWIDTH_USE_HT;
+       case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
+               return CONF_OPER_CHWIDTH_320MHZ;
        case 180: /* 60 GHz band, channels 1..8 */
                return CONF_OPER_CHWIDTH_2160MHZ;
        case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
index f069b74e14c9dcc81190acfc5c70fce71dbbbe01..52ee8dfdd5f549e484697e464c3eee0a5b356a61 100644 (file)
@@ -66,6 +66,7 @@ enum hostapd_chan_width_attr {
        HOSTAPD_CHAN_WIDTH_40M  = BIT(3),
        HOSTAPD_CHAN_WIDTH_80   = BIT(4),
        HOSTAPD_CHAN_WIDTH_160  = BIT(5),
+       HOSTAPD_CHAN_WIDTH_320  = BIT(6),
 };
 
 /* Filter gratuitous ARP */
index 8db786168b832d4917900c724a27ea93737488ff..84e6a9ebdc8407ce59fdc07493074c8fa4ef473a 100644 (file)
@@ -117,6 +117,8 @@ const char * channel_width_to_string(enum chan_width width)
                return "80+80 MHz";
        case CHAN_WIDTH_160:
                return "160 MHz";
+       case CHAN_WIDTH_320:
+               return "320 MHz";
        default:
                return "unknown";
        }
@@ -136,6 +138,8 @@ int channel_width_to_int(enum chan_width width)
        case CHAN_WIDTH_80P80:
        case CHAN_WIDTH_160:
                return 160;
+       case CHAN_WIDTH_320:
+               return 320;
        default:
                return 0;
        }
index 60e44a1a9fb06396b82253cef7f45cd131868717..78c0658a013232a97a6487daded7226c0458a517 100644 (file)
@@ -215,6 +215,8 @@ enum chan_width convert2width(int width)
                return CHAN_WIDTH_80P80;
        case NL80211_CHAN_WIDTH_160:
                return CHAN_WIDTH_160;
+       case NL80211_CHAN_WIDTH_320:
+               return CHAN_WIDTH_320;
        }
        return CHAN_WIDTH_UNKNOWN;
 }
@@ -4941,6 +4943,9 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
                case 160:
                        cw = NL80211_CHAN_WIDTH_160;
                        break;
+               case 320:
+                       cw = NL80211_CHAN_WIDTH_320;
+                       break;
                default:
                        return -EINVAL;
                }
index 00f8b0cbbd9b9d925cd372d0093b3d65fa5303e5..70a10655d583b9f6f3e09e127ff59a8de27eedb8 100644 (file)
@@ -674,6 +674,9 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
        case CHAN_WIDTH_80P80:
                freq1 = cf1 - 30;
                break;
+       case CHAN_WIDTH_320:
+               freq1 = cf1 - 150;
+               break;
        case CHAN_WIDTH_UNKNOWN:
        case CHAN_WIDTH_2160:
        case CHAN_WIDTH_4320:
@@ -2791,6 +2794,9 @@ static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data *drv,
                case NL80211_CHAN_WIDTH_160:
                        ed.sta_opmode.chan_width = CHAN_WIDTH_160;
                        break;
+               case NL80211_CHAN_WIDTH_320:
+                       ed.sta_opmode.chan_width = CHAN_WIDTH_320;
+                       break;
                default:
                        ed.sta_opmode.chan_width = CHAN_WIDTH_UNKNOWN;
                        break;
index 2bbbaab208031fa3c3f06a54da44b3414ae97b83..7adb7687beb093f256f2cd3b4687065b14af5802 100644 (file)
@@ -5989,6 +5989,8 @@ static int parse_freq(int chwidth, int freq2)
                return CONF_OPER_CHWIDTH_80MHZ;
        case 160:
                return CONF_OPER_CHWIDTH_160MHZ;
+       case 320:
+               return CONF_OPER_CHWIDTH_320MHZ;
        default:
                wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
                           chwidth);