diff options
-rw-r--r-- | include/linux/pkt_sched.h | 1 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 18 |
2 files changed, 16 insertions, 3 deletions
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 410b33d014d2..ffe975c3f1d8 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h | |||
@@ -509,6 +509,7 @@ enum { | |||
509 | TCA_NETEM_CORRUPT, | 509 | TCA_NETEM_CORRUPT, |
510 | TCA_NETEM_LOSS, | 510 | TCA_NETEM_LOSS, |
511 | TCA_NETEM_RATE, | 511 | TCA_NETEM_RATE, |
512 | TCA_NETEM_ECN, | ||
512 | __TCA_NETEM_MAX, | 513 | __TCA_NETEM_MAX, |
513 | }; | 514 | }; |
514 | 515 | ||
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 110973145a4b..231cd11aa6e2 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <net/netlink.h> | 27 | #include <net/netlink.h> |
28 | #include <net/pkt_sched.h> | 28 | #include <net/pkt_sched.h> |
29 | #include <net/inet_ecn.h> | ||
29 | 30 | ||
30 | #define VERSION "1.3" | 31 | #define VERSION "1.3" |
31 | 32 | ||
@@ -78,6 +79,7 @@ struct netem_sched_data { | |||
78 | psched_tdiff_t jitter; | 79 | psched_tdiff_t jitter; |
79 | 80 | ||
80 | u32 loss; | 81 | u32 loss; |
82 | u32 ecn; | ||
81 | u32 limit; | 83 | u32 limit; |
82 | u32 counter; | 84 | u32 counter; |
83 | u32 gap; | 85 | u32 gap; |
@@ -374,9 +376,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
374 | ++count; | 376 | ++count; |
375 | 377 | ||
376 | /* Drop packet? */ | 378 | /* Drop packet? */ |
377 | if (loss_event(q)) | 379 | if (loss_event(q)) { |
378 | --count; | 380 | if (q->ecn && INET_ECN_set_ce(skb)) |
379 | 381 | sch->qstats.drops++; /* mark packet */ | |
382 | else | ||
383 | --count; | ||
384 | } | ||
380 | if (count == 0) { | 385 | if (count == 0) { |
381 | sch->qstats.drops++; | 386 | sch->qstats.drops++; |
382 | kfree_skb(skb); | 387 | kfree_skb(skb); |
@@ -706,6 +711,7 @@ static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = { | |||
706 | [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) }, | 711 | [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) }, |
707 | [TCA_NETEM_RATE] = { .len = sizeof(struct tc_netem_rate) }, | 712 | [TCA_NETEM_RATE] = { .len = sizeof(struct tc_netem_rate) }, |
708 | [TCA_NETEM_LOSS] = { .type = NLA_NESTED }, | 713 | [TCA_NETEM_LOSS] = { .type = NLA_NESTED }, |
714 | [TCA_NETEM_ECN] = { .type = NLA_U32 }, | ||
709 | }; | 715 | }; |
710 | 716 | ||
711 | static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, | 717 | static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, |
@@ -776,6 +782,9 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
776 | if (tb[TCA_NETEM_RATE]) | 782 | if (tb[TCA_NETEM_RATE]) |
777 | get_rate(sch, tb[TCA_NETEM_RATE]); | 783 | get_rate(sch, tb[TCA_NETEM_RATE]); |
778 | 784 | ||
785 | if (tb[TCA_NETEM_ECN]) | ||
786 | q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); | ||
787 | |||
779 | q->loss_model = CLG_RANDOM; | 788 | q->loss_model = CLG_RANDOM; |
780 | if (tb[TCA_NETEM_LOSS]) | 789 | if (tb[TCA_NETEM_LOSS]) |
781 | ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]); | 790 | ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]); |
@@ -902,6 +911,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
902 | if (nla_put(skb, TCA_NETEM_RATE, sizeof(rate), &rate)) | 911 | if (nla_put(skb, TCA_NETEM_RATE, sizeof(rate), &rate)) |
903 | goto nla_put_failure; | 912 | goto nla_put_failure; |
904 | 913 | ||
914 | if (q->ecn && nla_put_u32(skb, TCA_NETEM_ECN, q->ecn)) | ||
915 | goto nla_put_failure; | ||
916 | |||
905 | if (dump_loss_model(q, skb) != 0) | 917 | if (dump_loss_model(q, skb) != 0) |
906 | goto nla_put_failure; | 918 | goto nla_put_failure; |
907 | 919 | ||