P2P: Stop listen state if Action frame TX is needed on another channel
This speeds up P2P responses to frames received on an operating channel in case there is an ongoing P2P listen operation on another channel. This is applicable to drivers that support multiple channels in concurrently. This addresses an issue showing up in the p2ps_channel_active_go_and_station_different_mcc test case where the Provision Discovery Request frame can be received on the operating channel of a group instead of the Listen channel. The response was delayed until the listen operation timed out and this took too long time for the peer to receive the response. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
b3e8ca65a6
commit
947b5a1532
4 changed files with 30 additions and 10 deletions
|
@ -1076,7 +1076,7 @@ static int p2p_run_after_scan(struct p2p_data *p2p)
|
|||
p2p->after_scan_tx->bssid,
|
||||
(u8 *) (p2p->after_scan_tx + 1),
|
||||
p2p->after_scan_tx->len,
|
||||
p2p->after_scan_tx->wait_time);
|
||||
p2p->after_scan_tx->wait_time, NULL);
|
||||
os_free(p2p->after_scan_tx);
|
||||
p2p->after_scan_tx = NULL;
|
||||
return 1;
|
||||
|
@ -4973,6 +4973,8 @@ int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
|
|||
const u8 *src, const u8 *bssid, const u8 *buf,
|
||||
size_t len, unsigned int wait_time)
|
||||
{
|
||||
int res, scheduled;
|
||||
|
||||
if (p2p->p2p_scan_running) {
|
||||
p2p_dbg(p2p, "Delay Action frame TX until p2p_scan completes");
|
||||
if (p2p->after_scan_tx) {
|
||||
|
@ -4993,8 +4995,16 @@ int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
|
||||
buf, len, wait_time);
|
||||
res = p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
|
||||
buf, len, wait_time, &scheduled);
|
||||
if (res == 0 && scheduled && p2p->in_listen && freq > 0 &&
|
||||
(unsigned int) p2p->drv_in_listen != freq) {
|
||||
p2p_dbg(p2p,
|
||||
"Stop listen on %d MHz to allow a frame to be sent immediately on %d MHz",
|
||||
p2p->drv_in_listen, freq);
|
||||
p2p_stop_listen_for_freq(p2p, freq);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -665,6 +665,8 @@ struct p2p_config {
|
|||
* @buf: Frame body (starting from Category field)
|
||||
* @len: Length of buf in octets
|
||||
* @wait_time: How many msec to wait for a response frame
|
||||
* @scheduled: Return value indicating whether the transmissions was
|
||||
* scheduled to happen once the radio is available
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* The Action frame may not be transmitted immediately and the status
|
||||
|
@ -675,7 +677,7 @@ struct p2p_config {
|
|||
*/
|
||||
int (*send_action)(void *ctx, unsigned int freq, const u8 *dst,
|
||||
const u8 *src, const u8 *bssid, const u8 *buf,
|
||||
size_t len, unsigned int wait_time);
|
||||
size_t len, unsigned int wait_time, int *scheduled);
|
||||
|
||||
/**
|
||||
* send_action_done - Notify that Action frame sequence was completed
|
||||
|
|
|
@ -941,7 +941,8 @@ int p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id,
|
|||
if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr,
|
||||
group->cfg->interface_addr,
|
||||
group->cfg->interface_addr,
|
||||
wpabuf_head(req), wpabuf_len(req), 200) < 0)
|
||||
wpabuf_head(req), wpabuf_len(req), 200, NULL)
|
||||
< 0)
|
||||
{
|
||||
p2p_dbg(p2p, "Failed to send Action frame");
|
||||
}
|
||||
|
|
|
@ -1584,20 +1584,27 @@ static int wpas_send_action_work(struct wpa_supplicant *wpa_s,
|
|||
|
||||
static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
|
||||
const u8 *src, const u8 *bssid, const u8 *buf,
|
||||
size_t len, unsigned int wait_time)
|
||||
size_t len, unsigned int wait_time, int *scheduled)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = ctx;
|
||||
int listen_freq = -1, send_freq = -1;
|
||||
|
||||
if (scheduled)
|
||||
*scheduled = 0;
|
||||
if (wpa_s->p2p_listen_work)
|
||||
listen_freq = wpa_s->p2p_listen_work->freq;
|
||||
if (wpa_s->p2p_send_action_work)
|
||||
send_freq = wpa_s->p2p_send_action_work->freq;
|
||||
if (listen_freq != (int) freq && send_freq != (int) freq) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d)",
|
||||
listen_freq, send_freq);
|
||||
return wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
|
||||
len, wait_time);
|
||||
int res;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d freq=%u)",
|
||||
listen_freq, send_freq, freq);
|
||||
res = wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
|
||||
len, wait_time);
|
||||
if (res == 0 && scheduled)
|
||||
*scheduled = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "P2P: Use ongoing radio work for Action frame TX");
|
||||
|
|
Loading…
Reference in a new issue