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); |
