]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
hostapd: DFS with 40/80 MHz channel width support
authorJanusz Dziedzic <janusz.dziedzic@tieto.com>
Wed, 16 Oct 2013 09:18:52 +0000 (12:18 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 17 Oct 2013 18:05:44 +0000 (21:05 +0300)
Signed-hostap: Janusz Dziedzic <janusz.dziedzic@tieto.com>

src/ap/ap_drv_ops.c
src/ap/ap_drv_ops.h
src/ap/dfs.c
src/ap/dfs.h
src/ap/drv_callbacks.c
src/ap/hw_features.c
src/ap/hw_features.h

index b4123b8123f6c93431fa3a0a4be376bec7180798..062182aff8c92ce516593e198d6a0abffa5f73b7 100644 (file)
@@ -718,36 +718,26 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
                                         len, 0);
 }
 
-
-int hostapd_start_dfs_cac(struct hostapd_data *hapd, int freq, int flags)
+int hostapd_start_dfs_cac(struct hostapd_data *hapd, int mode, int freq,
+                         int channel, int ht_enabled, int vht_enabled,
+                         int sec_channel_offset, int vht_oper_chwidth,
+                         int center_segment0, int center_segment1)
 {
        struct hostapd_freq_params data;
 
        if (!hapd->driver || !hapd->driver->start_dfs_cac)
                return 0;
 
-       if (!(flags & HOSTAPD_CHAN_RADAR)) {
-               wpa_printf(MSG_ERROR, "Can't start DFS_CAC, the channel %u is "
-                          "not DFS channel", hapd->iconf->channel);
-               return -1;
-       }
-
        if (!hapd->iface->conf->ieee80211h) {
                wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
                           "is not enabled");
                return -1;
        }
 
-       if (hapd->iface->conf->secondary_channel) {
-               wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
-                          "on HT40 is not supported");
-               return -1;
-       }
-
-       if (hostapd_set_freq_params(&data, hapd->iconf->hw_mode, freq,
-                                   hapd->iconf->channel,
-                                   hapd->iconf->ieee80211n,
-                                   0, 0, 0, 0, 0))
+       if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
+                                   vht_enabled, sec_channel_offset,
+                                   vht_oper_chwidth, center_segment0,
+                                   center_segment1))
                return -1;
 
        return hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
index d56aa91064e33bf31e7b02422b093712c97fd2e5..8cbdde663bbfd5dc0ddadc5a8916b89c16a1841c 100644 (file)
@@ -101,7 +101,10 @@ int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
                      int reassoc, u16 status, const u8 *ie, size_t len);
 int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
                      u8 *tspec_ie, size_t tspec_ielen);
-int hostapd_start_dfs_cac(struct hostapd_data *hapd, int freq, int flags);
+int hostapd_start_dfs_cac(struct hostapd_data *hapd, int mode, int freq,
+                         int channel, int ht_enabled, int vht_enabled,
+                         int sec_channel_offset, int vht_oper_chwidth,
+                         int center_segment0, int center_segment1);
 
 
 #include "drivers/driver.h"
index 387b6258c894464af9e29a391cc0c416fa2311cb..5e040f5651b913e568bd711d1d335e9b59b79b0c 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * DFS - Dynamic Frequency Selection
  * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2013, Qualcomm Atheros, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
 #include "utils/common.h"
 #include "common/ieee802_11_defs.h"
 #include "hostapd.h"
-#include "hw_features.h"
 #include "ap_drv_ops.h"
 #include "drivers/driver.h"
 #include "dfs.h"
 
 
