From: Ahmad Kholaif Date: Thu, 5 Mar 2015 01:24:36 +0000 (-0800) Subject: DFS offload: Add main DFS handler for offloaded case X-Git-Tag: hostap_2_4~38 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fhostap.git;a=commitdiff_plain;h=c13578c3392ccad72cf591383c49841169b7deb4 DFS offload: Add main DFS handler for offloaded case 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 --- diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 46a1d8685..da6fd4646 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1,7 +1,7 @@ /* * DFS - Dynamic Frequency Selection * Copyright (c) 2002-2013, Jouni Malinen - * 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; +} diff --git a/src/ap/dfs.h b/src/ap/dfs.h index a619c55c2..be8c0e600 100644 --- a/src/ap/dfs.h +++ b/src/ap/dfs.h @@ -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 */ diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index c39989c34..bd980e2e9 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -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); diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index e641b129f..f6019ac20 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -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) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index ed8d46619..aca0b7322 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -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; diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 05fe32b45..7f0b296d2 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -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);