P2P: Try SD Query with each non-ACK peer only once per search iteration
The previous behavior of bursting out all retry attempts of an SD Query frame during a single search/listen iteration does not look very helpful in the case where the peer does not ACK the query frame. Since the peer was found in the search, but is not ACKing frames anymore, it is likely that it left its listen state and we might as well do something more useful to burst out a significant number of frames in hopes of seeing the peer. Modify the SD Query design during P2P Search to send out only a single attempt (with likely multiple link-layer retries, if needed) per search/listen iteration to each peer that has pending SD queries. Once no more peers with pending queries remain, force another Listen and Search phase to go through before continuing with the pending SD queries. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
e9ccfc38fd
commit
cba9ebfdc2
3 changed files with 48 additions and 5 deletions
|
@ -1228,6 +1228,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
|
|||
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
|
||||
p2p->find_type = type;
|
||||
p2p_device_clear_reported(p2p);
|
||||
os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
|
||||
p2p_set_state(p2p, P2P_SEARCH);
|
||||
p2p->search_delay = search_delay;
|
||||
p2p->in_search_delay = 0;
|
||||
|
@ -3163,13 +3164,18 @@ int p2p_set_country(struct p2p_data *p2p, const char *country)
|
|||
|
||||
static int p2p_pre_find_operation(struct p2p_data *p2p, struct p2p_device *dev)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (dev->sd_pending_bcast_queries == 0) {
|
||||
/* Initialize with total number of registered broadcast
|
||||
* SD queries. */
|
||||
dev->sd_pending_bcast_queries = p2p->num_p2p_sd_queries;
|
||||
}
|
||||
|
||||
if (p2p_start_sd(p2p, dev) == 0)
|
||||
res = p2p_start_sd(p2p, dev);
|
||||
if (res == -2)
|
||||
return -2;
|
||||
if (res == 0)
|
||||
return 1;
|
||||
|
||||
if (dev->req_config_methods &&
|
||||
|
@ -3189,7 +3195,7 @@ static int p2p_pre_find_operation(struct p2p_data *p2p, struct p2p_device *dev)
|
|||
void p2p_continue_find(struct p2p_data *p2p)
|
||||
{
|
||||
struct p2p_device *dev;
|
||||
int found;
|
||||
int found, res;
|
||||
|
||||
p2p_set_state(p2p, P2P_SEARCH);
|
||||
|
||||
|
@ -3202,10 +3208,13 @@ void p2p_continue_find(struct p2p_data *p2p)
|
|||
}
|
||||
if (!found)
|
||||
continue;
|
||||
if (p2p_pre_find_operation(p2p, dev) > 0) {
|
||||
res = p2p_pre_find_operation(p2p, dev);
|
||||
if (res > 0) {
|
||||
p2p->last_p2p_find_oper = dev;
|
||||
return;
|
||||
}
|
||||
if (res == -2)
|
||||
goto skip_sd;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3213,14 +3222,19 @@ void p2p_continue_find(struct p2p_data *p2p)
|
|||
* iteration device.
|
||||
*/
|
||||
dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
|
||||
if (p2p_pre_find_operation(p2p, dev) > 0) {
|
||||
res = p2p_pre_find_operation(p2p, dev);
|
||||
if (res > 0) {
|
||||
p2p->last_p2p_find_oper = dev;
|
||||
return;
|
||||
}
|
||||
if (res == -2)
|
||||
goto skip_sd;
|
||||
if (dev == p2p->last_p2p_find_oper)
|
||||
break;
|
||||
}
|
||||
|
||||
skip_sd:
|
||||
os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
|
||||
p2p_listen_in_find(p2p, 1);
|
||||
}
|
||||
|
||||
|
@ -3232,8 +3246,17 @@ static void p2p_sd_cb(struct p2p_data *p2p, int success)
|
|||
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
|
||||
|
||||
if (!success) {
|
||||
if (p2p->sd_peer)
|
||||
if (p2p->sd_peer) {
|
||||
if (is_zero_ether_addr(p2p->sd_query_no_ack)) {
|
||||
os_memcpy(p2p->sd_query_no_ack,
|
||||
p2p->sd_peer->info.p2p_device_addr,
|
||||
ETH_ALEN);
|
||||
p2p_dbg(p2p,
|
||||
"First SD Query no-ACK in this search iteration: "
|
||||
MACSTR, MAC2STR(p2p->sd_query_no_ack));
|
||||
}
|
||||
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
|
||||
}
|
||||
p2p->sd_peer = NULL;
|
||||
if (p2p->state != P2P_IDLE)
|
||||
p2p_continue_find(p2p);
|
||||
|
|
|
@ -308,6 +308,18 @@ struct p2p_data {
|
|||
*/
|
||||
int num_p2p_sd_queries;
|
||||
|
||||
/**
|
||||
* sd_query_no_ack - The first peer (Dev Addr) that did not ACK SD Query
|
||||
*
|
||||
* This is used to track the first peer that did not ACK an SD Query
|
||||
* within a single P2P Search iteration. All zeros address means no such
|
||||
* peer was yet seen. This information is used to allow a new Listen and
|
||||
* Search phases to be once every pending SD Query has been sent once to
|
||||
* each peer instead of looping all pending attempts continuously until
|
||||
* running out of retry maximums.
|
||||
*/
|
||||
u8 sd_query_no_ack[ETH_ALEN];
|
||||
|
||||
/* GO Negotiation data */
|
||||
|
||||
/**
|
||||
|
|
|
@ -288,6 +288,14 @@ int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev)
|
|||
query = p2p_pending_sd_req(p2p, dev);
|
||||
if (query == NULL)
|
||||
return -1;
|
||||
if (p2p->state == P2P_SEARCH &&
|
||||
os_memcmp(p2p->sd_query_no_ack, dev->info.p2p_device_addr,
|
||||
ETH_ALEN) == 0) {
|
||||
p2p_dbg(p2p, "Do not start Service Discovery with " MACSTR
|
||||
" due to it being the first no-ACK peer in this search iteration",
|
||||
MAC2STR(dev->info.p2p_device_addr));
|
||||
return -2;
|
||||
}
|
||||
|
||||
p2p_dbg(p2p, "Start Service Discovery with " MACSTR,
|
||||
MAC2STR(dev->info.p2p_device_addr));
|
||||
|
|
Loading…
Reference in a new issue