static void acs_scan_complete(struct hostapd_iface *iface) { int err; iface->scan_cb = NULL; wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)", iface->conf->acs_num_scans); err = hostapd_drv_get_survey(iface->bss[0], 0); if (err) { wpa_printf(MSG_ERROR, "ACS: Failed to get survey data"); goto fail; } if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) { err = acs_request_scan(iface); if (err) { wpa_printf(MSG_ERROR, "ACS: Failed to request scan"); goto fail; } return; } acs_study(iface); return; fail: hostapd_acs_completed(iface, 1); acs_fail(iface); }
static void acs_study(struct hostapd_iface *iface) { struct hostapd_channel_data *ideal_chan; int err; err = acs_study_options(iface); if (err < 0) { wpa_printf(MSG_ERROR, "ACS: All study options have failed"); goto fail; } ideal_chan = acs_find_ideal_chan(iface); if (!ideal_chan) { wpa_printf(MSG_ERROR, "ACS: Failed to compute ideal channel"); err = -1; goto fail; } iface->conf->channel = ideal_chan->chan; if (iface->conf->ieee80211ac) acs_adjust_vht_center_freq(iface); err = 0; fail: /* * hostapd_setup_interface_complete() will return -1 on failure, * 0 on success and 0 is HOSTAPD_CHAN_VALID :) */ if (hostapd_acs_completed(iface, err) == HOSTAPD_CHAN_VALID) { acs_cleanup(iface); return; } /* This can possibly happen if channel parameters (secondary * channel, center frequencies) are misconfigured */ wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid, please report this along with your config file."); acs_fail(iface); }
void hostapd_acs_channel_selected(struct hostapd_data *hapd, struct acs_selected_channels *acs_res) { int ret, i; int err = 0; if (hapd->iconf->channel) { wpa_printf(MSG_INFO, "ACS: Channel was already set to %d", hapd->iconf->channel); return; } if (!hapd->iface->current_mode) { for (i = 0; i < hapd->iface->num_hw_features; i++) { struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i]; if (mode->mode == acs_res->hw_mode) { hapd->iface->current_mode = mode; break; } } if (!hapd->iface->current_mode) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_WARNING, "driver selected to bad hw_mode"); err = 1; goto out; } } hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel); if (!acs_res->pri_channel) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_WARNING, "driver switched to bad channel"); err = 1; goto out; } hapd->iconf->channel = acs_res->pri_channel; hapd->iconf->acs = 1; if (acs_res->sec_channel == 0) hapd->iconf->secondary_channel = 0; else if (acs_res->sec_channel < acs_res->pri_channel) hapd->iconf->secondary_channel = -1; else if (acs_res->sec_channel > acs_res->pri_channel) hapd->iconf->secondary_channel = 1; else { wpa_printf(MSG_ERROR, "Invalid secondary channel!"); err = 1; goto out; } if (hapd->iface->conf->ieee80211ac) { /* set defaults for backwards compatibility */ hapd->iconf->vht_oper_centr_freq_seg1_idx = 0; hapd->iconf->vht_oper_centr_freq_seg0_idx = 0; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; if (acs_res->ch_width == 80) { hapd->iconf->vht_oper_centr_freq_seg0_idx = acs_res->vht_seg0_center_ch; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ; } else if (acs_res->ch_width == 160) { if (acs_res->vht_seg1_center_ch == 0) { hapd->iconf->vht_oper_centr_freq_seg0_idx = acs_res->vht_seg0_center_ch; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ; } else { hapd->iconf->vht_oper_centr_freq_seg0_idx = acs_res->vht_seg0_center_ch; hapd->iconf->vht_oper_centr_freq_seg1_idx = acs_res->vht_seg1_center_ch; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80P80MHZ; } } } out: ret = hostapd_acs_completed(hapd->iface, err); if (ret) { wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid"); } }