aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-3.3/046-fq_codel-qdisc-backlog.patch
blob: f9bcbbd08f77ba2aebed37d9fe60ba51b286025f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
From 7bd90773f89001ea4960ed47676b550137f3facb Mon Sep 17 00:00:00 2001
From: Eric Dumazet <edumazet@google.com>
Date: Wed, 16 May 2012 04:39:09 +0000
Subject: [PATCH] fq_codel: should use qdisc backlog as threshold

commit 865ec5523dadbedefbc5710a68969f686a28d928 upstream.

codel_should_drop() logic allows a packet being not dropped if queue
size is under max packet size.

In fq_codel, we have two possible backlogs : The qdisc global one, and
the flow local one.

The meaningful one for codel_should_drop() should be the global backlog,
not the per flow one, so that thin flows can have a non zero drop/mark
probability.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Dave Taht <dave.taht@bufferbloat.net>
Cc: Kathleen Nichols <nichols@pollere.com>
Cc: Van Jacobson <van@pollere.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/codel.h      |   15 +++++++--------
 net/sched/sch_codel.c    |    4 ++--
 net/sched/sch_fq_codel.c |    5 +++--
 3 files changed, 12 insertions(+), 12 deletions(-)

--- a/include/net/codel.h
+++ b/include/net/codel.h
@@ -205,7 +205,7 @@ static codel_time_t codel_control_law(co
 
 
 static bool codel_should_drop(const struct sk_buff *skb,
-			      unsigned int *backlog,
+			      struct Qdisc *sch,
 			      struct codel_vars *vars,
 			      struct codel_params *params,
 			      struct codel_stats *stats,
@@ -219,13 +219,13 @@ static bool codel_should_drop(const stru
 	}
 
 	vars->ldelay = now - codel_get_enqueue_time(skb);
-	*backlog -= qdisc_pkt_len(skb);
+	sch->qstats.backlog -= qdisc_pkt_len(skb);
 
 	if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket))
 		stats->maxpacket = qdisc_pkt_len(skb);
 
 	if (codel_time_before(vars->ldelay, params->target) ||
-	    *backlog <= stats->maxpacket) {
+	    sch->qstats.backlog <= stats->maxpacket) {
 		/* went below - stay below for at least interval */
 		vars->first_above_time = 0;
 		return false;
@@ -249,8 +249,7 @@ static struct sk_buff *codel_dequeue(str
 				     struct codel_params *params,
 				     struct codel_vars *vars,
 				     struct codel_stats *stats,
-				     codel_skb_dequeue_t dequeue_func,
-				     u32 *backlog)
+				     codel_skb_dequeue_t dequeue_func)
 {
 	struct sk_buff *skb = dequeue_func(vars, sch);
 	codel_time_t now;
@@ -261,7 +260,7 @@ static struct sk_buff *codel_dequeue(str
 		return skb;
 	}
 	now = codel_get_time();
-	drop = codel_should_drop(skb, backlog, vars, params, stats, now);
+	drop = codel_should_drop(skb, sch, vars, params, stats, now);
 	if (vars->dropping) {
 		if (!drop) {
 			/* sojourn time below target - leave dropping state */
@@ -292,7 +291,7 @@ static struct sk_buff *codel_dequeue(str
 				qdisc_drop(skb, sch);
 				stats->drop_count++;
 				skb = dequeue_func(vars, sch);
-				if (!codel_should_drop(skb, backlog,
+				if (!codel_should_drop(skb, sch,
 						       vars, params, stats, now)) {
 					/* leave dropping state */
 					vars->dropping = false;
@@ -313,7 +312,7 @@ static struct sk_buff *codel_dequeue(str
 			stats->drop_count++;
 
 			skb = dequeue_func(vars, sch);
-			drop = codel_should_drop(skb, backlog, vars, params,
+			drop = codel_should_drop(skb, sch, vars, params,
 						 stats, now);
 		}
 		vars->dropping = true;
--- a/net/sched/sch_codel.c
+++ b/net/sched/sch_codel.c
@@ -77,8 +77,8 @@ static struct sk_buff *codel_qdisc_deque
 	struct codel_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
 
-	skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats,
-			    dequeue, &sch->qstats.backlog);
+	skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue);
+
 	/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
 	 * or HTB crashes. Defer it for next round.
 	 */
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -217,13 +217,14 @@ static int fq_codel_enqueue(struct sk_bu
  */
 static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
 {
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
 	struct fq_codel_flow *flow;
 	struct sk_buff *skb = NULL;
 
 	flow = container_of(vars, struct fq_codel_flow, cvars);
 	if (flow->head) {
 		skb = dequeue_head(flow);
-		sch->qstats.backlog -= qdisc_pkt_len(skb);
+		q->backlogs[flow - q->flows] -= qdisc_pkt_len(skb);
 		sch->q.qlen--;
 	}
 	return skb;
@@ -256,7 +257,7 @@ begin:
 	prev_ecn_mark = q->cstats.ecn_mark;
 
 	skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
-			    dequeue, &q->backlogs[flow - q->flows]);
+			    dequeue);
 
 	flow->dropped += q->cstats.drop_count - prev_drop_count;
 	flow->dropped += q->cstats.ecn_mark - prev_ecn_mark;