]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sched/sch_netem.c
Merge tag 'iommu-updates-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
[linux.git] / net / sched / sch_netem.c
index cc9d8133afcdb7fe1b6b4c35f9d96d636ea11035..b17f2ed970e296adc57bed458ec3cced4fc6705b 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * net/sched/sch_netem.c       Network emulator
  *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License.
- *
  *             Many of the algorithms and ideas for this came from
  *             NIST Net which is not copyrighted.
  *
@@ -443,8 +439,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        struct netem_skb_cb *cb;
        struct sk_buff *skb2;
        struct sk_buff *segs = NULL;
-       unsigned int len = 0, last_len, prev_len = qdisc_pkt_len(skb);
-       int nb = 0;
+       unsigned int prev_len = qdisc_pkt_len(skb);
        int count = 1;
        int rc = NET_XMIT_SUCCESS;
        int rc_drop = NET_XMIT_DROP;
@@ -498,16 +493,14 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
         */
        if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
                if (skb_is_gso(skb)) {
-                       segs = netem_segment(skb, sch, to_free);
-                       if (!segs)
+                       skb = netem_segment(skb, sch, to_free);
+                       if (!skb)
                                return rc_drop;
-               } else {
-                       segs = skb;
+                       segs = skb->next;
+                       skb_mark_not_on_list(skb);
+                       qdisc_skb_cb(skb)->pkt_len = skb->len;
                }
 
-               skb = segs;
-               segs = segs->next;
-
                skb = skb_unshare(skb, GFP_ATOMIC);
                if (unlikely(!skb)) {
                        qdisc_qstats_drop(sch);
@@ -524,6 +517,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
 
        if (unlikely(sch->q.qlen >= sch->limit)) {
+               /* re-link segs, so that qdisc_drop_all() frees them all */
+               skb->next = segs;
                qdisc_drop_all(skb, sch, to_free);
                return rc_drop;
        }
@@ -597,6 +592,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 
 finish_segs:
        if (segs) {
+               unsigned int len, last_len;
+               int nb = 0;
+
+               len = skb->len;
+
                while (segs) {
                        skb2 = segs->next;
                        skb_mark_not_on_list(segs);
@@ -612,9 +612,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                        }
                        segs = skb2;
                }
-               sch->q.qlen += nb;
-               if (nb > 1)
-                       qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
+               qdisc_tree_reduce_backlog(sch, -nb, prev_len - len);
        }
        return NET_XMIT_SUCCESS;
 }
@@ -935,8 +933,9 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
        }
 
        if (nested_len >= nla_attr_size(0))
-               return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len),
-                                nested_len, policy, NULL);
+               return nla_parse_deprecated(tb, maxtype,
+                                           nla_data(nla) + NLA_ALIGN(len),
+                                           nested_len, policy, NULL);
 
        memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
        return 0;
@@ -1079,7 +1078,7 @@ static int dump_loss_model(const struct netem_sched_data *q,
 {
        struct nlattr *nest;
 
-       nest = nla_nest_start(skb, TCA_NETEM_LOSS);
+       nest = nla_nest_start_noflag(skb, TCA_NETEM_LOSS);
        if (nest == NULL)
                goto nla_put_failure;