[packages/kernel] - removed ESFQ, no upstream updates for 8 years - updated IMQ patch

baggins baggins at pld-linux.org
Sun Oct 9 15:22:43 CEST 2016


commit d5ed51b7363a66e1296f45ec0a857f0267013ee3
Author: Jan Rękorajski <baggins at pld-linux.org>
Date:   Sun Oct 9 15:21:23 2016 +0200

    - removed ESFQ, no upstream updates for 8 years
    - updated IMQ patch

 kernel-esfq.patch | 793 ------------------------------------------------------
 kernel-imq.patch  | 220 +++++++--------
 kernel.spec       |   9 -
 3 files changed, 98 insertions(+), 924 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index 7c22b8f..512f49c 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -27,7 +27,6 @@
 %bcond_with	nfsroot		# build with root on NFS support
 
 %bcond_without	imq		# imq support
-%bcond_with	esfq		# esfq support
 %bcond_without	ipv6		# ipv6 support
 
 %bcond_with	vserver		# support for VServer
@@ -168,9 +167,6 @@ Patch40:	kernel-layer7.patch
 # http://www.linuximq.net
 Patch50:	kernel-imq.patch
 
-# http://fatooh.org/esfq-2.6/sfq-2.6.24.1.tar.bz2
-Patch53:	kernel-esfq.patch
-
 # by Baggins request:
 # derived from ftp://ftp.cmf.nrl.navy.mil/pub/chas/linux-atm/vbr/vbr-kernel-diffs
 Patch55:	kernel-atm-vbr.patch
@@ -670,11 +666,6 @@ cd linux-%{basever}
 %patch50 -p1
 %endif
 
-# esfq
-%if %{with esfq}
-%patch53 -p1
-%endif
-
 %patch55 -p1
 %patch56 -p1
 
