From 370017d968e071522357ea88c0c6aaed02853222 Mon Sep 17 00:00:00 2001 From: Ahmad Kholaif Date: Thu, 23 Jul 2015 17:39:45 -0700 Subject: [PATCH] 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 --- src/p2p/p2p.c | 17 +++++++++ src/p2p/p2p.h | 9 +++++ src/p2p/p2p_i.h | 3 ++ wpa_supplicant/p2p_supplicant.c | 66 ++++++++++++++++++++++++++++++--- 4 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index b106fcf87..8cf0b9c6d 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -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"); 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]); + } +} diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 4b1c1f180..15b093ae8 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -23,6 +23,11 @@ #define P2P_MAX_QUERY_HASH 6 #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 */ @@ -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_set_own_pref_freq_list(struct p2p_data *p2p, + const unsigned int *pref_freq_list, + unsigned int size); + #endif /* P2P_H */ diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index f4b24058b..3d6bc7054 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -538,6 +538,9 @@ struct p2p_data { u16 authorized_oob_dev_pw_id; struct wpabuf **vendor_elem; + + unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS]; + unsigned int num_pref_freq; }; /** diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 8f90e38ad..9c11b9ab4 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -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, - 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; 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, 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); + 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 */ if (best_freq > 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; const u8 *if_addr; 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) return -1; @@ -5001,13 +5048,16 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, return ret; } + size = P2P_MAX_PREF_CHANNELS; res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq, - go_intent == 15); + go_intent == 15, pref_freq_list, &size); if (res) return res; wpas_p2p_set_own_freq_preference(wpa_s, 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); 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 res; 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; 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; + size = P2P_MAX_PREF_CHANNELS; 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) return res; @@ -6263,6 +6316,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, int persistent; int freq = 0, force_freq = 0, pref_freq = 0; int res; + unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size; wpa_s->p2p_persistent_go_freq = 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) return -1; + size = P2P_MAX_PREF_CHANNELS; 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) return res; wpas_p2p_set_own_freq_preference(wpa_s, force_freq);