On Sat, Mar 04, 2017 at 10:04:51PM +0100, Stefan Sperling wrote:
> This diff makes the RTS threshold dynamic in 11n mode.
> It flips the RTS threshold between DEFAULT (512 bytes) and MAX (the
> maximum size of a non-aggregated 802.11 frame).

Things have been working fine for me with this diff.
Any concerns about putting it in?

> The decision whether to use RTS is implemented as a heuristic described
> in the MiRA paper.
> 
> MiRa enables RTS if there are retries with almost no loss, indicating
> competition with other APs and clients. It leaves RTS disabled if
> there is a lot of loss, indicating we are too far away from the AP
> or using a bad Tx rate which won't cover the distance.
> 
> Because an athn(4) hostap needs a per-client threshold I am introducing
> ni_rtsthreshold in struct ieee80211_node. This could completely replace
> the ic_rtsthreshold in struct ieee80211com eventually. For now I am only
> switching 11n capable drivers over to ni_rtsthreshold.
> 
> I am interested in test reports.
> When testing this please look for changes in both latency and throughput
> and let me know if you think it behaves better or worse with this diff.
> 
> Index: dev/ic/ar5008.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar5008.c,v
> retrieving revision 1.42
> diff -u -p -r1.42 ar5008.c
> --- dev/ic/ar5008.c   1 Feb 2017 12:45:56 -0000       1.42
> +++ dev/ic/ar5008.c   4 Mar 2017 15:29:02 -0000
> @@ -1513,7 +1513,7 @@ ar5008_tx(struct athn_softc *sc, struct 
>               
>               htprot = (ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);
>               /* NB: Group frames are sent using CCK in 802.11b/g. */
> -             if (totlen > ic->ic_rtsthreshold) {
> +             if (totlen > ni->ni_rtsthreshold) {
>                       ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE;
>               } else if (((ic->ic_flags & IEEE80211_F_USEPROT) &&
>                   athn_rates[ridx[0]].phy == IEEE80211_T_OFDM) ||
> Index: dev/ic/ath.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ath.c,v
> retrieving revision 1.112
> diff -u -p -r1.112 ath.c
> --- dev/ic/ath.c      22 Jan 2017 10:17:37 -0000      1.112
> +++ dev/ic/ath.c      4 Mar 2017 15:29:23 -0000
> @@ -2259,7 +2259,7 @@ ath_tx_start(struct ath_softc *sc, struc
>       if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
>               flags |= HAL_TXDESC_NOACK;      /* no ack on broad/multicast */
>               sc->sc_stats.ast_tx_noack++;
> -     } else if (pktlen > ic->ic_rtsthreshold) {
> +     } else if (pktlen > ni->ni_rtsthreshold) {
>               flags |= HAL_TXDESC_RTSENA;     /* RTS based on frame length */
>               sc->sc_stats.ast_tx_rts++;
>       }
> Index: dev/pci/if_iwm.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
> retrieving revision 1.165
> diff -u -p -r1.165 if_iwm.c
> --- dev/pci/if_iwm.c  20 Feb 2017 15:38:04 -0000      1.165
> +++ dev/pci/if_iwm.c  4 Mar 2017 15:30:11 -0000
> @@ -4038,7 +4038,7 @@ iwm_tx(struct iwm_softc *sc, struct mbuf
>  
>       if (type == IEEE80211_FC0_TYPE_DATA &&
>           !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
> -         (totlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold ||
> +         (totlen + IEEE80211_CRC_LEN > ni->ni_rtsthreshold ||
>           (ic->ic_flags & IEEE80211_F_USEPROT)))
>               flags |= IWM_TX_CMD_FLG_PROT_REQUIRE;
>  
> Index: dev/pci/if_iwn.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
> retrieving revision 1.184
> diff -u -p -r1.184 if_iwn.c
> --- dev/pci/if_iwn.c  20 Feb 2017 15:38:04 -0000      1.184
> +++ dev/pci/if_iwn.c  4 Mar 2017 15:30:02 -0000
> @@ -2992,7 +2992,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf
>       /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
>       if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
>               /* NB: Group frames are sent using CCK in 802.11b/g/n (2GHz). */
> -             if (totlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
> +             if (totlen + IEEE80211_CRC_LEN > ni->ni_rtsthreshold) {
>                       flags |= IWN_TX_NEED_RTS;
>               } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
>                   ridx >= IWN_RIDX_OFDM6) {
> Index: net80211/ieee80211_mira.c
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_mira.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 ieee80211_mira.c
> --- net80211/ieee80211_mira.c 28 Jan 2017 16:01:36 -0000      1.10
> +++ net80211/ieee80211_mira.c 4 Mar 2017 16:55:00 -0000
> @@ -84,6 +84,9 @@ void        ieee80211_mira_probe_next_rate(stru
>  uint32_t ieee80211_mira_valid_rates(struct ieee80211com *,
>           struct ieee80211_node *);
>  uint32_t ieee80211_mira_mcs_below(struct ieee80211_mira_node *, int);
> +void ieee80211_mira_set_rts_threshold(struct ieee80211_mira_node *,
> +         struct ieee80211com *, struct ieee80211_node *);
> +void ieee80211_mira_reset_interference_stats(struct ieee80211_mira_node *);
>  
>  /* We use fixed point arithmetic with 64 bit integers. */
>  #define MIRA_FP_SHIFT        21
> @@ -381,7 +384,7 @@ ieee80211_mira_toverhead(struct ieee8021
>               (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_40))
>               rts = 1;
>       else
> -             rts = (mn->ampdu_size > ic->ic_rtsthreshold);
> +             rts = (mn->ampdu_size > ni->ni_rtsthreshold);
>  
>       if (rts) {
>               /* Assume RTS/CTS were sent at a basic rate. */
> @@ -1024,6 +1027,82 @@ ieee80211_mira_mcs_below(struct ieee8021
>       return mcs_mask;
>  }
>  
> +/* Constants involved in detecting suspected frame collisions. */
> +#define MIRA_COLLISION_MIN_FRAMES    11      /* XXX magic number */
> +#define MIRA_COLLISION_LOSS_PERCENTAGE       10
> +#define MIRA_COLLISION_DETECTED              3
> +
> +/* 
> + * Set the RTS threshold based on suspected interference from other STAs.
> + * Note that HT protection settings may enforce RTS regardless of threshold.
> + *
> + * See section 5.2 in MiRa paper.
> + * XXX The paper's algorithm assumes aggregated frames. We run the algorithm
> + * over the result of several individual frames instead since we do not yet
> + * support Tx aggregation.
> + */
> +void
> +ieee80211_mira_set_rts_threshold(struct ieee80211_mira_node *mn,
> +    struct ieee80211com *ic, struct ieee80211_node *ni)
> +{
> +     uint16_t rtsthreshold = IEEE80211_RTS_MAX; /* disable RTS by default */
> +     uint32_t loss;
> +     /* Magic number from MiRA paper ("cost/benefit ratio"). */
> +     static const uint64_t k = MIRA_FP_1 + (MIRA_FP_1 / 2); /* 1.5 */
> +
> +     /* Update interference window stats. */
> +     mn->ifwnd_frames += mn->frames;
> +     mn->ifwnd_retries += mn->retries;
> +     mn->ifwnd_txfail += mn->txfail;
> +     mn->ifwnd_size += mn->ampdu_size;
> +     if (mn->ifwnd_frames < MIRA_COLLISION_MIN_FRAMES)
> +             return; /* not enough frames yet */
> +
> +     /* Check whether the loss pattern indicates frame collisions. */
> +     loss = (mn->ifwnd_txfail * 100) / mn->ifwnd_frames;
> +     if (mn->ifwnd_retries >= 1 && loss < MIRA_COLLISION_LOSS_PERCENTAGE) {
> +             if (mn->ifwnd == 0) {
> +                     /* First frame collision confirmed. */
> +                     mn->ifwnd = MIRA_COLLISION_DETECTED;
> +             } else if (mn->ifwnd == MIRA_COLLISION_DETECTED) {
> +                     /* Successive frame collision confirmed. */
> +                     int rate = ieee80211_mira_best_basic_rate(ni);
> +                     uint64_t txtime, rtsoverhead;
> +                     txtime = ieee80211_mira_ht_txtime(mn->ifwnd_size,
> +                         ni->ni_txmcs, IEEE80211_IS_CHAN_2GHZ(ni->ni_chan));
> +                     rtsoverhead = ieee80211_mira_legacy_txtime(MIRA_RTSLEN,
> +                         rate, ic);
> +                     rtsoverhead += ieee80211_mira_legacy_txtime(MIRA_CTSLEN,
> +                         rate, ic);
> +                     /* convert to fixed-point */
> +                     txtime <<= MIRA_FP_SHIFT;
> +                     rtsoverhead <<= MIRA_FP_SHIFT;
> +                     /* Enable RTS if potential gains outweigh overhead. */
> +                     if (txtime >= MIRA_FP_MUL(k, rtsoverhead))
> +                             rtsthreshold = IEEE80211_RTS_DEFAULT;
> +             }
> +     } else if (mn->ifwnd > 0)
> +             mn->ifwnd--;
> +
> +#ifdef MIRA_DEBUG
> +     if (ni->ni_rtsthreshold != rtsthreshold)
> +             DPRINTF(("%s RTS threshold %d (%d retries, %d%% loss)\n",
> +                 ether_sprintf(ni->ni_macaddr), rtsthreshold,
> +                 mn->ifwnd_retries, loss));
> +#endif
> +     ni->ni_rtsthreshold = rtsthreshold;
> +     ieee80211_mira_reset_interference_stats(mn);
> +}
> +
> +void
> +ieee80211_mira_reset_interference_stats(struct ieee80211_mira_node *mn)
> +{
> +     mn->ifwnd_frames = 0;
> +     mn->ifwnd_retries = 0;
> +     mn->ifwnd_txfail = 0;
> +     mn->ifwnd_size = 0;
> +}
> +
>  void
>  ieee80211_mira_choose(struct ieee80211_mira_node *mn, struct ieee80211com 
> *ic,
>      struct ieee80211_node *ni)
> @@ -1060,6 +1139,7 @@ ieee80211_mira_choose(struct ieee80211_m
>                                   IEEE80211_MIRA_PROBE_TIMEOUT_MIN;
>                               mn->g[best].nprobes = 0;
>                               mn->g[best].nprobe_bytes = 0;
> +                             ieee80211_mira_reset_interference_stats(mn);
>                       } else
>                               ni->ni_txmcs = mn->best_mcs;
>                       ieee80211_mira_probe_done(mn);
> @@ -1068,6 +1148,7 @@ ieee80211_mira_choose(struct ieee80211_m
>               splx(s);
>               return;
>       } else {
> +             ieee80211_mira_set_rts_threshold(mn, ic, ni);
>               ieee80211_mira_reset_driver_stats(mn);
>               ieee80211_mira_schedule_probe_timers(mn, ni);
>       }
> Index: net80211/ieee80211_mira.h
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_mira.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 ieee80211_mira.h
> --- net80211/ieee80211_mira.h 12 Jan 2017 18:06:57 -0000      1.3
> +++ net80211/ieee80211_mira.h 4 Mar 2017 16:30:29 -0000
> @@ -89,6 +89,13 @@ struct ieee80211_mira_node {
>  
>       /* Goodput statistics for each MCS. */
>       struct ieee80211_mira_goodput_stats g[IEEE80211_MIRA_NUM_RATES];
> +
> +     /* Interference observation window (see MiRa paper section 5.2). */
> +     int ifwnd;
> +     uint32_t ifwnd_frames;
> +     uint32_t ifwnd_retries;
> +     uint32_t ifwnd_txfail;
> +     uint32_t ifwnd_size;
>  };
>  
>  /* Initialize rate control state. */
> Index: net80211/ieee80211_node.c
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v
> retrieving revision 1.115
> diff -u -p -r1.115 ieee80211_node.c
> --- net80211/ieee80211_node.c 4 Mar 2017 12:44:27 -0000       1.115
> +++ net80211/ieee80211_node.c 4 Mar 2017 16:54:10 -0000
> @@ -184,6 +184,7 @@ ieee80211_node_lateattach(struct ifnet *
>       if (ni == NULL)
>               panic("unable to setup inital BSS node");
>       ni->ni_chan = IEEE80211_CHAN_ANYC;
> +     ni->ni_rtsthreshold = IEEE80211_RTS_DEFAULT;
>       ic->ic_bss = ieee80211_ref_node(ni);
>       ic->ic_txpower = IEEE80211_TXPOWER_MAX;
>  #ifndef IEEE80211_STA_ONLY
> Index: net80211/ieee80211_node.h
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_node.h,v
> retrieving revision 1.67
> diff -u -p -r1.67 ieee80211_node.h
> --- net80211/ieee80211_node.h 4 Mar 2017 12:44:27 -0000       1.67
> +++ net80211/ieee80211_node.h 4 Mar 2017 16:54:10 -0000
> @@ -277,6 +277,7 @@ struct ieee80211_node {
>       int                     ni_inact;       /* inactivity mark count */
>       int                     ni_txrate;      /* index to ni_rates[] */
>       int                     ni_state;
> +     uint16_t                ni_rtsthreshold;
>  
>       u_int16_t               ni_flags;       /* special-purpose state */
>  #define IEEE80211_NODE_ERP           0x0001
> 
> 
> 
> 

Reply via email to