aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/pkt_sched.h4
-rw-r--r--net/sched/sch_gred.c25
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
144static inline int gred_use_ecn(struct gred_sched *t)
145{
146 return t->red_flags & TC_RED_ECN;
147}
148
143static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) 149static 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);