diff --git a/kernel-esfq.patch b/kernel-esfq.patch
deleted file mode 100644
index 355a644..0000000
--- a/kernel-esfq.patch
+++ /dev/null
@@ -1,793 +0,0 @@
-diff -Naur linux-2.6.24.orig/include/uapi/linux/pkt_sched.h linux-2.6.24/include/uapi/linux/pkt_sched.h
---- linux-2.6.24.orig/include/uapi/linux/pkt_sched.h	2008-01-24 14:58:37.000000000 -0800
-+++ linux-2.6.24/include/uapi/linux/pkt_sched.h	2008-01-28 00:27:12.000000000 -0800
-@@ -157,6 +157,33 @@
-  *	to change these parameters in compile time.
-  */
- 
-+/* ESFQ section */
-+
-+enum
-+{
-+        /* traditional */
-+	TCA_ESFQ_HASH_CLASSIC,
-+	TCA_ESFQ_HASH_DST,
-+	TCA_ESFQ_HASH_SRC,
-+	TCA_ESFQ_HASH_FWMARK,
-+	/* conntrack */
-+	TCA_ESFQ_HASH_CTORIGDST,
-+	TCA_ESFQ_HASH_CTORIGSRC,
-+	TCA_ESFQ_HASH_CTREPLDST,
-+	TCA_ESFQ_HASH_CTREPLSRC,
-+	TCA_ESFQ_HASH_CTNATCHG,
-+};
-+
-+struct tc_esfq_qopt
-+{
-+	unsigned	quantum;	/* Bytes per round allocated to flow */
-+	int		perturb_period;	/* Period of hash perturbation */
-+	__u32		limit;		/* Maximal packets in queue */
-+	unsigned	divisor;	/* Hash divisor  */
-+	unsigned	flows;		/* Maximal number of flows  */
-+	unsigned	hash_kind;	/* Hash function to use for flow identification */
-+};
-+
- /* RED section */
- 
- enum
-diff -Naur linux-2.6.24.orig/net/sched/Kconfig linux-2.6.24/net/sched/Kconfig
---- linux-2.6.24.orig/net/sched/Kconfig	2008-01-24 14:58:37.000000000 -0800
-+++ linux-2.6.24/net/sched/Kconfig	2008-01-28 00:27:12.000000000 -0800
-@@ -139,6 +139,37 @@
- 	  To compile this code as a module, choose M here: the
- 	  module will be called sch_sfq.
- 
-+config NET_SCH_ESFQ
-+	tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
-+	---help---
-+	  Say Y here if you want to use the Enhanced Stochastic Fairness
-+	  Queueing (ESFQ) packet scheduling algorithm for some of your network
-+	  devices or as a leaf discipline for a classful qdisc such as HTB or
-+	  CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
-+	  references to the SFQ algorithm).
-+
-+	  This is an enchanced SFQ version which allows you to control some
-+	  hardcoded values in the SFQ scheduler.
-+
-+	  ESFQ also adds control of the hash function used to identify packet
-+	  flows. The original SFQ discipline hashes by connection; ESFQ add
-+	  several other hashing methods, such as by src IP or by dst IP, which
-+	  can be more fair to users in some networking situations.
-+	  
-+	  To compile this code as a module, choose M here: the
-+	  module will be called sch_esfq.
-+
-+config NET_SCH_ESFQ_NFCT
-+	bool "Connection Tracking Hash Types"
-+	depends on NET_SCH_ESFQ && NF_CONNTRACK
-+	---help---
-+	  Say Y here to enable support for hashing based on netfilter connection
-+	  tracking information. This is useful for a router that is also using
-+	  NAT to connect privately-addressed hosts to the Internet. If you want
-+	  to provide fair distribution of upstream bandwidth, ESFQ must use
-+	  connection tracking information, since all outgoing packets will share
-+	  the same source address.
-+
- config NET_SCH_TEQL
- 	tristate "True Link Equalizer (TEQL)"
- 	---help---
-diff -Naur linux-2.6.24.orig/net/sched/Makefile linux-2.6.24/net/sched/Makefile
---- linux-2.6.24.orig/net/sched/Makefile	2008-01-24 14:58:37.000000000 -0800
-+++ linux-2.6.24/net/sched/Makefile	2008-01-28 00:27:12.000000000 -0800
-@@ -23,6 +23,7 @@
- obj-$(CONFIG_NET_SCH_INGRESS)	+= sch_ingress.o 
- obj-$(CONFIG_NET_SCH_DSMARK)	+= sch_dsmark.o
- obj-$(CONFIG_NET_SCH_SFQ)	+= sch_sfq.o
-+obj-$(CONFIG_NET_SCH_ESFQ)	+= sch_esfq.o
- obj-$(CONFIG_NET_SCH_TBF)	+= sch_tbf.o
- obj-$(CONFIG_NET_SCH_TEQL)	+= sch_teql.o
- obj-$(CONFIG_NET_SCH_PRIO)	+= sch_prio.o
-diff -Naur linux-2.6.24.orig/net/sched/sch_esfq.c linux-2.6.24/net/sched/sch_esfq.c
---- linux-2.6.24.orig/net/sched/sch_esfq.c	1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.6.24/net/sched/sch_esfq.c	2008-01-28 00:27:22.000000000 -0800
-@@ -0,0 +1,700 @@
-+/*
-+ * net/sched/sch_esfq.c	Extended Stochastic Fairness Queueing discipline.
-+ *
-+ *		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, or (at your option) any later version.
-+ *
-+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
-+ *
-+ * Changes:	Alexander Atanasov, <alex at ssi.bg>
-+ *		Added dynamic depth,limit,divisor,hash_kind options.
-+ *		Added dst and src hashes.
-+ *
-+ * 		Alexander Clouter, <alex at digriz.org.uk>
-+ *		Ported ESFQ to Linux 2.6.
-+ *
-+ * 		Corey Hickey, <bugfood-c at fatooh.org>
-+ *		Maintenance of the Linux 2.6 port.
-+ *		Added fwmark hash (thanks to Robert Kurjata).
-+ *		Added usage of jhash.
-+ *		Added conntrack support.
-+ *		Added ctnatchg hash (thanks to Ben Pfountz).
-+ */
-+
-+#include <linux/module.h>
-+#include <asm/uaccess.h>
-+
-+#include <linux/bitops.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/jiffies.h>
-+#include <linux/string.h>
-+#include <linux/mm.h>
-+#include <linux/socket.h>
-+#include <linux/sockios.h>
-+#include <linux/in.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/if_ether.h>
-+#include <linux/inet.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/notifier.h>
-+#include <linux/init.h>
-+#include <net/ip.h>
-+#include <net/netlink.h>
-+#include <linux/ipv6.h>
-+#include <net/route.h>
-+#include <linux/skbuff.h>
-+#include <net/sock.h>
-+#include <net/pkt_sched.h>
-+#include <linux/jhash.h>
-+#include <net/netfilter/nf_conntrack.h>
-+
-+/*	Stochastic Fairness Queuing algorithm.
-+	For more comments look at sch_sfq.c.
-+	The difference is that you can change limit, depth,
-+	hash table size and choose alternate hash types.
-+	
-+	classic:	same as in sch_sfq.c
-+	dst:		destination IP address
-+	src:		source IP address
-+	fwmark:		netfilter mark value
-+	ctorigdst:	original destination IP address
-+	ctorigsrc:	original source IP address
-+	ctrepldst:	reply destination IP address
-+	ctreplsrc:	reply source IP 
-+	
-+*/
-+
-+#define ESFQ_HEAD 0
-+#define ESFQ_TAIL 1
-+
-+/* This type should contain at least SFQ_DEPTH*2 values */
-+typedef unsigned int esfq_index;
-+
-+struct esfq_head
-+{
-+	esfq_index	next;
-+	esfq_index	prev;
-+};
-+
-+struct esfq_sched_data
-+{
-+/* Parameters */
-+	int		perturb_period;
-+	unsigned	quantum;	/* Allotment per round: MUST BE >= MTU */
-+	int		limit;
-+	unsigned	depth;
-+	unsigned	hash_divisor;
-+	unsigned	hash_kind;
-+/* Variables */
-+	struct timer_list perturb_timer;
-+	int		perturbation;
-+	esfq_index	tail;		/* Index of current slot in round */
-+	esfq_index	max_depth;	/* Maximal depth */
-+
-+	esfq_index	*ht;			/* Hash table */
-+	esfq_index	*next;			/* Active slots link */
-+	short		*allot;			/* Current allotment per slot */
-+	unsigned short	*hash;			/* Hash value indexed by slots */
-+	struct sk_buff_head	*qs;		/* Slot queue */
-+	struct esfq_head	*dep;		/* Linked list of slots, indexed by depth */
-+};
-+
-+/* This contains the info we will hash. */
-+struct esfq_packet_info
-+{
-+	u32	proto;		/* protocol or port */
-+	u32	src;		/* source from packet header */
-+	u32	dst;		/* destination from packet header */
-+	u32	ctorigsrc;	/* original source from conntrack */
-+	u32	ctorigdst;	/* original destination from conntrack */
-+	u32	ctreplsrc;	/* reply source from conntrack */
-+	u32	ctrepldst;	/* reply destination from conntrack */
-+	u32	mark;		/* netfilter mark (fwmark) */
-+};
-+
-+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
-+{
-+	return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
-+}
-+
-+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
-+{
-+	return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
-+}
-+
-+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
-+{
-+	return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
-+}
-+
-+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
-+{
-+	struct esfq_packet_info info;
-+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
-+	enum ip_conntrack_info ctinfo;
-+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
-+#endif
-+	
-+	switch (skb->protocol) {
-+	case __constant_htons(ETH_P_IP):
-+	{
-+		struct iphdr *iph = ip_hdr(skb);
-+		info.dst = iph->daddr;
-+		info.src = iph->saddr;
-+		if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
-+		    (iph->protocol == IPPROTO_TCP ||
-+		     iph->protocol == IPPROTO_UDP ||
-+		     iph->protocol == IPPROTO_SCTP ||
-+		     iph->protocol == IPPROTO_DCCP ||
-+		     iph->protocol == IPPROTO_ESP))
-+			info.proto = *(((u32*)iph) + iph->ihl);
-+		else
-+			info.proto = iph->protocol;
-+		break;
-+	}
-+	case __constant_htons(ETH_P_IPV6):
-+	{
-+		struct ipv6hdr *iph = ipv6_hdr(skb);
-+		/* Hash ipv6 addresses into a u32. This isn't ideal,
-+		 * but the code is simple. */
-+		info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
-+		info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
-+		if (iph->nexthdr == IPPROTO_TCP ||
-+		    iph->nexthdr == IPPROTO_UDP ||
-+		    iph->nexthdr == IPPROTO_SCTP ||
-+		    iph->nexthdr == IPPROTO_DCCP ||
-+		    iph->nexthdr == IPPROTO_ESP)
-+			info.proto = *(u32*)&iph[1];
-+		else
-+			info.proto = iph->nexthdr;
-+		break;
-+	}
-+	default:
-+		info.dst   = (u32)(unsigned long)skb_dst(skb);
-+		info.src   = (u32)(unsigned long)skb->sk;
-+		info.proto = skb->protocol;
-+	}
-+
-+	info.mark = skb->mark;
-+
-+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
-+	/* defaults if there is no conntrack info */
-+	info.ctorigsrc = info.src;
-+	info.ctorigdst = info.dst;
-+	info.ctreplsrc = info.dst;
-+	info.ctrepldst = info.src;
-+	/* collect conntrack info */
-+	if (ct && ct != &nf_conntrack_untracked) {
-+		if (skb->protocol == __constant_htons(ETH_P_IP)) {
-+			info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
-+			info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
-+			info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
-+			info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
-+		}
-+		else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
-+			/* Again, hash ipv6 addresses into a single u32. */
-+			info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
-+			info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
-+			info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
-+			info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
-+		}
-+
-+	}
-+#endif
-+
-+	switch(q->hash_kind) {
-+	case TCA_ESFQ_HASH_CLASSIC:
-+		return esfq_jhash_3words(q, info.dst, info.src, info.proto);
-+	case TCA_ESFQ_HASH_DST:
-+		return esfq_jhash_1word(q, info.dst);
-+	case TCA_ESFQ_HASH_SRC:
-+		return esfq_jhash_1word(q, info.src);
-+	case TCA_ESFQ_HASH_FWMARK:
-+		return esfq_jhash_1word(q, info.mark);
-+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
-+	case TCA_ESFQ_HASH_CTORIGDST:
-+		return esfq_jhash_1word(q, info.ctorigdst);
-+	case TCA_ESFQ_HASH_CTORIGSRC:
-+		return esfq_jhash_1word(q, info.ctorigsrc);
-+	case TCA_ESFQ_HASH_CTREPLDST:
-+		return esfq_jhash_1word(q, info.ctrepldst);
-+	case TCA_ESFQ_HASH_CTREPLSRC:
-+		return esfq_jhash_1word(q, info.ctreplsrc);
-+	case TCA_ESFQ_HASH_CTNATCHG:
-+	{
-+		if (info.ctorigdst == info.ctreplsrc)
-+			return esfq_jhash_1word(q, info.ctorigsrc);
-+		return esfq_jhash_1word(q, info.ctreplsrc);
-+	}
-+#endif
-+	default:
-+		if (net_ratelimit())
-+			printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
-+	}
-+	return esfq_jhash_3words(q, info.dst, info.src, info.proto);
-+}
-+
-+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
-+{
-+	esfq_index p, n;
-+	int d = q->qs[x].qlen + q->depth;
-+
-+	p = d;
-+	n = q->dep[d].next;
-+	q->dep[x].next = n;
-+	q->dep[x].prev = p;
-+	q->dep[p].next = q->dep[n].prev = x;
-+}
-+
-+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
-+{
-+	esfq_index p, n;
-+
-+	n = q->dep[x].next;
-+	p = q->dep[x].prev;
-+	q->dep[p].next = n;
-+	q->dep[n].prev = p;
-+
-+	if (n == p && q->max_depth == q->qs[x].qlen + 1)
-+		q->max_depth--;
-+
-+	esfq_link(q, x);
-+}
-+
-+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
-+{
-+	esfq_index p, n;
-+	int d;
-+
-+	n = q->dep[x].next;
-+	p = q->dep[x].prev;
-+	q->dep[p].next = n;
-+	q->dep[n].prev = p;
-+	d = q->qs[x].qlen;
-+	if (q->max_depth < d)
-+		q->max_depth = d;
-+
-+	esfq_link(q, x);
-+}
-+
-+static unsigned int esfq_drop(struct Qdisc *sch)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	esfq_index d = q->max_depth;
-+	struct sk_buff *skb;
-+	unsigned int len;
-+
-+	/* Queue is full! Find the longest slot and
-+	   drop a packet from it */
-+
-+	if (d > 1) {
-+		esfq_index x = q->dep[d+q->depth].next;
-+		skb = q->qs[x].prev;
-+		len = skb->len;
-+		__skb_unlink(skb, &q->qs[x]);
-+		kfree_skb(skb);
-+		esfq_dec(q, x);
-+		sch->q.qlen--;
-+		sch->qstats.drops++;
-+		sch->qstats.backlog -= len;
-+		return len;
-+	}
-+
-+	if (d == 1) {
-+		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
-+		d = q->next[q->tail];
-+		q->next[q->tail] = q->next[d];
-+		q->allot[q->next[d]] += q->quantum;
-+		skb = q->qs[d].prev;
-+		len = skb->len;
-+		__skb_unlink(skb, &q->qs[d]);
-+		kfree_skb(skb);
-+		esfq_dec(q, d);
-+		sch->q.qlen--;
-+		q->ht[q->hash[d]] = q->depth;
-+		sch->qstats.drops++;
-+		sch->qstats.backlog -= len;
-+		return len;
-+	}
-+
-+	return 0;
-+}
-+
-+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
-+{
-+	unsigned hash = esfq_hash(q, skb);
-+	unsigned depth = q->depth;
-+	esfq_index x;
-+
-+	x = q->ht[hash];
-+	if (x == depth) {
-+		q->ht[hash] = x = q->dep[depth].next;
-+		q->hash[x] = hash;
-+	}
-+
-+	if (end == ESFQ_TAIL)
-+		__skb_queue_tail(&q->qs[x], skb);
-+	else
-+		__skb_queue_head(&q->qs[x], skb);
-+
-+	esfq_inc(q, x);
-+	if (q->qs[x].qlen == 1) {		/* The flow is new */
-+		if (q->tail == depth) {	/* It is the first flow */
-+			q->tail = x;
-+			q->next[x] = x;
-+			q->allot[x] = q->quantum;
-+		} else {
-+			q->next[x] = q->next[q->tail];
-+			q->next[q->tail] = x;
-+			q->tail = x;
-+		}
-+	}
-+}
-+
-+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	esfq_q_enqueue(skb, q, ESFQ_TAIL);
-+	sch->qstats.backlog += skb->len;
-+	if (++sch->q.qlen < q->limit-1) {
-+		sch->bstats.bytes += skb->len;
-+		sch->bstats.packets++;
-+		return 0;
-+	}
-+
-+	sch->qstats.drops++;
-+	esfq_drop(sch);
-+	return NET_XMIT_CN;
-+}
-+
-+static struct sk_buff *esfq_peek(struct Qdisc* sch)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	esfq_index a;
-+
-+	/* No active slots */
-+	if (q->tail == q->depth)
-+		return NULL;
-+
-+	a = q->next[q->tail];
-+	return skb_peek(&q->qs[a]);
-+}
-+
-+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
-+{
-+	struct sk_buff *skb;
-+	unsigned depth = q->depth;
-+	esfq_index a, old_a;
-+
-+	/* No active slots */
-+	if (q->tail == depth)
-+		return NULL;
-+	
-+	a = old_a = q->next[q->tail];
-+	
-+	/* Grab packet */
-+	skb = __skb_dequeue(&q->qs[a]);
-+	esfq_dec(q, a);
-+	
-+	/* Is the slot empty? */
-+	if (q->qs[a].qlen == 0) {
-+		q->ht[q->hash[a]] = depth;
-+		a = q->next[a];
-+		if (a == old_a) {
-+			q->tail = depth;
-+			return skb;
-+		}
-+		q->next[q->tail] = a;
-+		q->allot[a] += q->quantum;
-+	} else if ((q->allot[a] -= skb->len) <= 0) {
-+		q->tail = a;
-+		a = q->next[a];
-+		q->allot[a] += q->quantum;
-+	}
-+	
-+	return skb;
-+}
-+
-+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	struct sk_buff *skb;
-+
-+	skb = esfq_q_dequeue(q);
-+	if (skb == NULL)
-+		return NULL;
-+	sch->q.qlen--;
-+	sch->qstats.backlog -= skb->len;
-+	return skb;
-+}
-+
-+static void esfq_q_destroy(struct esfq_sched_data *q)
-+{
-+	del_timer(&q->perturb_timer);
-+	if(q->ht)
-+		kfree(q->ht);
-+	if(q->dep)
-+		kfree(q->dep);
-+	if(q->next)
-+		kfree(q->next);
-+	if(q->allot)
-+		kfree(q->allot);
-+	if(q->hash)
-+		kfree(q->hash);
-+	if(q->qs)
-+		kfree(q->qs);
-+}
-+
-+static void esfq_destroy(struct Qdisc *sch)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	esfq_q_destroy(q);
-+}
-+
-+
-+static void esfq_reset(struct Qdisc* sch)
-+{
-+	struct sk_buff *skb;
-+
-+	while ((skb = esfq_dequeue(sch)) != NULL)
-+		kfree_skb(skb);
-+}
-+
-+static void esfq_perturbation(unsigned long arg)
-+{
-+	struct Qdisc *sch = (struct Qdisc*)arg;
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+
-+	q->perturbation = prandom_u32() & 0x1F;
-+
-+	if (q->perturb_period) {
-+		q->perturb_timer.expires = jiffies + q->perturb_period;
-+		add_timer(&q->perturb_timer);
-+	}
-+}
-+
-+static unsigned int esfq_check_hash(unsigned int kind)
-+{
-+	switch (kind) {
-+	case TCA_ESFQ_HASH_CTORIGDST:
-+	case TCA_ESFQ_HASH_CTORIGSRC:
-+	case TCA_ESFQ_HASH_CTREPLDST:
-+	case TCA_ESFQ_HASH_CTREPLSRC:
-+	case TCA_ESFQ_HASH_CTNATCHG:
-+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
-+	{
-+		if (net_ratelimit())
-+			printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
-+		return TCA_ESFQ_HASH_CLASSIC;
-+	}
-+#endif
-+	case TCA_ESFQ_HASH_CLASSIC:
-+	case TCA_ESFQ_HASH_DST:
-+	case TCA_ESFQ_HASH_SRC:
-+	case TCA_ESFQ_HASH_FWMARK:
-+		return kind;
-+	default:
-+	{
-+		if (net_ratelimit())
-+			printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
-+		return TCA_ESFQ_HASH_CLASSIC;
-+	}
-+	}
-+}
-+	
-+static int esfq_q_init(struct esfq_sched_data *q, struct nlattr *opt)
-+{
-+	struct tc_esfq_qopt *ctl = nla_data(opt);
-+	esfq_index p = ~0U/2;
-+	int i;
-+	
-+	if (opt && opt->nla_len < nla_attr_size(sizeof(*ctl)))
-+		return -EINVAL;
-+
-+	q->perturbation = 0;
-+	q->hash_kind = TCA_ESFQ_HASH_CLASSIC;
-+	q->max_depth = 0;
-+	if (opt == NULL) {
-+		q->perturb_period = 0;
-+		q->hash_divisor = 1024;
-+		q->tail = q->limit = q->depth = 128;
-+		
-+	} else {
-+		struct tc_esfq_qopt *ctl = nla_data(opt);
-+		if (ctl->quantum)
-+			q->quantum = ctl->quantum;
-+		q->perturb_period = ctl->perturb_period*HZ;
-+		q->hash_divisor = ctl->divisor ? : 1024;
-+		q->tail = q->limit = q->depth = ctl->flows ? : 128;
-+		
-+		if ( q->depth > p - 1 )
-+			return -EINVAL;
-+		
-+		if (ctl->limit)
-+			q->limit = min_t(u32, ctl->limit, q->depth);
-+		
-+		if (ctl->hash_kind) {
-+			q->hash_kind = esfq_check_hash(ctl->hash_kind);
-+		}
-+	}
-+	
-+	q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
-+	if (!q->ht)
-+		goto err_case;
-+	q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
-+	if (!q->dep)
-+		goto err_case;
-+	q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
-+	if (!q->next)
-+		goto err_case;
-+	q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
-+	if (!q->allot)
-+		goto err_case;
-+	q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
-+	if (!q->hash)
-+		goto err_case;
-+	q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
-+	if (!q->qs)
-+		goto err_case;
-+	
-+	for (i=0; i< q->hash_divisor; i++)
-+		q->ht[i] = q->depth;
-+	for (i=0; i<q->depth; i++) {
-+		skb_queue_head_init(&q->qs[i]);
-+		q->dep[i+q->depth].next = i+q->depth;
-+		q->dep[i+q->depth].prev = i+q->depth;
-+	}
-+	
-+	for (i=0; i<q->depth; i++)
-+		esfq_link(q, i);
-+	return 0;
-+err_case:
-+	esfq_q_destroy(q);
-+	return -ENOBUFS;
-+}
-+
-+static int esfq_init(struct Qdisc *sch, struct nlattr *opt)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	int err;
-+	
-+	q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
-+	if ((err = esfq_q_init(q, opt)))
-+		return err;
-+
-+	init_timer(&q->perturb_timer);
-+	q->perturb_timer.data = (unsigned long)sch;
-+	q->perturb_timer.function = esfq_perturbation;
-+	if (q->perturb_period) {
-+		q->perturb_timer.expires = jiffies + q->perturb_period;
-+		add_timer(&q->perturb_timer);
-+	}
-+	
-+	return 0;
-+}
-+
-+static int esfq_change(struct Qdisc *sch, struct nlattr *opt)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	struct esfq_sched_data new;
-+	struct sk_buff *skb;
-+	int err;
-+	
-+	/* set up new queue */
-+	memset(&new, 0, sizeof(struct esfq_sched_data));
-+	new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
-+	if ((err = esfq_q_init(&new, opt)))
-+		return err;
-+
-+	/* copy all packets from the old queue to the new queue */
-+	sch_tree_lock(sch);
-+	while ((skb = esfq_q_dequeue(q)) != NULL)
-+		esfq_q_enqueue(skb, &new, ESFQ_TAIL);
-+	
-+	/* clean up the old queue */
-+	esfq_q_destroy(q);
-+
-+	/* copy elements of the new queue into the old queue */
-+	q->perturb_period = new.perturb_period;
-+	q->quantum        = new.quantum;
-+	q->limit          = new.limit;
-+	q->depth          = new.depth;
-+	q->hash_divisor   = new.hash_divisor;
-+	q->hash_kind      = new.hash_kind;
-+	q->tail           = new.tail;
-+	q->max_depth      = new.max_depth;
-+	q->ht    = new.ht;
-+	q->dep   = new.dep;
-+	q->next  = new.next;
-+	q->allot = new.allot;
-+	q->hash  = new.hash;
-+	q->qs    = new.qs;
-+
-+	/* finish up */
-+	if (q->perturb_period) {
-+		q->perturb_timer.expires = jiffies + q->perturb_period;
-+		add_timer(&q->perturb_timer);
-+	} else {
-+		q->perturbation = 0;
-+	}
-+	sch_tree_unlock(sch);
-+	return 0;
-+}
-+
-+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
-+{
-+	struct esfq_sched_data *q = qdisc_priv(sch);
-+	unsigned char *b = skb_tail_pointer(skb);
-+	struct tc_esfq_qopt opt;
-+
-+	opt.quantum = q->quantum;
-+	opt.perturb_period = q->perturb_period/HZ;
-+
-+	opt.limit = q->limit;
-+	opt.divisor = q->hash_divisor;
-+	opt.flows = q->depth;
-+	opt.hash_kind = q->hash_kind;
-+
-+	if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))
-+		goto nla_put_failure;
-+	return skb->len;
-+
-+nla_put_failure:
-+	nlmsg_trim(skb, b);
-+	return -1;
-+}
-+
-+static struct Qdisc_ops esfq_qdisc_ops =
-+{
-+	.next		=	NULL,
-+	.cl_ops		=	NULL,
-+	.id		=	"esfq",
-+	.priv_size	=	sizeof(struct esfq_sched_data),
-+	.enqueue	=	esfq_enqueue,
-+	.dequeue	=	esfq_dequeue,
-+	.peek		=	esfq_peek,
-+	.drop		=	esfq_drop,
-+	.init		=	esfq_init,
-+	.reset		=	esfq_reset,
-+	.destroy	=	esfq_destroy,
-+	.change		=	esfq_change,
-+	.dump		=	esfq_dump,
-+	.owner		=	THIS_MODULE,
-+};
-+
-+static int __init esfq_module_init(void)
-+{
-+	return register_qdisc(&esfq_qdisc_ops);
-+}
-+static void __exit esfq_module_exit(void) 
-+{
-+	unregister_qdisc(&esfq_qdisc_ops);
-+}
-+module_init(esfq_module_init)
-+module_exit(esfq_module_exit)
-+MODULE_LICENSE("GPL");
diff --git a/kernel-imq.patch b/kernel-imq.patch
index cc4028b..cbfd042 100644
--- a/kernel-imq.patch
+++ b/kernel-imq.patch
@@ -1,7 +1,7 @@
-diff -Naupr linux-4.7_orig/drivers/net/imq.c linux-4.7/drivers/net/imq.c
---- linux-4.7_orig/drivers/net/imq.c	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.7/drivers/net/imq.c	2016-07-26 20:58:55.635901659 +0700
-@@ -0,0 +1,903 @@
+diff -Naupr linux-4.8_orig/drivers/net/imq.c linux-4.8/drivers/net/imq.c
+--- linux-4.8_orig/drivers/net/imq.c	1970-01-01 07:00:00.000000000 +0700
++++ linux-4.8/drivers/net/imq.c	2016-10-03 07:59:56.140345020 +0700
+@@ -0,0 +1,904 @@
 +/*
 + *             Pseudo-driver for the intermediate queue device.
 + *
@@ -553,6 +553,7 @@ diff -Naupr linux-4.7_orig/drivers/net/imq.c linux-4.7/drivers/net/imq.c
 +{
 +	struct sk_buff *skb_orig, *skb, *skb_shared, *skb_popd;
 +	struct Qdisc *q;
++	struct sk_buff **to_free;
 +	struct netdev_queue *txq;
 +	spinlock_t *root_lock;
 +	int users;
@@ -611,7 +612,7 @@ diff -Naupr linux-4.7_orig/drivers/net/imq.c linux-4.7/drivers/net/imq.c
 +
 +	/* backup skb->cb, as qdisc layer will overwrite it */
 +	skb_save_cb(skb_shared);
