P2P: Modify wpas_p2p_init_go_params()

Not all paths in wpas_p2p_init_go_params() verified that the candidate
frequency can be used for GO purposes. Fix this, and in addition
re-factor the code to put better emphasis on the frequency selection
priorities.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
This commit is contained in:
Ilan Peer 2015-07-27 22:24:23 +03:00 committed by Jouni Malinen
parent a7160f7ede
commit b130812100

View file

@ -5355,30 +5355,45 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
} }
static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, static int wpas_p2p_supported_freq_go(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params, const struct p2p_channels *channels,
const struct p2p_channels *channels) int freq)
{
if (!wpas_p2p_disallowed_freq(wpa_s->global, freq) &&
p2p_supported_freq_go(wpa_s->global->p2p, freq) &&
freq_included(wpa_s, channels, freq))
return 1;
return 0;
}
static void wpas_p2p_select_go_freq_no_pref(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params,
const struct p2p_channels *channels)
{ {
unsigned int i, r; unsigned int i, r;
/* first try some random selection of the social channels */ /* first try some random selection of the social channels */
if (os_get_random((u8 *) &r, sizeof(r)) < 0) if (os_get_random((u8 *) &r, sizeof(r)) < 0)
return -1; return;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
params->freq = 2412 + ((r + i) % 3) * 25; params->freq = 2412 + ((r + i) % 3) * 25;
if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
freq_included(wpa_s, channels, params->freq) &&
p2p_supported_freq(wpa_s->global->p2p, params->freq))
goto out; goto out;
} }
/* try all channels in reg. class 81 */ /* try all other channels in operating class 81 */
for (i = 0; i < 11; i++) { for (i = 0; i < 11; i++) {
params->freq = 2412 + i * 5; params->freq = 2412 + i * 5;
if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
freq_included(wpa_s, channels, params->freq) && /* skip social channels; covered in the previous loop */
p2p_supported_freq(wpa_s->global->p2p, params->freq)) if (params->freq == 2412 ||
params->freq == 2437 ||
params->freq == 2462)
continue;
if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
goto out; goto out;
} }
@ -5416,12 +5431,12 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s,
goto out; goto out;
} }
params->freq = 0;
wpa_printf(MSG_DEBUG, "P2P: No 2.4, 5, or 60 GHz channel allowed"); wpa_printf(MSG_DEBUG, "P2P: No 2.4, 5, or 60 GHz channel allowed");
return -1; return;
out: out:
wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference known)", wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference known)",
params->freq); params->freq);
return 0;
} }
@ -5431,7 +5446,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
const struct p2p_channels *channels) const struct p2p_channels *channels)
{ {
struct wpa_used_freq_data *freqs; struct wpa_used_freq_data *freqs;
unsigned int pref_freq, cand_freq; unsigned int cand;
unsigned int num, i; unsigned int num, i;
os_memset(params, 0, sizeof(*params)); os_memset(params, 0, sizeof(*params));
@ -5443,81 +5458,6 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "P2P: %s called for an active GO", wpa_printf(MSG_DEBUG, "P2P: %s called for an active GO",
__func__); __func__);
if (freq) {
if (!freq_included(wpa_s, channels, freq)) {
wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
"accepted", freq);
return -1;
}
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
"frequency %d MHz", freq);
params->freq = freq;
} else if (wpa_s->conf->p2p_oper_reg_class == 81 &&
wpa_s->conf->p2p_oper_channel >= 1 &&
wpa_s->conf->p2p_oper_channel <= 11 &&
freq_included(wpa_s, channels,
2407 + 5 * wpa_s->conf->p2p_oper_channel)) {
params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
} else if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
wpa_s->conf->p2p_oper_reg_class == 116 ||
wpa_s->conf->p2p_oper_reg_class == 117 ||
wpa_s->conf->p2p_oper_reg_class == 124 ||
wpa_s->conf->p2p_oper_reg_class == 125 ||
wpa_s->conf->p2p_oper_reg_class == 126 ||
wpa_s->conf->p2p_oper_reg_class == 127) &&
freq_included(wpa_s, channels,
5000 + 5 * wpa_s->conf->p2p_oper_channel)) {
params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
} else if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_overall_freq > 0 &&
p2p_supported_freq_go(wpa_s->global->p2p,
wpa_s->best_overall_freq) &&
freq_included(wpa_s, channels, wpa_s->best_overall_freq)) {
params->freq = wpa_s->best_overall_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall "
"channel %d MHz", params->freq);
} else if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_24_freq > 0 &&
p2p_supported_freq_go(wpa_s->global->p2p,
wpa_s->best_24_freq) &&
freq_included(wpa_s, channels, wpa_s->best_24_freq)) {
params->freq = wpa_s->best_24_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz "
"channel %d MHz", params->freq);
} else if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_5_freq > 0 &&
p2p_supported_freq_go(wpa_s->global->p2p,
wpa_s->best_5_freq) &&
freq_included(wpa_s, channels, wpa_s->best_5_freq)) {
params->freq = wpa_s->best_5_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
"channel %d MHz", params->freq);
} else if ((pref_freq = p2p_get_pref_freq(wpa_s->global->p2p,
channels))) {
params->freq = pref_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
"channels", params->freq);
} else if (wpa_s->p2p_group_common_freqs) {
for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
if (freq_included(wpa_s, channels,
wpa_s->p2p_group_common_freqs[i])) {
params->freq = wpa_s->p2p_group_common_freqs[i];
wpa_printf(MSG_DEBUG,
"P2P: Use freq %d MHz common with the peer",
params->freq);
break;
}
}
} else {
/* no preference, select some channel */
if (wpas_p2p_select_freq_no_pref(wpa_s, params, channels) < 0)
return -1;
}
freqs = os_calloc(wpa_s->num_multichan_concurrent, freqs = os_calloc(wpa_s->num_multichan_concurrent,
sizeof(struct wpa_used_freq_data)); sizeof(struct wpa_used_freq_data));
if (!freqs) if (!freqs)
@ -5526,41 +5466,166 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
num = wpas_p2p_valid_oper_freqs(wpa_s, freqs, num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
wpa_s->num_multichan_concurrent); wpa_s->num_multichan_concurrent);
cand_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num); /* try using the forced freq */
if (freq) {
if (!wpas_p2p_supported_freq_go(wpa_s, channels, freq)) {
wpa_printf(MSG_DEBUG,
"P2P: Forced GO freq %d MHz not accepted",
freq);
goto fail;
}
for (i = 0; i < num; i++) {
if (freqs[i].freq == freq) {
wpa_printf(MSG_DEBUG,
"P2P: forced freq (%d MHz) is also shared",
freq);
params->freq = freq;
goto success;
}
}
/* First try the best used frequency if possible */
if (!freq && cand_freq > 0) {
params->freq = cand_freq;
} else if (!freq) {
if (wpas_p2p_num_unused_channels(wpa_s) <= 0) { if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"P2P: Cannot force GO on any of the channels we are already using"); "P2P: Cannot force GO on freq (%d MHz) as all the channels are in use",
os_free(freqs); freq);
return -1; goto fail;
} else {
wpa_printf(MSG_DEBUG,
"P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels");
}
} else {
for (i = 0; i < num; i++) {
if (freqs[i].freq == freq)
break;
} }
if (i == num) { wpa_printf(MSG_DEBUG,
if (wpas_p2p_num_unused_channels(wpa_s) <= 0) { "P2P: force GO freq (%d MHz) on a free channel",
if (freq) freq);
wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%u MHz) as all the channels are in use", freq); params->freq = freq;
os_free(freqs); goto success;
return -1; }
} else {
wpa_printf(MSG_DEBUG, "P2P: Use one of the free channels"); /* consider using one of the shared frequencies */
if (num) {
cand = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
wpa_printf(MSG_DEBUG,
"P2P: Use shared freq (%d MHz) for GO",
freq);
params->freq = cand;
goto success;
}
/* try using one of the shared freqs */
for (i = 0; i < num; i++) {
if (wpas_p2p_supported_freq_go(wpa_s, channels,
freqs[i].freq)) {
wpa_printf(MSG_DEBUG,
"P2P: Use shared freq (%d MHz) for GO",
freq);
params->freq = freqs[i].freq;
goto success;
} }
} }
} }
if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
wpa_printf(MSG_DEBUG,
"P2P: Cannot force GO on any of the channels we are already using");
goto fail;
}
/* try using the setting from the configuration file */
if (wpa_s->conf->p2p_oper_reg_class == 81 &&
wpa_s->conf->p2p_oper_channel >= 1 &&
wpa_s->conf->p2p_oper_channel <= 11 &&
wpas_p2p_supported_freq_go(
wpa_s, channels,
2407 + 5 * wpa_s->conf->p2p_oper_channel)) {
params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
goto success;
}
if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
wpa_s->conf->p2p_oper_reg_class == 116 ||
wpa_s->conf->p2p_oper_reg_class == 117 ||
wpa_s->conf->p2p_oper_reg_class == 124 ||
wpa_s->conf->p2p_oper_reg_class == 125 ||
wpa_s->conf->p2p_oper_reg_class == 126 ||
wpa_s->conf->p2p_oper_reg_class == 127) &&
wpas_p2p_supported_freq_go(wpa_s, channels,
5000 +
5 * wpa_s->conf->p2p_oper_channel)) {
params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
goto success;
}
/* Try using best channels */
if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_overall_freq > 0 &&
wpas_p2p_supported_freq_go(wpa_s, channels,
wpa_s->best_overall_freq)) {
params->freq = wpa_s->best_overall_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall "
"channel %d MHz", params->freq);
goto success;
}
if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_24_freq > 0 &&
wpas_p2p_supported_freq_go(wpa_s, channels,
wpa_s->best_24_freq)) {
params->freq = wpa_s->best_24_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz "
"channel %d MHz", params->freq);
goto success;
}
if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_5_freq > 0 &&
wpas_p2p_supported_freq_go(wpa_s, channels,
wpa_s->best_5_freq)) {
params->freq = wpa_s->best_5_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
"channel %d MHz", params->freq);
goto success;
}
/* try using preferred channels */
cand = p2p_get_pref_freq(wpa_s->global->p2p, channels);
if (cand && wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
params->freq = cand;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
"channels", params->freq);
goto success;
}
/* Try using one of the group common freqs */
if (wpa_s->p2p_group_common_freqs) {
for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
cand = wpa_s->p2p_group_common_freqs[i];
if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
params->freq = cand;
wpa_printf(MSG_DEBUG,
"P2P: Use freq %d MHz common with the peer",
params->freq);
goto success;
}
}
}
/* no preference, select some channel */
wpas_p2p_select_go_freq_no_pref(wpa_s, params, channels);
if (params->freq == 0) {
wpa_printf(MSG_DEBUG, "P2P: did not find a freq for GO use");
goto fail;
}
success:
os_free(freqs); os_free(freqs);
return 0; return 0;
fail:
os_free(freqs);
return -1;
} }