ACS: Extend acs_find_ideal_chan() to support multiple modes
This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou <neojou@gmail.com>
This commit is contained in:
parent
141a8815e7
commit
c60362e6e8
1 changed files with 77 additions and 54 deletions
131
src/ap/acs.c
131
src/ap/acs.c
|
@ -622,58 +622,24 @@ static int is_common_24ghz_chan(int chan)
|
||||||
#define ACS_24GHZ_PREFER_1_6_11 0.8
|
#define ACS_24GHZ_PREFER_1_6_11 0.8
|
||||||
#endif /* ACS_24GHZ_PREFER_1_6_11 */
|
#endif /* ACS_24GHZ_PREFER_1_6_11 */
|
||||||
|
|
||||||
/*
|
static void
|
||||||
* At this point it's assumed chan->interference_factor has been computed.
|
acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
* This function should be reusable regardless of interference computation
|
struct hostapd_hw_modes *mode,
|
||||||
* option (survey, BSS, spectral, ...). chan->interference factor must be
|
int n_chans, u32 bw,
|
||||||
* summable (i.e., must be always greater than zero).
|
struct hostapd_channel_data **rand_chan,
|
||||||
*/
|
struct hostapd_channel_data **ideal_chan,
|
||||||
static struct hostapd_channel_data *
|
long double *ideal_factor)
|
||||||
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 = NULL;
|
||||||
*rand_chan = NULL;
|
long double factor;
|
||||||
long double factor, ideal_factor = 0;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
int n_chans = 1;
|
|
||||||
u32 bw;
|
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
|
|
||||||
/* TODO: HT40- support */
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
|
|
||||||
if (iface->conf->ieee80211n &&
|
|
||||||
iface->conf->secondary_channel == -1) {
|
|
||||||
wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iface->conf->ieee80211n &&
|
|
||||||
iface->conf->secondary_channel)
|
|
||||||
n_chans = 2;
|
|
||||||
|
|
||||||
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
|
|
||||||
switch (hostapd_get_oper_chwidth(iface->conf)) {
|
|
||||||
case CHANWIDTH_80MHZ:
|
|
||||||
n_chans = 4;
|
|
||||||
break;
|
|
||||||
case CHANWIDTH_160MHZ:
|
|
||||||
n_chans = 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bw = num_chan_to_bw(n_chans);
|
|
||||||
|
|
||||||
/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"ACS: Survey analysis for selected bandwidth %d MHz", bw);
|
|
||||||
|
|
||||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
|
||||||
double total_weight;
|
double total_weight;
|
||||||
struct acs_bias *bias, tmp_bias;
|
struct acs_bias *bias, tmp_bias;
|
||||||
|
|
||||||
chan = &iface->current_mode->channels[i];
|
chan = &mode->channels[i];
|
||||||
|
|
||||||
/* Since in the current ACS implementation the first channel is
|
/* Since in the current ACS implementation the first channel is
|
||||||
* always a primary channel, skip channels not available as
|
* always a primary channel, skip channels not available as
|
||||||
|
@ -694,7 +660,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||||
|
|
||||||
/* HT40 on 5 GHz has a limited set of primary channels as per
|
/* HT40 on 5 GHz has a limited set of primary channels as per
|
||||||
* 11n Annex J */
|
* 11n Annex J */
|
||||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||||
iface->conf->ieee80211n &&
|
iface->conf->ieee80211n &&
|
||||||
iface->conf->secondary_channel &&
|
iface->conf->secondary_channel &&
|
||||||
!acs_usable_ht40_chan(chan)) {
|
!acs_usable_ht40_chan(chan)) {
|
||||||
|
@ -703,7 +669,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||||
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
|
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
|
||||||
if (hostapd_get_oper_chwidth(iface->conf) ==
|
if (hostapd_get_oper_chwidth(iface->conf) ==
|
||||||
CHANWIDTH_80MHZ &&
|
CHANWIDTH_80MHZ &&
|
||||||
|
@ -755,7 +721,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||||
|
|
||||||
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
|
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
|
||||||
* channel interference factor. */
|
* channel interference factor. */
|
||||||
if (is_24ghz_mode(iface->current_mode->mode)) {
|
if (is_24ghz_mode(mode->mode)) {
|
||||||
for (j = 0; j < n_chans; j++) {
|
for (j = 0; j < n_chans; j++) {
|
||||||
adj_chan = acs_find_chan(iface, chan->freq +
|
adj_chan = acs_find_chan(iface, chan->freq +
|
||||||
(j * 20) - 5);
|
(j * 20) - 5);
|
||||||
|
@ -801,7 +767,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||||
break;
|
break;
|
||||||
bias = NULL;
|
bias = NULL;
|
||||||
}
|
}
|
||||||
} else if (is_24ghz_mode(iface->current_mode->mode) &&
|
} else if (is_24ghz_mode(mode->mode) &&
|
||||||
is_common_24ghz_chan(chan->chan)) {
|
is_common_24ghz_chan(chan->chan)) {
|
||||||
tmp_bias.channel = chan->chan;
|
tmp_bias.channel = chan->chan;
|
||||||
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
|
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
|
||||||
|
@ -820,14 +786,71 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acs_usable_chan(chan) &&
|
if (acs_usable_chan(chan) &&
|
||||||
(!ideal_chan || factor < ideal_factor)) {
|
(!*ideal_chan || factor < *ideal_factor)) {
|
||||||
ideal_factor = factor;
|
*ideal_factor = factor;
|
||||||
ideal_chan = chan;
|
*ideal_chan = chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This channel would at least be usable */
|
/* This channel would at least be usable */
|
||||||
if (!rand_chan)
|
if (!(*rand_chan))
|
||||||
rand_chan = chan;
|
*rand_chan = chan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point it's assumed chan->interference_factor has been computed.
|
||||||
|
* This function should be reusable regardless of interference computation
|
||||||
|
* option (survey, BSS, spectral, ...). chan->interference factor must be
|
||||||
|
* summable (i.e., must be always greater than zero).
|
||||||
|
*/
|
||||||
|
static struct hostapd_channel_data *
|
||||||
|
acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
struct hostapd_channel_data *ideal_chan = NULL,
|
||||||
|
*rand_chan = NULL;
|
||||||
|
long double ideal_factor = 0;
|
||||||
|
int i;
|
||||||
|
int n_chans = 1;
|
||||||
|
u32 bw;
|
||||||
|
struct hostapd_hw_modes *mode;
|
||||||
|
|
||||||
|
/* TODO: HT40- support */
|
||||||
|
|
||||||
|
if (iface->conf->ieee80211n &&
|
||||||
|
iface->conf->secondary_channel == -1) {
|
||||||
|
wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iface->conf->ieee80211n &&
|
||||||
|
iface->conf->secondary_channel)
|
||||||
|
n_chans = 2;
|
||||||
|
|
||||||
|
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
|
||||||
|
switch (hostapd_get_oper_chwidth(iface->conf)) {
|
||||||
|
case CHANWIDTH_80MHZ:
|
||||||
|
n_chans = 4;
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_160MHZ:
|
||||||
|
n_chans = 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bw = num_chan_to_bw(n_chans);
|
||||||
|
|
||||||
|
/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"ACS: Survey analysis for selected bandwidth %d MHz", bw);
|
||||||
|
|
||||||
|
for (i = 0; i < iface->num_hw_features; i++) {
|
||||||
|
mode = &iface->hw_features[i];
|
||||||
|
if (!hostapd_hw_skip_mode(iface, mode))
|
||||||
|
acs_find_ideal_chan_mode(iface, mode, n_chans, bw,
|
||||||
|
&rand_chan, &ideal_chan,
|
||||||
|
&ideal_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ideal_chan) {
|
if (ideal_chan) {
|
||||||
|
|
Loading…
Reference in a new issue