]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Fix offchannel TX done handling for sequence of TX frames
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 15 Jun 2017 18:18:07 +0000 (21:18 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 17 Jun 2017 15:04:54 +0000 (18:04 +0300)
There could be multiple pending TX operations and if the earlier ones
have used wait_time, but the last one did not, the driver call for
canceling pending wait was not done. This could result in the driver
getting stuck waiting for the previously scheduled wait time and not
being able to do new operations until that. Fix this by canceling the
wait if any of the past offchannel_send_action() calls since the last
offchannel_send_action_done() used non-zero wait_time.

This was showing up as issues in certain DPP Public Action frame
sequences when the same offchannel operation is used with multiple
frames and the last frame in the sequence does not need wait_time.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
wpa_supplicant/offchannel.c
wpa_supplicant/wpa_supplicant_i.h

index 26d41a4ad5c6303a88377cd42ce1ef05c96e6170..b74be7dad4acfade264a6a09306358e81a41b8d3 100644 (file)
@@ -310,6 +310,8 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
 
                iface = wpas_get_tx_interface(wpa_s, src);
                wpa_s->action_tx_wait_time = wait_time;
+               if (wait_time)
+                       wpa_s->action_tx_wait_time_used = 1;
 
                ret = wpa_drv_send_action(
                        iface, wpa_s->pending_action_freq,
@@ -398,13 +400,14 @@ void offchannel_send_action_done(struct wpa_supplicant *wpa_s)
        wpabuf_free(wpa_s->pending_action_tx);
        wpa_s->pending_action_tx = NULL;
        if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX &&
-           wpa_s->action_tx_wait_time)
+           (wpa_s->action_tx_wait_time || wpa_s->action_tx_wait_time_used))
                wpa_drv_send_action_cancel_wait(wpa_s);
        else if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
                wpa_drv_cancel_remain_on_channel(wpa_s);
                wpa_s->off_channel_freq = 0;
                wpa_s->roc_waiting_drv_freq = 0;
        }
+       wpa_s->action_tx_wait_time_used = 0;
 }
 
 
index 45dc05c7f4218169fe48453351307a51cbd13df3..9c0500191ac48a4ed57403342c3e069795475eae 100644 (file)
@@ -827,6 +827,7 @@ struct wpa_supplicant {
                                            result);
        unsigned int roc_waiting_drv_freq;
        int action_tx_wait_time;
+       int action_tx_wait_time_used;
 
        int p2p_mgmt;