+static int dfs_get_used_n_chans(struct hostapd_data *hapd)
+{
+       int n_chans = 1;
+
+       if (hapd->iconf->ieee80211n && hapd->iconf->secondary_channel)
+               n_chans = 2;
+
+       if (hapd->iconf->ieee80211ac) {
+               switch (hapd->iconf->vht_oper_chwidth) {
+               case VHT_CHANWIDTH_USE_HT:
+                       break;
+               case VHT_CHANWIDTH_80MHZ:
+                       n_chans = 4;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return n_chans;
+}
+
+
+static int dfs_channel_available(struct hostapd_channel_data *chan)
+{
+       if (chan->flag & HOSTAPD_CHAN_DISABLED)
+               return 0;
+       if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
+           ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
+            HOSTAPD_CHAN_DFS_UNAVAILABLE))
+               return 0;
+       return 1;
+}
+
+
+static int dfs_is_ht40_allowed(struct hostapd_channel_data *chan)
+{
+       int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
+                         184, 192 };
+       unsigned int i;
+
+       for (i = 0; i < sizeof(allowed) / sizeof(allowed[0]); i++) {
+               if (chan->chan == allowed[i])
+                       return 1;
+       }
+
+       return 0;
+}
+
+
 static int hostapd_dfs_find_channel(struct hostapd_data *hapd,
                                    struct hostapd_channel_data **ret_chan,
                                    int idx)
 {
        struct hostapd_hw_modes *mode;
-       struct hostapd_channel_data *chan;
-       int i, channel_idx = 0;
+       struct hostapd_channel_data *chan, *next_chan;
+       int i, j, channel_idx = 0, n_chans;
 
        mode = hapd->iface->current_mode;
+       n_chans = dfs_get_used_n_chans(hapd);
 
+       wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans);
        for (i = 0; i < mode->num_channels; i++) {
                chan = &mode->channels[i];
 
-               if (chan->flag & HOSTAPD_CHAN_DISABLED)
+               /* Skip not available channels */
+               if (!dfs_channel_available(chan))
                        continue;
 
-               if (chan->flag & HOSTAPD_CHAN_RADAR &&
-                   chan->flag & HOSTAPD_CHAN_DFS_UNAVAILABLE)
-                       continue;
+               /* Skip HT40/VHT uncompatible channels */
+               if (hapd->iconf->ieee80211n &&
+                   hapd->iconf->secondary_channel) {
+                       if (!dfs_is_ht40_allowed(chan))
+                               continue;
+
+                       for (j = 1; j < n_chans; j++) {
+                               next_chan = &mode->channels[i + j];
+                               if (!dfs_channel_available(next_chan))
+                                       break;
+                       }
+                       if (j != n_chans)
+                               continue;
+
+                       /* Set HT40+ */
+                       hapd->iconf->secondary_channel = 1;
+               }
 
                if (ret_chan && idx == channel_idx) {
                        wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);
                        *ret_chan = chan;
                        return idx;
                }
+               wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan);
                channel_idx++;
        }
        return channel_idx;
 }
 
 
