P2P: Prefer direct Probe Response frames over GO's client list
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Wed, 10 Jun 2015 08:43:37 +0000 (11:43 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 14 Jun 2015 20:16:55 +0000 (23:16 +0300)
A P2P Client may be discoverable and reply to Probe Request frames,
while at the same time the P2P GO would also be discoverable and include
the P2P Client information in the P2P Group Info attribute of the Probe
Response frames.

If a seeker constantly hears the Probe Response frames from a P2P Client
and then from the GO, but handles them in the opposite order (due to
scan results ordering), the more valuable Probe Response frame from the
P2P Client will be ignored. Fix this by defining a threshold (1 second)
during which the direct Probe Response frame will be preferred over the
information acquired from the GO and will not be considered as old.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Reviewed-by: Ilan Peer <ilan.peer@intel.com>
src/p2p/p2p.c
src/p2p/p2p_i.h

index 8306ef1..7a05c66 100644 (file)
@@ -541,6 +541,7 @@ static int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
                os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
                os_memcpy(dev->member_in_go_iface, go_interface_addr,
                          ETH_ALEN);
+               dev->flags |= P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT;
        }
 
        return 0;
@@ -759,22 +760,30 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
 
        /*
         * Update the device entry only if the new peer
-        * entry is newer than the one previously stored.
+        * entry is newer than the one previously stored, or if
+        * the device was previously seen as a P2P Client in a group
+        * and the new entry isn't older than a threshold.
         */
        if (dev->last_seen.sec > 0 &&
-           os_reltime_before(rx_time, &dev->last_seen)) {
-               p2p_dbg(p2p, "Do not update peer entry based on old frame (rx_time=%u.%06u last_seen=%u.%06u)",
+           os_reltime_before(rx_time, &dev->last_seen) &&
+           (!(dev->flags & P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT) ||
+            os_reltime_expired(&dev->last_seen, rx_time,
+                               P2P_DEV_GROUP_CLIENT_RESP_THRESHOLD))) {
+               p2p_dbg(p2p,
+                       "Do not update peer entry based on old frame (rx_time=%u.%06u last_seen=%u.%06u flags=0x%x)",
                        (unsigned int) rx_time->sec,
                        (unsigned int) rx_time->usec,
                        (unsigned int) dev->last_seen.sec,
-                       (unsigned int) dev->last_seen.usec);
+                       (unsigned int) dev->last_seen.usec,
+                       dev->flags);
                p2p_parse_free(&msg);
                return -1;
        }
 
        os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_reltime));
 
-       dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
+       dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY |
+                       P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT);
 
        if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
                os_memcpy(dev->interface_addr, addr, ETH_ALEN);
@@ -4167,7 +4176,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\n"
+                         "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
                          "status=%d\n"
                          "invitation_reqs=%u\n",
                          (int) (now.sec - dev->last_seen.sec),
@@ -4211,6 +4220,8 @@ int p2p_get_peer_info_txt(const struct p2p_peer_info *info,
                          "[FORCE_FREQ]" : "",
                          dev->flags & P2P_DEV_PD_FOR_JOIN ?
                          "[PD_FOR_JOIN]" : "",
+                         dev->flags & P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT ?
+                         "[LAST_SEEN_AS_GROUP_CLIENT]" : "",
                          dev->status,
                          dev->invitation_reqs);
        if (os_snprintf_error(end - pos, res))
index 289a62d..853121c 100644 (file)
 
 #define P2P_GO_NEG_CNF_MAX_RETRY_COUNT 1
 
+/*
+ * A threshold (in seconds) to prefer a direct Probe Response frame from a P2P
+ * Device over the P2P Client Info received from a GO.
+ */
+#define P2P_DEV_GROUP_CLIENT_RESP_THRESHOLD 1
+
 enum p2p_role_indication;
 
 /*
@@ -107,6 +113,8 @@ struct p2p_device {
 #define P2P_DEV_WAIT_INV_REQ_ACK BIT(19)
 #define P2P_DEV_P2PS_REPORTED BIT(20)
 #define P2P_DEV_PD_PEER_P2PS BIT(21)
+#define P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT BIT(22)
+
        unsigned int flags;
 
        int status; /* enum p2p_status_code */