| From 7c960a26b2c7abeb31df195d81453f08bda401f1 Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Mon, 30 Apr 2012 23:11:05 +0000 |
| Subject: [PATCH] netem: add ECN capability |
| |
| commit e4ae004b84b315dd4b762e474f97403eac70f76a upstream. |
| |
| Add ECN (Explicit Congestion Notification) marking capability to netem |
| |
| tc qdisc add dev eth0 root netem drop 0.5 ecn |
| |
| Instead of dropping packets, try to ECN mark them. |
| |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Cc: Neal Cardwell <ncardwell@google.com> |
| Cc: Tom Herbert <therbert@google.com> |
| Cc: Hagen Paul Pfeifer <hagen@jauu.net> |
| Cc: Stephen Hemminger <shemminger@vyatta.com> |
| Acked-by: Hagen Paul Pfeifer <hagen@jauu.net> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| --- |
| include/linux/pkt_sched.h | 1 + |
| net/sched/sch_netem.c | 18 +++++++++++++++--- |
| 2 files changed, 16 insertions(+), 3 deletions(-) |
| |
| --- a/include/linux/pkt_sched.h |
| +++ b/include/linux/pkt_sched.h |
| @@ -509,6 +509,7 @@ enum { |
| TCA_NETEM_CORRUPT, |
| TCA_NETEM_LOSS, |
| TCA_NETEM_RATE, |
| + TCA_NETEM_ECN, |
| __TCA_NETEM_MAX, |
| }; |
| |
| --- a/net/sched/sch_netem.c |
| +++ b/net/sched/sch_netem.c |
| @@ -26,6 +26,7 @@ |
| |
| #include <net/netlink.h> |
| #include <net/pkt_sched.h> |
| +#include <net/inet_ecn.h> |
| |
| #define VERSION "1.3" |
| |
| @@ -78,6 +79,7 @@ struct netem_sched_data { |
| psched_tdiff_t jitter; |
| |
| u32 loss; |
| + u32 ecn; |
| u32 limit; |
| u32 counter; |
| u32 gap; |
| @@ -366,9 +368,12 @@ static int netem_enqueue(struct sk_buff |
| ++count; |
| |
| /* Drop packet? */ |
| - if (loss_event(q)) |
| - --count; |
| - |
| + if (loss_event(q)) { |
| + if (q->ecn && INET_ECN_set_ce(skb)) |
| + sch->qstats.drops++; /* mark packet */ |
| + else |
| + --count; |
| + } |
| if (count == 0) { |
| sch->qstats.drops++; |
| kfree_skb(skb); |
| @@ -692,6 +697,7 @@ static const struct nla_policy netem_pol |
| [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) }, |
| [TCA_NETEM_RATE] = { .len = sizeof(struct tc_netem_rate) }, |
| [TCA_NETEM_LOSS] = { .type = NLA_NESTED }, |
| + [TCA_NETEM_ECN] = { .type = NLA_U32 }, |
| }; |
| |
| static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, |
| @@ -762,6 +768,9 @@ static int netem_change(struct Qdisc *sc |
| if (tb[TCA_NETEM_RATE]) |
| get_rate(sch, tb[TCA_NETEM_RATE]); |
| |
| + if (tb[TCA_NETEM_ECN]) |
| + q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); |
| + |
| q->loss_model = CLG_RANDOM; |
| if (tb[TCA_NETEM_LOSS]) |
| ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]); |
| @@ -881,6 +890,9 @@ static int netem_dump(struct Qdisc *sch, |
| rate.cell_overhead = q->cell_overhead; |
| NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate); |
| |
| + if (q->ecn && nla_put_u32(skb, TCA_NETEM_ECN, q->ecn)) |
| + goto nla_put_failure; |
| + |
| if (dump_loss_model(q, skb) != 0) |
| goto nla_put_failure; |
| |