ACS: Allow specific channels to be preferred
The new acs_chan_bias configuration parameter is a space-separated list of <channel>:<bias> pairs. It can be used to increase (or decrease) the likelihood of a specific channel to be selected by the ACS algorithm. The total interference factor for each channel gets multiplied by the specified bias value before finding the channel with the lowest value. In other words, values between 0.0 and 1.0 can be used to make a channel more likely to be picked while values larger than 1.0 make the specified channel less likely to be picked. This can be used, e.g., to prefer the commonly used 2.4 GHz band channels 1, 6, and 11 (which is the default behavior on 2.4 GHz band if no acs_chan_bias parameter is specified). Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
6f41a25805
commit
68fa00c341
5 changed files with 117 additions and 4 deletions
54
src/ap/acs.c
54
src/ap/acs.c
|
@ -517,6 +517,19 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
|
|||
}
|
||||
|
||||
|
||||
static int is_24ghz_mode(enum hostapd_hw_mode mode)
|
||||
{
|
||||
return mode == HOSTAPD_MODE_IEEE80211B ||
|
||||
mode == HOSTAPD_MODE_IEEE80211G;
|
||||
}
|
||||
|
||||
|
||||
static int is_common_24ghz_chan(int chan)
|
||||
{
|
||||
return chan == 1 || chan == 6 || chan == 11;
|
||||
}
|
||||
|
||||
|
||||
#ifndef ACS_ADJ_WEIGHT
|
||||
#define ACS_ADJ_WEIGHT 0.85
|
||||
#endif /* ACS_ADJ_WEIGHT */
|
||||
|
@ -525,6 +538,15 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
|
|||
#define ACS_NEXT_ADJ_WEIGHT 0.55
|
||||
#endif /* ACS_NEXT_ADJ_WEIGHT */
|
||||
|
||||
#ifndef ACS_24GHZ_PREFER_1_6_11
|
||||
/*
|
||||
* Select commonly used channels 1, 6, 11 by default even if a neighboring
|
||||
* channel has a smaller interference factor as long as it is not better by more
|
||||
* than this multiplier.
|
||||
*/
|
||||
#define ACS_24GHZ_PREFER_1_6_11 0.8
|
||||
#endif /* ACS_24GHZ_PREFER_1_6_11 */
|
||||
|
||||
/*
|
||||
* At this point it's assumed chan->interface_factor has been computed.
|
||||
* This function should be reusable regardless of interference computation
|
||||
|
@ -539,6 +561,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
long double factor, ideal_factor = 0;
|
||||
int i, j;
|
||||
int n_chans = 1;
|
||||
unsigned int k;
|
||||
|
||||
/* TODO: HT40- support */
|
||||
|
||||
|
@ -566,6 +589,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
double total_weight;
|
||||
struct acs_bias *bias, tmp_bias;
|
||||
|
||||
chan = &iface->current_mode->channels[i];
|
||||
|
||||
|
@ -619,8 +643,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
|
||||
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
|
||||
* channel interference factor. */
|
||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B ||
|
||||
iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) {
|
||||
if (is_24ghz_mode(iface->current_mode->mode)) {
|
||||
for (j = 0; j < n_chans; j++) {
|
||||
adj_chan = acs_find_chan(iface, chan->freq +
|
||||
(j * 20) - 5);
|
||||
|
@ -658,8 +681,31 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
|
||||
factor /= total_weight;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ACS: * channel %d: total interference = %Lg",
|
||||
chan->chan, factor);
|
||||
bias = NULL;
|
||||
if (iface->conf->acs_chan_bias) {
|
||||
for (k = 0; k < iface->conf->num_acs_chan_bias; k++) {
|
||||
bias = &iface->conf->acs_chan_bias[k];
|
||||
if (bias->channel == chan->chan)
|
||||
break;
|
||||
bias = NULL;
|
||||
}
|
||||
} else if (is_24ghz_mode(iface->current_mode->mode) &&
|
||||
is_common_24ghz_chan(chan->chan)) {
|
||||
tmp_bias.channel = chan->chan;
|
||||
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
|
||||
bias = &tmp_bias;
|
||||
}
|
||||
|
||||
if (bias) {
|
||||
factor *= bias->bias;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: * channel %d: total interference = %Lg (%f bias)",
|
||||
chan->chan, factor, bias->bias);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: * channel %d: total interference = %Lg",
|
||||
chan->chan, factor);
|
||||
}
|
||||
|
||||
if (acs_usable_chan(chan) &&
|
||||
(!ideal_chan || factor < ideal_factor)) {
|
||||
|
|
|
@ -574,6 +574,9 @@ void hostapd_config_free(struct hostapd_config *conf)
|
|||
os_free(conf->basic_rates);
|
||||
os_free(conf->chanlist);
|
||||
os_free(conf->driver_params);
|
||||
#ifdef CONFIG_ACS
|
||||
os_free(conf->acs_chan_bias);
|
||||
#endif /* CONFIG_ACS */
|
||||
|
||||
os_free(conf);
|
||||
}
|
||||
|
|
|
@ -639,6 +639,11 @@ struct hostapd_config {
|
|||
|
||||
#ifdef CONFIG_ACS
|
||||
unsigned int acs_num_scans;
|
||||
struct acs_bias {
|
||||
int channel;
|
||||
double bias;
|
||||
} *acs_chan_bias;
|
||||
unsigned int num_acs_chan_bias;
|
||||
#endif /* CONFIG_ACS */
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue