diff mbox

[1/2] P2P: Addressing few issues seen with Broadcast SD

Message ID 137202264661b954a4fa6ffea014c5182616aa68.1391502949.git.jithu@broadcom.com
State Superseded
Headers show

Commit Message

Jithu Jance Feb. 4, 2014, 9:09 a.m. UTC
1) Suppose we have multiple peers and we have peers advertising
SD capability, but no services registered for adverstising.
In this case, even if there are mutliple broadcast queries set,
we might end up sending only the lastly added Broadcast to the
same device (Since SD_INFO won't get set for the first broadcast)

2) Some times it is seen that before advancing to next device in the
list, the scan results come and updates SD_SCHEDULE flag. This will
result in sending the already sent query to the same device without
giving chance to other devices. This issue again is seen with peer
devices advertising SD capability without any services registered.

Signed-hostap: Jithu Jance <jithu@broadcom.com>
---
 src/p2p/p2p.c    |   19 +++++++++----------
 src/p2p/p2p_i.h  |    6 ++++++
 src/p2p/p2p_sd.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 63 insertions(+), 14 deletions(-)

--
1.7.9.5
diff mbox

Patch

diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 8aabfc0..9b22e22 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -732,9 +732,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;

@@ -2384,6 +2381,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);
@@ -2618,13 +2616,18 @@  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 (dev->sd_pending_bcast_queries == 0) {
+			/* Initialize with Total number of Registered BCAST Queries*/
+			dev->sd_pending_bcast_queries = p2p->num_p2p_sd_queries;
+		}
+
+		if (dev->sd_pending_bcast_queries > 0) {
 			if (p2p_start_sd(p2p, dev) == 0)
 				return;
 			else
 				break;
 		} else if (dev->req_config_methods &&
-			   !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
+		   !(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),
@@ -2646,7 +2649,6 @@  static void p2p_sd_cb(struct p2p_data *p2p, int success)

 	if (!success) {
 		if (p2p->sd_peer) {
-			p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
 			p2p->sd_peer = NULL;
 		}
 		p2p_continue_find(p2p);
@@ -3457,7 +3459,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",
@@ -3480,9 +3482,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 3e105eb..926fdd9 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -105,6 +105,7 @@  struct p2p_device {

 	u8 go_timeout;
 	u8 client_timeout;
+	int sd_pending_bcast_queries;
 };

 struct p2p_sd_query {
@@ -250,6 +251,11 @@  struct p2p_data {
 	 */
 	struct p2p_sd_query *sd_query;

+	/**
+	 * total number of sd broadcast 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 0e0c7f1..6dd10e8 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,17 @@  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 */
+			else if (count == (dev->sd_pending_bcast_queries - 1)) {
+				return q;
+			} else
+				count++;
+		}
 		if (!q->for_all_peers &&
 		    os_memcmp(q->peer, dev->info.p2p_device_addr, ETH_ALEN) ==
 		    0)
@@ -80,10 +90,25 @@  static int p2p_unlink_sd_query(struct p2p_data *p2p,
 			       struct p2p_sd_query *query)
 {
 	struct p2p_sd_query *q, *prev;
+	struct p2p_device *dev;
+	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->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 send to the device and is to be removed.
+						 * So update the pending count.
+						 */
+						dev->sd_pending_bcast_queries--;
+					}
+				}
+			}
 			if (prev)
 				prev->next = q->next;
 			else
@@ -92,6 +117,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;
 	}
@@ -262,6 +289,16 @@  int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev)
 		ret = -1;
 	}

+	/* Update the pending Bcast sd query count for this device */
+	dev->sd_pending_bcast_queries--;
+
+	/*
+	 * If there are no pending bcast query 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;
@@ -841,8 +878,15 @@  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 bcast 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;