P2P: Use preferred frequency list from the local driver

If the driver supports the preferred frequency list extension, use this
information from the driver when no explicitly configured preference
list (p2p_pref_chan) is present for P2P operating channel selection.
This commit adds this for GO Negotiation and Invitation use cases.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Ahmad Kholaif 2015-07-23 17:39:45 -07:00 committed by Jouni Malinen
parent 9baaac2d84
commit 370017d968
4 changed files with 90 additions and 5 deletions

View file

@ -5383,3 +5383,20 @@ void p2p_go_neg_wait_timeout(void *eloop_ctx, void *timeout_ctx)
"Timeout on waiting peer to become ready for GO Negotiation"); "Timeout on waiting peer to become ready for GO Negotiation");
p2p_go_neg_failed(p2p, -1); p2p_go_neg_failed(p2p, -1);
} }
void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
const unsigned int *pref_freq_list,
unsigned int size)
{
unsigned int i;
if (size > P2P_MAX_PREF_CHANNELS)
size = P2P_MAX_PREF_CHANNELS;
p2p->num_pref_freq = size;
for (i = 0; i < size; i++) {
p2p->pref_freq_list[i] = pref_freq_list[i];
p2p_dbg(p2p, "Own preferred frequency list[%u]=%u MHz",
i, p2p->pref_freq_list[i]);
}
}

View file

@ -23,6 +23,11 @@
#define P2P_MAX_QUERY_HASH 6 #define P2P_MAX_QUERY_HASH 6
#define P2PS_FEATURE_CAPAB_CPT_MAX 2 #define P2PS_FEATURE_CAPAB_CPT_MAX 2
/**
* P2P_MAX_PREF_CHANNELS - Maximum number of preferred channels
*/
#define P2P_MAX_PREF_CHANNELS 100
/** /**
* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes * P2P_MAX_REG_CLASSES - Maximum number of regulatory classes
*/ */
@ -2302,4 +2307,8 @@ struct p2ps_advertisement * p2p_get_p2ps_adv_list(struct p2p_data *p2p);
*/ */
void p2p_expire_peers(struct p2p_data *p2p); void p2p_expire_peers(struct p2p_data *p2p);
void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
const unsigned int *pref_freq_list,
unsigned int size);
#endif /* P2P_H */ #endif /* P2P_H */

View file

@ -538,6 +538,9 @@ struct p2p_data {
u16 authorized_oob_dev_pw_id; u16 authorized_oob_dev_pw_id;
struct wpabuf **vendor_elem; struct wpabuf **vendor_elem;
unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS];
unsigned int num_pref_freq;
}; };
/** /**

View file

@ -4792,11 +4792,16 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq, static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
int *force_freq, int *pref_freq, int go) int *force_freq, int *pref_freq, int go,
unsigned int *pref_freq_list,
unsigned int *num_pref_freq)
{ {
struct wpa_used_freq_data *freqs; struct wpa_used_freq_data *freqs;
int res, best_freq, num_unused; int res, best_freq, num_unused;
unsigned int freq_in_use = 0, num, i; unsigned int freq_in_use = 0, num, i, max_pref_freq;
max_pref_freq = *num_pref_freq;
*num_pref_freq = 0;
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));
@ -4861,6 +4866,47 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
best_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num); best_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
if (!wpa_s->conf->num_p2p_pref_chan && *pref_freq == 0) {
enum wpa_driver_if_type iface_type;
if (go)
iface_type = WPA_IF_P2P_GO;
else
iface_type = WPA_IF_P2P_CLIENT;
wpa_printf(MSG_DEBUG, "P2P: best_freq=%d, go=%d",
best_freq, go);
res = wpa_drv_get_pref_freq_list(wpa_s, iface_type,
&max_pref_freq,
pref_freq_list);
if (!res && max_pref_freq > 0) {
*num_pref_freq = max_pref_freq;
i = 0;
while (wpas_p2p_disallowed_freq(wpa_s->global,
pref_freq_list[i]) &&
i < *num_pref_freq) {
wpa_printf(MSG_DEBUG,
"P2P: preferred_freq_list[%d]=%d is disallowed",
i, pref_freq_list[i]);
i++;
}
if (i != *num_pref_freq) {
best_freq = pref_freq_list[i];
wpa_printf(MSG_DEBUG,
"P2P: Using preferred_freq_list[%d]=%d",
i, best_freq);
} else {
wpa_printf(MSG_DEBUG,
"P2P: All driver preferred frequencies are disallowed for P2P use");
*num_pref_freq = 0;
}
} else {
wpa_printf(MSG_DEBUG,
"P2P: No preferred frequency list available");
}
}
/* We have a candidate frequency to use */ /* We have a candidate frequency to use */
if (best_freq > 0) { if (best_freq > 0) {
if (*pref_freq == 0 && num_unused > 0) { if (*pref_freq == 0 && num_unused > 0) {
@ -4925,6 +4971,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
enum wpa_driver_if_type iftype; enum wpa_driver_if_type iftype;
const u8 *if_addr; const u8 *if_addr;
struct wpa_ssid *ssid = NULL; struct wpa_ssid *ssid = NULL;
unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1; return -1;
@ -5001,13 +5048,16 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
return ret; return ret;
} }
size = P2P_MAX_PREF_CHANNELS;
res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq, res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
go_intent == 15); go_intent == 15, pref_freq_list, &size);
if (res) if (res)
return res; return res;
wpas_p2p_set_own_freq_preference(wpa_s, wpas_p2p_set_own_freq_preference(wpa_s,
force_freq ? force_freq : pref_freq); force_freq ? force_freq : pref_freq);
p2p_set_own_pref_freq_list(wpa_s->global->p2p, pref_freq_list, size);
wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s); wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
if (wpa_s->create_p2p_iface) { if (wpa_s->create_p2p_iface) {
@ -6190,6 +6240,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int force_freq = 0; int force_freq = 0;
int res; int res;
int no_pref_freq_given = pref_freq == 0; int no_pref_freq_given = pref_freq == 0;
unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
wpa_s->global->p2p_invite_group = NULL; wpa_s->global->p2p_invite_group = NULL;
if (peer_addr) if (peer_addr)
@ -6223,8 +6274,10 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
} }
wpa_s->pending_invite_ssid_id = ssid->id; wpa_s->pending_invite_ssid_id = ssid->id;
size = P2P_MAX_PREF_CHANNELS;
res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq, res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
role == P2P_INVITE_ROLE_GO); role == P2P_INVITE_ROLE_GO,
pref_freq_list, &size);
if (res) if (res)
return res; return res;
@ -6263,6 +6316,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
int persistent; int persistent;
int freq = 0, force_freq = 0, pref_freq = 0; int freq = 0, force_freq = 0, pref_freq = 0;
int res; int res;
unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
wpa_s->p2p_persistent_go_freq = 0; wpa_s->p2p_persistent_go_freq = 0;
wpa_s->p2p_go_ht40 = 0; wpa_s->p2p_go_ht40 = 0;
@ -6314,8 +6368,10 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1; return -1;
size = P2P_MAX_PREF_CHANNELS;
res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq, res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
role == P2P_INVITE_ROLE_ACTIVE_GO); role == P2P_INVITE_ROLE_ACTIVE_GO,
pref_freq_list, &size);
if (res) if (res)
return res; return res;
wpas_p2p_set_own_freq_preference(wpa_s, force_freq); wpas_p2p_set_own_freq_preference(wpa_s, force_freq);