kernel: backport patches improving fq_codel drop behavior
authorFelix Fietkau <nbd@nbd.name>
Thu, 12 May 2016 19:04:50 +0000 (21:04 +0200)
committerFelix Fietkau <nbd@nbd.name>
Thu, 12 May 2016 19:04:50 +0000 (21:04 +0200)
Signed-off-by: Felix Fietkau <nbd@nbd.name>
target/linux/generic/patches-4.4/030-net_sched-introduce-qdisc_replace-helper.patch [new file with mode: 0644]
target/linux/generic/patches-4.4/031-net_sched-update-hierarchical-backlog-too.patch [new file with mode: 0644]
target/linux/generic/patches-4.4/032-fq_codel-add-batch-ability-to-fq_codel_drop.patch [new file with mode: 0644]
target/linux/generic/patches-4.4/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch
target/linux/generic/patches-4.4/531-debloat_lzma.patch
target/linux/generic/patches-4.4/645-bridge_multicast_to_unicast.patch
target/linux/generic/patches-4.4/660-fq_codel_defaults.patch
target/linux/generic/patches-4.4/661-fq_codel_keep_dropped_stats.patch
target/linux/generic/patches-4.4/662-use_fq_codel_by_default.patch

diff --git a/target/linux/generic/patches-4.4/030-net_sched-introduce-qdisc_replace-helper.patch b/target/linux/generic/patches-4.4/030-net_sched-introduce-qdisc_replace-helper.patch
new file mode 100644 (file)
index 0000000..a3a601b
--- /dev/null
@@ -0,0 +1,237 @@
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Thu, 25 Feb 2016 14:55:00 -0800
+Subject: [PATCH] net_sched: introduce qdisc_replace() helper
+
+Remove nearly duplicated code and prepare for the following patch.
+
+Cc: Jamal Hadi Salim <jhs@mojatatu.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -698,6 +698,23 @@ static inline void qdisc_reset_queue(str
+       sch->qstats.backlog = 0;
+ }
++static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
++                                        struct Qdisc **pold)
++{
++      struct Qdisc *old;
++
++      sch_tree_lock(sch);
++      old = *pold;
++      *pold = new;
++      if (old != NULL) {
++              qdisc_tree_decrease_qlen(old, old->q.qlen);
++              qdisc_reset(old);
++      }
++      sch_tree_unlock(sch);
++
++      return old;
++}
++
+ static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch,
+                                             struct sk_buff_head *list)
+ {
+--- a/net/sched/sch_cbq.c
++++ b/net/sched/sch_cbq.c
+@@ -1624,13 +1624,8 @@ static int cbq_graft(struct Qdisc *sch,
+                       new->reshape_fail = cbq_reshape_fail;
+ #endif
+       }
+-      sch_tree_lock(sch);
+-      *old = cl->q;
+-      cl->q = new;
+-      qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-      qdisc_reset(*old);
+-      sch_tree_unlock(sch);
++      *old = qdisc_replace(sch, new, &cl->q);
+       return 0;
+ }
+--- a/net/sched/sch_drr.c
++++ b/net/sched/sch_drr.c
+@@ -226,11 +226,7 @@ static int drr_graft_class(struct Qdisc
+                       new = &noop_qdisc;
+       }
+-      sch_tree_lock(sch);
+-      drr_purge_queue(cl);
+-      *old = cl->qdisc;
+-      cl->qdisc = new;
+-      sch_tree_unlock(sch);
++      *old = qdisc_replace(sch, new, &cl->qdisc);
+       return 0;
+ }
+--- a/net/sched/sch_dsmark.c
++++ b/net/sched/sch_dsmark.c
+@@ -73,13 +73,7 @@ static int dsmark_graft(struct Qdisc *sc
+                       new = &noop_qdisc;
+       }
+-      sch_tree_lock(sch);
+-      *old = p->q;
+-      p->q = new;
+-      qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-      qdisc_reset(*old);
+-      sch_tree_unlock(sch);
+-
++      *old = qdisc_replace(sch, new, &p->q);
+       return 0;
+ }
+--- a/net/sched/sch_hfsc.c
++++ b/net/sched/sch_hfsc.c
+@@ -1215,11 +1215,7 @@ hfsc_graft_class(struct Qdisc *sch, unsi
+                       new = &noop_qdisc;
+       }
+-      sch_tree_lock(sch);
+-      hfsc_purge_queue(sch, cl);
+-      *old = cl->qdisc;
+-      cl->qdisc = new;
+-      sch_tree_unlock(sch);
++      *old = qdisc_replace(sch, new, &cl->qdisc);
+       return 0;
+ }
+--- a/net/sched/sch_htb.c
++++ b/net/sched/sch_htb.c
+@@ -1163,14 +1163,7 @@ static int htb_graft(struct Qdisc *sch,
+                                    cl->common.classid)) == NULL)
+               return -ENOBUFS;
+-      sch_tree_lock(sch);
+-      *old = cl->un.leaf.q;
+-      cl->un.leaf.q = new;
+-      if (*old != NULL) {
+-              qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-              qdisc_reset(*old);
+-      }
+-      sch_tree_unlock(sch);
++      *old = qdisc_replace(sch, new, &cl->un.leaf.q);
+       return 0;
+ }
+--- a/net/sched/sch_multiq.c
++++ b/net/sched/sch_multiq.c
+@@ -303,13 +303,7 @@ static int multiq_graft(struct Qdisc *sc
+       if (new == NULL)
+               new = &noop_qdisc;
+-      sch_tree_lock(sch);
+-      *old = q->queues[band];
+-      q->queues[band] = new;
+-      qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-      qdisc_reset(*old);
+-      sch_tree_unlock(sch);
+-
++      *old = qdisc_replace(sch, new, &q->queues[band]);
+       return 0;
+ }
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -1037,15 +1037,7 @@ static int netem_graft(struct Qdisc *sch
+ {
+       struct netem_sched_data *q = qdisc_priv(sch);
+-      sch_tree_lock(sch);
+-      *old = q->qdisc;
+-      q->qdisc = new;
+-      if (*old) {
+-              qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-              qdisc_reset(*old);
+-      }
+-      sch_tree_unlock(sch);
+-
++      *old = qdisc_replace(sch, new, &q->qdisc);
+       return 0;
+ }
+--- a/net/sched/sch_prio.c
++++ b/net/sched/sch_prio.c
+@@ -268,13 +268,7 @@ static int prio_graft(struct Qdisc *sch,
+       if (new == NULL)
+               new = &noop_qdisc;
+-      sch_tree_lock(sch);
+-      *old = q->queues[band];
+-      q->queues[band] = new;
+-      qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-      qdisc_reset(*old);
+-      sch_tree_unlock(sch);
+-
++      *old = qdisc_replace(sch, new, &q->queues[band]);
+       return 0;
+ }
+--- a/net/sched/sch_qfq.c
++++ b/net/sched/sch_qfq.c
+@@ -617,11 +617,7 @@ static int qfq_graft_class(struct Qdisc
+                       new = &noop_qdisc;
+       }
+-      sch_tree_lock(sch);
+-      qfq_purge_queue(cl);
+-      *old = cl->qdisc;
+-      cl->qdisc = new;
+-      sch_tree_unlock(sch);
++      *old = qdisc_replace(sch, new, &cl->qdisc);
+       return 0;
+ }
+--- a/net/sched/sch_red.c
++++ b/net/sched/sch_red.c
+@@ -313,12 +313,7 @@ static int red_graft(struct Qdisc *sch,
+       if (new == NULL)
+               new = &noop_qdisc;
+-      sch_tree_lock(sch);
+-      *old = q->qdisc;
+-      q->qdisc = new;
+-      qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-      qdisc_reset(*old);
+-      sch_tree_unlock(sch);
++      *old = qdisc_replace(sch, new, &q->qdisc);
+       return 0;
+ }
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -606,12 +606,7 @@ static int sfb_graft(struct Qdisc *sch,
+       if (new == NULL)
+               new = &noop_qdisc;
+-      sch_tree_lock(sch);
+-      *old = q->qdisc;
+-      q->qdisc = new;
+-      qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-      qdisc_reset(*old);
+-      sch_tree_unlock(sch);
++      *old = qdisc_replace(sch, new, &q->qdisc);
+       return 0;
+ }
+--- a/net/sched/sch_tbf.c
++++ b/net/sched/sch_tbf.c
+@@ -502,13 +502,7 @@ static int tbf_graft(struct Qdisc *sch,
+       if (new == NULL)
+               new = &noop_qdisc;
+-      sch_tree_lock(sch);
+-      *old = q->qdisc;
+-      q->qdisc = new;
+-      qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+-      qdisc_reset(*old);
+-      sch_tree_unlock(sch);
+-
++      *old = qdisc_replace(sch, new, &q->qdisc);
+       return 0;
+ }
diff --git a/target/linux/generic/patches-4.4/031-net_sched-update-hierarchical-backlog-too.patch b/target/linux/generic/patches-4.4/031-net_sched-update-hierarchical-backlog-too.patch
new file mode 100644 (file)
index 0000000..eb34eea
--- /dev/null
@@ -0,0 +1,647 @@
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Thu, 25 Feb 2016 14:55:01 -0800
+Subject: [PATCH] net_sched: update hierarchical backlog too
+
+When the bottom qdisc decides to, for example, drop some packet,
+it calls qdisc_tree_decrease_qlen() to update the queue length
+for all its ancestors, we need to update the backlog too to
+keep the stats on root qdisc accurate.
+
+Cc: Jamal Hadi Salim <jhs@mojatatu.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/include/net/codel.h
++++ b/include/net/codel.h
+@@ -162,12 +162,14 @@ struct codel_vars {
+  * struct codel_stats - contains codel shared variables and stats
+  * @maxpacket:        largest packet we've seen so far
+  * @drop_count:       temp count of dropped packets in dequeue()
++ * @drop_len: bytes of dropped packets in dequeue()
+  * ecn_mark:  number of packets we ECN marked instead of dropping
+  * ce_mark:   number of packets CE marked because sojourn time was above ce_threshold
+  */
+ struct codel_stats {
+       u32             maxpacket;
+       u32             drop_count;
++      u32             drop_len;
+       u32             ecn_mark;
+       u32             ce_mark;
+ };
+@@ -308,6 +310,7 @@ static struct sk_buff *codel_dequeue(str
+                                                                 vars->rec_inv_sqrt);
+                                       goto end;
+                               }
++                              stats->drop_len += qdisc_pkt_len(skb);
+                               qdisc_drop(skb, sch);
+                               stats->drop_count++;
+                               skb = dequeue_func(vars, sch);
+@@ -330,6 +333,7 @@ static struct sk_buff *codel_dequeue(str
+               if (params->ecn && INET_ECN_set_ce(skb)) {
+                       stats->ecn_mark++;
+               } else {
++                      stats->drop_len += qdisc_pkt_len(skb);
+                       qdisc_drop(skb, sch);
+                       stats->drop_count++;
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -396,7 +396,8 @@ struct Qdisc *dev_graft_qdisc(struct net
+                             struct Qdisc *qdisc);
+ void qdisc_reset(struct Qdisc *qdisc);
+ void qdisc_destroy(struct Qdisc *qdisc);
+-void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
++void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n,
++                             unsigned int len);
+ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
+                         const struct Qdisc_ops *ops);
+ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
+@@ -707,7 +708,7 @@ static inline struct Qdisc *qdisc_replac
+       old = *pold;
+       *pold = new;
+       if (old != NULL) {
+-              qdisc_tree_decrease_qlen(old, old->q.qlen);
++              qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog);
+               qdisc_reset(old);
+       }
+       sch_tree_unlock(sch);
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -744,14 +744,15 @@ static u32 qdisc_alloc_handle(struct net
+       return 0;
+ }
+-void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
++void qdisc_tree_reduce_backlog(struct Qdisc *sch, unsigned int n,
++                             unsigned int len)
+ {
+       const struct Qdisc_class_ops *cops;
+       unsigned long cl;
+       u32 parentid;
+       int drops;
+-      if (n == 0)
++      if (n == 0 && len == 0)
+               return;
+       drops = max_t(int, n, 0);
+       rcu_read_lock();
+@@ -774,11 +775,12 @@ void qdisc_tree_decrease_qlen(struct Qdi
+                       cops->put(sch, cl);
+               }
+               sch->q.qlen -= n;
++              sch->qstats.backlog -= len;
+               __qdisc_qstats_drop(sch, drops);
+       }
+       rcu_read_unlock();
+ }
+-EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
++EXPORT_SYMBOL(qdisc_tree_reduce_backlog);
+ static void notify_and_destroy(struct net *net, struct sk_buff *skb,
+                              struct nlmsghdr *n, u32 clid,
+--- a/net/sched/sch_cbq.c
++++ b/net/sched/sch_cbq.c
+@@ -1909,7 +1909,7 @@ static int cbq_delete(struct Qdisc *sch,
+ {
+       struct cbq_sched_data *q = qdisc_priv(sch);
+       struct cbq_class *cl = (struct cbq_class *)arg;
+-      unsigned int qlen;
++      unsigned int qlen, backlog;
+       if (cl->filters || cl->children || cl == &q->link)
+               return -EBUSY;
+@@ -1917,8 +1917,9 @@ static int cbq_delete(struct Qdisc *sch,
+       sch_tree_lock(sch);
+       qlen = cl->q->q.qlen;
++      backlog = cl->q->qstats.backlog;
+       qdisc_reset(cl->q);
+-      qdisc_tree_decrease_qlen(cl->q, qlen);
++      qdisc_tree_reduce_backlog(cl->q, qlen, backlog);
+       if (cl->next_alive)
+               cbq_deactivate_class(cl);
+--- a/net/sched/sch_choke.c
++++ b/net/sched/sch_choke.c
+@@ -128,8 +128,8 @@ static void choke_drop_by_idx(struct Qdi
+               choke_zap_tail_holes(q);
+       qdisc_qstats_backlog_dec(sch, skb);
++      qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb));
+       qdisc_drop(skb, sch);
+-      qdisc_tree_decrease_qlen(sch, 1);
+       --sch->q.qlen;
+ }
+@@ -456,6 +456,7 @@ static int choke_change(struct Qdisc *sc
+               old = q->tab;
+               if (old) {
+                       unsigned int oqlen = sch->q.qlen, tail = 0;
++                      unsigned dropped = 0;
+                       while (q->head != q->tail) {
+                               struct sk_buff *skb = q->tab[q->head];
+@@ -467,11 +468,12 @@ static int choke_change(struct Qdisc *sc
+                                       ntab[tail++] = skb;
+                                       continue;
+                               }
++                              dropped += qdisc_pkt_len(skb);
+                               qdisc_qstats_backlog_dec(sch, skb);
+                               --sch->q.qlen;
+                               qdisc_drop(skb, sch);
+                       }
+-                      qdisc_tree_decrease_qlen(sch, oqlen - sch->q.qlen);
++                      qdisc_tree_reduce_backlog(sch, oqlen - sch->q.qlen, dropped);
+                       q->head = 0;
+                       q->tail = tail;
+               }
+--- a/net/sched/sch_codel.c
++++ b/net/sched/sch_codel.c
+@@ -79,12 +79,13 @@ static struct sk_buff *codel_qdisc_deque
+       skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue);
+-      /* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
++      /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0,
+        * or HTB crashes. Defer it for next round.
+        */
+       if (q->stats.drop_count && sch->q.qlen) {
+-              qdisc_tree_decrease_qlen(sch, q->stats.drop_count);
++              qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len);
+               q->stats.drop_count = 0;
++              q->stats.drop_len = 0;
+       }
+       if (skb)
+               qdisc_bstats_update(sch, skb);
+@@ -116,7 +117,7 @@ static int codel_change(struct Qdisc *sc
+ {
+       struct codel_sched_data *q = qdisc_priv(sch);
+       struct nlattr *tb[TCA_CODEL_MAX + 1];
+-      unsigned int qlen;
++      unsigned int qlen, dropped = 0;
+       int err;
+       if (!opt)
+@@ -156,10 +157,11 @@ static int codel_change(struct Qdisc *sc
+       while (sch->q.qlen > sch->limit) {
+               struct sk_buff *skb = __skb_dequeue(&sch->q);
++              dropped += qdisc_pkt_len(skb);
+               qdisc_qstats_backlog_dec(sch, skb);
+               qdisc_drop(skb, sch);
+       }
+-      qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
++      qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
+       sch_tree_unlock(sch);
+       return 0;
+--- a/net/sched/sch_drr.c
++++ b/net/sched/sch_drr.c
+@@ -53,9 +53,10 @@ static struct drr_class *drr_find_class(
+ static void drr_purge_queue(struct drr_class *cl)
+ {
+       unsigned int len = cl->qdisc->q.qlen;
++      unsigned int backlog = cl->qdisc->qstats.backlog;
+       qdisc_reset(cl->qdisc);
+-      qdisc_tree_decrease_qlen(cl->qdisc, len);
++      qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
+ }
+ static const struct nla_policy drr_policy[TCA_DRR_MAX + 1] = {
+--- a/net/sched/sch_fq.c
++++ b/net/sched/sch_fq.c
+@@ -662,6 +662,7 @@ static int fq_change(struct Qdisc *sch,
+       struct fq_sched_data *q = qdisc_priv(sch);
+       struct nlattr *tb[TCA_FQ_MAX + 1];
+       int err, drop_count = 0;
++      unsigned drop_len = 0;
+       u32 fq_log;
+       if (!opt)
+@@ -736,10 +737,11 @@ static int fq_change(struct Qdisc *sch,
+               if (!skb)
+                       break;
++              drop_len += qdisc_pkt_len(skb);
+               kfree_skb(skb);
+               drop_count++;
+       }
+-      qdisc_tree_decrease_qlen(sch, drop_count);
++      qdisc_tree_reduce_backlog(sch, drop_count, drop_len);
+       sch_tree_unlock(sch);
+       return err;
+--- a/net/sched/sch_fq_codel.c
++++ b/net/sched/sch_fq_codel.c
+@@ -175,7 +175,7 @@ static unsigned int fq_codel_qdisc_drop(
+ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ {
+       struct fq_codel_sched_data *q = qdisc_priv(sch);
+-      unsigned int idx;
++      unsigned int idx, prev_backlog;
+       struct fq_codel_flow *flow;
+       int uninitialized_var(ret);
+@@ -203,6 +203,7 @@ static int fq_codel_enqueue(struct sk_bu
+       if (++sch->q.qlen <= sch->limit)
+               return NET_XMIT_SUCCESS;
++      prev_backlog = sch->qstats.backlog;
+       q->drop_overlimit++;
+       /* Return Congestion Notification only if we dropped a packet
+        * from this flow.
+@@ -211,7 +212,7 @@ static int fq_codel_enqueue(struct sk_bu
+               return NET_XMIT_CN;
+       /* As we dropped a packet, better let upper stack know this */
+-      qdisc_tree_decrease_qlen(sch, 1);
++      qdisc_tree_reduce_backlog(sch, 1, prev_backlog - sch->qstats.backlog);
+       return NET_XMIT_SUCCESS;
+ }
+@@ -241,6 +242,7 @@ static struct sk_buff *fq_codel_dequeue(
+       struct fq_codel_flow *flow;
+       struct list_head *head;
+       u32 prev_drop_count, prev_ecn_mark;
++      unsigned int prev_backlog;
+ begin:
+       head = &q->new_flows;
+@@ -259,6 +261,7 @@ begin:
+       prev_drop_count = q->cstats.drop_count;
+       prev_ecn_mark = q->cstats.ecn_mark;
++      prev_backlog = sch->qstats.backlog;
+       skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
+                           dequeue);
+@@ -276,12 +279,14 @@ begin:
+       }
+       qdisc_bstats_update(sch, skb);
+       flow->deficit -= qdisc_pkt_len(skb);
+-      /* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
++      /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0,
+        * or HTB crashes. Defer it for next round.
+        */
+       if (q->cstats.drop_count && sch->q.qlen) {
+-              qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
++              qdisc_tree_reduce_backlog(sch, q->cstats.drop_count,
++                                        q->cstats.drop_len);
+               q->cstats.drop_count = 0;
++              q->cstats.drop_len = 0;
+       }
+       return skb;
+ }
+@@ -372,11 +377,13 @@ static int fq_codel_change(struct Qdisc
+       while (sch->q.qlen > sch->limit) {
+               struct sk_buff *skb = fq_codel_dequeue(sch);
++              q->cstats.drop_len += qdisc_pkt_len(skb);
+               kfree_skb(skb);
+               q->cstats.drop_count++;
+       }
+-      qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
++      qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, q->cstats.drop_len);
+       q->cstats.drop_count = 0;
++      q->cstats.drop_len = 0;
+       sch_tree_unlock(sch);
+       return 0;
+--- a/net/sched/sch_hfsc.c
++++ b/net/sched/sch_hfsc.c
+@@ -895,9 +895,10 @@ static void
+ hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
+ {
+       unsigned int len = cl->qdisc->q.qlen;
++      unsigned int backlog = cl->qdisc->qstats.backlog;
+       qdisc_reset(cl->qdisc);
+-      qdisc_tree_decrease_qlen(cl->qdisc, len);
++      qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
+ }
+ static void
+--- a/net/sched/sch_hhf.c
++++ b/net/sched/sch_hhf.c
+@@ -382,6 +382,7 @@ static int hhf_enqueue(struct sk_buff *s
+       struct hhf_sched_data *q = qdisc_priv(sch);
+       enum wdrr_bucket_idx idx;
+       struct wdrr_bucket *bucket;
++      unsigned int prev_backlog;
+       idx = hhf_classify(skb, sch);
+@@ -409,6 +410,7 @@ static int hhf_enqueue(struct sk_buff *s
+       if (++sch->q.qlen <= sch->limit)
+               return NET_XMIT_SUCCESS;
++      prev_backlog = sch->qstats.backlog;
+       q->drop_overlimit++;
+       /* Return Congestion Notification only if we dropped a packet from this
+        * bucket.
+@@ -417,7 +419,7 @@ static int hhf_enqueue(struct sk_buff *s
+               return NET_XMIT_CN;
+       /* As we dropped a packet, better let upper stack know this. */
+-      qdisc_tree_decrease_qlen(sch, 1);
++      qdisc_tree_reduce_backlog(sch, 1, prev_backlog - sch->qstats.backlog);
+       return NET_XMIT_SUCCESS;
+ }
+@@ -527,7 +529,7 @@ static int hhf_change(struct Qdisc *sch,
+ {
+       struct hhf_sched_data *q = qdisc_priv(sch);
+       struct nlattr *tb[TCA_HHF_MAX + 1];
+-      unsigned int qlen;
++      unsigned int qlen, prev_backlog;
+       int err;
+       u64 non_hh_quantum;
+       u32 new_quantum = q->quantum;
+@@ -577,12 +579,14 @@ static int hhf_change(struct Qdisc *sch,
+       }
+       qlen = sch->q.qlen;
++      prev_backlog = sch->qstats.backlog;
+       while (sch->q.qlen > sch->limit) {
+               struct sk_buff *skb = hhf_dequeue(sch);
+               kfree_skb(skb);
+       }
+-      qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
++      qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen,
++                                prev_backlog - sch->qstats.backlog);
+       sch_tree_unlock(sch);
+       return 0;
+--- a/net/sched/sch_htb.c
++++ b/net/sched/sch_htb.c
+@@ -1265,7 +1265,6 @@ static int htb_delete(struct Qdisc *sch,
+ {
+       struct htb_sched *q = qdisc_priv(sch);
+       struct htb_class *cl = (struct htb_class *)arg;
+-      unsigned int qlen;
+       struct Qdisc *new_q = NULL;
+       int last_child = 0;
+@@ -1285,9 +1284,11 @@ static int htb_delete(struct Qdisc *sch,
+       sch_tree_lock(sch);
+       if (!cl->level) {
+-              qlen = cl->un.leaf.q->q.qlen;
++              unsigned int qlen = cl->un.leaf.q->q.qlen;
++              unsigned int backlog = cl->un.leaf.q->qstats.backlog;
++
+               qdisc_reset(cl->un.leaf.q);
+-              qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
++              qdisc_tree_reduce_backlog(cl->un.leaf.q, qlen, backlog);
+       }
+       /* delete from hash and active; remainder in destroy_class */
+@@ -1421,10 +1422,11 @@ static int htb_change_class(struct Qdisc
+               sch_tree_lock(sch);
+               if (parent && !parent->level) {
+                       unsigned int qlen = parent->un.leaf.q->q.qlen;
++                      unsigned int backlog = parent->un.leaf.q->qstats.backlog;
+                       /* turn parent into inner node */
+                       qdisc_reset(parent->un.leaf.q);
+-                      qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
++                      qdisc_tree_reduce_backlog(parent->un.leaf.q, qlen, backlog);
+                       qdisc_destroy(parent->un.leaf.q);
+                       if (parent->prio_activity)
+                               htb_deactivate(q, parent);
+--- a/net/sched/sch_multiq.c
++++ b/net/sched/sch_multiq.c
+@@ -218,7 +218,8 @@ static int multiq_tune(struct Qdisc *sch
+               if (q->queues[i] != &noop_qdisc) {
+                       struct Qdisc *child = q->queues[i];
+                       q->queues[i] = &noop_qdisc;
+-                      qdisc_tree_decrease_qlen(child, child->q.qlen);
++                      qdisc_tree_reduce_backlog(child, child->q.qlen,
++                                                child->qstats.backlog);
+                       qdisc_destroy(child);
+               }
+       }
+@@ -238,8 +239,9 @@ static int multiq_tune(struct Qdisc *sch
+                               q->queues[i] = child;
+                               if (old != &noop_qdisc) {
+-                                      qdisc_tree_decrease_qlen(old,
+-                                                               old->q.qlen);
++                                      qdisc_tree_reduce_backlog(old,
++                                                                old->q.qlen,
++                                                                old->qstats.backlog);
+                                       qdisc_destroy(old);
+                               }
+                               sch_tree_unlock(sch);
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -598,7 +598,8 @@ deliver:
+                               if (unlikely(err != NET_XMIT_SUCCESS)) {
+                                       if (net_xmit_drop_count(err)) {
+                                               qdisc_qstats_drop(sch);
+-                                              qdisc_tree_decrease_qlen(sch, 1);
++                                              qdisc_tree_reduce_backlog(sch, 1,
++                                                                        qdisc_pkt_len(skb));
+                                       }
+                               }
+                               goto tfifo_dequeue;
+--- a/net/sched/sch_pie.c
++++ b/net/sched/sch_pie.c
+@@ -183,7 +183,7 @@ static int pie_change(struct Qdisc *sch,
+ {
+       struct pie_sched_data *q = qdisc_priv(sch);
+       struct nlattr *tb[TCA_PIE_MAX + 1];
+-      unsigned int qlen;
++      unsigned int qlen, dropped = 0;
+       int err;
+       if (!opt)
+@@ -232,10 +232,11 @@ static int pie_change(struct Qdisc *sch,
+       while (sch->q.qlen > sch->limit) {
+               struct sk_buff *skb = __skb_dequeue(&sch->q);
++              dropped += qdisc_pkt_len(skb);
+               qdisc_qstats_backlog_dec(sch, skb);
+               qdisc_drop(skb, sch);
+       }
+-      qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
++      qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
+       sch_tree_unlock(sch);
+       return 0;
+--- a/net/sched/sch_prio.c
++++ b/net/sched/sch_prio.c
+@@ -191,7 +191,7 @@ static int prio_tune(struct Qdisc *sch,
+               struct Qdisc *child = q->queues[i];
+               q->queues[i] = &noop_qdisc;
+               if (child != &noop_qdisc) {
+-                      qdisc_tree_decrease_qlen(child, child->q.qlen);
++                      qdisc_tree_reduce_backlog(child, child->q.qlen, child->qstats.backlog);
+                       qdisc_destroy(child);
+               }
+       }
+@@ -210,8 +210,9 @@ static int prio_tune(struct Qdisc *sch,
+                               q->queues[i] = child;
+                               if (old != &noop_qdisc) {
+-                                      qdisc_tree_decrease_qlen(old,
+-                                                               old->q.qlen);
++                                      qdisc_tree_reduce_backlog(old,
++                                                                old->q.qlen,
++                                                                old->qstats.backlog);
+                                       qdisc_destroy(old);
+                               }
+                               sch_tree_unlock(sch);
+--- a/net/sched/sch_qfq.c
++++ b/net/sched/sch_qfq.c
+@@ -220,9 +220,10 @@ static struct qfq_class *qfq_find_class(
+ static void qfq_purge_queue(struct qfq_class *cl)
+ {
+       unsigned int len = cl->qdisc->q.qlen;
++      unsigned int backlog = cl->qdisc->qstats.backlog;
+       qdisc_reset(cl->qdisc);
+-      qdisc_tree_decrease_qlen(cl->qdisc, len);
++      qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
+ }
+ static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = {
+--- a/net/sched/sch_red.c
++++ b/net/sched/sch_red.c
+@@ -210,7 +210,8 @@ static int red_change(struct Qdisc *sch,
+       q->flags = ctl->flags;
+       q->limit = ctl->limit;
+       if (child) {
+-              qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
++              qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
++                                        q->qdisc->qstats.backlog);
+               qdisc_destroy(q->qdisc);
+               q->qdisc = child;
+       }
+--- a/net/sched/sch_sfb.c
++++ b/net/sched/sch_sfb.c
+@@ -510,7 +510,8 @@ static int sfb_change(struct Qdisc *sch,
+       sch_tree_lock(sch);
+-      qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
++      qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
++                                q->qdisc->qstats.backlog);
+       qdisc_destroy(q->qdisc);
+       q->qdisc = child;
+--- a/net/sched/sch_sfq.c
++++ b/net/sched/sch_sfq.c
+@@ -346,7 +346,7 @@ static int
+ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ {
+       struct sfq_sched_data *q = qdisc_priv(sch);
+-      unsigned int hash;
++      unsigned int hash, dropped;
+       sfq_index x, qlen;
+       struct sfq_slot *slot;
+       int uninitialized_var(ret);
+@@ -461,7 +461,7 @@ enqueue:
+               return NET_XMIT_SUCCESS;
+       qlen = slot->qlen;
+-      sfq_drop(sch);
++      dropped = sfq_drop(sch);
+       /* Return Congestion Notification only if we dropped a packet
+        * from this flow.
+        */
+@@ -469,7 +469,7 @@ enqueue:
+               return NET_XMIT_CN;
+       /* As we dropped a packet, better let upper stack know this */
+-      qdisc_tree_decrease_qlen(sch, 1);
++      qdisc_tree_reduce_backlog(sch, 1, dropped);
+       return NET_XMIT_SUCCESS;
+ }
+@@ -537,6 +537,7 @@ static void sfq_rehash(struct Qdisc *sch
+       struct sfq_slot *slot;
+       struct sk_buff_head list;
+       int dropped = 0;
++      unsigned int drop_len = 0;
+       __skb_queue_head_init(&list);
+@@ -565,6 +566,7 @@ static void sfq_rehash(struct Qdisc *sch
+                       if (x >= SFQ_MAX_FLOWS) {
+ drop:
+                               qdisc_qstats_backlog_dec(sch, skb);
++                              drop_len += qdisc_pkt_len(skb);
+                               kfree_skb(skb);
+                               dropped++;
+                               continue;
+@@ -594,7 +596,7 @@ drop:
+               }
+       }
+       sch->q.qlen -= dropped;
+-      qdisc_tree_decrease_qlen(sch, dropped);
++      qdisc_tree_reduce_backlog(sch, dropped, drop_len);
+ }
+ static void sfq_perturbation(unsigned long arg)
+@@ -618,7 +620,7 @@ static int sfq_change(struct Qdisc *sch,
+       struct sfq_sched_data *q = qdisc_priv(sch);
+       struct tc_sfq_qopt *ctl = nla_data(opt);
+       struct tc_sfq_qopt_v1 *ctl_v1 = NULL;
+-      unsigned int qlen;
++      unsigned int qlen, dropped = 0;
+       struct red_parms *p = NULL;
+       if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
+@@ -667,8 +669,8 @@ static int sfq_change(struct Qdisc *sch,
+       qlen = sch->q.qlen;
+       while (sch->q.qlen > q->limit)
+-              sfq_drop(sch);
+-      qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
++              dropped += sfq_drop(sch);
++      qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
+       del_timer(&q->perturb_timer);
+       if (q->perturb_period) {
+--- a/net/sched/sch_tbf.c
++++ b/net/sched/sch_tbf.c
+@@ -160,6 +160,7 @@ static int tbf_segment(struct sk_buff *s
+       struct tbf_sched_data *q = qdisc_priv(sch);
+       struct sk_buff *segs, *nskb;
+       netdev_features_t features = netif_skb_features(skb);
++      unsigned int len = 0, prev_len = qdisc_pkt_len(skb);
+       int ret, nb;
+       segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+@@ -172,6 +173,7 @@ static int tbf_segment(struct sk_buff *s
+               nskb = segs->next;
+               segs->next = NULL;
+               qdisc_skb_cb(segs)->pkt_len = segs->len;
++              len += segs->len;
+               ret = qdisc_enqueue(segs, q->qdisc);
+               if (ret != NET_XMIT_SUCCESS) {
+                       if (net_xmit_drop_count(ret))
+@@ -183,7 +185,7 @@ static int tbf_segment(struct sk_buff *s
+       }
+       sch->q.qlen += nb;
+       if (nb > 1)
+-              qdisc_tree_decrease_qlen(sch, 1 - nb);
++              qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
+       consume_skb(skb);
+       return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
+ }
+@@ -399,7 +401,8 @@ static int tbf_change(struct Qdisc *sch,
+       sch_tree_lock(sch);
+       if (child) {
+-              qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
++              qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
++                                        q->qdisc->qstats.backlog);
+               qdisc_destroy(q->qdisc);
+               q->qdisc = child;
+       }
diff --git a/target/linux/generic/patches-4.4/032-fq_codel-add-batch-ability-to-fq_codel_drop.patch b/target/linux/generic/patches-4.4/032-fq_codel-add-batch-ability-to-fq_codel_drop.patch
new file mode 100644 (file)
index 0000000..94c9c7f
--- /dev/null
@@ -0,0 +1,189 @@
+From: Eric Dumazet <edumazet@google.com>
+Date: Sun, 1 May 2016 16:47:26 -0700
+Subject: [PATCH] fq_codel: add batch ability to fq_codel_drop()
+
+In presence of inelastic flows and stress, we can call
+fq_codel_drop() for every packet entering fq_codel qdisc.
+
+fq_codel_drop() is quite expensive, as it does a linear scan
+of 4 KB of memory to find a fat flow.
+Once found, it drops the oldest packet of this flow.
+
+Instead of dropping a single packet, try to drop 50% of the backlog
+of this fat flow, with a configurable limit of 64 packets per round.
+
+TCA_FQ_CODEL_DROP_BATCH_SIZE is the new attribute to make this
+limit configurable.
+
+With this strategy the 4 KB search is amortized to a single cache line
+per drop [1], so fq_codel_drop() no longer appears at the top of kernel
+profile in presence of few inelastic flows.
+
+[1] Assuming a 64byte cache line, and 1024 buckets
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Dave Taht <dave.taht@gmail.com>
+Cc: Jonathan Morton <chromatix99@gmail.com>
+Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
+Acked-by: Dave Taht
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/include/uapi/linux/pkt_sched.h
++++ b/include/uapi/linux/pkt_sched.h
+@@ -711,6 +711,7 @@ enum {
+       TCA_FQ_CODEL_FLOWS,
+       TCA_FQ_CODEL_QUANTUM,
+       TCA_FQ_CODEL_CE_THRESHOLD,
++      TCA_FQ_CODEL_DROP_BATCH_SIZE,
+       __TCA_FQ_CODEL_MAX
+ };
+--- a/net/sched/sch_fq_codel.c
++++ b/net/sched/sch_fq_codel.c
+@@ -57,6 +57,7 @@ struct fq_codel_sched_data {
+       u32             flows_cnt;      /* number of flows */
+       u32             perturbation;   /* hash perturbation */
+       u32             quantum;        /* psched_mtu(qdisc_dev(sch)); */
++      u32             drop_batch_size;
+       struct codel_params cparams;
+       struct codel_stats cstats;
+       u32             drop_overlimit;
+@@ -133,17 +134,20 @@ static inline void flow_queue_add(struct
+       skb->next = NULL;
+ }
+-static unsigned int fq_codel_drop(struct Qdisc *sch)
++static unsigned int fq_codel_drop(struct Qdisc *sch, unsigned int max_packets)
+ {
+       struct fq_codel_sched_data *q = qdisc_priv(sch);
+       struct sk_buff *skb;
+       unsigned int maxbacklog = 0, idx = 0, i, len;
+       struct fq_codel_flow *flow;
++      unsigned int threshold;
+-      /* Queue is full! Find the fat flow and drop packet from it.
++      /* Queue is full! Find the fat flow and drop packet(s) from it.
+        * This might sound expensive, but with 1024 flows, we scan
+        * 4KB of memory, and we dont need to handle a complex tree
+        * in fast path (packet queue/enqueue) with many cache misses.
++       * In stress mode, we'll try to drop 64 packets from the flow,
++       * amortizing this linear lookup to one cache line per drop.
+        */
+       for (i = 0; i < q->flows_cnt; i++) {
+               if (q->backlogs[i] > maxbacklog) {
+@@ -151,15 +155,24 @@ static unsigned int fq_codel_drop(struct
+                       idx = i;
+               }
+       }
++
++      /* Our goal is to drop half of this fat flow backlog */
++      threshold = maxbacklog >> 1;
++
+       flow = &q->flows[idx];
+-      skb = dequeue_head(flow);
+-      len = qdisc_pkt_len(skb);
++      len = 0;
++      i = 0;
++      do {
++              skb = dequeue_head(flow);
++              len += qdisc_pkt_len(skb);
++              kfree_skb(skb);
++      } while (++i < max_packets && len < threshold);
++
++      flow->dropped += i;
+       q->backlogs[idx] -= len;
+-      sch->q.qlen--;
+-      qdisc_qstats_drop(sch);
+-      qdisc_qstats_backlog_dec(sch, skb);
+-      kfree_skb(skb);
+-      flow->dropped++;
++      sch->qstats.drops += i;
++      sch->qstats.backlog -= len;
++      sch->q.qlen -= i;
+       return idx;
+ }
+@@ -168,14 +181,14 @@ static unsigned int fq_codel_qdisc_drop(
+       unsigned int prev_backlog;
+       prev_backlog = sch->qstats.backlog;
+-      fq_codel_drop(sch);
++      fq_codel_drop(sch, 1U);
+       return prev_backlog - sch->qstats.backlog;
+ }
+ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ {
+       struct fq_codel_sched_data *q = qdisc_priv(sch);
+-      unsigned int idx, prev_backlog;
++      unsigned int idx, prev_backlog, prev_qlen;
+       struct fq_codel_flow *flow;
+       int uninitialized_var(ret);
+@@ -204,16 +217,22 @@ static int fq_codel_enqueue(struct sk_bu
+               return NET_XMIT_SUCCESS;
+       prev_backlog = sch->qstats.backlog;
+-      q->drop_overlimit++;
+-      /* Return Congestion Notification only if we dropped a packet
+-       * from this flow.
++      prev_qlen = sch->q.qlen;
++
++      /* fq_codel_drop() is quite expensive, as it performs a linear search
++       * in q->backlogs[] to find a fat flow.
++       * So instead of dropping a single packet, drop half of its backlog
++       * with a 64 packets limit to not add a too big cpu spike here.
+        */
+-      if (fq_codel_drop(sch) == idx)
+-              return NET_XMIT_CN;
++      ret = fq_codel_drop(sch, q->drop_batch_size);
+-      /* As we dropped a packet, better let upper stack know this */
+-      qdisc_tree_reduce_backlog(sch, 1, prev_backlog - sch->qstats.backlog);
+-      return NET_XMIT_SUCCESS;
++      q->drop_overlimit += prev_qlen - sch->q.qlen;
++
++      /* As we dropped packet(s), better let upper stack know this */
++      qdisc_tree_reduce_backlog(sch, prev_qlen - sch->q.qlen,
++                                prev_backlog - sch->qstats.backlog);
++
++      return ret == idx ? NET_XMIT_CN : NET_XMIT_SUCCESS;
+ }
+ /* This is the specific function called from codel_dequeue()
+@@ -323,6 +342,7 @@ static const struct nla_policy fq_codel_
+       [TCA_FQ_CODEL_FLOWS]    = { .type = NLA_U32 },
+       [TCA_FQ_CODEL_QUANTUM]  = { .type = NLA_U32 },
+       [TCA_FQ_CODEL_CE_THRESHOLD] = { .type = NLA_U32 },
++      [TCA_FQ_CODEL_DROP_BATCH_SIZE] = { .type = NLA_U32 },
+ };
+ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt)
+@@ -374,6 +394,9 @@ static int fq_codel_change(struct Qdisc
+       if (tb[TCA_FQ_CODEL_QUANTUM])
+               q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
++      if (tb[TCA_FQ_CODEL_DROP_BATCH_SIZE])
++              q->drop_batch_size = min(1U, nla_get_u32(tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]));
++
+       while (sch->q.qlen > sch->limit) {
+               struct sk_buff *skb = fq_codel_dequeue(sch);
+@@ -419,6 +442,7 @@ static int fq_codel_init(struct Qdisc *s
+       sch->limit = 10*1024;
+       q->flows_cnt = 1024;
++      q->drop_batch_size = 64;
+       q->quantum = psched_mtu(qdisc_dev(sch));
+       q->perturbation = prandom_u32();
+       INIT_LIST_HEAD(&q->new_flows);
+@@ -476,6 +500,8 @@ static int fq_codel_dump(struct Qdisc *s
+                       q->cparams.ecn) ||
+           nla_put_u32(skb, TCA_FQ_CODEL_QUANTUM,
+                       q->quantum) ||
++          nla_put_u32(skb, TCA_FQ_CODEL_DROP_BATCH_SIZE,
++                      q->drop_batch_size) ||
+           nla_put_u32(skb, TCA_FQ_CODEL_FLOWS,
+                       q->flows_cnt))
+               goto nla_put_failure;
index a69d197..4a056c8 100644 (file)
@@ -284,15 +284,15 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
 +      EXPORT(kexec_argv_buf)
 +      .skip           KEXEC_COMMAND_LINE_SIZE
 +      .size           kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE
-+
-+kexec_argv:
-+      EXPORT(kexec_argv)
-+      .skip           KEXEC_ARGV_SIZE
-+      .size           kexec_argv, KEXEC_ARGV_SIZE
  
 -relocate_new_kernel_size:
 -      EXPORT(relocate_new_kernel_size)
 -      PTR             relocate_new_kernel_end - relocate_new_kernel
 -      .size           relocate_new_kernel_size, PTRSIZE
++kexec_argv:
++      EXPORT(kexec_argv)
++      .skip           KEXEC_ARGV_SIZE
++      .size           kexec_argv, KEXEC_ARGV_SIZE
++
 +kexec_relocate_new_kernel_end:
 +      EXPORT(kexec_relocate_new_kernel_end)
index aa3c498..bbf2b75 100644 (file)
  {
    UInt32 dicSize;
    Byte d;
-@@ -935,7 +883,7 @@ static SRes LzmaDec_AllocateProbs2(CLzma
+@@ -935,33 +883,11 @@ static SRes LzmaDec_AllocateProbs2(CLzma
    return SZ_OK;
  }
  
 -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
-+static SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
- {
-   CLzmaProps propNew;
-   RINOK(LzmaProps_Decode(&propNew, props, propsSize));
-@@ -943,28 +891,6 @@ SRes LzmaDec_AllocateProbs(CLzmaDec *p,
-   p->prop = propNew;
-   return SZ_OK;
- }
--
--SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
 -{
 -  CLzmaProps propNew;
--  SizeT dicBufSize;
 -  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
 -  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+-  p->prop = propNew;
+-  return SZ_OK;
+-}
+-
+-SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
++static SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+ {
+   CLzmaProps propNew;
+-  SizeT dicBufSize;
+   RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+   RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
 -  dicBufSize = propNew.dicSize;
 -  if (p->dic == 0 || dicBufSize != p->dicBufSize)
 -  {
 -    }
 -  }
 -  p->dicBufSize = dicBufSize;
--  p->prop = propNew;
--  return SZ_OK;
--}
- SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
-     const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+   p->prop = propNew;
+   return SZ_OK;
+ }
 --- a/include/linux/lzma/LzmaEnc.h
 +++ b/include/linux/lzma/LzmaEnc.h
 @@ -31,9 +31,6 @@ typedef struct _CLzmaEncProps
index f729f38..7232b93 100644 (file)
@@ -382,8 +382,6 @@ Implement optinal multicast->unicast conversion for igmp snooping
  
 -              port = (unsigned long)lport > (unsigned long)rport ?
 -                     lport : rport;
--
--              prev = maybe_deliver(prev, port, skb, __packet_hook);
 +              if ((unsigned long)lport > (unsigned long)rport) {
 +                      port = lport;
 +                      addr = p->unicast ? p->eth_addr : NULL;
@@ -391,7 +389,8 @@ Implement optinal multicast->unicast conversion for igmp snooping
 +                      port = rport;
 +                      addr = NULL;
 +              }
-+
+-              prev = maybe_deliver(prev, port, skb, __packet_hook);
 +              if (addr)
 +                      prev = maybe_deliver_addr(prev, port, skb, addr,
 +                                                __packet_hook);
index bee4fcd..bbf2810 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/sched/sch_fq_codel.c
 +++ b/net/sched/sch_fq_codel.c
-@@ -410,8 +410,8 @@ static int fq_codel_init(struct Qdisc *s
+@@ -440,8 +440,8 @@ static int fq_codel_init(struct Qdisc *s
        struct fq_codel_sched_data *q = qdisc_priv(sch);
        int i;
  
@@ -8,6 +8,6 @@
 -      q->flows_cnt = 1024;
 +      sch->limit = 1024;
 +      q->flows_cnt = 128;
+       q->drop_batch_size = 64;
        q->quantum = psched_mtu(qdisc_dev(sch));
        q->perturbation = prandom_u32();
-       INIT_LIST_HEAD(&q->new_flows);
index 45a8d68..cb3bb2f 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/sched/sch_fq_codel.c
 +++ b/net/sched/sch_fq_codel.c
-@@ -198,7 +198,6 @@ static int fq_codel_enqueue(struct sk_bu
+@@ -211,7 +211,6 @@ static int fq_codel_enqueue(struct sk_bu
                list_add_tail(&flow->flowchain, &q->new_flows);
                q->new_flow_count++;
                flow->deficit = q->quantum;
index 6910cfa..37b601a 100644 (file)
@@ -13,7 +13,7 @@
          device, it has to decide which ones to send first, which ones to
 --- a/net/sched/sch_fq_codel.c
 +++ b/net/sched/sch_fq_codel.c
-@@ -621,7 +621,7 @@ static const struct Qdisc_class_ops fq_c
+@@ -654,7 +654,7 @@ static const struct Qdisc_class_ops fq_c
        .walk           =       fq_codel_walk,
  };
  
@@ -22,7 +22,7 @@
        .cl_ops         =       &fq_codel_class_ops,
        .id             =       "fq_codel",
        .priv_size      =       sizeof(struct fq_codel_sched_data),
-@@ -637,6 +637,7 @@ static struct Qdisc_ops fq_codel_qdisc_o
+@@ -670,6 +670,7 @@ static struct Qdisc_ops fq_codel_qdisc_o
        .dump_stats =   fq_codel_dump_stats,
        .owner          =       THIS_MODULE,
  };
@@ -84,7 +84,7 @@
                if (qdisc == NULL) {
 --- a/net/sched/sch_api.c
 +++ b/net/sched/sch_api.c
-@@ -1946,7 +1946,7 @@ static int __init pktsched_init(void)
+@@ -1948,7 +1948,7 @@ static int __init pktsched_init(void)
                return err;
        }