diff options
| author | Dmitry Shmidt <dimitrysh@google.com> | 2013-10-24 11:08:13 -0700 |
|---|---|---|
| committer | Dmitry Shmidt <dimitrysh@google.com> | 2013-10-24 11:08:13 -0700 |
| commit | 4ce9c87407c036fc83eb5a6044ddf976c86f53fc (patch) | |
| tree | 79a484914a928a845e8410ec65a2129516a60f62 /src/ap | |
| parent | 051af73b8f8014eff33330aead0f36944b3403e6 (diff) | |
| download | android_external_wpa_supplicant_8-4ce9c87407c036fc83eb5a6044ddf976c86f53fc.tar.gz android_external_wpa_supplicant_8-4ce9c87407c036fc83eb5a6044ddf976c86f53fc.tar.bz2 android_external_wpa_supplicant_8-4ce9c87407c036fc83eb5a6044ddf976c86f53fc.zip | |
Cumulative patch from commit fa56315cfc9ebaff2b210ed99d43dda9b16bdf56
fa56315 eap_proxy: Add context data pointer to the get_imsi call
07041c6 eap_proxy: Confirm eap_proxy initialization before reading SIM info
47d986e P2P: Check Action frame payload match before accepted TX status
d259249 Fix ENABLE_NETWORK not to reconnect in disconnected state
677cf19 hostapd: Select any supported channel if ACS fails
20f9cb1 hostapd: Allow ACS to deal with partial survey data
3645fd5 hostapd: Propagate ACS errors to iface setup
0e1d0b3 hostapd: Don't get stuck after failed ACS
af8a827 Make frequency range list routines more general
941dae0 P2P: Add more user friendly debug print of channel lists
Change-Id: I942dbbc0cb92f4e09626ec6ea17f6ea583c17f1a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'src/ap')
| -rw-r--r-- | src/ap/acs.c | 109 | ||||
| -rw-r--r-- | src/ap/acs.h | 2 | ||||
| -rw-r--r-- | src/ap/hw_features.c | 17 |
3 files changed, 79 insertions, 49 deletions
diff --git a/src/ap/acs.c b/src/ap/acs.c index d5e3f596..8536e481 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -352,16 +352,6 @@ acs_survey_chan_interference_factor(struct hostapd_iface *iface, } -static int acs_usable_chan(struct hostapd_channel_data *chan) -{ - if (dl_list_empty(&chan->survey_list)) - return 0; - if (chan->flag & HOSTAPD_CHAN_DISABLED) - return 0; - return 1; -} - - static int acs_usable_ht40_chan(struct hostapd_channel_data *chan) { const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, @@ -398,28 +388,54 @@ static int acs_survey_is_sufficient(struct freq_survey *survey) } +static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan) +{ + struct freq_survey *survey; + + dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list) + { + if (!acs_survey_is_sufficient(survey)) { + wpa_printf(MSG_ERROR, "ACS: Channel %d has insufficient survey data", + chan->chan); + return 0; + } + } + + return 1; + +} + + static int acs_surveys_are_sufficient(struct hostapd_iface *iface) { int i; struct hostapd_channel_data *chan; - struct freq_survey *survey; + int valid = 0; for (i = 0; i < iface->current_mode->num_channels; i++) { chan = &iface->current_mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; - dl_list_for_each(survey, &chan->survey_list, - struct freq_survey, list) - { - if (!acs_survey_is_sufficient(survey)) { - wpa_printf(MSG_ERROR, "ACS: Channel %d has insufficient survey data", - chan->chan); - return 0; - } - } + if (!acs_survey_list_is_sufficient(chan)) + continue; + + valid++; } + /* We need at least survey data for one channel */ + return !!valid; +} + + +static int acs_usable_chan(struct hostapd_channel_data *chan) +{ + if (dl_list_empty(&chan->survey_list)) + return 0; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + return 0; + if (!acs_survey_list_is_sufficient(chan)) + return 0; return 1; } @@ -456,7 +472,7 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, for (i = 0; i < iface->current_mode->num_channels; i++) { chan = &iface->current_mode->channels[i]; - if (!acs_usable_chan(chan)) + if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; if (chan->freq == freq) @@ -476,7 +492,8 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, static struct hostapd_channel_data * acs_find_ideal_chan(struct hostapd_iface *iface) { - struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL; + struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL, + *rand_chan = NULL; long double factor, ideal_factor = 0; int i, j; int n_chans = 1; @@ -508,9 +525,10 @@ acs_find_ideal_chan(struct hostapd_iface *iface) for (i = 0; i < iface->current_mode->num_channels; i++) { chan = &iface->current_mode->channels[i]; - if (!acs_usable_chan(chan)) + if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; + /* HT40 on 5 GHz has a limited set of primary channels as per * 11n Annex J */ if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && @@ -522,14 +540,17 @@ acs_find_ideal_chan(struct hostapd_iface *iface) continue; } - factor = chan->interference_factor; + factor = 0; + if (acs_usable_chan(chan)) + factor = chan->interference_factor; for (j = 1; j < n_chans; j++) { adj_chan = acs_find_chan(iface, chan->freq + (j * 20)); if (!adj_chan) break; - factor += adj_chan->interference_factor; + if (acs_usable_chan(adj_chan)) + factor += adj_chan->interference_factor; } if (j != n_chans) { @@ -548,22 +569,22 @@ acs_find_ideal_chan(struct hostapd_iface *iface) adj_chan = acs_find_chan(iface, chan->freq + (j * 20) - 5); - if (adj_chan) + if (adj_chan && acs_usable_chan(adj_chan)) factor += adj_chan->interference_factor; adj_chan = acs_find_chan(iface, chan->freq + (j * 20) - 10); - if (adj_chan) + if (adj_chan && acs_usable_chan(adj_chan)) factor += adj_chan->interference_factor; adj_chan = acs_find_chan(iface, chan->freq + (j * 20) + 5); - if (adj_chan) + if (adj_chan && acs_usable_chan(adj_chan)) factor += adj_chan->interference_factor; adj_chan = acs_find_chan(iface, chan->freq + (j * 20) + 10); - if (adj_chan) + if (adj_chan && acs_usable_chan(adj_chan)) factor += adj_chan->interference_factor; } } @@ -571,17 +592,24 @@ acs_find_ideal_chan(struct hostapd_iface *iface) wpa_printf(MSG_DEBUG, "ACS: * channel %d: total interference = %Lg", chan->chan, factor); - if (!ideal_chan || factor < ideal_factor) { + if (acs_usable_chan(chan) && + (!ideal_chan || factor < ideal_factor)) { ideal_factor = factor; ideal_chan = chan; } + + /* This channel would at least be usable */ + if (!rand_chan) + rand_chan = chan; } - if (ideal_chan) + if (ideal_chan) { wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg", ideal_chan->chan, ideal_chan->freq, ideal_factor); + return ideal_chan; + } - return ideal_chan; + return rand_chan; } @@ -655,6 +683,7 @@ static void acs_study(struct hostapd_iface *iface) ideal_chan = acs_find_ideal_chan(iface); if (!ideal_chan) { wpa_printf(MSG_ERROR, "ACS: Failed to compute ideal channel"); + err = -1; goto fail; } @@ -663,24 +692,20 @@ static void acs_study(struct hostapd_iface *iface) 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 :) */ - switch (hostapd_acs_completed(iface)) { - case HOSTAPD_CHAN_VALID: + if (hostapd_acs_completed(iface, err) == HOSTAPD_CHAN_VALID) { acs_cleanup(iface); return; - case HOSTAPD_CHAN_INVALID: - case HOSTAPD_CHAN_ACS: - default: - /* 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."); - goto fail; } -fail: + /* 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); } diff --git a/src/ap/acs.h b/src/ap/acs.h index 0d1d0f1a..a41f17f3 100644 --- a/src/ap/acs.h +++ b/src/ap/acs.h @@ -13,7 +13,7 @@ #ifdef CONFIG_ACS enum hostapd_chan_status acs_init(struct hostapd_iface *iface); -int hostapd_acs_completed(struct hostapd_iface *iface); +int hostapd_acs_completed(struct hostapd_iface *iface, int err); #else /* CONFIG_ACS */ diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 9e5becc3..609ed535 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -758,9 +758,12 @@ static void hostapd_notify_bad_chans(struct hostapd_iface *iface) } -int hostapd_acs_completed(struct hostapd_iface *iface) +int hostapd_acs_completed(struct hostapd_iface *iface, int err) { - int ret; + int ret = -1; + + if (err) + goto out; switch (hostapd_check_chans(iface)) { case HOSTAPD_CHAN_VALID: @@ -768,23 +771,25 @@ int hostapd_acs_completed(struct hostapd_iface *iface) case HOSTAPD_CHAN_ACS: wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); hostapd_notify_bad_chans(iface); - return -1; + goto out; case HOSTAPD_CHAN_INVALID: default: wpa_printf(MSG_ERROR, "ACS picked unusable channels"); hostapd_notify_bad_chans(iface); - return -1; + goto out; } ret = hostapd_check_ht_capab(iface); if (ret < 0) - return -1; + goto out; if (ret == 1) { wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); return 0; } - return hostapd_setup_interface_complete(iface, 0); + ret = 0; +out: + return hostapd_setup_interface_complete(iface, ret); } |
