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 <jouni@qca.qualcomm.com>
This commit is contained in:
parent
5de81d7a7a
commit
c13578c339
6 changed files with 109 additions and 1 deletions
52
src/ap/dfs.c
52
src/ap/dfs.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue