Simon's team successfully[1] tested the attached patches on top of felix's lede staging tree on monday against 30 stations. The initial results were lovely, at the rates he tested at.
If anyone out there is daring enough to try building these for the wndr3800, wndr3700v2 and nanostation, (or anything else with ath9k in it!) it would be very good to put these through as many other scenarios as possible, notably adhoc and wds need to get looked at - but go forth! blow things up anyway you can! measure! Flent has a rtt_fair_var test if you can get multiple stations going... Virtual beer to you, if you put your build up somewhere. The staging tree: https://git.lede-project.org/?p=lede/nbd/staging.git;a=summary ---------- Forwarded message ---------- From: Toke Høiland-Jørgensen <t...@toke.dk> Date: Mon, Aug 8, 2016 at 12:49 PM Subject: Re: u alive today? patch To: Dave Taht <dave.t...@gmail.com> Cc: Simon Wunderlich <s...@simonwunderlich.de> Dave Taht <dave.t...@gmail.com> writes: > I am hanging with simon today, have lab setup, was hoping to do some > patching... These are for LEDE; just dump them in package/kernel/mac80211/patches -Toke -- Dave Täht Let's go make home routers and wifi faster! With better software! http://blog.cerowrt.org
From 9ef266357c98faece1b4b400cf83fd9a5bbfcafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <t...@toke.dk> Date: Wed, 22 Jun 2016 13:48:14 +0200 Subject: [PATCH 2/3] ath9k: Measure per-station airtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds hooks to measure the airtime used by stations for TX and RX. The cumulative time is accounted in a stats structure and exported in debugfs. Uses the ts->duration + retry-chain information to account for time spent transmitting to a station. The RX airtime is measured as the duration from first to last frame in an aggregate, using the rs_tstamp fields. Signed-off-by: Toke Høiland-Jørgensen <t...@toke.dk> --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 +++ drivers/net/wireless/ath/ath9k/debug.h | 13 +++++++ drivers/net/wireless/ath/ath9k/debug_sta.c | 45 +++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/recv.c | 58 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/xmit.c | 46 ++++++++++++++++++++++-- 5 files changed, 164 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 083d96b..5bcdc8d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -258,9 +258,11 @@ struct ath_node { bool sleeping; bool no_ps_filter; + u32 airtime_rx_start; #ifdef CPTCFG_ATH9K_STATION_STATISTICS struct ath_rx_rate_stats rx_rate_stats; + struct ath_airtime_stats airtime_stats; #endif u8 key_idx[4]; @@ -561,6 +563,8 @@ void ath_txq_schedule_all(struct ath_softc *sc); int ath_tx_init(struct ath_softc *sc, int nbufs); int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *q); +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, + int width, int half_gi, bool shortPreamble); void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); void ath_assign_seq(struct ath_common *common, struct sk_buff *skb); int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index a078cdd..8659a96 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -221,6 +221,11 @@ struct ath_rx_rate_stats { } cck_stats[4]; }; +struct ath_airtime_stats { + u32 rx_airtime; + u32 tx_airtime; +}; + #define ANT_MAIN 0 #define ANT_ALT 1 @@ -314,12 +319,20 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb); +void ath_debug_airtime(struct ath_softc *sc, + struct ath_node *an, + u32 rx, u32 tx); #else static inline void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb) { } +static inline void ath_debug_airtime(struct ath_softc *sc, + struct ath_node *an, + u32 rx, u32 tx) +{ +} #endif /* CPTCFG_ATH9K_STATION_STATISTICS */ #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index df22e7c..d0d211e 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -242,6 +242,50 @@ static const struct file_operations fops_node_recv = { .llseek = default_llseek, }; +void ath_debug_airtime(struct ath_softc *sc, + struct ath_node *an, + u32 rx, + u32 tx) +{ + struct ath_airtime_stats *astats = &an->airtime_stats; + + astats->rx_airtime += rx; + astats->tx_airtime += tx; +} + +static ssize_t read_airtime(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_node *an = file->private_data; + struct ath_airtime_stats *astats; + u32 len = 0, size = 128; + char *buf; + size_t retval; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + astats = &an->airtime_stats; + + len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime); + len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime); + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; +} + + +static const struct file_operations fops_airtime = { + .read = read_airtime, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + + void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -251,4 +295,5 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr); debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv); + debugfs_create_file("airtime", S_IRUGO, dir, an, &fops_airtime); } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 32160fc..87c3c0e 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -991,6 +991,63 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc, } } +static void ath_rx_count_airtime(struct ath_softc *sc, + struct ath_rx_status *rs, + struct sk_buff *skb) +{ + struct ath_node *an; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_sta *sta; + struct ieee80211_rx_status *rxs; + const struct ieee80211_rate *rate; + bool is_sgi, is_40, is_sp; + int phy; + u32 airtime = 0; + + if (!ieee80211_is_data(hdr->frame_control)) + return; + + rcu_read_lock(); + + sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); + if (!sta) + goto exit; + an = (struct ath_node *) sta->drv_priv; + + if (rs->rs_isaggr && rs->rs_firstaggr) { + an->airtime_rx_start = rs->rs_tstamp; + } else if (rs->rs_isaggr && !rs->rs_moreaggr && an->airtime_rx_start) { + airtime = rs->rs_tstamp - an->airtime_rx_start; + } else if (!rs->rs_isaggr) { + an->airtime_rx_start = 0; + + rxs = IEEE80211_SKB_RXCB(skb); + + is_sgi = !!(rxs->flag & RX_FLAG_SHORT_GI); + is_40 = !!(rxs->flag & RX_FLAG_40MHZ); + is_sp = !!(rxs->flag & RX_FLAG_SHORTPRE); + + if (!!(rxs->flag & RX_FLAG_HT)) { + /* MCS rates */ + + airtime += ath_pkt_duration(sc, rxs->rate_idx, rs->rs_datalen, + is_40, is_sgi, is_sp); + } else { + + phy = IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM; + rate = &common->sbands[rxs->band].bitrates[rxs->rate_idx]; + airtime += ath9k_hw_computetxtime(ah, phy, rate->bitrate * 100, + rs->rs_datalen, rxs->rate_idx, is_sp); + } + } + + ath_debug_airtime(sc, an, airtime, 0); +exit: + rcu_read_unlock(); +} + int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) { struct ath_rxbuf *bf; @@ -1137,6 +1194,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ath9k_antenna_check(sc, &rs); ath9k_apply_ampdu_details(sc, &rs, rxs); ath_debug_rate_stats(sc, &rs, skb); + ath_rx_count_airtime(sc, &rs, skb); hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_ack(hdr->frame_control)) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b508a49..a0de873 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -676,6 +676,46 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); } +static void ath_tx_count_airtime(struct ath_softc *sc, + struct ath_buf *bf, + struct ath_tx_status *ts) +{ + struct ath_node *an; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_tx_rate rates[4]; + struct ieee80211_sta *sta; + int i; + u32 airtime = 0; + + skb = bf->bf_mpdu; + if(!skb) + return; + + hdr = (struct ieee80211_hdr *)skb->data; + memcpy(rates, bf->rates, sizeof(rates)); + + rcu_read_lock(); + + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); + if(!sta) + goto exit; + + + an = (struct ath_node *) sta->drv_priv; + + airtime += ts->duration * (ts->ts_longretry + 1); + + for(i=0; i < ts->ts_rateindex; i++) + airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count; + + ath_debug_airtime(sc, an, 0, airtime); + +exit: + rcu_read_unlock(); +} + static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_tx_status *ts, struct ath_buf *bf, struct list_head *bf_head) @@ -693,6 +733,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, ts->ts_rateindex); + ath_tx_count_airtime(sc, bf, ts); hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data; sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); @@ -1042,8 +1084,8 @@ finish: * width - 0 for 20 MHz, 1 for 40 MHz * half_gi - to use 4us v/s 3.6 us for symbol time */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, - int width, int half_gi, bool shortPreamble) +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, + int width, int half_gi, bool shortPreamble) { u32 nbits, nsymbits, duration, nsymbols; int streams; -- 2.9.0
From 80473865e0123b197dbb676dcede26a219d5d769 Mon Sep 17 00:00:00 2001 From: dave taht <d...@taht.net> Date: Wed, 3 Aug 2016 08:20:22 -0700 Subject: [PATCH] mac80211: Use more standard codel and fq_codel defaults Having the quantum parameter at a single packet saves 5+ runs through the inner loop of fq_codel, and makes the fast/slow concept work for all flows. The codel target should be thought of as "are you willing to tolerate more than X delay for more than interval Y ms", and the target should be thought of as more of a percentage of the interval, where 5% is the point of maximum "power". Additionally: It is better to reduce the maximum size of the txop when there are many stations queueing up, and to try to hold the delay low, but this patch doesn't do that. --- include/net/fq_impl.h | 2 +- net/mac80211/tx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/fq_impl.h b/include/net/fq_impl.h index 163f3ed..9afb1b6 100644 --- a/include/net/fq_impl.h +++ b/include/net/fq_impl.h @@ -249,7 +249,7 @@ static int fq_init(struct fq *fq, int flows_cnt) spin_lock_init(&fq->lock); fq->flows_cnt = max_t(u32, flows_cnt, 1); fq->perturbation = prandom_u32(); - fq->quantum = 300; + fq->quantum = 1514; fq->limit = 8192; fq->flows = kcalloc(fq->flows_cnt, sizeof(fq->flows[0]), GFP_KERNEL); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 91461c4..eb8b1c9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1443,7 +1443,7 @@ int ieee80211_txq_setup_flows(struct ieee80211_local *local) codel_params_init(&local->cparams); codel_stats_init(&local->cstats); local->cparams.interval = MS2TIME(100); - local->cparams.target = MS2TIME(20); + local->cparams.target = MS2TIME(5); local->cparams.ecn = true; local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]), -- 2.7.4
339-ath9k-Add-a-per-station-airtime-deficit-scheduler.patch
Description: Binary data
_______________________________________________ Cerowrt-devel mailing list Cerowrt-devel@lists.bufferbloat.net https://lists.bufferbloat.net/listinfo/cerowrt-devel