diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 2ecc5473c..7170e47ed 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -733,9 +733,6 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, p2p_parse_free(&msg); - if (p2p_pending_sd_req(p2p, dev)) - dev->flags |= P2P_DEV_SD_SCHEDULE; - if (dev->flags & P2P_DEV_REPORTED) return 0; @@ -2406,6 +2403,7 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) p2p->go_timeout = 100; p2p->client_timeout = 20; + p2p->num_p2p_sd_queries = 0; p2p_dbg(p2p, "initialized"); p2p_channels_dump(p2p, "channels", &p2p->cfg->channels); @@ -2641,13 +2639,16 @@ void p2p_continue_find(struct p2p_data *p2p) struct p2p_device *dev; p2p_set_state(p2p, P2P_SEARCH); dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { - if (dev->flags & P2P_DEV_SD_SCHEDULE) { - if (p2p_start_sd(p2p, dev) == 0) - return; - else - break; - } else if (dev->req_config_methods && - !(dev->flags & P2P_DEV_PD_FOR_JOIN)) { + 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) + return; + if (dev->req_config_methods && + !(dev->flags & P2P_DEV_PD_FOR_JOIN)) { p2p_dbg(p2p, "Send pending Provision Discovery Request to " MACSTR " (config methods 0x%x)", MAC2STR(dev->info.p2p_device_addr), @@ -2668,10 +2669,7 @@ 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) { - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; - p2p->sd_peer = NULL; - } + p2p->sd_peer = NULL; p2p_continue_find(p2p); return; } @@ -3216,7 +3214,6 @@ static void p2p_timeout_sd_during_find(struct p2p_data *p2p) p2p_dbg(p2p, "Service Discovery Query timeout"); if (p2p->sd_peer) { p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; p2p->sd_peer = NULL; } p2p_continue_find(p2p); @@ -3487,7 +3484,7 @@ int p2p_get_peer_info_txt(const struct p2p_peer_info *info, "country=%c%c\n" "oper_freq=%d\n" "req_config_methods=0x%x\n" - "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" + "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s\n" "status=%d\n" "wait_count=%u\n" "invitation_reqs=%u\n", @@ -3510,9 +3507,6 @@ int p2p_get_peer_info_txt(const struct p2p_peer_info *info, dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "", dev->flags & P2P_DEV_NOT_YET_READY ? "[NOT_YET_READY]" : "", - dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "", - dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" : - "", dev->flags & P2P_DEV_PD_PEER_DISPLAY ? "[PD_PEER_DISPLAY]" : "", dev->flags & P2P_DEV_PD_PEER_KEYPAD ? diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index f1050836c..6de346166 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -81,8 +81,6 @@ struct p2p_device { #define P2P_DEV_PROBE_REQ_ONLY BIT(0) #define P2P_DEV_REPORTED BIT(1) #define P2P_DEV_NOT_YET_READY BIT(2) -#define P2P_DEV_SD_INFO BIT(3) -#define P2P_DEV_SD_SCHEDULE BIT(4) #define P2P_DEV_PD_PEER_DISPLAY BIT(5) #define P2P_DEV_PD_PEER_KEYPAD BIT(6) #define P2P_DEV_USER_REJECTED BIT(7) @@ -110,6 +108,7 @@ struct p2p_device { u8 go_timeout; u8 client_timeout; + int sd_pending_bcast_queries; }; struct p2p_sd_query { @@ -256,6 +255,12 @@ struct p2p_data { */ struct p2p_sd_query *sd_query; + /** + * num_p2p_sd_queries - Total number of broadcast SD queries present in + * the list + */ + int num_p2p_sd_queries; + /* GO Negotiation data */ /** diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c index 0e0c7f121..26b9c2d3d 100644 --- a/src/p2p/p2p_sd.c +++ b/src/p2p/p2p_sd.c @@ -52,6 +52,7 @@ struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, { struct p2p_sd_query *q; int wsd = 0; + int count = 0; if (!(dev->info.dev_capab & P2P_DEV_CAPAB_SERVICE_DISCOVERY)) return NULL; /* peer does not support SD */ @@ -64,8 +65,19 @@ struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, /* Use WSD only if the peer indicates support or it */ if (q->wsd && !wsd) continue; - if (q->for_all_peers && !(dev->flags & P2P_DEV_SD_INFO)) - return q; + /* if the query is a broadcast query */ + if (q->for_all_peers) { + /* + * check if there are any broadcast queries pending for + * this device + */ + if (dev->sd_pending_bcast_queries <= 0) + return NULL; + /* query number that needs to be send to the device */ + if (count == dev->sd_pending_bcast_queries - 1) + return q; + count++; + } if (!q->for_all_peers && os_memcmp(q->peer, dev->info.p2p_device_addr, ETH_ALEN) == 0) @@ -76,14 +88,37 @@ struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, } +static void p2p_decrease_sd_bc_queries(struct p2p_data *p2p, int query_number) +{ + struct p2p_device *dev; + + p2p->num_p2p_sd_queries--; + dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { + if (query_number <= dev->sd_pending_bcast_queries - 1) { + /* + * Query not yet sent to the device and it is to be + * removed, so update the pending count. + */ + dev->sd_pending_bcast_queries--; + } + } +} + + static int p2p_unlink_sd_query(struct p2p_data *p2p, struct p2p_sd_query *query) { struct p2p_sd_query *q, *prev; + int query_number = 0; + q = p2p->sd_queries; prev = NULL; while (q) { if (q == query) { + /* If the query is a broadcast query, decrease one from + * all the devices */ + if (query->for_all_peers) + p2p_decrease_sd_bc_queries(p2p, query_number); if (prev) prev->next = q->next; else @@ -92,6 +127,8 @@ static int p2p_unlink_sd_query(struct p2p_data *p2p, p2p->sd_query = NULL; return 1; } + if (q->for_all_peers) + query_number++; prev = q; q = q->next; } @@ -118,6 +155,7 @@ void p2p_free_sd_queries(struct p2p_data *p2p) q = q->next; p2p_free_sd_query(prev); } + p2p->num_p2p_sd_queries = 0; } @@ -262,6 +300,16 @@ int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev) ret = -1; } + /* Update the pending broadcast SD query count for this device */ + dev->sd_pending_bcast_queries--; + + /* + * If there are no pending broadcast queries for this device, mark it as + * done (-1). + */ + if (dev->sd_pending_bcast_queries == 0) + dev->sd_pending_bcast_queries = -1; + wpabuf_free(req); return ret; @@ -541,8 +589,6 @@ void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, p2p_dbg(p2p, "Service Update Indicator: %u", update_indic); pos += 2; - p2p->sd_peer->flags |= P2P_DEV_SD_INFO; - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; p2p->sd_peer = NULL; if (p2p->sd_query) { @@ -787,8 +833,6 @@ skip_nqp_header: return; } - p2p->sd_peer->flags |= P2P_DEV_SD_INFO; - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; p2p->sd_peer = NULL; if (p2p->sd_query) { @@ -841,8 +885,16 @@ void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst, if (dst == NULL) { struct p2p_device *dev; - dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) - dev->flags &= ~P2P_DEV_SD_INFO; + + p2p->num_p2p_sd_queries++; + + /* Update all the devices for the newly added broadcast query */ + dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { + if (dev->sd_pending_bcast_queries <= 0) + dev->sd_pending_bcast_queries = 1; + else + dev->sd_pending_bcast_queries++; + } } return q; diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P index 7354bbf03..bfad50149 100644 --- a/wpa_supplicant/README-P2P +++ b/wpa_supplicant/README-P2P @@ -230,9 +230,8 @@ discovery protocols and requests this to be sent to all discovered peers (note: this can result in long response frames). The pending requests are sent during device discovery (see p2p_find). -Only a single pending wildcard query is supported, but there can be -multiple pending peer device specific queries (each will be sent in -sequence whenever the peer is found). +There can be multiple pending peer device specific queries (each will be +sent in sequence whenever the peer is found). This command returns an identifier for the pending query (e.g., "1f77628") that can be used to cancel the request. Directed requests