]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DFS offload: Add main DFS handler for offloaded case
authorAhmad Kholaif <akholaif@qca.qualcomm.com>
Thu, 5 Mar 2015 01:24:36 +0000 (17:24 -0800)
committerJouni Malinen <j@w1.fi>
Thu, 5 Mar 2015 15:21:30 +0000 (17:21 +0200)
Add handling logic for DFS offloaded case, and add a helper function
that takes the frequency (MHz) as a param and returns 1 if given channel
requires DFS, or 0 otherwise.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/dfs.c
src/ap/dfs.h
src/ap/drv_callbacks.c
src/ap/hostapd.c
src/common/ieee802_11_common.c
src/common/ieee802_11_common.h

index 46a1d86859558e501dc058b0ac12ab14cacaf753..da6fd4646710177f4812d0f7d126a1adae7c4dbe 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DFS - Dynamic Frequency Selection
  * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2013, Qualcomm Atheros, Inc.
+ * Copyright (c) 2013-2015, Qualcomm Atheros, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -1012,3 +1012,53 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
                res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1);
        return res;
 }
+
+
+int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+                         int ht_enabled, int chan_offset, int chan_width,
+                         int cf1, int cf2)
+{
+       wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+               "freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
+               "seg1=%d cac_time=%ds",
+               freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60);
+       iface->cac_started = 1;
+       return 0;
+}
+
+
+/*
+ * Main DFS handler for offloaded case.
+ * 2 - continue channel/AP setup for non-DFS channel
+ * 1 - continue channel/AP setup for DFS channel
+ * 0 - channel/AP setup will be continued after CAC
+ * -1 - hit critical error
+ */
+int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
+{
+       wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
+                  __func__, iface->cac_started);
+
+       /*
+        * If DFS has already been started, then we are being called from a
+        * callback to continue AP/channel setup. Reset the CAC start flag and
+        * return.
+        */
+       if (iface->cac_started) {
+               wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
+                          __func__, iface->cac_started);
+               iface->cac_started = 0;
+               return 1;
+       }
+
+       if (ieee80211_is_dfs(iface->freq)) {
+               wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS",
+                          __func__, iface->freq);
+               return 0;
+       }
+
+       wpa_printf(MSG_DEBUG,
+                  "%s: freq %d MHz does not require DFS. Continue channel/AP setup",
+                  __func__, iface->freq);
+       return 2;
+}
index a619c55c212c5819b962c942b5faf4b703aecdac..be8c0e6001c9579cd886c919417ab6e3f0effb1e 100644 (file)
@@ -22,5 +22,9 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
                             int ht_enabled,
                             int chan_offset, int chan_width, int cf1, int cf2);
 int hostapd_is_dfs_required(struct hostapd_iface *iface);
+int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+                         int ht_enabled, int chan_offset, int chan_width,
+                         int cf1, int cf2);
+int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
 
 #endif /* DFS_H */
index c39989c34eb8bf88d48965556b609b649c7a4685..bd980e2e9af7091c0e0437316eaeac5532cf3fd8 100644 (file)
@@ -1032,6 +1032,16 @@ static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
                                 radar->cf1, radar->cf2);
 }
 
+
+static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+                                         struct dfs_event *radar)
+{
+       wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
+       hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
+                             radar->chan_offset, radar->chan_width,
+                             radar->cf1, radar->cf2);
+}
+
 #endif /* NEED_AP_MLME */
 
 
@@ -1207,6 +1217,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                hostapd_channel_list_updated(
                        hapd->iface, data->channel_list_changed.initiator);
                break;
+       case EVENT_DFS_CAC_STARTED:
+               if (!data)
+                       break;
+               hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
+               break;
 #endif /* NEED_AP_MLME */
        case EVENT_INTERFACE_ENABLED:
                wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
index e641b129fa35e3433f9f9610959aa8e16defd0f9..f6019ac20f0c759fc5de92476c1f7f23eaf81269 100644 (file)
@@ -1377,6 +1377,7 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
        size_t j;
        u8 *prev_addr;
        int delay_apply_cfg = 0;
+       int res_dfs_offload = 0;
 
        if (err)
                goto fail;
@@ -1403,6 +1404,23 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
                                        goto fail;
                                return res;
                        }
+               } else {
+                       /* If DFS is offloaded to the driver */
+                       res_dfs_offload = hostapd_handle_dfs_offload(iface);
+                       if (res_dfs_offload <= 0) {
+                               if (res_dfs_offload < 0)
+                                       goto fail;
+                       } else {
+                               wpa_printf(MSG_DEBUG,
+                                          "Proceed with AP/channel setup");
+                               /*
+                                * If this is a DFS channel, move to completing
+                                * AP setup.
+                                */
+                               if (res_dfs_offload == 1)
+                                       goto dfs_offload;
+                               /* Otherwise fall through. */
+                       }
                }
 #endif /* NEED_AP_MLME */
 
@@ -1497,6 +1515,19 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
                        goto fail;
        }
 
+       if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+           !res_dfs_offload) {
+               /*
+                * If freq is DFS, and DFS is offloaded to the driver, then wait
+                * for CAC to complete.
+                */
+               wpa_printf(MSG_DEBUG, "%s: Wait for CAC to complete", __func__);
+               return res_dfs_offload;
+       }
+
+#ifdef NEED_AP_MLME
+dfs_offload:
+#endif /* NEED_AP_MLME */
        hostapd_set_state(iface, HAPD_IFACE_ENABLED);
        wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
        if (hapd->setup_complete_cb)
index ed8d46619ad779e0aea53ccc7ac5a3cb08fe2f23..aca0b73223bb8b3ff2b3c41a0de31f761802d26b 100644 (file)
@@ -826,6 +826,13 @@ int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
 }
 
 
+int ieee80211_is_dfs(int freq)
+{
+       /* TODO: this could be more accurate to better cover all domains */
+       return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
+}
+
+
 static int is_11b(u8 rate)
 {
        return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
index 05fe32b450c1a024fb955eb1a82d337382053ac1..7f0b296d2b00a340863c3afcb568cb47dc8edb76 100644 (file)
@@ -108,6 +108,7 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
                          const char *name, const char *val);
 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
+int ieee80211_is_dfs(int freq);
 
 int supp_rates_11b_only(struct ieee802_11_elems *elems);