[Bloat] tc linklayer ADSL calc broken after commit 56b765b79 (htb: improved accuracy at high rates)

Eric Dumazet eric.dumazet at gmail.com
Sun Jun 2 17:15:55 EDT 2013


On Wed, 2013-05-29 at 15:13 +0200, Jesper Dangaard Brouer wrote:
> I recently discovered that the (traffic control) tc linklayer
> calculations for ATM/ADSL have been broken by:
>  commit 56b765b79 (htb: improved accuracy at high rates).
> 
> Thus, people shaping on ADSL links, using e.g.:
>  tc class add ... htb rate X ceil Y linklayer atm overhead 10
> 

It seems the "overhead 10" was never reported back by 
"tc -s class show dev ... "

Also, the "linklayer atm" changes the data[] part, and this one is not
matched in qdisc_get_rtab()

So two different rate specifications, but sharing same struct
tc_ratespec could be shared... Oh well.

It seems following fix would be needed anyway ?

[PATCH] net_sched: qdisc_get_rtab() must check data[] array

qdisc_get_rtab() should check not only the keys in struct tc_ratespec,
but also the full data[] array.

"tc ... linklayer atm " only perturbs values in the 256 slots array.

Signed-off-by: Eric Dumazet <edumazet at google.com>
---
 net/sched/sch_api.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 2b935e7..281c1bd 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -291,17 +291,18 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
 {
 	struct qdisc_rate_table *rtab;
 
+	if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
+	    nla_len(tab) != TC_RTAB_SIZE)
+		return NULL;
+
 	for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) {
-		if (memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) == 0) {
+		if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) &&
+		    !memcmp(&rtab->data, nla_data(tab), 1024)) {
 			rtab->refcnt++;
 			return rtab;
 		}
 	}
 
-	if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
-	    nla_len(tab) != TC_RTAB_SIZE)
-		return NULL;
-
 	rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);
 	if (rtab) {
 		rtab->rate = *r;





More information about the Bloat mailing list