P2P: Fix shared frequency preference for concurrent operations

Commit 50285f5ca8 changed number of rules
in channel selection and among other things, it broke the design where
the currently used operating channel on a virtual interface that is
shared by the same radio is preferred to avoid costs related to
multi-channel concurrency. Fix this regression by making the P2P module
aware of the shared channel and using that preference as the highest
priority when re-selecting the channel during negotiation.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-03-14 16:22:31 +02:00 committed by Jouni Malinen
parent 62e10e6e3d
commit 6cb27aa85f
5 changed files with 47 additions and 0 deletions

View file

@ -4202,6 +4202,14 @@ void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
} }
void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
{
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own frequency preference: "
"%d MHz", freq);
p2p->own_freq_preference = freq;
}
const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p) const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
{ {
if (p2p == NULL || p2p->go_neg_peer == NULL) if (p2p == NULL || p2p->go_neg_peer == NULL)

View file

@ -1641,6 +1641,17 @@ void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan);
void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5, void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
int freq_overall); int freq_overall);
/**
* p2p_set_own_freq_preference - Set own preference for channel
* @p2p: P2P module context from p2p_init()
* @freq: Frequency (MHz) of the preferred channel or 0 if no preference
*
* This function can be used to set a preference on the operating channel based
* on frequencies used on the other virtual interfaces that share the same
* radio. If non-zero, this is used to try to avoid multi-channel concurrency.
*/
void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq);
const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p); const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p);
/** /**

View file

@ -350,6 +350,18 @@ void p2p_reselect_channel(struct p2p_data *p2p,
u8 op_reg_class, op_channel; u8 op_reg_class, op_channel;
unsigned int i; unsigned int i;
if (p2p->own_freq_preference > 0 &&
p2p_freq_to_channel(p2p->cfg->country, p2p->own_freq_preference,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick own channel "
"preference (reg_class %u channel %u) from "
"intersection", op_reg_class, op_channel);
p2p->op_reg_class = op_reg_class;
p2p->op_channel = op_channel;
return;
}
if (p2p->best_freq_overall > 0 && if (p2p->best_freq_overall > 0 &&
p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall, p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
&op_reg_class, &op_channel) == 0 && &op_reg_class, &op_channel) == 0 &&

View file

@ -417,6 +417,7 @@ struct p2p_data {
int best_freq_24; int best_freq_24;
int best_freq_5; int best_freq_5;
int best_freq_overall; int best_freq_overall;
int own_freq_preference;
/** /**
* wps_vendor_ext - WPS Vendor Extensions to add * wps_vendor_ext - WPS Vendor Extensions to add

View file

@ -93,6 +93,15 @@ static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s); static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
static void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s,
int freq)
{
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return;
p2p_set_own_freq_preference(wpa_s->global->p2p, freq);
}
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res) struct wpa_scan_results *scan_res)
{ {
@ -2410,11 +2419,14 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
} }
accept_inv: accept_inv:
wpas_p2p_set_own_freq_preference(wpa_s, 0);
if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, cur_bssid) == 0 && if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, cur_bssid) == 0 &&
wpa_s->assoc_freq) { wpa_s->assoc_freq) {
wpa_printf(MSG_DEBUG, "P2P: Trying to force channel to match " wpa_printf(MSG_DEBUG, "P2P: Trying to force channel to match "
"the channel we are already using"); "the channel we are already using");
*force_freq = wpa_s->assoc_freq; *force_freq = wpa_s->assoc_freq;
wpas_p2p_set_own_freq_preference(wpa_s, wpa_s->assoc_freq);
} }
res = wpa_drv_shared_freq(wpa_s); res = wpa_drv_shared_freq(wpa_s);
@ -2423,6 +2435,7 @@ accept_inv:
"with the channel we are already using on a " "with the channel we are already using on a "
"shared interface"); "shared interface");
*force_freq = res; *force_freq = res;
wpas_p2p_set_own_freq_preference(wpa_s, res);
} }
return P2P_SC_SUCCESS; return P2P_SC_SUCCESS;
@ -3736,6 +3749,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
&oper_freq); &oper_freq);
if (res) if (res)
return res; return res;
wpas_p2p_set_own_freq_preference(wpa_s, oper_freq);
wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s); wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
@ -4807,6 +4821,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
&oper_freq); &oper_freq);
if (res) if (res)
return res; return res;
wpas_p2p_set_own_freq_preference(wpa_s, oper_freq);
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid, return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len, force_freq, ssid->ssid, ssid->ssid_len, force_freq,