Merge branches 'acpi_pad-bugzilla-42981', 'apei-bugzilla-43282', 'video-bugzilla...
[firefly-linux-kernel-4.4.55.git] / net / sched / sch_netem.c
index ebd22966f7480aaacb49ca892c774ac23c477acb..a2a95aabf9c22bd3b0b0bbbe558feb1c1f65430a 100644 (file)
@@ -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;
@@ -374,9 +376,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                ++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);
@@ -704,6 +709,7 @@ static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
        [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,
@@ -774,6 +780,9 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
        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]);
@@ -832,7 +841,8 @@ static int dump_loss_model(const struct netem_sched_data *q,
                        .p23 = q->clg.a5,
                };
 
-               NLA_PUT(skb, NETEM_LOSS_GI, sizeof(gi), &gi);
+               if (nla_put(skb, NETEM_LOSS_GI, sizeof(gi), &gi))
+                       goto nla_put_failure;
                break;
        }
        case CLG_GILB_ELL: {
@@ -843,7 +853,8 @@ static int dump_loss_model(const struct netem_sched_data *q,
                        .k1 = q->clg.a4,
                };
 
-               NLA_PUT(skb, NETEM_LOSS_GE, sizeof(ge), &ge);
+               if (nla_put(skb, NETEM_LOSS_GE, sizeof(ge), &ge))
+                       goto nla_put_failure;
                break;
        }
        }
@@ -872,26 +883,34 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
        qopt.loss = q->loss;
        qopt.gap = q->gap;
        qopt.duplicate = q->duplicate;
-       NLA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+       if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt))
+               goto nla_put_failure;
 
        cor.delay_corr = q->delay_cor.rho;
        cor.loss_corr = q->loss_cor.rho;
        cor.dup_corr = q->dup_cor.rho;
-       NLA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
+       if (nla_put(skb, TCA_NETEM_CORR, sizeof(cor), &cor))
+               goto nla_put_failure;
 
        reorder.probability = q->reorder;
        reorder.correlation = q->reorder_cor.rho;
-       NLA_PUT(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder);
+       if (nla_put(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder))
+               goto nla_put_failure;
 
        corrupt.probability = q->corrupt;
        corrupt.correlation = q->corrupt_cor.rho;
-       NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
+       if (nla_put(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt))
+               goto nla_put_failure;
 
        rate.rate = q->rate;
        rate.packet_overhead = q->packet_overhead;
        rate.cell_size = q->cell_size;
        rate.cell_overhead = q->cell_overhead;
-       NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
+       if (nla_put(skb, TCA_NETEM_RATE, sizeof(rate), &rate))
+               goto nla_put_failure;
+
+       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;