When switching APs we queue a deauth frame to the old AP, which
should be the last frame queued to hardware before we switch.

To send the deauth frame ieee80211_send_mgmt() gets called.
ieee80211_send_mgmt() calls if_start(), a driver-specific function
which usually loops over the outgoing management frame queue first,
and then the data frame queue.

To prevent transmission of additional data frames during AP switch,
the net80211 stack sets the TX_MGMT_ONLY flag which tells if_start()
to skip the data frame queue. This flag currently gets set too late,
so sending the deauth frame could also result in additional data frames
being queued after the deauth frame. The diff below fixes this issue.

diff 8fdeade23c5858406f2bc5e8be973aa2a970bd92 /usr/src (staged changes)
blob - 535c281bdd8e0d4eb22fd5476c8df2e24cb62be8
blob + e9ca2c9645ced26c272a3b4e63557c9e4e1b60ac
--- sys/net80211/ieee80211_node.c
+++ sys/net80211/ieee80211_node.c
@@ -1451,6 +1451,9 @@ ieee80211_end_scan(struct ifnet *ifp)
 
                ic->ic_bgscan_fail = 0;
 
+               /* Prevent dispatch of additional data frames to hardware. */
+               ic->ic_xflags |= IEEE80211_F_TX_MGMT_ONLY;
+
                /* 
                 * We are going to switch APs. Stop A-MPDU Tx and
                 * queue a de-auth frame addressed to our current AP.
@@ -1461,12 +1464,10 @@ ieee80211_end_scan(struct ifnet *ifp)
                    IEEE80211_FC0_SUBTYPE_DEAUTH,
                    IEEE80211_REASON_AUTH_LEAVE) != 0) {
                        ic->ic_flags &= ~IEEE80211_F_BGSCAN;
+                       ic->ic_xflags &= ~IEEE80211_F_TX_MGMT_ONLY;
                        free(arg, M_DEVBUF, sizeof(*arg));
                        return;
                }
-
-               /* Prevent dispatch of additional data frames to hardware. */
-               ic->ic_xflags |= IEEE80211_F_TX_MGMT_ONLY;
 
                /* 
                 * Install a callback which will switch us to the new AP once

Reply via email to