This patch causes STA mode interfaces to disassociate if transmission of assoc/auth critical packets failed. Signed-off-by: Felix Fietkau --- a/ath/if_ath.c +++ b/ath/if_ath.c @@ -8334,6 +8334,14 @@ ath_tx_processq(struct ath_softc *sc, st #endif if (ts->ts_status & HAL_TXERR_XRETRY) { sc->sc_stats.ast_tx_xretries++; + if (SKB_CB(bf->bf_skb)->auth_pkt && + (ni->ni_vap->iv_opmode == IEEE80211_M_STA)) { + struct ieee80211vap *vap = ni->ni_vap; + + /* if roaming is enabled, try reassociating, otherwise + * disassociate and go back to the scan state */ + vap->iv_mgtsend.function(vap->iv_mgtsend.data); + } if (ni->ni_flags & IEEE80211_NODE_UAPSD_TRIG) { ni->ni_stats.ns_tx_eosplost++; DPRINTF(sc, ATH_DEBUG_UAPSD, --- a/net80211/ieee80211_linux.c +++ b/net80211/ieee80211_linux.c @@ -156,6 +156,7 @@ ieee80211_getmgtframe(u_int8_t **frm, u_ if (off != 0) skb_reserve(skb, align - off); + SKB_CB(skb)->auth_pkt = 0; SKB_CB(skb)->ni = NULL; SKB_CB(skb)->flags = 0; SKB_CB(skb)->next = NULL; --- a/net80211/ieee80211_linux.h +++ b/net80211/ieee80211_linux.h @@ -393,6 +393,7 @@ typedef spinlock_t acl_lock_t; void (*next_destructor)(struct sk_buff *skb); #endif struct sk_buff *next; /* fast frame sk_buf chain */ + u_int8_t auth_pkt; }; --- a/net80211/ieee80211_output.c +++ b/net80211/ieee80211_output.c @@ -778,6 +778,8 @@ ieee80211_encap(struct ieee80211_node *n else hdrsize = sizeof(struct ieee80211_frame); + SKB_CB(skb)->auth_pkt = (eh.ether_type == __constant_htons(ETHERTYPE_PAE)); + switch (vap->iv_opmode) { case IEEE80211_M_IBSS: case IEEE80211_M_AHDEMO: @@ -1622,6 +1624,7 @@ ieee80211_add_xr_param(u_int8_t *frm, st ie->param_len = frm - &ie->param_oui[0]; return frm; } + #endif /* * Send a probe request frame with the specified ssid @@ -1886,6 +1889,7 @@ ieee80211_send_mgmt(struct ieee80211_nod sizeof(u_int16_t)+IEEE80211_CHALLENGE_LEN : 0)); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); + SKB_CB(skb)->auth_pkt = 1; ((__le16 *)frm)[0] = (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED) @@ -1960,6 +1964,7 @@ ieee80211_send_mgmt(struct ieee80211_nod vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].length); if (skb == NULL) senderr(ENOMEM, is_tx_nobuf); + SKB_CB(skb)->auth_pkt = 1; capinfo = 0; if (vap->iv_opmode == IEEE80211_M_IBSS)