]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DFS: Add support for 80+80 MHz when going through channel switch
authorPravas Kumar Panda <kumarpan@codeaurora.org>
Fri, 6 Mar 2020 09:36:42 +0000 (15:06 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 6 Mar 2020 19:44:31 +0000 (21:44 +0200)
After a radar signal is detected, the AP should switch to another
channel, but in the case of 80+80 MHz, channel switch failed because
hostapd did not select the secondary channel in the process. Fix this by
selecting a secondary channel in the case of 80+80 MHz.

Signed-off-by: Xin Wang <xwangw@codeaurora.org>
Signed-off-by: Pravas Kumar Panda <kumarpan@codeaurora.org>
src/ap/dfs.c

index 6c8cd6cac07fbe65a76984aed74e3eeb731f8d8a..6fc806d7b6cadde08089c8d7d25d715823527960 100644 (file)
@@ -263,6 +263,7 @@ static int dfs_find_channel(struct hostapd_iface *iface,
 static void dfs_adjust_center_freq(struct hostapd_iface *iface,
                                   struct hostapd_channel_data *chan,
                                   int secondary_channel,
+                                  int sec_chan_idx_80p80,
                                   u8 *oper_centr_freq_seg0_idx,
                                   u8 *oper_centr_freq_seg1_idx)
 {
@@ -289,8 +290,14 @@ static void dfs_adjust_center_freq(struct hostapd_iface *iface,
        case CHANWIDTH_160MHZ:
                *oper_centr_freq_seg0_idx = chan->chan + 14;
                break;
+       case CHANWIDTH_80P80MHZ:
+               *oper_centr_freq_seg0_idx = chan->chan + 6;
+               *oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6;
+               break;
+
        default:
-               wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now");
+               wpa_printf(MSG_INFO,
+                          "DFS: Unsupported channel width configuration");
                *oper_centr_freq_seg0_idx = 0;
                break;
        }
@@ -469,8 +476,11 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
 {
        struct hostapd_hw_modes *mode;
        struct hostapd_channel_data *chan = NULL;
+       struct hostapd_channel_data *chan2 = NULL;
        int num_available_chandefs;
-       int chan_idx;
+       int chan_idx, chan_idx2;
+       int sec_chan_idx_80p80 = -1;
+       int i;
        u32 _rand;
 
        wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
@@ -496,11 +506,12 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
                return NULL;
        chan_idx = _rand % num_available_chandefs;
        dfs_find_channel(iface, &chan, chan_idx, skip_radar);
-       if (chan)
-               wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)",
-                          chan->freq, chan->chan);
-       else
+       if (!chan) {
                wpa_printf(MSG_DEBUG, "DFS: no random channel found");
+               return NULL;
+       }
+       wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)",
+                  chan->freq, chan->chan);
 
        /* dfs_find_channel() calculations assume HT40+ */
        if (iface->conf->secondary_channel)
@@ -508,8 +519,45 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
        else
                *secondary_channel = 0;
 
+       /* Get secondary channel for HT80P80 */
+       if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80P80MHZ) {
+               if (num_available_chandefs <= 1) {
+                       wpa_printf(MSG_ERROR,
+                                  "only 1 valid chan, can't support 80+80");
+                       return NULL;
+               }
+
+               /*
+                * Loop all channels except channel1 to find a valid channel2
+                * that is not adjacent to channel1.
+                */
+               for (i = 0; i < num_available_chandefs - 1; i++) {
+                       /* start from chan_idx + 1, end when chan_idx - 1 */
+                       chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs;
+                       dfs_find_channel(iface, &chan2, chan_idx2, skip_radar);
+                       if (chan2 && abs(chan2->chan - chan->chan) > 12) {
+                               /* two channels are not adjacent */
+                               sec_chan_idx_80p80 = chan2->chan;
+                               wpa_printf(MSG_DEBUG,
+                                          "DFS: got second chan: %d (%d)",
+                                          chan2->freq, chan2->chan);
+                               break;
+                       }
+               }
+
+               /* Check if we got a valid secondary channel which is not
+                * adjacent to the first channel.
+                */
+               if (sec_chan_idx_80p80 == -1) {
+                       wpa_printf(MSG_INFO,
+                                  "DFS: failed to get chan2 for 80+80");
+                       return NULL;
+               }
+       }
+
        dfs_adjust_center_freq(iface, chan,
                               *secondary_channel,
+                              sec_chan_idx_80p80,
                               oper_centr_freq_seg0_idx,
                               oper_centr_freq_seg1_idx);