[4/4] DFS: add supported channel BW checking

Message ID 20180301114929.420-5-dlebed@quantenna.com
State New
Headers show
Series
  • Implement supported channel BW checking
Related show

Commit Message

Dmitrii Lebed March 1, 2018, 11:49 a.m.
From: Dmitry Lebed <dlebed@quantenna.com>

While selecting new channel as a reation to radar event
we need to take into account supported BW for each channel
provided via nl80211.
Without this modification hostapd can select unsupported
channel, will fail to use it and eventually will halt.

Signed-off-by: Dmitry Lebed <dlebed@quantenna.com>
---
 src/ap/dfs.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

--
2.16.1



This email, including its contents and any attachment(s), may contain confidential information of Quantenna Communications, Inc. and is solely for the intended recipient(s). If you may have received this in error, please contact the sender and permanently delete this email, its contents and any attachment(s).

Patch

diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 8c56cbb96..f2c115ca5 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -143,18 +143,30 @@  static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
 {
        struct hostapd_channel_data *first_chan, *chan;
        int i;
+       const u32 bw = num_chan_to_bw(num_chans);

        if (first_chan_idx + num_chans > mode->num_channels)
                return 0;

        first_chan = &mode->channels[first_chan_idx];

+       /* hostapd DFS implementation assumes first channel as primary,
+        * if it's not allowed to use fist channel as primary
+        * then decline the whole channel range */
+       if (!chan_pri_allowed(first_chan))
+               return 0;
+
        for (i = 0; i < num_chans; i++) {
                chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
                                         first_chan_idx);
                if (!chan)
                        return 0;

+               /* HT 40MHz secondary channel availability checked only for
+                * primary channel */
+               if (!chan_bw_allowed(chan, bw, 1, !i))
+                       return 0;
+
                if (!dfs_channel_available(chan, skip_radar))
                        return 0;
        }
@@ -195,9 +207,9 @@  static int dfs_find_channel(struct hostapd_iface *iface,
                chan = &mode->channels[i];

                /* Skip HT40/VHT incompatible channels */
-               if (iface->conf->ieee80211n &&
-                   iface->conf->secondary_channel &&
-                   !dfs_is_chan_allowed(chan, n_chans))
+               if (iface->conf->ieee80211n && iface->conf->secondary_channel &&
+                   (!dfs_is_chan_allowed(chan, n_chans) ||
+                    !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)))
                        continue;

                /* Skip incompatible chandefs */