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;
> 

Reply via email to