On Mon, Dec 07, 2020 at 02:36:05PM +0100, Tobias Heider wrote: > Hi, > > our net80211 gapwait accounting implementation seems to have several > problems: > - If we lose packets with serial numbers 0 und 2 but receive the > packet with serial number 1, the first gap wait timeout will > skip serial number 0, flush out serial number 1 and then wait > for serial number 2. However, at this time the timeout is not > re-armed and we have to wait for a window slide. > - The logic that does gap skip if too many packets are in the reorder > buffer does not kick in if we lose two packets (as gapwait cannot > reach windowsize - 1. Additionally, what the logic does is mostly > equivalent to a normal window slide if we receive a packet that is > beyond the window. So remove this logic completely. > > To fix this use ba_gapwait to actually count all the packets > currently in the reorder buffer and restart the gap timeout if the > buffer is not empty after we flush out some of the packets. > > Found and fix by Christian Erhardt (CC). > > ok? I am happy with this if it works well during testing.
Could someone convince phessler@ to take this for a flight in Minecraft? > Index: ieee80211_input.c > =================================================================== > RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v > retrieving revision 1.221 > diff -u -p -r1.221 ieee80211_input.c > --- ieee80211_input.c 28 Aug 2020 12:01:48 -0000 1.221 > +++ ieee80211_input.c 7 Dec 2020 12:58:31 -0000 > @@ -839,30 +839,10 @@ ieee80211_input_ba(struct ieee80211com * > /* 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); > } > @@ -894,6 +874,7 @@ ieee80211_input_ba_seq(struct ieee80211c > 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; > @@ -916,12 +897,18 @@ ieee80211_input_ba_flush(struct ieee8021 > 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); > } > > /* > @@ -989,6 +976,7 @@ ieee80211_ba_move_window(struct ieee8021 > 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; >