diff options
-rw-r--r-- | include/linux/pkt_sched.h | 4 | ||||
-rw-r--r-- | net/sched/sch_gred.c | 25 |
2 files changed, 23 insertions, 6 deletions
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index d053add3dca7..0ebe320223e2 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h | |||
@@ -220,8 +220,8 @@ struct tc_gred_sopt | |||
220 | __u32 DPs; | 220 | __u32 DPs; |
221 | __u32 def_DP; | 221 | __u32 def_DP; |
222 | __u8 grio; | 222 | __u8 grio; |
223 | __u8 pad1; | 223 | __u8 flags; |
224 | __u16 pad2; | 224 | __u16 pad1; |
225 | }; | 225 | }; |
226 | 226 | ||
227 | /* HTB section */ | 227 | /* HTB section */ |
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 69f0fd45d4c3..079b0a4ea1c2 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c | |||
@@ -55,6 +55,7 @@ struct gred_sched | |||
55 | { | 55 | { |
56 | struct gred_sched_data *tab[MAX_DPs]; | 56 | struct gred_sched_data *tab[MAX_DPs]; |
57 | unsigned long flags; | 57 | unsigned long flags; |
58 | u32 red_flags; | ||
58 | u32 DPs; | 59 | u32 DPs; |
59 | u32 def; | 60 | u32 def; |
60 | struct red_parms wred_set; | 61 | struct red_parms wred_set; |
@@ -140,6 +141,11 @@ static inline void gred_store_wred_set(struct gred_sched *table, | |||
140 | table->wred_set.qavg = q->parms.qavg; | 141 | table->wred_set.qavg = q->parms.qavg; |
141 | } | 142 | } |
142 | 143 | ||
144 | static inline int gred_use_ecn(struct gred_sched *t) | ||
145 | { | ||
146 | return t->red_flags & TC_RED_ECN; | ||
147 | } | ||
148 | |||
143 | static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 149 | static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) |
144 | { | 150 | { |
145 | struct gred_sched_data *q=NULL; | 151 | struct gred_sched_data *q=NULL; |
@@ -198,13 +204,22 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
198 | 204 | ||
199 | case RED_PROB_MARK: | 205 | case RED_PROB_MARK: |
200 | sch->qstats.overlimits++; | 206 | sch->qstats.overlimits++; |
201 | q->stats.prob_drop++; | 207 | if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { |
202 | goto congestion_drop; | 208 | q->stats.prob_drop++; |
209 | goto congestion_drop; | ||
210 | } | ||
211 | |||
212 | q->stats.prob_mark++; | ||
213 | break; | ||
203 | 214 | ||
204 | case RED_HARD_MARK: | 215 | case RED_HARD_MARK: |
205 | sch->qstats.overlimits++; | 216 | sch->qstats.overlimits++; |
206 | q->stats.forced_drop++; | 217 | if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { |
207 | goto congestion_drop; | 218 | q->stats.forced_drop++; |
219 | goto congestion_drop; | ||
220 | } | ||
221 | q->stats.forced_mark++; | ||
222 | break; | ||
208 | } | 223 | } |
209 | 224 | ||
210 | if (q->backlog + skb->len <= q->limit) { | 225 | if (q->backlog + skb->len <= q->limit) { |
@@ -348,6 +363,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) | |||
348 | sch_tree_lock(sch); | 363 | sch_tree_lock(sch); |
349 | table->DPs = sopt->DPs; | 364 | table->DPs = sopt->DPs; |
350 | table->def = sopt->def_DP; | 365 | table->def = sopt->def_DP; |
366 | table->red_flags = sopt->flags; | ||
351 | 367 | ||
352 | /* | 368 | /* |
353 | * Every entry point to GRED is synchronized with the above code | 369 | * Every entry point to GRED is synchronized with the above code |
@@ -489,6 +505,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
489 | .DPs = table->DPs, | 505 | .DPs = table->DPs, |
490 | .def_DP = table->def, | 506 | .def_DP = table->def, |
491 | .grio = gred_rio_mode(table), | 507 | .grio = gred_rio_mode(table), |
508 | .flags = table->red_flags, | ||
492 | }; | 509 | }; |
493 | 510 | ||
494 | opts = RTA_NEST(skb, TCA_OPTIONS); | 511 | opts = RTA_NEST(skb, TCA_OPTIONS); |