-+	qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
++	qdisc_enqueue_root(skb_shared, q, to_free); /* might kfree_skb */
 +	if (likely(atomic_read(&skb_shared->users) == users + 1)) {
 +		bool validate;
 +
@@ -901,13 +902,13 @@ diff -Naupr linux-4.7_orig/drivers/net/imq.c linux-4.7/drivers/net/imq.c
 +MODULE_PARM_DESC(numqueues, "number of queues per IMQ device");
 +MODULE_PARM_DESC(imq_dev_accurate_stats, "Notify if need the accurate imq device stats");
 +
-+MODULE_AUTHOR("http://https://github.com/imq/linuximq");
++MODULE_AUTHOR("https://github.com/imq/linuximq");
 +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information.");
 +MODULE_LICENSE("GPL");
 +MODULE_ALIAS_RTNL_LINK("imq");
-diff -Naupr linux-4.7_orig/drivers/net/Kconfig linux-4.7/drivers/net/Kconfig
---- linux-4.7_orig/drivers/net/Kconfig	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/drivers/net/Kconfig	2016-07-26 20:58:55.635901659 +0700
+diff -Naupr linux-4.8_orig/drivers/net/Kconfig linux-4.8/drivers/net/Kconfig
+--- linux-4.8_orig/drivers/net/Kconfig	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/drivers/net/Kconfig	2016-10-03 07:59:56.140345020 +0700
 @@ -258,6 +258,125 @@ config RIONET_RX_SIZE
  	depends on RIONET
  	default "128"
@@ -1034,9 +1035,9 @@ diff -Naupr linux-4.7_orig/drivers/net/Kconfig linux-4.7/drivers/net/Kconfig
  config TUN
  	tristate "Universal TUN/TAP device driver support"
  	depends on INET
-diff -Naupr linux-4.7_orig/drivers/net/Makefile linux-4.7/drivers/net/Makefile
---- linux-4.7_orig/drivers/net/Makefile	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/drivers/net/Makefile	2016-07-26 20:58:55.635901659 +0700
+diff -Naupr linux-4.8_orig/drivers/net/Makefile linux-4.8/drivers/net/Makefile
+--- linux-4.8_orig/drivers/net/Makefile	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/drivers/net/Makefile	2016-10-03 07:59:56.200344939 +0700
 @@ -11,6 +11,7 @@ obj-$(CONFIG_DUMMY) += dummy.o
  obj-$(CONFIG_EQUALIZER) += eql.o
  obj-$(CONFIG_IFB) += ifb.o
@@ -1045,9 +1046,9 @@ diff -Naupr linux-4.7_orig/drivers/net/Makefile linux-4.7/drivers/net/Makefile
  obj-$(CONFIG_MACVLAN) += macvlan.o
  obj-$(CONFIG_MACVTAP) += macvtap.o
  obj-$(CONFIG_MII) += mii.o
-diff -Naupr linux-4.7_orig/include/linux/imq.h linux-4.7/include/linux/imq.h
---- linux-4.7_orig/include/linux/imq.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.7/include/linux/imq.h	2016-07-26 20:58:55.639235009 +0700
+diff -Naupr linux-4.8_orig/include/linux/imq.h linux-4.8/include/linux/imq.h
+--- linux-4.8_orig/include/linux/imq.h	1970-01-01 07:00:00.000000000 +0700
++++ linux-4.8/include/linux/imq.h	2016-10-03 07:59:56.200344939 +0700
 @@ -0,0 +1,13 @@
 +#ifndef _IMQ_H
 +#define _IMQ_H
@@ -1062,10 +1063,10 @@ diff -Naupr linux-4.7_orig/include/linux/imq.h linux-4.7/include/linux/imq.h
 +
 +#endif /* _IMQ_H */
 +
-diff -Naupr linux-4.7_orig/include/linux/netdevice.h linux-4.7/include/linux/netdevice.h
---- linux-4.7_orig/include/linux/netdevice.h	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/include/linux/netdevice.h	2016-07-26 20:58:55.639235009 +0700
-@@ -3558,6 +3558,19 @@ static inline void netif_tx_unlock_bh(st
+diff -Naupr linux-4.8_orig/include/linux/netdevice.h linux-4.8/include/linux/netdevice.h
+--- linux-4.8_orig/include/linux/netdevice.h	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/include/linux/netdevice.h	2016-10-03 07:59:56.200344939 +0700
+@@ -3602,6 +3602,19 @@ static inline void netif_tx_unlock_bh(st
  	}						\
  }
  
@@ -1085,9 +1086,9 @@ diff -Naupr linux-4.7_orig/include/linux/netdevice.h linux-4.7/include/linux/net
  static inline void netif_tx_disable(struct net_device *dev)
  {
  	unsigned int i;
-diff -Naupr linux-4.7_orig/include/linux/netfilter/xt_IMQ.h linux-4.7/include/linux/netfilter/xt_IMQ.h
---- linux-4.7_orig/include/linux/netfilter/xt_IMQ.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.7/include/linux/netfilter/xt_IMQ.h	2016-07-26 20:58:55.639235009 +0700
+diff -Naupr linux-4.8_orig/include/linux/netfilter/xt_IMQ.h linux-4.8/include/linux/netfilter/xt_IMQ.h
+--- linux-4.8_orig/include/linux/netfilter/xt_IMQ.h	1970-01-01 07:00:00.000000000 +0700
++++ linux-4.8/include/linux/netfilter/xt_IMQ.h	2016-10-03 07:59:56.200344939 +0700
 @@ -0,0 +1,9 @@
 +#ifndef _XT_IMQ_H
 +#define _XT_IMQ_H
@@ -1098,9 +1099,9 @@ diff -Naupr linux-4.7_orig/include/linux/netfilter/xt_IMQ.h linux-4.7/include/li
 +
 +#endif /* _XT_IMQ_H */
 +
-diff -Naupr linux-4.7_orig/include/linux/netfilter_ipv4/ipt_IMQ.h linux-4.7/include/linux/netfilter_ipv4/ipt_IMQ.h
---- linux-4.7_orig/include/linux/netfilter_ipv4/ipt_IMQ.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.7/include/linux/netfilter_ipv4/ipt_IMQ.h	2016-07-26 20:58:55.639235009 +0700
+diff -Naupr linux-4.8_orig/include/linux/netfilter_ipv4/ipt_IMQ.h linux-4.8/include/linux/netfilter_ipv4/ipt_IMQ.h
+--- linux-4.8_orig/include/linux/netfilter_ipv4/ipt_IMQ.h	1970-01-01 07:00:00.000000000 +0700
++++ linux-4.8/include/linux/netfilter_ipv4/ipt_IMQ.h	2016-10-03 07:59:56.200344939 +0700
 @@ -0,0 +1,10 @@
 +#ifndef _IPT_IMQ_H
 +#define _IPT_IMQ_H
@@ -1112,9 +1113,9 @@ diff -Naupr linux-4.7_orig/include/linux/netfilter_ipv4/ipt_IMQ.h linux-4.7/incl
 +
 +#endif /* _IPT_IMQ_H */
 +
-diff -Naupr linux-4.7_orig/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-4.7/include/linux/netfilter_ipv6/ip6t_IMQ.h
---- linux-4.7_orig/include/linux/netfilter_ipv6/ip6t_IMQ.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.7/include/linux/netfilter_ipv6/ip6t_IMQ.h	2016-07-26 20:58:55.639235009 +0700
+diff -Naupr linux-4.8_orig/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-4.8/include/linux/netfilter_ipv6/ip6t_IMQ.h
+--- linux-4.8_orig/include/linux/netfilter_ipv6/ip6t_IMQ.h	1970-01-01 07:00:00.000000000 +0700
++++ linux-4.8/include/linux/netfilter_ipv6/ip6t_IMQ.h	2016-10-03 07:59:56.200344939 +0700
 @@ -0,0 +1,10 @@
 +#ifndef _IP6T_IMQ_H
 +#define _IP6T_IMQ_H
@@ -1126,12 +1127,12 @@ diff -Naupr linux-4.7_orig/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-4.7/inc
 +
 +#endif /* _IP6T_IMQ_H */
 +
-diff -Naupr linux-4.7_orig/include/linux/skbuff.h linux-4.7/include/linux/skbuff.h
---- linux-4.7_orig/include/linux/skbuff.h	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/include/linux/skbuff.h	2016-07-26 20:58:55.639235009 +0700
-@@ -38,6 +38,10 @@
- #include <linux/splice.h>
+diff -Naupr linux-4.8_orig/include/linux/skbuff.h linux-4.8/include/linux/skbuff.h
+--- linux-4.8_orig/include/linux/skbuff.h	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/include/linux/skbuff.h	2016-10-03 07:59:56.200344939 +0700
+@@ -39,6 +39,10 @@
  #include <linux/in6.h>
+ #include <linux/if_packet.h>
  #include <net/flow.h>
 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
 +#include <linux/imq.h>
@@ -1140,7 +1141,7 @@ diff -Naupr linux-4.7_orig/include/linux/skbuff.h linux-4.7/include/linux/skbuff
  
  /* The interface for checksum offload between the stack and networking drivers
   * is as follows...
-@@ -647,6 +651,9 @@ struct sk_buff {
+@@ -655,6 +659,9 @@ struct sk_buff {
  	 * first. This is owned by whoever has the skb queued ATM.
  	 */
  	char			cb[48] __aligned(8);
@@ -1150,7 +1151,7 @@ diff -Naupr linux-4.7_orig/include/linux/skbuff.h linux-4.7/include/linux/skbuff
  
  	unsigned long		_skb_refdst;
  	void			(*destructor)(struct sk_buff *skb);
-@@ -656,6 +663,9 @@ struct sk_buff {
+@@ -664,6 +671,9 @@ struct sk_buff {
  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  	struct nf_conntrack	*nfct;
  #endif
@@ -1160,7 +1161,7 @@ diff -Naupr linux-4.7_orig/include/linux/skbuff.h linux-4.7/include/linux/skbuff
  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
  	struct nf_bridge_info	*nf_bridge;
  #endif
-@@ -723,6 +733,9 @@ struct sk_buff {
+@@ -731,6 +741,9 @@ struct sk_buff {
  	__u8			inner_protocol_type:1;
  	__u8			remcsum_offload:1;
  	/* 3 or 5 bit hole */
@@ -1170,7 +1171,7 @@ diff -Naupr linux-4.7_orig/include/linux/skbuff.h linux-4.7/include/linux/skbuff
  
  #ifdef CONFIG_NET_SCHED
  	__u16			tc_index;	/* traffic control index */
-@@ -879,6 +892,12 @@ void kfree_skb_list(struct sk_buff *segs
+@@ -896,6 +909,12 @@ void kfree_skb_list(struct sk_buff *segs
  void skb_tx_error(struct sk_buff *skb);
  void consume_skb(struct sk_buff *skb);
  void  __kfree_skb(struct sk_buff *skb);
@@ -1183,7 +1184,7 @@ diff -Naupr linux-4.7_orig/include/linux/skbuff.h linux-4.7/include/linux/skbuff
  extern struct kmem_cache *skbuff_head_cache;
  
  void kfree_skb_partial(struct sk_buff *skb, bool head_stolen);
-@@ -3523,6 +3542,10 @@ static inline void __nf_copy(struct sk_b
+@@ -3555,6 +3574,10 @@ static inline void __nf_copy(struct sk_b
  	if (copy)
  		dst->nfctinfo = src->nfctinfo;
  #endif
@@ -1194,9 +1195,9 @@ diff -Naupr linux-4.7_orig/include/linux/skbuff.h linux-4.7/include/linux/skbuff
  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
  	dst->nf_bridge  = src->nf_bridge;
  	nf_bridge_get(src->nf_bridge);
-diff -Naupr linux-4.7_orig/include/net/netfilter/nf_queue.h linux-4.7/include/net/netfilter/nf_queue.h
---- linux-4.7_orig/include/net/netfilter/nf_queue.h	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/include/net/netfilter/nf_queue.h	2016-07-26 20:58:55.642568359 +0700
+diff -Naupr linux-4.8_orig/include/net/netfilter/nf_queue.h linux-4.8/include/net/netfilter/nf_queue.h
+--- linux-4.8_orig/include/net/netfilter/nf_queue.h	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/include/net/netfilter/nf_queue.h	2016-10-03 07:59:56.200344939 +0700
 @@ -31,6 +31,12 @@ struct nf_queue_handler {
  void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
  void nf_unregister_queue_handler(struct net *net);
@@ -1210,9 +1211,9 @@ diff -Naupr linux-4.7_orig/include/net/netfilter/nf_queue.h linux-4.7/include/ne
  
  void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
  void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-diff -Naupr linux-4.7_orig/include/net/pkt_sched.h linux-4.7/include/net/pkt_sched.h
---- linux-4.7_orig/include/net/pkt_sched.h	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/include/net/pkt_sched.h	2016-07-26 20:58:55.642568359 +0700
+diff -Naupr linux-4.8_orig/include/net/pkt_sched.h linux-4.8/include/net/pkt_sched.h
+--- linux-4.8_orig/include/net/pkt_sched.h	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/include/net/pkt_sched.h	2016-10-03 07:59:56.200344939 +0700
 @@ -105,6 +105,8 @@ int sch_direct_xmit(struct sk_buff *skb,
  
  void __qdisc_run(struct Qdisc *q);
@@ -1222,25 +1223,26 @@ diff -Naupr linux-4.7_orig/include/net/pkt_sched.h linux-4.7/include/net/pkt_sch
  static inline void qdisc_run(struct Qdisc *q)
  {
  	if (qdisc_run_begin(q))
-diff -Naupr linux-4.7_orig/include/net/sch_generic.h linux-4.7/include/net/sch_generic.h
---- linux-4.7_orig/include/net/sch_generic.h	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/include/net/sch_generic.h	2016-07-26 20:58:55.642568359 +0700
-@@ -523,6 +523,12 @@ static inline int qdisc_enqueue(struct s
- 	return sch->enqueue(skb, sch);
+diff -Naupr linux-4.8_orig/include/net/sch_generic.h linux-4.8/include/net/sch_generic.h
+--- linux-4.8_orig/include/net/sch_generic.h	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/include/net/sch_generic.h	2016-10-03 07:59:56.200344939 +0700
+@@ -510,6 +510,13 @@ static inline int qdisc_enqueue(struct s
+ 	return sch->enqueue(skb, sch, to_free);
  }
  
-+static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch)
++static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch,
++				      struct sk_buff **to_free)
 +{
 +    qdisc_skb_cb(skb)->pkt_len = skb->len;
-+    return qdisc_enqueue(skb, sch) & NET_XMIT_MASK;
++    return qdisc_enqueue(skb, sch, to_free) & NET_XMIT_MASK;
 +}
 +
  static inline bool qdisc_is_percpu_stats(const struct Qdisc *q)
  {
  	return q->flags & TCQ_F_CPUSTATS;
-diff -Naupr linux-4.7_orig/include/uapi/linux/netfilter.h linux-4.7/include/uapi/linux/netfilter.h
---- linux-4.7_orig/include/uapi/linux/netfilter.h	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/include/uapi/linux/netfilter.h	2016-07-26 20:58:55.642568359 +0700
+diff -Naupr linux-4.8_orig/include/uapi/linux/netfilter.h linux-4.8/include/uapi/linux/netfilter.h
+--- linux-4.8_orig/include/uapi/linux/netfilter.h	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/include/uapi/linux/netfilter.h	2016-10-03 07:59:56.203678268 +0700
 @@ -14,7 +14,8 @@
  #define NF_QUEUE 3
  #define NF_REPEAT 4
@@ -1251,10 +1253,10 @@ diff -Naupr linux-4.7_orig/include/uapi/linux/netfilter.h linux-4.7/include/uapi
  
  /* we overload the higher bits for encoding auxiliary data such as the queue
   * number or errno values. Not nice, but better than additional function
-diff -Naupr linux-4.7_orig/net/core/dev.c linux-4.7/net/core/dev.c
---- linux-4.7_orig/net/core/dev.c	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/core/dev.c	2016-07-26 20:58:55.642568359 +0700
-@@ -139,6 +139,9 @@
+diff -Naupr linux-4.8_orig/net/core/dev.c linux-4.8/net/core/dev.c
+--- linux-4.8_orig/net/core/dev.c	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/core/dev.c	2016-10-03 07:59:56.203678268 +0700
+@@ -141,6 +141,9 @@
  #include <linux/netfilter_ingress.h>
  #include <linux/sctp.h>
  #include <linux/crash_dump.h>
@@ -1264,39 +1266,10 @@ diff -Naupr linux-4.7_orig/net/core/dev.c linux-4.7/net/core/dev.c
  
  #include "net-sysfs.h"
  
-@@ -2908,7 +2911,12 @@ static int xmit_one(struct sk_buff *skb,
- 	unsigned int len;
- 	int rc;
- 
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	if ((!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) &&
-+		!(skb->imq_flags & IMQ_F_ENQUEUE))
-+#else
- 	if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all))
-+#endif
- 		dev_queue_xmit_nit(skb, dev);
- 
- 	len = skb->len;
-@@ -2946,6 +2954,7 @@ out:
- 	*ret = rc;
- 	return skb;
- }
-+EXPORT_SYMBOL(dev_hard_start_xmit);
- 
- static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
- 					  netdev_features_t features)
-@@ -3032,6 +3041,7 @@ struct sk_buff *validate_xmit_skb_list(s
- 	}
- 	return head;
- }
-+EXPORT_SYMBOL(validate_xmit_skb_list);
- 
- static void qdisc_pkt_len_init(struct sk_buff *skb)
- {
-diff -Naupr linux-4.7_orig/net/core/skbuff.c linux-4.7/net/core/skbuff.c
---- linux-4.7_orig/net/core/skbuff.c	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/core/skbuff.c	2016-07-26 20:58:55.645901708 +0700
-@@ -81,6 +81,87 @@ struct kmem_cache *skbuff_head_cache __r
+diff -Naupr linux-4.8_orig/net/core/skbuff.c linux-4.8/net/core/skbuff.c
+--- linux-4.8_orig/net/core/skbuff.c	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/core/skbuff.c	2016-10-03 07:59:56.203678268 +0700
+@@ -82,6 +82,87 @@ struct kmem_cache *skbuff_head_cache __r
  static struct kmem_cache *skbuff_fclone_cache __read_mostly;
  int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
  EXPORT_SYMBOL(sysctl_max_skb_frags);
@@ -1384,7 +1357,7 @@ diff -Naupr linux-4.7_orig/net/core/skbuff.c linux-4.7/net/core/skbuff.c
  
  /**
   *	skb_panic - private function for out-of-line support
-@@ -653,6 +734,28 @@ static void skb_release_head_state(struc
+@@ -654,6 +735,28 @@ static void skb_release_head_state(struc
  		WARN_ON(in_irq());
  		skb->destructor(skb);
  	}
@@ -1413,7 +1386,7 @@ diff -Naupr linux-4.7_orig/net/core/skbuff.c linux-4.7/net/core/skbuff.c
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
  	nf_conntrack_put(skb->nfct);
  #endif
-@@ -842,6 +945,10 @@ static void __copy_skb_header(struct sk_
+@@ -843,6 +946,10 @@ static void __copy_skb_header(struct sk_
  	new->sp			= secpath_get(old->sp);
  #endif
  	__nf_copy(new, old, false);
@@ -1424,7 +1397,7 @@ diff -Naupr linux-4.7_orig/net/core/skbuff.c linux-4.7/net/core/skbuff.c
  
  	/* Note : this field could be in headers_start/headers_end section
  	 * It is not yet because we do not want to have a 16 bit hole
-@@ -3433,6 +3540,13 @@ void __init skb_init(void)
+@@ -3439,6 +3546,13 @@ void __init skb_init(void)
  						0,
  						SLAB_HWCACHE_ALIGN|SLAB_PANIC,
  						NULL);
@@ -1438,9 +1411,9 @@ diff -Naupr linux-4.7_orig/net/core/skbuff.c linux-4.7/net/core/skbuff.c
  }
  
  /**
-diff -Naupr linux-4.7_orig/net/ipv6/ip6_output.c linux-4.7/net/ipv6/ip6_output.c
---- linux-4.7_orig/net/ipv6/ip6_output.c	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/ipv6/ip6_output.c	2016-07-26 20:58:55.645901708 +0700
+diff -Naupr linux-4.8_orig/net/ipv6/ip6_output.c linux-4.8/net/ipv6/ip6_output.c
+--- linux-4.8_orig/net/ipv6/ip6_output.c	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/ipv6/ip6_output.c	2016-10-03 07:59:56.203678268 +0700
 @@ -65,9 +65,6 @@ static int ip6_finish_output2(struct net
  	struct in6_addr *nexthop;
  	int ret;
@@ -1465,10 +1438,10 @@ diff -Naupr linux-4.7_orig/net/ipv6/ip6_output.c linux-4.7/net/ipv6/ip6_output.c
  	return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
  			    net, sk, skb, NULL, dev,
  			    ip6_finish_output,
-diff -Naupr linux-4.7_orig/net/netfilter/core.c linux-4.7/net/netfilter/core.c
---- linux-4.7_orig/net/netfilter/core.c	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/netfilter/core.c	2016-07-26 20:58:55.645901708 +0700
-@@ -311,9 +311,11 @@ next_hook:
+diff -Naupr linux-4.8_orig/net/netfilter/core.c linux-4.8/net/netfilter/core.c
+--- linux-4.8_orig/net/netfilter/core.c	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/netfilter/core.c	2016-10-03 07:59:56.203678268 +0700
+@@ -311,10 +311,14 @@ next_hook:
  		ret = NF_DROP_GETERR(verdict);
  		if (ret == 0)
  			ret = -EPERM;
@@ -1480,12 +1453,15 @@ diff -Naupr linux-4.7_orig/net/netfilter/core.c linux-4.7/net/netfilter/core.c
 +				   verdict >> NF_VERDICT_QBITS,
 +				  verdict & NF_VERDICT_MASK);
  		if (err < 0) {
++			if (err == -ECANCELED)
++				goto next_hook;
  			if (err == -ESRCH &&
  			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
-diff -Naupr linux-4.7_orig/net/netfilter/Kconfig linux-4.7/net/netfilter/Kconfig
---- linux-4.7_orig/net/netfilter/Kconfig	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/netfilter/Kconfig	2016-07-26 20:58:55.645901708 +0700
-@@ -807,6 +807,18 @@ config NETFILTER_XT_TARGET_LOG
+ 				goto next_hook;
+diff -Naupr linux-4.8_orig/net/netfilter/Kconfig linux-4.8/net/netfilter/Kconfig
+--- linux-4.8_orig/net/netfilter/Kconfig	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/netfilter/Kconfig	2016-10-03 07:59:56.203678268 +0700
+@@ -805,6 +805,18 @@ config NETFILTER_XT_TARGET_LOG
  
  	  To compile it as a module, choose M here.  If unsure, say N.
  
@@ -1504,9 +1480,9 @@ diff -Naupr linux-4.7_orig/net/netfilter/Kconfig linux-4.7/net/netfilter/Kconfig
  config NETFILTER_XT_TARGET_MARK
  	tristate '"MARK" target support'
  	depends on NETFILTER_ADVANCED
-diff -Naupr linux-4.7_orig/net/netfilter/Makefile linux-4.7/net/netfilter/Makefile
---- linux-4.7_orig/net/netfilter/Makefile	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/netfilter/Makefile	2016-07-26 20:58:55.645901708 +0700
+diff -Naupr linux-4.8_orig/net/netfilter/Makefile linux-4.8/net/netfilter/Makefile
+--- linux-4.8_orig/net/netfilter/Makefile	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/netfilter/Makefile	2016-10-03 07:59:56.203678268 +0700
 @@ -115,6 +115,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) +=
  obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
  obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
@@ -1515,9 +1491,9 @@ diff -Naupr linux-4.7_orig/net/netfilter/Makefile linux-4.7/net/netfilter/Makefi
  obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
  obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
  obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o
-diff -Naupr linux-4.7_orig/net/netfilter/nf_internals.h linux-4.7/net/netfilter/nf_internals.h
---- linux-4.7_orig/net/netfilter/nf_internals.h	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/netfilter/nf_internals.h	2016-07-26 20:58:55.645901708 +0700
+diff -Naupr linux-4.8_orig/net/netfilter/nf_internals.h linux-4.8/net/netfilter/nf_internals.h
+--- linux-4.8_orig/net/netfilter/nf_internals.h	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/netfilter/nf_internals.h	2016-10-03 07:59:56.203678268 +0700
 @@ -18,7 +18,7 @@ unsigned int nf_iterate(struct list_head
  
  /* nf_queue.c */
@@ -1527,9 +1503,9 @@ diff -Naupr linux-4.7_orig/net/netfilter/nf_internals.h linux-4.7/net/netfilter/
  void nf_queue_nf_hook_drop(struct net *net, struct nf_hook_ops *ops);
  int __init netfilter_queue_init(void);
  
-diff -Naupr linux-4.7_orig/net/netfilter/nf_queue.c linux-4.7/net/netfilter/nf_queue.c
---- linux-4.7_orig/net/netfilter/nf_queue.c	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/netfilter/nf_queue.c	2016-07-26 20:58:55.649235058 +0700
+diff -Naupr linux-4.8_orig/net/netfilter/nf_queue.c linux-4.8/net/netfilter/nf_queue.c
+--- linux-4.8_orig/net/netfilter/nf_queue.c	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/netfilter/nf_queue.c	2016-10-03 07:59:56.203678268 +0700
 @@ -27,6 +27,23 @@
   * receives, no matter what.
   */
@@ -1595,9 +1571,9 @@ diff -Naupr linux-4.7_orig/net/netfilter/nf_queue.c linux-4.7/net/netfilter/nf_q
  		if (err < 0) {
  			if (err == -ESRCH &&
  			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
-diff -Naupr linux-4.7_orig/net/netfilter/xt_IMQ.c linux-4.7/net/netfilter/xt_IMQ.c
---- linux-4.7_orig/net/netfilter/xt_IMQ.c	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.7/net/netfilter/xt_IMQ.c	2016-07-26 20:58:55.649235058 +0700
+diff -Naupr linux-4.8_orig/net/netfilter/xt_IMQ.c linux-4.8/net/netfilter/xt_IMQ.c
+--- linux-4.8_orig/net/netfilter/xt_IMQ.c	1970-01-01 07:00:00.000000000 +0700
++++ linux-4.8/net/netfilter/xt_IMQ.c	2016-10-03 07:59:56.203678268 +0700
 @@ -0,0 +1,72 @@
 +/*
 + * This target marks packets to be enqueued to an imq device
@@ -1671,10 +1647,10 @@ diff -Naupr linux-4.7_orig/net/netfilter/xt_IMQ.c linux-4.7/net/netfilter/xt_IMQ
 +MODULE_ALIAS("ipt_IMQ");
 +MODULE_ALIAS("ip6t_IMQ");
 +
-diff -Naupr linux-4.7_orig/net/sched/sch_generic.c linux-4.7/net/sched/sch_generic.c
---- linux-4.7_orig/net/sched/sch_generic.c	2016-07-25 02:23:50.000000000 +0700
-+++ linux-4.7/net/sched/sch_generic.c	2016-07-26 20:58:55.649235058 +0700
-@@ -110,6 +110,14 @@ static struct sk_buff *dequeue_skb(struc
+diff -Naupr linux-4.8_orig/net/sched/sch_generic.c linux-4.8/net/sched/sch_generic.c
+--- linux-4.8_orig/net/sched/sch_generic.c	2016-10-03 06:24:33.000000000 +0700
++++ linux-4.8/net/sched/sch_generic.c	2016-10-03 07:59:56.207011597 +0700
+@@ -154,6 +154,14 @@ bulk:
  	return skb;
  }
  
@@ -1688,4 +1664,4 @@ diff -Naupr linux-4.7_orig/net/sched/sch_generic.c linux-4.7/net/sched/sch_gener
 +
  /*
   * Transmit possibly several skbs, and handle the return status as
-  * required. Holding the __QDISC___STATE_RUNNING bit guarantees that
+  * required. Owning running seqcount bit guarantees that
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/kernel.git/commitdiff/aa0e7109250278ddee50ff7cfd4f16643b574dd5




More information about the pld-cvs-commit mailing list