[Make-wifi-fast] [PATCH] mac80211: Dynamically set CoDel parameters per station.

Jim Gettys jg at freedesktop.org
Sat Sep 10 15:54:44 EDT 2016


On Sat, Sep 10, 2016 at 3:33 PM, Toke Høiland-Jørgensen <toke at toke.dk>
wrote:

> CoDel can be too aggressive if a station sends at a very low rate,
> leading to starvation. This gets worse the more stations are present, as
> each station gets more bursty the longer the round-robin scheduling
> between stations takes.
>
> This adds dynamic adjustment of CoDel parameters per station. It uses
> the rate selection information to estimate throughput and sets more
> lenient CoDel parameters if the estimated throughput is below a
> threshold. To not change parameters too often, a hysteresis of two
> seconds is added.
>

​Where is this 2 second constant coming from?  I'd expect it should be of
order the maximum RTT (or a small constant factor of that, which for
intercontinental connections should be 200-300ms.

More interestingly, maybe the adjustment should be related to the # of
active stations.

Basically, I'm pushing back about an arbitrary number apparently picked out
of thin air... ;-).
                                           - Jim
​


>
> A new callback is added that drivers can use to notify mac80211 about
> changes in expected throughput, so the same adjustment can be made for
> cards that implement rate control in firmware. Drivers that don't use
> this will just get the default parameters.
>
> The threshold used and the CoDel parameters set for slow stations are
> chosen to err on the side of caution. I.e. rather be too lenient than
> too aggressive. A better algorithm can then be added later.
>
> Cc: Michal Kazior <michal.kazior at tieto.com>
> Cc: Felix Fietkau <nbd at nbd.name>
> Signed-off-by: Toke Høiland-Jørgensen <toke at toke.dk>
> ---
>  include/net/mac80211.h  | 17 +++++++++++++++++
>  net/mac80211/rate.c     |  2 ++
>  net/mac80211/sta_info.c | 35 +++++++++++++++++++++++++++++++++++
>  net/mac80211/sta_info.h | 12 ++++++++++++
>  net/mac80211/tx.c       |  9 ++++++++-
>  5 files changed, 74 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index cca510a..6e0cf85 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -4089,6 +4089,23 @@ void ieee80211_get_tx_rates(struct ieee80211_vif
> *vif,
>                             int max_rates);
>
>  /**
> + * ieee80211_sta_set_expected_throughput - set the expected throughput
> for a
> + * station
> + *
> + * Call this function to notify mac80211 about a change in expected
> throughput
> + * to a station. A driver for a device that does rate control in firmware
> can
> + * call this function when the expected throughput estimate towards a
> station
> + * changes. The information is used to tune the CoDel AQM applied to
> traffic
> + * going towards that station (which can otherwise be too aggressive and
> cause
> + * slow stations to starve).
> + *
> + * @sta: the station to set throughput for.
> + * @thr: the current expected throughput in kbps.
> + */
> +void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
> +                                          u32 thr);
> +
> +/**
>   * ieee80211_tx_status - transmit status callback
>   *
>   * Call this function for all transmitted frames after they have been
> diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
> index 206698b..5370f5c 100644
> --- a/net/mac80211/rate.c
> +++ b/net/mac80211/rate.c
> @@ -890,6 +890,8 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
>
>         drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
>
> +       sta_update_codel_params(sta, sta_get_expected_throughput(sta));
> +
>         return 0;
>  }
>  EXPORT_SYMBOL(rate_control_set_rates);
> diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
> index 19f14c9..6deda4a 100644
> --- a/net/mac80211/sta_info.c
> +++ b/net/mac80211/sta_info.c
> @@ -20,6 +20,7 @@
>  #include <linux/timer.h>
>  #include <linux/rtnetlink.h>
>
> +#include <net/codel.h>
>  #include <net/mac80211.h>
>  #include "ieee80211_i.h"
>  #include "driver-ops.h"
> @@ -419,6 +420,8 @@ struct sta_info *sta_info_alloc(struct
> ieee80211_sub_if_data *sdata,
>
>         sta->sta.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA;
>
> +       sta_update_codel_params(sta, 0);
> +
>         sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
>
>         return sta;
> @@ -2306,6 +2309,15 @@ u32 sta_get_expected_throughput(struct sta_info
> *sta)
>         return thr;
>  }
>
> +void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
> +                                          u32 thr)
> +{
> +       struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
> +
> +       sta_update_codel_params(sta, thr);
> +}
> +EXPORT_SYMBOL(ieee80211_sta_set_expected_throughput);
> +
>  unsigned long ieee80211_sta_last_active(struct sta_info *sta)
>  {
>         struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);
> @@ -2314,3 +2326,26 @@ unsigned long ieee80211_sta_last_active(struct
> sta_info *sta)
>                 return stats->last_rx;
>         return sta->status_stats.last_ack;
>  }
> +
> +void sta_update_codel_params(struct sta_info *sta, u32 thr)
> +{
> +       u64 now = ktime_get_ns();
> +
> +       if (!sta->sdata->local->ops->wake_tx_queue)
> +               return;
> +
> +       if (now - sta->cparams.update_time < STA_CPARAMS_HYSTERESIS)
> +               return;
> +
> +       if (thr && thr < STA_SLOW_THRESHOLD) {
> +               sta->cparams.params.target = MS2TIME(50);
> +               sta->cparams.params.interval = MS2TIME(300);
> +               sta->cparams.params.ecn = false;
> +       } else {
> +               sta->cparams.params.target = MS2TIME(20);
> +               sta->cparams.params.interval = MS2TIME(100);
> +               sta->cparams.params.ecn = true;
> +       }
> +       sta->cparams.params.ce_threshold = CODEL_DISABLED_THRESHOLD;
> +       sta->cparams.update_time = now;
> +}
> diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
> index 0556be3..ad088ff 100644
> --- a/net/mac80211/sta_info.h
> +++ b/net/mac80211/sta_info.h
> @@ -384,6 +384,14 @@ struct ieee80211_sta_rx_stats {
>         u64 msdu[IEEE80211_NUM_TIDS + 1];
>  };
>
> +#define STA_CPARAMS_HYSTERESIS (2L * NSEC_PER_SEC)
> +#define STA_SLOW_THRESHOLD     8000 /* 8 Mbps */
> +
> +struct sta_codel_params {
> +       struct codel_params params;
> +       u64 update_time;
> +};
> +
>  /**
>   * struct sta_info - STA information
>   *
> @@ -437,6 +445,7 @@ struct ieee80211_sta_rx_stats {
>   * @known_smps_mode: the smps_mode the client thinks we are in. Relevant
> for
>   *     AP only.
>   * @cipher_scheme: optional cipher scheme for this station
> + * @cparams: CoDel parameters for this station.
>   * @reserved_tid: reserved TID (if any, otherwise
> IEEE80211_TID_UNRESERVED)
>   * @fast_tx: TX fastpath information
>   * @fast_rx: RX fastpath information
> @@ -540,6 +549,8 @@ struct sta_info {
>         enum ieee80211_smps_mode known_smps_mode;
>         const struct ieee80211_cipher_scheme *cipher_scheme;
>
> +       struct sta_codel_params cparams;
> +
>         u8 reserved_tid;
>
>         struct cfg80211_chan_def tdls_chandef;
> @@ -713,6 +724,7 @@ void sta_set_rate_info_tx(struct sta_info *sta,
>  void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
>
>  u32 sta_get_expected_throughput(struct sta_info *sta);
> +void sta_update_codel_params(struct sta_info *sta, u32 thr);
>
>  void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
>                           unsigned long exp_time);
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index efc38e7..ec60ac1 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -1342,9 +1342,16 @@ static struct sk_buff *fq_tin_dequeue_func(struct
> fq *fq,
>
>         local = container_of(fq, struct ieee80211_local, fq);
>         txqi = container_of(tin, struct txq_info, tin);
> -       cparams = &local->cparams;
>         cstats = &local->cstats;
>
> +       if (txqi->txq.sta) {
> +               struct sta_info *sta = container_of(txqi->txq.sta,
> +                                                   struct sta_info, sta);
> +               cparams = &sta->cparams.params;
> +       } else {
> +               cparams = &local->cparams;
> +       }
> +
>         if (flow == &txqi->def_flow)
>                 cvars = &txqi->def_cvars;
>         else
> --
> 2.9.3
>
> base-commit: abc3750c31320f36e230f88b235a90e0a35f7032
> _______________________________________________
> Make-wifi-fast mailing list
> Make-wifi-fast at lists.bufferbloat.net
> https://lists.bufferbloat.net/listinfo/make-wifi-fast
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.bufferbloat.net/pipermail/make-wifi-fast/attachments/20160910/2243d49b/attachment-0001.html>


More information about the Make-wifi-fast mailing list