]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EHT: Downgrade bandwidths for VHT and HE when using puncturing
authorAloka Dixit <quic_alokad@quicinc.com>
Tue, 14 Mar 2023 04:59:17 +0000 (21:59 -0700)
committerJouni Malinen <j@w1.fi>
Fri, 17 Mar 2023 17:46:24 +0000 (19:46 +0200)
Legacy modes (VHT, HE) should advertise downgraded bandwidth if
RU puncturing is enabled in EHT mode. This is required for the legacy
stations which cannot parse the EHT Operation elements hence do not
support EHT RU puncturing.

Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
Signed-off-by: Ramanathan Choodamani <quic_rchoodam@quicinc.com>
src/ap/ieee802_11.c
src/ap/ieee802_11.h
src/ap/ieee802_11_he.c
src/ap/ieee802_11_vht.c

index fff557d8ee08717201aa8e9cc9b89ff1bc357b1b..8304e3c26ab8ba9ce014c2f4674ad96496e5d3b8 100644 (file)
@@ -7027,4 +7027,73 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
        return eid;
 }
 
+
+static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
+{
+       u8 first_chan = *seg0 - 6, sec_chan;
+
+       switch (bitmap) {
+       case 0x6:
+               *seg0 = 0;
+               return;
+       case 0x8:
+       case 0x4:
+       case 0x2:
+       case 0x1:
+       case 0xC:
+       case 0x3:
+               if (pri_chan < *seg0)
+                       *seg0 -= 4;
+               else
+                       *seg0 += 4;
+               break;
+       }
+
+       if (pri_chan < *seg0)
+               sec_chan = pri_chan + 4;
+       else
+               sec_chan = pri_chan - 4;
+
+       if (bitmap & BIT((sec_chan - first_chan) / 4))
+               *seg0 = 0;
+}
+
+
+static void punct_update_legacy_bw_160(u8 bitmap, u8 pri,
+                                      enum oper_chan_width *width, u8 *seg0)
+{
+       if (pri < *seg0) {
+               *seg0 -= 8;
+               if (bitmap & 0x0F) {
+                       *width = 0;
+                       punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
+               }
+       } else {
+               *seg0 += 8;
+               if (bitmap & 0xF0) {
+                       *width = 0;
+                       punct_update_legacy_bw_80((bitmap & 0xF0) >> 4, pri,
+                                                 seg0);
+               }
+       }
+}
+
+
+void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
+                           u8 *seg0, u8 *seg1)
+{
+       if (*width == CONF_OPER_CHWIDTH_80MHZ && (bitmap & 0xF)) {
+               *width = CONF_OPER_CHWIDTH_USE_HT;
+               punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
+       }
+
+       if (*width == CONF_OPER_CHWIDTH_160MHZ && (bitmap & 0xFF)) {
+               *width = CONF_OPER_CHWIDTH_80MHZ;
+               *seg1 = 0;
+               punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0);
+       }
+
+       /* TODO: 320 MHz */
+}
+
 #endif /* CONFIG_NATIVE_WINDOWS */
index 5f443fcb8abba4a8c4f2291cf2db67498530430e..1e4c843f6695369a99819b37ba4128d2a9078ba0 100644 (file)
@@ -18,6 +18,7 @@ struct ieee80211_vht_capabilities;
 struct ieee80211_mgmt;
 struct radius_sta;
 enum ieee80211_op_mode;
+enum oper_chan_width;
 
 int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
                    struct hostapd_frame_info *fi);
@@ -222,5 +223,7 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
                        unsigned int frame_stype, u8 elem_count,
                        u8 **elem_offset,
                        const u8 *known_bss, size_t known_bss_len);
+void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
+                           enum oper_chan_width *width, u8 *seg0, u8 *seg1);
 
 #endif /* IEEE802_11_H */
index 12273c34c04fc3294218ddf515e1c27e3ac2ad2f..548a44821fb8dd29ce1dfb9a517f3a25ecb58fe0 100644 (file)
@@ -219,10 +219,20 @@ 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)) {
+               enum oper_chan_width oper_chwidth =
+                       hostapd_get_oper_chwidth(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;
 
+#ifdef CONFIG_IEEE80211BE
+               if (hapd->iconf->punct_bitmap) {
+                       punct_update_legacy_bw(hapd->iconf->punct_bitmap,
+                                              hapd->iconf->channel,
+                                              &oper_chwidth, &seg0, &seg1);
+               }
+#endif /* CONFIG_IEEE80211BE */
+
                if (!seg0)
                        seg0 = hapd->iconf->channel;
 
@@ -253,7 +263,7 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
                *pos++ = control;
 
                /* Channel Center Freq Seg0/Seg1 */
-               if (hapd->iconf->he_oper_chwidth == 2) {
+               if (oper_chwidth == 2) {
                        /*
                         * Seg 0 indicates the channel center frequency index of
                         * the 160 MHz channel.
index 681b6d78f51384d506750ba31c897f3f81daae65..db615a38bc1b560cc0d73edd9886c93929a50eed 100644 (file)
@@ -75,6 +75,10 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
 {
        struct ieee80211_vht_operation *oper;
        u8 *pos = eid;
+       enum oper_chan_width oper_chwidth =
+               hostapd_get_oper_chwidth(hapd->iconf);
+       u8 seg0 = hapd->iconf->vht_oper_centr_freq_seg0_idx;
+       u8 seg1 = hapd->iconf->vht_oper_centr_freq_seg1_idx;
 
        if (is_6ghz_op_class(hapd->iconf->op_class))
                return eid;
@@ -85,18 +89,24 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
        oper = (struct ieee80211_vht_operation *) pos;
        os_memset(oper, 0, sizeof(*oper));
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iconf->punct_bitmap) {
+               punct_update_legacy_bw(hapd->iconf->punct_bitmap,
+                                      hapd->iconf->channel,
+                                      &oper_chwidth, &seg0, &seg1);
+       }
+#endif /* CONFIG_IEEE80211BE */
+
        /*
         * center freq = 5 GHz + (5 * index)
         * So index 42 gives center freq 5.210 GHz
         * which is channel 42 in 5G band
         */
-       oper->vht_op_info_chan_center_freq_seg0_idx =
-               hapd->iconf->vht_oper_centr_freq_seg0_idx;
-       oper->vht_op_info_chan_center_freq_seg1_idx =
-               hapd->iconf->vht_oper_centr_freq_seg1_idx;
+       oper->vht_op_info_chan_center_freq_seg0_idx = seg0;
+       oper->vht_op_info_chan_center_freq_seg1_idx = seg1;
 
-       oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth;
-       if (hapd->iconf->vht_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
+       oper->vht_op_info_chwidth = oper_chwidth;
+       if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
                /*
                 * Convert 160 MHz channel width to new style as interop
                 * workaround.
@@ -109,8 +119,7 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
                        oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
                else
                        oper->vht_op_info_chan_center_freq_seg0_idx += 8;
-       } else if (hapd->iconf->vht_oper_chwidth ==
-                  CONF_OPER_CHWIDTH_80P80MHZ) {
+       } else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
                /*
                 * Convert 80+80 MHz channel width to new style as interop
                 * workaround.