misc/168170: [net80211] ieee80211_send_bar() doesn't complete correctly if there's a resource shortage

Adrian Chadd adrian at FreeBSD.org
Sun May 20 17:30:14 UTC 2012


>Number:         168170
>Category:       misc
>Synopsis:       [net80211] ieee80211_send_bar() doesn't complete correctly if there's a resource shortage
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun May 20 17:30:02 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Adrian Chadd
>Release:        -HEAD
>Organization:
>Environment:
FreeBSD freebsd-wifi-build 10.0-CURRENT FreeBSD 10.0-CURRENT #5 r235338:235659M: Wed Dec 31 16:00:00 PST 1969     adrian at dummy:/home/adrian/work/freebsd/svn/obj/mipseb/mips.mips/usr/home/adrian/work/freebsd/svn/src/sys/RSPRO  mips

>Description:
I'm seeing scenarios where the TID pauses, tying up all ath_buf entries (and mbufs, further up in the network stack) until the STA is forcibly removed.

Here's a snippet from the AP log:

ath1: ath_tx_tid_drain: node 0xc1d8a000: bf=0xc1cd417c: addbaw=1, dobaw=1, seqno_assign=1, seqno_required=1, seqno=1560, retry=10
ath1: ath_tx_tid_drain: node 0xc1d8a000: bf=0xc1cd417c: tid txq_depth=78 hwq_depth=0, bar_wait=1
ath1: ath_tx_tid_drain: node 0xc1d8a000: bf=0xc1cd417c: tid 0: txq_depth=0, txq_aggr_depth=0, sched=0, paused=1, hwq_depth=0, incomp=0, baw_head=123, baw_tail=33 txa_start=1537, ni_txseqs=1575

After doing a whole lot of digging, I found this:

* ieee80211_bar_send() is called from the wifi driver. If it fails there then the wifi driver will have to consider the BAR failed and continue.
* if it succeeds, then the wifi driver should hold TXing any further frames until it completes.
* If it does succeed, then bar_start_timer() is called.
* If the TX completes succesfully, then everything is ok
* But then, if it fails - either it's told that it fails or it times out, bar_timeout() is (eventually) called. The timer here has completed, so it won't be called again.
* It then calls ieee80211_send_bar(), which should try sending again.
* .. but if the call to ieee80211_send_bar() fails, the timer is never restarted - its only restarted _if_ ieee80211_send_bar() actually successfully completed.
>How-To-Repeat:
Fire up 802.11n on ath(4) in hostap mode; wait for TX failures to occur.

>Fix:
I'm not entirely sure. It may be good enough to just call bar_start_timer() from bar_timeout(), just to enforce that the timer needs to be kicked along whether or not ieee80211_send_bar() succeeded.

The other problem is resource exhaustion. At this point, all ieee80211_send_bar() calls may fail because the driver is completely out of internal buffers (here ath_buf), or the network stack has exhausted all mbufs.

So it likely requires a few fixes in a few places.

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list