Tweak the heuristic net80211 RA is using to decide whether enough
authorstsp <stsp@openbsd.org>
Mon, 3 May 2021 08:46:28 +0000 (08:46 +0000)
committerstsp <stsp@openbsd.org>
Mon, 3 May 2021 08:46:28 +0000 (08:46 +0000)
statistics have been gathered for a candidate Tx rate. The goal is
to avoid Tx rate choices that might turn out to be too optimistic.

In practice this only affects the case where we probe upwards. If the
current Tx rate starts seeing loss we will still scale down very quickly.

Based on a larger collection of patches by Christian Ehrhardt.
I have made stylistic tweaks for consistency.

Tested:
iwn 6205: stsp, Josh Grosse
iwm 7265: stsp
iwm 8265: Matthias Schmidt
iwm 9260: phessler

sys/net80211/ieee80211_ra.c

index ec419b8..8fa9a4f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_ra.c,v 1.2 2021/03/25 16:23:39 mestre Exp $ */
+/*     $OpenBSD: ieee80211_ra.c,v 1.3 2021/05/03 08:46:28 stsp Exp $   */
 
 /*
  * Copyright (c) 2021 Christian Ehrhardt <ehrhardt@genua.de>
@@ -41,8 +41,6 @@ void  ieee80211_ra_probe_next_rateset(struct ieee80211_ra_node *,
            struct ieee80211_node *, const struct ieee80211_ht_rateset *);
 int    ieee80211_ra_next_mcs(struct ieee80211_ra_node *,
            struct ieee80211_node *);
-int    ieee80211_ra_probe_valid(struct ieee80211_ra_node *,
-           struct ieee80211_node *);
 void   ieee80211_ra_probe_done(struct ieee80211_ra_node *);
 int    ieee80211_ra_intra_mode_ra_finished(
            struct ieee80211_ra_node *, struct ieee80211_node *);
@@ -57,6 +55,7 @@ void  ieee80211_ra_probe_next_rate(struct ieee80211_ra_node *,
 int    ieee80211_ra_valid_tx_mcs(struct ieee80211com *, int);
 uint32_t ieee80211_ra_valid_rates(struct ieee80211com *,
            struct ieee80211_node *);
+int    ieee80211_ra_probe_valid(struct ieee80211_ra_goodput_stats *);
 
 /* We use fixed point arithmetic with 64 bit integers. */
 #define RA_FP_SHIFT    21
@@ -155,12 +154,6 @@ ieee80211_ra_get_txrate(int mcs, int sgi20)
 /* A rate's goodput has to be at least this much larger to be "better". */
 #define IEEE80211_RA_RATE_THRESHOLD    (RA_FP_1 / 64) /* ~ 0.015 */
 
-/* Number of (sub-)frames which render a probe valid. */
-#define IEEE80211_RA_MIN_PROBE_FRAMES  8
-
-/* Number of Tx retries which, alternatively, render a probe valid. */
-#define IEEE80211_RA_MAX_PROBE_RETRIES 4
-
 int
 ieee80211_ra_next_lower_intra_rate(struct ieee80211_ra_node *rn,
     struct ieee80211_node *ni)
@@ -345,13 +338,6 @@ ieee80211_ra_next_mcs(struct ieee80211_ra_node *rn,
        return next;
 }
 
-int
-ieee80211_ra_probe_valid(struct ieee80211_ra_node *rn,
-    struct ieee80211_node *ni)
-{
-       return rn->valid_probes & (1UL << ni->ni_txmcs);
-}
-
 void
 ieee80211_ra_probe_clear(struct ieee80211_ra_node *rn,
     struct ieee80211_node *ni)
@@ -536,6 +522,21 @@ ieee80211_ra_valid_rates(struct ieee80211com *ic, struct ieee80211_node *ni)
        return valid_mcs;
 }
 
+int
+ieee80211_ra_probe_valid(struct ieee80211_ra_goodput_stats *g)
+{
+       /* 128 packets make up a valid probe in any case. */
+       if (g->nprobe_pkts >= 128)
+               return 1;
+
+       /* 8 packets with > 75% loss make a valid probe, too. */
+       if (g->nprobe_pkts >= 8 &&
+           g->nprobe_pkts - g->nprobe_fail < g->nprobe_pkts / 4)
+               return 1;
+
+       return 0;
+}
+
 void
 ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn,
     struct ieee80211com *ic, struct ieee80211_node *ni,
@@ -562,11 +563,11 @@ ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn,
        g->nprobe_pkts += total;
        g->nprobe_fail += fail;
 
-       if (g->nprobe_pkts < IEEE80211_RA_MIN_PROBE_FRAMES &&
-            g->nprobe_fail < IEEE80211_RA_MAX_PROBE_RETRIES) {
+       if (!ieee80211_ra_probe_valid(g)) {
                splx(s);
                return;
        }
+       rn->valid_probes |= 1U << mcs;
 
        if (g->nprobe_fail > g->nprobe_pkts) {
                DPRINTF(("%s fail %u > pkts %u\n",
@@ -577,7 +578,6 @@ ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn,
 
        sfer = g->nprobe_fail << RA_FP_SHIFT;
        sfer /= g->nprobe_pkts;
-       rn->valid_probes |= 1U << mcs;
        g->nprobe_fail = 0;
        g->nprobe_pkts = 0;
 
@@ -615,7 +615,7 @@ ieee80211_ra_choose(struct ieee80211_ra_node *rn, struct ieee80211com *ic,
 
        if (rn->probing) {
                /* Probe another rate or settle at the best rate. */
-               if (!ieee80211_ra_probe_valid(rn, ni)) {
+               if (!(rn->valid_probes & (1UL << ni->ni_txmcs))) {
                        splx(s);
                        return;
                }