+static void dfs_adjust_vht_center_freq(struct hostapd_data *hapd,
+                                      struct hostapd_channel_data *chan)
+{
+       if (!hapd->iconf->ieee80211ac)
+               return;
+
+       if (!chan)
+               return;
+
+       switch (hapd->iconf->vht_oper_chwidth) {
+       case VHT_CHANWIDTH_USE_HT:
+               hapd->iconf->vht_oper_centr_freq_seg0_idx = chan->chan + 2;
+               break;
+       case VHT_CHANWIDTH_80MHZ:
+               hapd->iconf->vht_oper_centr_freq_seg0_idx = chan->chan + 6;
+               break;
+       default:
+               wpa_printf(MSG_INFO, "DFS only VHT20/40/80 is supported now");
+               break;
+       }
+
+       wpa_printf(MSG_DEBUG, "DFS adjusting VHT center frequency: %d",
+                  hapd->iconf->vht_oper_centr_freq_seg0_idx);
+}
+
+
+/* Return start channel idx we will use for mode->channels[idx] */
+static int dfs_get_start_chan_idx(struct hostapd_data *hapd)
+{
+       struct hostapd_hw_modes *mode;
+       struct hostapd_channel_data *chan;
+       int channel_no = hapd->iconf->channel;
+       int res = -1, i;
+
+       /* HT40- */
+       if (hapd->iconf->ieee80211n && hapd->iconf->secondary_channel == -1)
+               channel_no -= 4;
+
+       /* VHT */
+       if (hapd->iconf->ieee80211ac) {
+               switch (hapd->iconf->vht_oper_chwidth) {
+               case VHT_CHANWIDTH_USE_HT:
+                       break;
+               case VHT_CHANWIDTH_80MHZ:
+                       channel_no =
+                               hapd->iconf->vht_oper_centr_freq_seg0_idx - 6;
+                       break;
+               default:
+                       wpa_printf(MSG_INFO,
+                                  "DFS only VHT20/40/80 is supported now");
+                       channel_no = -1;
+                       break;
+               }
+       }
+
+       /* Get idx */
+       mode = hapd->iface->current_mode;
+       for (i = 0; i < mode->num_channels; i++) {
+               chan = &mode->channels[i];
+               if (chan->chan == channel_no) {
+                       res = i;
+                       break;
+               }
+       }
+
+       if (res == -1)
+               wpa_printf(MSG_DEBUG, "DFS chan_idx seems wrong: -1");
+
+       return res;
+}
+
+
+/* At least one channel have radar flag */
+static int dfs_check_chans_radar(struct hostapd_data *hapd, int start_chan_idx,
+                                int n_chans)
+{
+       struct hostapd_channel_data *channel;
+       struct hostapd_hw_modes *mode;
+       int i, res = 0;
+
+       mode = hapd->iface->current_mode;
+
+       for (i = 0; i < n_chans; i++) {
+               channel = &mode->channels[start_chan_idx + i];
+               if (channel->flag & HOSTAPD_CHAN_RADAR)
+                       res++;
+       }
+
+       return res;
+}
+
+
+/* All channels available */
+static int dfs_check_chans_available(struct hostapd_data *hapd,
+                                    int start_chan_idx, int n_chans)
+{
+       struct hostapd_channel_data *channel;
+       struct hostapd_hw_modes *mode;
+       int i;
+
+       mode = hapd->iface->current_mode;
+
+       for(i = 0; i < n_chans; i++) {
+               channel = &mode->channels[start_chan_idx + i];
+               if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) !=
+                   HOSTAPD_CHAN_DFS_AVAILABLE)
+                       break;
+       }
+
+       return i == n_chans;
+}
+
+
+/* At least one channel unavailable */
+static int dfs_check_chans_unavailable(struct hostapd_data *hapd,
+                                      int start_chan_idx,
+                                      int n_chans)
+{
+       struct hostapd_channel_data *channel;
+       struct hostapd_hw_modes *mode;
+       int i, res = 0;
+
+       mode = hapd->iface->current_mode;
+
+       for(i = 0; i < n_chans; i++) {
+               channel = &mode->channels[start_chan_idx + i];
+               if (channel->flag & HOSTAPD_CHAN_DISABLED)
+                       res++;
+               if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) ==
+                   HOSTAPD_CHAN_DFS_UNAVAILABLE)
+                       res++;
+       }
+
+       return res;
+}
+
+
 struct hostapd_channel_data * hostapd_dfs_get_valid_channel(
        struct hostapd_data *hapd)
 {
@@ -73,11 +278,14 @@ struct hostapd_channel_data * hostapd_dfs_get_valid_channel(
                hostapd_dfs_find_channel(hapd, &chan, new_channel_idx);
        }
 
+       /* VHT */
+       dfs_adjust_vht_center_freq(hapd, chan);
+
        return chan;
 }
 
 
