]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Stop listen state if Action frame TX is needed on another channel
authorJouni Malinen <j@w1.fi>
Sun, 17 Feb 2019 14:53:03 +0000 (16:53 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 17 Feb 2019 14:53:03 +0000 (16:53 +0200)
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>
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_group.c
wpa_supplicant/p2p_supplicant.c

index 4bbd1bcca097a7b4845d24af0a2725fd68ffbdae..157bf891c4ab873da629fe8d7569a2691b276e17 100644 (file)
@@ -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;
 }
 
 
index f2969ee1323731ab6188527764f29b5e3f482cb5..425b037be51586bbd8d6c5ef3fd8c19c53a34111 100644 (file)
@@ -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
index 16c28a0d95ee73d09e97bb7f7cffd82880ebfb3f..aa18af6c16c6bfea2b5885e1cdb35d763d403c16 100644 (file)
@@ -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");
        }
index e265128b7a9153479797abfd58d2956841e7be66..18fd02c3e88d87d37725d1da4a85af7f3ff12213 100644 (file)
@@ -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");