From: Jussi Kivilinna <jussi.kivilinna@iki.fi>
+This patch is for kernel version 3.12.4+.
+
See: http://linuximq.net/
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
---
drivers/net/Kconfig | 119 ++++
drivers/net/Makefile | 1
- drivers/net/imq.c | 1001 +++++++++++++++++++++++++++++++
+ drivers/net/imq.c | 1007 +++++++++++++++++++++++++++++++
include/linux/imq.h | 13
include/linux/netfilter/xt_IMQ.h | 9
include/linux/netfilter_ipv4/ipt_IMQ.h | 10
include/linux/netfilter_ipv6/ip6t_IMQ.h | 10
- include/linux/skbuff.h | 23 +
+ include/linux/skbuff.h | 22 +
include/net/netfilter/nf_queue.h | 6
include/uapi/linux/netfilter.h | 3
net/core/dev.c | 8
net/netfilter/nf_internals.h | 2
net/netfilter/nf_queue.c | 36 +
net/netfilter/xt_IMQ.c | 72 ++
- 19 files changed, 1444 insertions(+), 10 deletions(-)
+ 19 files changed, 1449 insertions(+), 10 deletions(-)
create mode 100644 drivers/net/imq.c
create mode 100644 include/linux/imq.h
create mode 100644 include/linux/netfilter/xt_IMQ.h
create mode 100644 net/netfilter/xt_IMQ.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
-index 3835321..77550a9 100644
+index b45b240..5a20da0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
-@@ -207,6 +207,125 @@ config RIONET_RX_SIZE
+@@ -203,6 +203,125 @@ config RIONET_RX_SIZE
depends on RIONET
default "128"
tristate "Universal TUN/TAP device driver support"
select CRC32
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
-index ef3d090..b474ff4 100644
+index 3fef8a8..12dafc0 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_MII) += mii.o
diff --git a/drivers/net/imq.c b/drivers/net/imq.c
new file mode 100644
-index 0000000..fd3e6c5
+index 0000000..801bc8c
--- /dev/null
+++ b/drivers/net/imq.c
-@@ -0,0 +1,1001 @@
+@@ -0,0 +1,1012 @@
+/*
+ * Pseudo-driver for the intermediate queue device.
+ *
+ * - Fixed GSO handling for 3.10, see imq_nf_queue() for comments.
+ * - Don't copy skb->cb_next when copying or cloning skbuffs.
+ *
++ * 2013/09/16 - Jussi Kivilinna <jussi.kivilinna@iki.fi>
++ * - Port to 3.11
++ *
++ * 2013/11/12 - Jussi Kivilinna <jussi.kivilinna@iki.fi>
++ * - Port to 3.12
++ *
+ * Also, many thanks to pablo Sebastian Greco for making the initial
+ * patch and to those who helped the testing.
+ *
+
+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num);
+
-+static nf_hookfn imq_nf_hook;
++static unsigned int imq_nf_hook(const struct nf_hook_ops *ops,
++ struct sk_buff *pskb,
++ const struct net_device *indev,
++ const struct net_device *outdev,
++ int (*okfn)(struct sk_buff *));
+
+static struct nf_hook_ops imq_ops[] = {
+ {
+ return retval;
+}
+
-+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
++static unsigned int imq_nf_hook(const struct nf_hook_ops *ops,
++ struct sk_buff *pskb,
+ const struct net_device *indev,
+ const struct net_device *outdev,
+ int (*okfn)(struct sk_buff *))
+#endif /* _IP6T_IMQ_H */
+
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
-index dec1748..1f17280 100644
+index f66f346..d699b19 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -33,6 +33,9 @@
/* Don't change this without changing skb_csum_unnecessary! */
#define CHECKSUM_NONE 0
-@@ -420,6 +423,9 @@ struct sk_buff {
+@@ -418,6 +421,9 @@ struct sk_buff {
* first. This is owned by whoever has the skb queued ATM.
*/
char cb[48] __aligned(8);
unsigned long _skb_refdst;
#ifdef CONFIG_XFRM
-@@ -458,6 +464,9 @@ struct sk_buff {
- #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
- struct sk_buff *nfct_reasm;
+@@ -453,6 +459,9 @@ struct sk_buff {
+ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ struct nf_conntrack *nfct;
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ struct nf_queue_entry *nf_queue_entry;
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
-@@ -497,6 +506,10 @@ struct sk_buff {
- /* 7/9 bit hole (depending on ndisc_nodetype presence) */
- kmemcheck_bitfield_end(flags2);
-
+@@ -490,6 +490,9 @@ struct sk_buff {
+ __u8 csum_valid:1;
+ __u8 csum_complete_sw:1;
+ /* 3/5 bit hole (depending on ndisc_nodetype presence) */
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ __u8 imq_flags:IMQ_F_BITS;
+#endif
-+
- #ifdef CONFIG_NET_DMA
- dma_cookie_t dma_cookie;
- #endif
-@@ -626,6 +639,12 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb)
+ kmemcheck_bitfield_end(flags2);
+
+ #if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL
+@@ -625,6 +637,12 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb)
return (struct rtable *)skb_dst(skb);
}
+extern int skb_restore_cb(struct sk_buff *skb);
+#endif
+
- extern void kfree_skb(struct sk_buff *skb);
- extern void kfree_skb_list(struct sk_buff *segs);
- extern void skb_tx_error(struct sk_buff *skb);
-@@ -2754,6 +2773,10 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
- dst->nfct_reasm = src->nfct_reasm;
- nf_conntrack_get_reasm(src->nfct_reasm);
+ void kfree_skb(struct sk_buff *skb);
+ void kfree_skb_list(struct sk_buff *segs);
+ void skb_tx_error(struct sk_buff *skb);
+@@ -2635,6 +2653,10 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
+ nf_conntrack_get(src->nfct);
+ dst->nfctinfo = src->nfctinfo;
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ dst->imq_flags = src->imq_flags;
@@ -29,6 +29,12 @@ struct nf_queue_handler {
void nf_register_queue_handler(const struct nf_queue_handler *qh);
void nf_unregister_queue_handler(void);
- extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
+ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
+
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
/* 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 --git a/net/core/dev.c b/net/core/dev.c
-index 7ddbb31..125b7b9 100644
+index 3d13874..9842f21 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
-@@ -129,6 +129,9 @@
- #include <linux/inetdevice.h>
- #include <linux/cpu_rmap.h>
- #include <linux/static_key.h>
+@@ -131,6 +131,9 @@
+ #include <linux/hashtable.h>
+ #include <linux/vmalloc.h>
+ #include <linux/if_macvlan.h>
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+#include <linux/imq.h>
+#endif
#include "net-sysfs.h"
-@@ -2573,7 +2576,12 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
+@@ -2595,7 +2598,12 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
}
}
skb_len = skb->len;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index 1c1738c..5d1b75b 100644
+index c28c7fe..a5f1888 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
-@@ -73,6 +73,9 @@
+@@ -73,6 +73,84 @@
struct kmem_cache *skbuff_head_cache __read_mostly;
static struct kmem_cache *skbuff_fclone_cache __read_mostly;
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
-
- static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
-@@ -92,6 +95,82 @@ static int sock_pipe_buf_steal(struct pipe_inode_info *pipe,
- return 1;
- }
-
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++
+/* Control buffer save/restore for IMQ devices */
+struct skb_cb_table {
+ char cb[48] __aligned(8);
+}
+#endif
- /* Pipe buffer operations for a socket. */
- static const struct pipe_buf_operations sock_pipe_buf_ops = {
-@@ -582,6 +661,28 @@ static void skb_release_head_state(struct sk_buff *skb)
+ /**
+ * skb_panic - private function for out-of-line support
+@@ -577,6 +656,28 @@ static void skb_release_head_state(struct sk_buff *skb)
WARN_ON(in_irq());
skb->destructor(skb);
}
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
nf_conntrack_put(skb->nfct);
#endif
-@@ -716,6 +817,10 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+@@ -709,6 +810,10 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->sp = secpath_get(old->sp);
#endif
memcpy(new->cb, old->cb, sizeof(old->cb));
new->csum = old->csum;
new->local_df = old->local_df;
new->pkt_type = old->pkt_type;
-@@ -3095,6 +3200,13 @@ void __init skb_init(void)
+@@ -3112,6 +3217,13 @@ void __init skb_init(void)
0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
NULL);
/**
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index 6e3ddf8..ddae387 100644
+index b6fa35e..08dcfef 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
-@@ -89,9 +89,6 @@ static int ip6_finish_output2(struct sk_buff *skb)
+@@ -64,9 +64,6 @@ static int ip6_finish_output2(struct sk_buff *skb)
struct in6_addr *nexthop;
int ret;
if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
-@@ -167,6 +164,13 @@ int ip6_output(struct sk_buff *skb)
+@@ -143,6 +140,13 @@ int ip6_output(struct sk_buff *skb)
return 0;
}
ip6_finish_output,
!(IP6CB(skb)->flags & IP6SKB_REROUTED));
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
-index 56d22ca..58f40f8 100644
+index 6e839b6..45ac31c 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
-@@ -641,6 +641,18 @@ config NETFILTER_XT_TARGET_LOG
+@@ -630,6 +630,18 @@ config NETFILTER_XT_TARGET_LOG
To compile it as a module, choose M here. If unsure, say N.
tristate '"MARK" target support'
depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
-index a1abf87..2c0cbf4 100644
+index c3a0a12..9647f06 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
-index 857ca9f..93fe11b 100644
+index 593b16e..740cd69 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -191,9 +191,11 @@ next_hook:
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -29,7 +29,7 @@ extern int nf_queue(struct sk_buff *skb,
- struct net_device *indev,
- struct net_device *outdev,
- int (*okfn)(struct sk_buff *),
-- unsigned int queuenum);
-+ unsigned int queuenum, unsigned int queuetype);
- extern int __init netfilter_queue_init(void);
+ int nf_queue(struct sk_buff *skb, struct nf_hook_ops *elem, u_int8_t pf,
+ unsigned int hook, struct net_device *indev,
+ struct net_device *outdev, int (*okfn)(struct sk_buff *),
+- unsigned int queuenum);
++ unsigned int queuenum, unsigned int queuetype);
+ int __init netfilter_queue_init(void);
/* nf_log.c */
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c