P2P: Reselect operating channel preference based on best channels

When the peer does not include our initial preference in the Channel
List attribute during GO Negotiation, try to use the best channel of
the other band as the new preference instead of falling back to the
first channel in the intersection.
This commit is contained in:
Jouni Malinen 2010-11-10 13:34:33 +02:00 committed by Jouni Malinen
parent 7cfc4ac319
commit 91626c9fa7

View file

@ -292,6 +292,57 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
} }
static void p2p_reselect_channel(struct p2p_data *p2p,
struct p2p_channels *intersection)
{
struct p2p_reg_class *cl;
int freq;
u8 op_reg_class, op_channel;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
"channel (reg_class %u channel %u) not acceptable to the "
"peer", p2p->op_reg_class, p2p->op_channel);
/* First, try to pick the best channel from another band */
freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class,
p2p->op_channel);
if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 &&
p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
&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 best 5 GHz "
"channel (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 (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 &&
p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
&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 best 2.4 GHz "
"channel (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;
}
/*
* Fall back to whatever is included in the channel intersection since
* no better options seems to be available.
*/
cl = &intersection->reg_class[0];
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick another channel "
"(reg_class %u channel %u) from intersection",
cl->reg_class, cl->channel[0]);
p2p->op_reg_class = cl->reg_class;
p2p->op_channel = cl->channel[0];
}
void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa, void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq) const u8 *data, size_t len, int rx_freq)
{ {
@ -543,20 +594,8 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
} }
if (!p2p_channels_includes(&intersection, if (!p2p_channels_includes(&intersection,
p2p->op_reg_class, p2p->op_reg_class,
p2p->op_channel)) { p2p->op_channel))
struct p2p_reg_class *cl; p2p_reselect_channel(p2p, &intersection);
cl = &intersection.reg_class[0];
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Selected operating channel "
"(reg_class %u channel %u) not "
"acceptable to the peer - pick "
"another channel (reg_class %u "
"channel %u)",
p2p->op_reg_class, p2p->op_channel,
cl->reg_class, cl->channel[0]);
p2p->op_reg_class = cl->reg_class;
p2p->op_channel = cl->channel[0];
}
p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len); p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len);
} }
@ -937,20 +976,8 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
c->channel, c->channels); c->channel, c->channels);
} }
if (!p2p_channels_includes(&intersection, p2p->op_reg_class, if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
p2p->op_channel)) { p2p->op_channel))
struct p2p_reg_class *cl; p2p_reselect_channel(p2p, &intersection);
cl = &intersection.reg_class[0];
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Selected operating channel "
"(reg_class %u channel %u) not "
"acceptable to the peer - pick "
"another channel (reg_class %u "
"channel %u)",
p2p->op_reg_class, p2p->op_channel,
cl->reg_class, cl->channel[0]);
p2p->op_reg_class = cl->reg_class;
p2p->op_channel = cl->channel[0];
}
p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len); p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len);
} }