diff mbox

[PATCHv2,2/2] mac80211: Tear down BA session on BAR tx failure

Message ID 1313072262-25413-2-git-send-email-helmut.schaa@googlemail.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Helmut Schaa Aug. 11, 2011, 2:17 p.m. UTC
As described at [1] some STAs (i.e. Intel 5100 Windows) can end up
correctly BlockAcking incoming frames without delivering them to user
space if a AMPDU subframe got lost and we don't flush the receipients
reorder buffer with a BlockAckReq. This in turn results in stuck
connections.

According to 802.11n-2009 it is not necessary to send a BAR to flush
the recepients RX reorder buffer but we still do that to be polite.

However, assume the following frame exchange:

AP -> STA, AMPDU (failed)
AP -> STA, BAR (failed)

The client in question then ends up in the same situation and won't
deliver frames to userspace anymore since we weren't able to flush
its reorder buffer.

This is not a hypothetical situation but I was able to observe this
exact behavior during a stress test between a rt2800pci AP and a Intel
5100 Windows client.

In order to work around this issue just tear down the BA session as
soon as a BAR failed to be TX'ed.

[1] http://comments.gmane.org/gmane.linux.kernel.wireless.general/66867

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---

Changes since v1:
- Fix commit message typos
- Make use of IEEE80211_BAR_CTRL_* defines
- Exclude Multi TID BARs (we don't send Multi TID bars yet and they need
  multiple TIDs being processed)

 net/mac80211/status.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

Comments

Johannes Berg Sept. 6, 2011, 7:39 p.m. UTC | #1
> +			/*
> +			 * BAR failed, let's tear down the BA session as a
> +			 * last resort as some STAs (Intel 5100 on Windows)
> +			 * can get stuck when the BA window isn't flushed
> +			 * correctly.
> +			 */
> +			bar = (struct ieee80211_bar *) skb->data;
> +			if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
> +				tid = (bar->control &
> +				       IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
> +				      IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
> +				ieee80211_stop_tx_ba_session(&sta->sta, tid);

Meh. Please, everyone, run sparse:

net/mac80211/status.c:276:34: warning: restricted __le16 degrades to integer
net/mac80211/status.c:277:43: warning: restricted __le16 degrades to integer

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 1658efa..02a8c13 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -187,6 +187,8 @@  void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 	int rates_idx = -1;
 	bool send_to_cooked;
 	bool acked;
+	struct ieee80211_bar *bar;
+	u16 tid;
 
 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
 		if (info->status.rates[i].idx < 0) {
@@ -243,6 +245,22 @@  void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 					   tid, ssn);
 		}
 
+		if (!acked && ieee80211_is_back_req(fc)) {
+			/*
+			 * BAR failed, let's tear down the BA session as a
+			 * last resort as some STAs (Intel 5100 on Windows)
+			 * can get stuck when the BA window isn't flushed
+			 * correctly.
+			 */
+			bar = (struct ieee80211_bar *) skb->data;
+			if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
+				tid = (bar->control &
+				       IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
+				      IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
+				ieee80211_stop_tx_ba_session(&sta->sta, tid);
+			}
+		}
+
 		if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
 			ieee80211_handle_filtered_frame(local, sta, skb);
 			rcu_read_unlock();