-int ieee802_11_set_dfs_state(struct hostapd_data *hapd, int freq, u32 state)
+static int set_dfs_state_freq(struct hostapd_data *hapd, int freq, u32 state)
 {
        struct hostapd_hw_modes *mode;
        struct hostapd_channel_data *chan = NULL;
@@ -87,11 +295,7 @@ int ieee802_11_set_dfs_state(struct hostapd_data *hapd, int freq, u32 state)
        if (mode == NULL)
                return 0;
 
-       if (mode->mode != HOSTAPD_MODE_IEEE80211A) {
-               wpa_printf(MSG_WARNING, "current_mode != IEEE80211A");
-               return 0;
-       }
-
+       wpa_printf(MSG_DEBUG, "set_dfs_state 0x%X for %d MHz", state, freq);
        for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
                chan = &hapd->iface->current_mode->channels[i];
                if (chan->freq == freq) {
@@ -107,6 +311,113 @@ int ieee802_11_set_dfs_state(struct hostapd_data *hapd, int freq, u32 state)
 }
 
 
+static int set_dfs_state(struct hostapd_data *hapd, int freq, int ht_enabled,
+                        int chan_offset, int chan_width, int cf1,
+                        int cf2, u32 state)
+{
+       int n_chans = 1, i;
+       struct hostapd_hw_modes *mode;
+       int frequency = freq;
+       int ret = 0;
+
+       mode = hapd->iface->current_mode;
+       if (mode == NULL)
+               return 0;
+
+       if (mode->mode != HOSTAPD_MODE_IEEE80211A) {
+               wpa_printf(MSG_WARNING, "current_mode != IEEE80211A");
+               return 0;
+       }
+
+       /* Seems cf1 and chan_width is enough here */
+       switch (chan_width) {
+       case CHAN_WIDTH_20_NOHT:
+       case CHAN_WIDTH_20:
+               n_chans = 1;
+               frequency = cf1;
+               break;
+       case CHAN_WIDTH_40:
+               n_chans = 2;
+               frequency = cf1 - 10;
+               break;
+       case CHAN_WIDTH_80:
+               n_chans = 4;
+               frequency = cf1 - 30;
+               break;
+       default:
+               wpa_printf(MSG_INFO, "DFS chan_width %d not supported",
+                          chan_width);
+               break;
+       }
+
+       wpa_printf(MSG_DEBUG, "DFS freq: %dMHz, n_chans: %d", frequency,
+                  n_chans);
+       for (i = 0; i < n_chans; i++) {
+               ret += set_dfs_state_freq(hapd, frequency, state);
+               frequency = frequency + 20;
+       }
+
+       return ret;
+}
+
+
+static int dfs_are_channels_overlapped(struct hostapd_data *hapd, int freq,
+                                      int chan_width, int cf1, int cf2)
+{
+       int start_chan_idx;
+       struct hostapd_hw_modes *mode;
+       struct hostapd_channel_data *chan;
+       int n_chans, i, j, frequency = freq, radar_n_chans = 1;
+       u8 radar_chan;
+       int res = 0;
+
+       if (hapd->iface->freq == freq)
+               res++;
+
+       /* Our configuration */
+       mode = hapd->iface->current_mode;
+       start_chan_idx = dfs_get_start_chan_idx(hapd);
+       n_chans = dfs_get_used_n_chans(hapd);
+
+       /* Reported via radar event */
+       switch (chan_width) {
+       case CHAN_WIDTH_20_NOHT:
+       case CHAN_WIDTH_20:
+               radar_n_chans = 1;
+               frequency = cf1;
+               break;
+       case CHAN_WIDTH_40:
+               radar_n_chans = 2;
+               frequency = cf1 - 10;
+               break;
+       case CHAN_WIDTH_80:
+               radar_n_chans = 4;
+               frequency = cf1 - 30;
+               break;
+       default:
+               wpa_printf(MSG_INFO, "DFS chan_width %d not supported",
+                          chan_width);
+               break;
+       }
+
+       ieee80211_freq_to_chan(frequency, &radar_chan);
+
+       for (i = 0; i < n_chans; i++) {
+               chan = &mode->channels[start_chan_idx + i];
+               for (j = 0; j < radar_n_chans; j++) {
+                       wpa_printf(MSG_DEBUG, "checking our: %d, radar: %d",
+                                  chan->chan, radar_chan + j * 4);
+                       if (chan->chan == radar_chan + j * 4)
+                               res++;
+               }
+       }
+
+       wpa_printf(MSG_DEBUG, "overlapped: %d", res);
+
+       return res;
+}
+
+
 /*
  * Main DFS handler
  * 1 - continue channel/ap setup
@@ -115,28 +426,40 @@ int ieee802_11_set_dfs_state(struct hostapd_data *hapd, int freq, u32 state)
  */
 int hostapd_handle_dfs(struct hostapd_data *hapd)
 {
-       int flags;
        struct hostapd_channel_data *channel;
-
-       /* Handle DFS channel */
-check_dfs_chan_again:
-       flags = hostapd_hw_get_channel_flag(hapd, hapd->iconf->channel);
-       if (flags & HOSTAPD_CHAN_RADAR) {
-               switch (flags & HOSTAPD_CHAN_DFS_MASK) {
-               case HOSTAPD_CHAN_DFS_USABLE:
-                       wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz",
-                                  hapd->iface->freq);
-                       if (hostapd_start_dfs_cac(hapd,
-                                                 hapd->iface->freq,
-                                                 flags)) {
-                               wpa_printf(MSG_DEBUG, "DFS start_dfs_cac() failed");
-                               return -1;
-                       }
-                       /* Continue initialisation after CAC */
-                       return 0;
-               case HOSTAPD_CHAN_DFS_UNAVAILABLE:
-                       wpa_printf(MSG_DEBUG, "HOSTAPD_CHAN_DFS_UNAVAILABLE, get new chan");
-                       /* find other channel here */
+       int res, n_chans, start_chan_idx;
+
+       do {
+               /* Get start (first) channel for current configuration */
+               start_chan_idx = dfs_get_start_chan_idx(hapd);
+               if (start_chan_idx == -1)
+                       return -1;
+
+               /* Get number of used channels, depend on width */
+               n_chans = dfs_get_used_n_chans(hapd);
+
+               /* Check if any of configured channels require DFS */
+               res = dfs_check_chans_radar(hapd, start_chan_idx, n_chans);
+               wpa_printf(MSG_DEBUG,
+                          "DFS %d channels required radar detection",
+                          res);
+               if (!res)
+                       return 1;
+
+               /* Check if all channels are DFS available */
+               res = dfs_check_chans_available(hapd, start_chan_idx, n_chans);
+               wpa_printf(MSG_DEBUG,
+                          "DFS all channels available, (SKIP CAC): %s",
+                          res ? "yes" : "no");
+               if (res)
+                       return 1;
+
+               /* Check if any of configured channels is unavailable */
+               res = dfs_check_chans_unavailable(hapd, start_chan_idx,
+                                                 n_chans);
+               wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s",
+                          res, res ? "yes": "no");
+               if (res) {
                        channel = hostapd_dfs_get_valid_channel(hapd);
                        if (!channel) {
                                wpa_printf(MSG_ERROR, "could not get valid channel");
@@ -144,34 +467,46 @@ check_dfs_chan_again:
                        }
                        hapd->iconf->channel = channel->chan;
                        hapd->iface->freq = channel->freq;
-                       goto check_dfs_chan_again;
-               case HOSTAPD_CHAN_DFS_AVAILABLE:
-                       /* We don't need CAC here */
-                       wpa_printf(MSG_DEBUG, "HOSTAPD_CHAN_DFS_AVAILABLE, skip CAC");
-                       break;
-               default:
-                       break;
                }
+       } while (res);
+
+       /* Finally start CAC */
+       wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", hapd->iface->freq);
+       if (hostapd_start_dfs_cac(hapd, hapd->iconf->hw_mode,
+                                 hapd->iface->freq,
+                                 hapd->iconf->channel,
+                                 hapd->iconf->ieee80211n,
+                                 hapd->iconf->ieee80211ac,
+                                 hapd->iconf->secondary_channel,
+                                 hapd->iconf->vht_oper_chwidth,
+                                 hapd->iconf->vht_oper_centr_freq_seg0_idx,
+                                 hapd->iconf->vht_oper_centr_freq_seg1_idx)) {
+               wpa_printf(MSG_DEBUG, "DFS start_dfs_cac() failed");
+               return -1;
        }
 
-       return 1;
+       return 0;
 }
 
 
-int ieee802_11_complete_cac(struct hostapd_data *hapd, int success, int freq)
+int hostapd_dfs_complete_cac(struct hostapd_data *hapd, int success, int freq,
+                            int ht_enabled, int chan_offset, int chan_width,
+                            int cf1, int cf2)
 {
        struct hostapd_channel_data *channel;
        int err = 1;
 
        if (success) {
                /* Complete iface/ap configuration */
-               ieee802_11_set_dfs_state(hapd, freq,
-                                        HOSTAPD_CHAN_DFS_AVAILABLE);
+               set_dfs_state(hapd, freq, ht_enabled, chan_offset,
+                             chan_width, cf1, cf2,
+                             HOSTAPD_CHAN_DFS_AVAILABLE);
                hostapd_setup_interface_complete(hapd->iface, 0);
        } else {
                /* Switch to new channel */
-               ieee802_11_set_dfs_state(hapd, freq,
-                                        HOSTAPD_CHAN_DFS_UNAVAILABLE);
+               set_dfs_state(hapd, freq, ht_enabled, chan_offset,
+                             chan_width, cf1, cf2,
+                             HOSTAPD_CHAN_DFS_UNAVAILABLE);
                channel = hostapd_dfs_get_valid_channel(hapd);
                if (channel) {
                        hapd->iconf->channel = channel->chan;
@@ -205,3 +540,44 @@ int ieee802_11_start_channel_switch(struct hostapd_data *hapd)
        hostapd_setup_interface_complete(hapd->iface, err);
        return 0;
 }
+
+
+int hostapd_dfs_radar_detected(struct hostapd_data *hapd, int freq,
+                              int ht_enabled, int chan_offset, int chan_width,
+                              int cf1, int cf2)
+{
+       int res;
+
+       if (!hapd->iconf->ieee80211h)
+               return 0;
+
+       /* mark radar frequency as invalid */
+       res = set_dfs_state(hapd, freq, ht_enabled, chan_offset,
+                           chan_width, cf1, cf2,
+                           HOSTAPD_CHAN_DFS_UNAVAILABLE);
+
+       /* Skip if reported radar event not overlapped our channels */
+       res = dfs_are_channels_overlapped(hapd, freq, chan_width, cf1, cf2);
+       if (!res)
+               return 0;
+
+       /* we are working on non-DFS channel - skip event */
+       if (res == 0)
+               return 0;
+
+       /* radar detected while operating, switch the channel. */
+       res = ieee802_11_start_channel_switch(hapd);
+
+       return res;
+}
+
+
+int hostapd_dfs_nop_finished(struct hostapd_data *hapd, int freq,
+                            int ht_enabled, int chan_offset, int chan_width,
+                            int cf1, int cf2)
+{
+       /* TODO add correct implementation here */
+       set_dfs_state(hapd, freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
+                     HOSTAPD_CHAN_DFS_USABLE);
+       return 0;
+}
index 3a4e875820b62a094f77f71a4aadd7c870641c59..c9f0578e8e4959bcac7e85eff62dad9748e3982b 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * DFS - Dynamic Frequency Selection
  * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2013, Qualcomm Atheros, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -8,11 +9,17 @@
 #ifndef DFS_H
 #define DFS_H
 
-struct hostapd_channel_data * hostapd_dfs_get_valid_channel(
-       struct hostapd_data *hapd);
-int ieee802_11_complete_cac(struct hostapd_data *hapd, int success, int freq);
-int ieee802_11_set_dfs_state(struct hostapd_data *hapd, int freq, u32 state);
-int ieee802_11_start_channel_switch(struct hostapd_data *hapd);
 int hostapd_handle_dfs(struct hostapd_data *hapd);
 
+int hostapd_dfs_complete_cac(struct hostapd_data *hapd, int success, int freq,
+                            int ht_enabled, int chan_offset, int chan_width,
+                            int cf1, int cf2);
+int hostapd_dfs_radar_detected(struct hostapd_data *hapd, int freq,
+                              int ht_enabled,
+                              int chan_offset, int chan_width,
+                              int cf1, int cf2);
+int hostapd_dfs_nop_finished(struct hostapd_data *hapd, int freq,
+                            int ht_enabled,
+                            int chan_offset, int chan_width, int cf1, int cf2);
+
 #endif /* DFS_H */
index 6fa83c927a542873a000cb7cffaba0bcb21c7e7c..774d2418102e3cb3192bde0ca084880ff49e98c8 100644 (file)
@@ -791,27 +791,10 @@ static void hostapd_event_get_survey(struct hostapd_data *hapd,
 static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
                                             struct dfs_event *radar)
 {
-       int res;
-
        wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
-
-       if (!hapd->iconf->ieee80211h)
-               return;
-
-       /* mark radar frequency as invalid */
-       res = ieee802_11_set_dfs_state(hapd, radar->freq,
-                                      HOSTAPD_CHAN_DFS_UNAVAILABLE);
-
-       /* other frequency, just mark it and return. */
-       if (hapd->iface->freq != radar->freq)
-               return;
-
-       /* we are working on non-DFS channel - skip event */
-       if (res == 0)
-               return;
-
-       /* radar detected while operating, switch the channel. */
-       ieee802_11_start_channel_switch(hapd);
+       hostapd_dfs_radar_detected(hapd, radar->freq, radar->ht_enabled,
+                                  radar->chan_offset, radar->chan_width,
+                                  radar->cf1, radar->cf2);
 }
 
 
@@ -819,7 +802,9 @@ static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd,
                                           struct dfs_event *radar)
 {
        wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
-       ieee802_11_complete_cac(hapd, 1, radar->freq);
+       hostapd_dfs_complete_cac(hapd, 1, radar->freq, radar->ht_enabled,
+                                radar->chan_offset, radar->chan_width,
+                                radar->cf1, radar->cf2);
 }
 
 
@@ -827,7 +812,9 @@ static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd,
                                          struct dfs_event *radar)
 {
        wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
-       ieee802_11_complete_cac(hapd, 0, radar->freq);
+       hostapd_dfs_complete_cac(hapd, 0, radar->freq, radar->ht_enabled,
+                                radar->chan_offset, radar->chan_width,
+                                radar->cf1, radar->cf2);
 }
 
 
@@ -835,7 +822,9 @@ static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
                                           struct dfs_event *radar)
 {
        wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
-       ieee802_11_set_dfs_state(hapd, radar->freq, HOSTAPD_CHAN_DFS_USABLE);
+       hostapd_dfs_nop_finished(hapd, radar->freq, radar->ht_enabled,
+                                radar->chan_offset, radar->chan_width,
+                                radar->cf1, radar->cf2);
 }
 
 #endif /* NEED_AP_MLME */
index 7e351d784757c45810637b04803ddefae87034e1..9e5becc3d29a052d4339471d5e3b79f86c1d94f1 100644 (file)
@@ -889,21 +889,3 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
 
        return 0;
 }
-
-
-int hostapd_hw_get_channel_flag(struct hostapd_data *hapd, int chan)
-{
-       int i;
-
-       if (!hapd->iface->current_mode)
-               return 0;
-
-       for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
-               struct hostapd_channel_data *ch =
-                       &hapd->iface->current_mode->channels[i];
-               if (ch->chan == chan)
-                       return ch->flag;
-       }
-
-       return 0;
-}
index b8e287b824b89df5e6db72a7046fdedbd89fc56e..abadcd137db1e8b66b1bf9ff8be4177f8ffff0e7 100644 (file)
@@ -28,7 +28,6 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
 int hostapd_check_ht_capab(struct hostapd_iface *iface);
 int hostapd_prepare_rates(struct hostapd_iface *iface,
                          struct hostapd_hw_modes *mode);
-int hostapd_hw_get_channel_flag(struct hostapd_data *hapd, int chan);
 #else /* NEED_AP_MLME */
 static inline void
 hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,