summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortobhe <tobhe@openbsd.org>2020-12-08 14:40:55 +0000
committertobhe <tobhe@openbsd.org>2020-12-08 14:40:55 +0000
commite565f47515d8e87f34a74ff3644f0ebf6817d477 (patch)
treeea00b943d8c5525fd18094a03e8e7c94848fbef9
parentUse a while loop instead of goto in uvm_fault(). (diff)
downloadwireguard-openbsd-e565f47515d8e87f34a74ff3644f0ebf6817d477.tar.xz
wireguard-openbsd-e565f47515d8e87f34a74ff3644f0ebf6817d477.zip
Fix gapwait accounting. Count all the packets in the reorder
buffer. Restart the gap timeout if the buffer is not empty after we flush out some of the packets. Found by and fix from Christian Ehrhardt ok stsp@ phessler@
-rw-r--r--sys/net80211/ieee80211_input.c36
1 files changed, 12 insertions, 24 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 525756e6e02..2c9ee3ab48a 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_input.c,v 1.222 2020/12/08 10:28:22 tobhe Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.223 2020/12/08 14:40:55 tobhe Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -850,30 +850,10 @@ ieee80211_input_ba(struct ieee80211com *ic, struct mbuf *m,
/* store Rx meta-data too */
rxi->rxi_flags |= IEEE80211_RXI_AMPDU_DONE;
ba->ba_buf[idx].rxi = *rxi;
+ ba->ba_gapwait++;
- if (ba->ba_buf[ba->ba_head].m == NULL) {
- if (ba->ba_gapwait < (ba->ba_winsize - 1)) {
- if (ba->ba_gapwait == 0) {
- timeout_add_msec(&ba->ba_gap_to,
- IEEE80211_BA_GAP_TIMEOUT);
- }
- ba->ba_gapwait++;
- } else {
- /*
- * A full BA window worth of frames is now waiting.
- * Skip the missing frame at the head of the window.
- */
- int skipped = ieee80211_input_ba_gap_skip(ba);
- ic->ic_stats.is_ht_rx_ba_frame_lost += skipped;
- ba->ba_gapwait = 0;
- if (timeout_pending(&ba->ba_gap_to))
- timeout_del(&ba->ba_gap_to);
- }
- } else {
- ba->ba_gapwait = 0;
- if (timeout_pending(&ba->ba_gap_to))
- timeout_del(&ba->ba_gap_to);
- }
+ if (ba->ba_buf[ba->ba_head].m == NULL && ba->ba_gapwait == 1)
+ timeout_add_msec(&ba->ba_gap_to, IEEE80211_BA_GAP_TIMEOUT);
ieee80211_input_ba_flush(ic, ni, ba, ml);
}
@@ -905,6 +885,7 @@ ieee80211_input_ba_seq(struct ieee80211com *ic, struct ieee80211_node *ni,
ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m,
ni, &ba->ba_buf[ba->ba_head].rxi, ml);
ba->ba_buf[ba->ba_head].m = NULL;
+ ba->ba_gapwait--;
} else
ic->ic_stats.is_ht_rx_ba_frame_lost++;
ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
@@ -927,12 +908,18 @@ ieee80211_input_ba_flush(struct ieee80211com *ic, struct ieee80211_node *ni,
ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m, ni,
&ba->ba_buf[ba->ba_head].rxi, ml);
ba->ba_buf[ba->ba_head].m = NULL;
+ ba->ba_gapwait--;
ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
/* move window forward */
ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;
}
ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
+
+ if (timeout_pending(&ba->ba_gap_to))
+ timeout_del(&ba->ba_gap_to);
+ if (ba->ba_gapwait)
+ timeout_add_msec(&ba->ba_gap_to, IEEE80211_BA_GAP_TIMEOUT);
}
/*
@@ -1000,6 +987,7 @@ ieee80211_ba_move_window(struct ieee80211com *ic, struct ieee80211_node *ni,
ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m, ni,
&ba->ba_buf[ba->ba_head].rxi, ml);
ba->ba_buf[ba->ba_head].m = NULL;
+ ba->ba_gapwait--;
} else
ic->ic_stats.is_ht_rx_ba_frame_lost++;
ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;