--- /dev/null
+--- linux-2.6.20.7-original/drivers/net/imq.c 1970-01-01 02:00:00.000000000 +0200\r
++++ linux-2.6.20.7/drivers/net/imq.c 2007-04-19 16:22:34.000000000 +0300\r
+@@ -0,0 +1,402 @@\r
++/*\r
++ * Pseudo-driver for the intermediate queue device.\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version\r
++ * 2 of the License, or (at your option) any later version.\r
++ *\r
++ * Authors: Patrick McHardy, <kaber@trash.net>\r
++ *\r
++ * The first version was written by Martin Devera, <devik@cdi.cz>\r
++ *\r
++ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>\r
++ * - Update patch to 2.4.21\r
++ * Sebastian Strollo <sstrollo@nortelnetworks.com>\r
++ * - Fix "Dead-loop on netdevice imq"-issue\r
++ * Marcel Sebek <sebek64@post.cz>\r
++ * - Update to 2.6.2-rc1\r
++ *\r
++ * After some time of inactivity there is a group taking care\r
++ * of IMQ again: http://www.linuximq.net\r
++ *\r
++ *\r
++ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7 including\r
++ * the following changes:\r
++ *\r
++ * - Correction of ipv6 support "+"s issue (Hasso Tepper)\r
++ * - Correction of imq_init_devs() issue that resulted in\r
++ * kernel OOPS unloading IMQ as module (Norbert Buchmuller)\r
++ * - Addition of functionality to choose number of IMQ devices\r
++ * during kernel config (Andre Correa)\r
++ * - Addition of functionality to choose how IMQ hooks on\r
++ * PRE and POSTROUTING (after or before NAT) (Andre Correa)\r
++ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)\r
++ *\r
++ *\r
++ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were\r
++ * released with almost no problems. 2.6.14-x was released\r
++ * with some important changes: nfcache was removed; After\r
++ * some weeks of trouble we figured out that some IMQ fields\r
++ * in skb were missing in skbuff.c - skb_clone and copy_skb_header.\r
++ * These functions are correctly patched by this new patch version.\r
++ *\r
++ * Thanks for all who helped to figure out all the problems with\r
++ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,\r
++ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully\r
++ * I didn't forget anybody). I apologize again for my lack of time.\r
++ *\r
++ * More info at: http://www.linuximq.net/ (Andre Correa)\r
++ */\r
++\r
++#include <linux/module.h>\r
++#include <linux/kernel.h>\r
++#include <linux/moduleparam.h>\r
++#include <linux/skbuff.h>\r
++#include <linux/netdevice.h>\r
++#include <linux/rtnetlink.h>\r
++#include <linux/if_arp.h>\r
++#include <linux/netfilter.h>\r
++#include <linux/netfilter_ipv4.h>\r
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)\r
++ #include <linux/netfilter_ipv6.h>\r
++#endif\r
++#include <linux/imq.h>\r
++#include <net/pkt_sched.h>\r
++\r
++extern int qdisc_restart1(struct net_device *dev);\r
++\r
++static nf_hookfn imq_nf_hook;\r
++\r
++static struct nf_hook_ops imq_ingress_ipv4 = {\r
++ .hook = imq_nf_hook,\r
++ .owner = THIS_MODULE,\r
++ .pf = PF_INET,\r
++ .hooknum = NF_IP_PRE_ROUTING,\r
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)\r
++ .priority = NF_IP_PRI_MANGLE + 1\r
++#else\r
++ .priority = NF_IP_PRI_NAT_DST + 1\r
++#endif\r
++};\r
++\r
++static struct nf_hook_ops imq_egress_ipv4 = {\r
++ .hook = imq_nf_hook,\r
++ .owner = THIS_MODULE,\r
++ .pf = PF_INET,\r
++ .hooknum = NF_IP_POST_ROUTING,\r
++#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)\r
++ .priority = NF_IP_PRI_LAST\r
++#else\r
++ .priority = NF_IP_PRI_NAT_SRC - 1\r
++#endif\r
++};\r
++\r
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)\r
++static struct nf_hook_ops imq_ingress_ipv6 = {\r
++ .hook = imq_nf_hook,\r
++ .owner = THIS_MODULE,\r
++ .pf = PF_INET6,\r
++ .hooknum = NF_IP6_PRE_ROUTING,\r
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)\r
++ .priority = NF_IP6_PRI_MANGLE + 1\r
++#else\r
++ .priority = NF_IP6_PRI_NAT_DST + 1\r
++#endif\r
++};\r
++\r
++static struct nf_hook_ops imq_egress_ipv6 = {\r
++ .hook = imq_nf_hook,\r
++ .owner = THIS_MODULE,\r
++ .pf = PF_INET6,\r
++ .hooknum = NF_IP6_POST_ROUTING,\r
++#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)\r
++ .priority = NF_IP6_PRI_LAST\r
++#else\r
++ .priority = NF_IP6_PRI_NAT_SRC - 1\r
++#endif\r
++};\r
++#endif\r
++\r
++#if defined(CONFIG_IMQ_NUM_DEVS)\r
++static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;\r
++#else\r
++static unsigned int numdevs = 2;\r
++#endif\r
++\r
++static struct net_device *imq_devs;\r
++\r
++static struct net_device_stats *imq_get_stats(struct net_device *dev)\r
++{\r
++ return (struct net_device_stats *)dev->priv;\r
++}\r
++\r
++/* called for packets kfree'd in qdiscs at places other than enqueue */\r
++static void imq_skb_destructor(struct sk_buff *skb)\r
++{\r
++ struct nf_info *info = skb->nf_info;\r
++\r
++ if (info) {\r
++ if (info->indev)\r
++ dev_put(info->indev);\r
++ if (info->outdev)\r
++ dev_put(info->outdev);\r
++ kfree(info);\r
++ }\r
++}\r
++\r
++static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)\r
++{\r
++ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;\r
++\r
++ stats->tx_bytes += skb->len;\r
++ stats->tx_packets++;\r
++\r
++ skb->imq_flags = 0;\r
++ skb->destructor = NULL;\r
++\r
++ dev->trans_start = jiffies;\r
++ nf_reinject(skb, skb->nf_info, NF_ACCEPT);\r
++ return 0;\r
++}\r
++\r
++static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info, unsigned queue_num, void *data)\r
++{\r
++ struct net_device *dev;\r
++ struct net_device_stats *stats;\r
++ struct sk_buff *skb2 = NULL;\r
++ struct Qdisc *q;\r
++ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;\r
++ int ret = -1;\r
++\r
++ if (index > numdevs)\r
++ return -1;\r
++\r
++ dev = imq_devs + index;\r
++ if (!(dev->flags & IFF_UP)) {\r
++ skb->imq_flags = 0;\r
++ nf_reinject(skb, info, NF_ACCEPT);\r
++ return 0;\r
++ }\r
++ dev->last_rx = jiffies;\r
++\r
++ if (skb->destructor) {\r
++ skb2 = skb;\r
++ skb = skb_clone(skb, GFP_ATOMIC);\r
++ if (!skb)\r
++ return -1;\r
++ }\r
++ skb->nf_info = info;\r
++\r
++ stats = (struct net_device_stats *)dev->priv;\r
++ stats->rx_bytes+= skb->len;\r
++ stats->rx_packets++;\r
++\r
++ spin_lock_bh(&dev->queue_lock);\r
++ q = dev->qdisc;\r
++ if (q->enqueue) {\r
++ q->enqueue(skb_get(skb), q);\r
++ if (skb_shared(skb)) {\r
++ skb->destructor = imq_skb_destructor;\r
++ kfree_skb(skb);\r
++ ret = 0;\r
++ }\r
++ }\r
++ if (spin_is_locked(&dev->_xmit_lock))\r
++ netif_schedule(dev);\r
++ else\r
++ while (!netif_queue_stopped(dev) && qdisc_restart1(dev) < 0)\r
++ /* NOTHING */;\r
++\r
++ spin_unlock_bh(&dev->queue_lock);\r
++\r
++ if (skb2)\r
++ kfree_skb(ret ? skb : skb2);\r
++\r
++ return ret;\r
++}\r
++\r
++static struct nf_queue_handler nfqh = {\r
++ .name = "imq",\r
++ .outfn = imq_nf_queue,\r
++};\r
++\r
++static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff **pskb,\r
++ const struct net_device *indev,\r
++ const struct net_device *outdev,\r
++ int (*okfn)(struct sk_buff *))\r
++{\r
++ if ((*pskb)->imq_flags & IMQ_F_ENQUEUE)\r
++ return NF_QUEUE;\r
++\r
++ return NF_ACCEPT;\r
++}\r
++\r
++\r
++static int __init imq_init_hooks(void)\r
++{\r
++ int err;\r
++\r
++ err = nf_register_queue_handler(PF_INET, &nfqh);\r
++ if (err > 0)\r
++ goto err1;\r
++ if ((err = nf_register_hook(&imq_ingress_ipv4)))\r
++ goto err2;\r
++ if ((err = nf_register_hook(&imq_egress_ipv4)))\r
++ goto err3;\r
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)\r
++ if ((err = nf_register_queue_handler(PF_INET6, &nfqh)))\r
++ goto err4;\r
++ if ((err = nf_register_hook(&imq_ingress_ipv6)))\r
++ goto err5;\r
++ if ((err = nf_register_hook(&imq_egress_ipv6)))\r
++ goto err6;\r
++#endif\r
++\r
++ return 0;\r
++\r
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)\r
++err6:\r
++ nf_unregister_hook(&imq_ingress_ipv6);\r
++err5:\r
++ nf_unregister_queue_handler(PF_INET6);\r
++err4:\r
++ nf_unregister_hook(&imq_egress_ipv6);\r
++#endif\r
++err3:\r
++ nf_unregister_hook(&imq_ingress_ipv4);\r
++err2:\r
++ nf_unregister_queue_handler(PF_INET);\r
++err1:\r
++ return err;\r
++}\r
++\r
++static void __exit imq_unhook(void)\r
++{\r
++ nf_unregister_hook(&imq_ingress_ipv4);\r
++ nf_unregister_hook(&imq_egress_ipv4);\r
++ nf_unregister_queue_handler(PF_INET);\r
++#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)\r
++ nf_unregister_hook(&imq_ingress_ipv6);\r
++ nf_unregister_hook(&imq_egress_ipv6);\r
++ nf_unregister_queue_handler(PF_INET6);\r
++#endif\r
++}\r
++\r
++static int __init imq_dev_init(struct net_device *dev)\r
++{\r
++ dev->hard_start_xmit = imq_dev_xmit;\r
++ dev->type = ARPHRD_VOID;\r
++ dev->mtu = 16000;\r
++ dev->tx_queue_len = 11000;\r
++ dev->flags = IFF_NOARP;\r
++ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);\r
++ if (dev->priv == NULL)\r
++ return -ENOMEM;\r
++ memset(dev->priv, 0, sizeof(struct net_device_stats));\r
++ dev->get_stats = imq_get_stats;\r
++\r
++ return 0;\r
++}\r
++\r
++static void imq_dev_uninit(struct net_device *dev)\r
++{\r
++ kfree(dev->priv);\r
++}\r
++\r
++static int __init imq_init_devs(void)\r
++{\r
++ struct net_device *dev;\r
++ int i,j;\r
++ j = numdevs;\r
++\r
++ if (!numdevs || numdevs > IMQ_MAX_DEVS) {\r
++ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",\r
++ IMQ_MAX_DEVS);\r
++ return -EINVAL;\r
++ }\r
++\r
++ imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);\r
++ if (!imq_devs)\r
++ return -ENOMEM;\r
++ memset(imq_devs, 0, sizeof(struct net_device) * numdevs);\r
++\r
++ /* we start counting at zero */\r
++ numdevs--;\r
++\r
++ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {\r
++ SET_MODULE_OWNER(dev);\r
++ strcpy(dev->name, "imq%d");\r
++ dev->init = imq_dev_init;\r
++ dev->uninit = imq_dev_uninit;\r
++\r
++ if (register_netdev(dev) < 0)\r
++ goto err_register;\r
++ }\r
++ printk(KERN_INFO "IMQ starting with %u devices...\n", j);\r
++ return 0;\r
++\r
++err_register:\r
++ for (; i; i--)\r
++ unregister_netdev(--dev);\r
++ kfree(imq_devs);\r
++ return -EIO;\r
++}\r
++\r
++static void imq_cleanup_devs(void)\r
++{\r
++ int i;\r
++ struct net_device *dev = imq_devs;\r
++\r
++ for (i = 0; i <= numdevs; i++)\r
++ unregister_netdev(dev++);\r
++\r
++ kfree(imq_devs);\r
++}\r
++\r
++static int __init imq_init_module(void)\r
++{\r
++ int err;\r
++\r
++ if ((err = imq_init_devs())) {\r
++ printk(KERN_ERR "IMQ: Error trying imq_init_devs()\n");\r
++ return err;\r
++ }\r
++ if ((err = imq_init_hooks())) {\r
++ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");\r
++ imq_cleanup_devs();\r
++ return err;\r
++ }\r
++\r
++ printk(KERN_INFO "IMQ driver loaded successfully.\n");\r
++\r
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)\r
++ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");\r
++#else\r
++ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");\r
++#endif\r
++#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)\r
++ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");\r
++#else\r
++ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");\r
++#endif\r
++\r
++ return 0;\r
++}\r
++\r
++static void __exit imq_cleanup_module(void)\r
++{\r
++ imq_unhook();\r
++ imq_cleanup_devs();\r
++ printk(KERN_INFO "IMQ driver unloaded successfully.\n");\r
++}\r
++\r
++\r
++module_init(imq_init_module);\r
++module_exit(imq_cleanup_module);\r
++\r
++module_param(numdevs, int, 0);\r
++MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");\r
++MODULE_AUTHOR("http://www.linuximq.net");\r
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");\r
++MODULE_LICENSE("GPL");\r
+--- linux-2.6.20.7-original/drivers/net/Kconfig 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/drivers/net/Kconfig 2007-04-19 16:22:34.000000000 +0300\r
+@@ -96,6 +96,129 @@\r
+ To compile this driver as a module, choose M here: the module\r
+ will be called eql. If unsure, say N.\r
+ \r
++config IMQ\r
++ tristate "IMQ (intermediate queueing device) support"\r
++ depends on NETDEVICES && NETFILTER\r
++ ---help---\r
++ The IMQ device(s) is used as placeholder for QoS queueing\r
++ disciplines. Every packet entering/leaving the IP stack can be\r
++ directed through the IMQ device where it's enqueued/dequeued to the\r
++ attached qdisc. This allows you to treat network devices as classes\r
++ and distribute bandwidth among them. Iptables is used to specify\r
++ through which IMQ device, if any, packets travel.\r
++\r
++ More information at: http://www.linuximq.net/\r
++\r
++ To compile this driver as a module, choose M here: the module\r
++ will be called imq. If unsure, say N.\r
++\r
++choice\r
++ prompt "IMQ behavior (PRE/POSTROUTING)"\r
++ depends on IMQ\r
++ default IMQ_BEHAVIOR_AB\r
++ help\r
++\r
++ This settings defines how IMQ behaves in respect to its\r
++ hooking in PREROUTING and POSTROUTING.\r
++\r
++ IMQ can work in any of the following ways:\r
++\r
++ PREROUTING | POSTROUTING\r
++ -----------------|-------------------\r
++ #1 After NAT | After NAT\r
++ #2 After NAT | Before NAT\r
++ #3 Before NAT | After NAT\r
++ #4 Before NAT | Before NAT\r
++\r
++ The default behavior is to hook before NAT on PREROUTING\r
++ and after NAT on POSTROUTING (#3).\r
++\r
++ This settings are specially usefull when trying to use IMQ\r
++ to shape NATed clients.\r
++\r
++ More information can be found at: www.linuximq.net\r
++\r
++ If not sure leave the default settings alone.\r
++\r
++config IMQ_BEHAVIOR_AA\r
++ bool "IMQ AA"\r
++ help\r
++ This settings defines how IMQ behaves in respect to its\r
++ hooking in PREROUTING and POSTROUTING.\r
++\r
++ Choosing this option will make IMQ hook like this:\r
++\r
++ PREROUTING: After NAT\r
++ POSTROUTING: After NAT\r
++\r
++ More information can be found at: www.linuximq.net\r
++\r
++ If not sure leave the default settings alone.\r
++\r
++config IMQ_BEHAVIOR_AB\r
++ bool "IMQ AB"\r
++ help\r
++ This settings defines how IMQ behaves in respect to its\r
++ hooking in PREROUTING and POSTROUTING.\r
++\r
++ Choosing this option will make IMQ hook like this:\r
++\r
++ PREROUTING: After NAT\r
++ POSTROUTING: Before NAT\r
++\r
++ More information can be found at: www.linuximq.net\r
++\r
++ If not sure leave the default settings alone.\r
++\r
++config IMQ_BEHAVIOR_BA\r
++ bool "IMQ BA"\r
++ help\r
++ This settings defines how IMQ behaves in respect to its\r
++ hooking in PREROUTING and POSTROUTING.\r
++\r
++ Choosing this option will make IMQ hook like this:\r
++\r
++ PREROUTING: Before NAT\r
++ POSTROUTING: After NAT\r
++\r
++ More information can be found at: www.linuximq.net\r
++\r
++ If not sure leave the default settings alone.\r
++\r
++config IMQ_BEHAVIOR_BB\r
++ bool "IMQ BB"\r
++ help\r
++ This settings defines how IMQ behaves in respect to its\r
++ hooking in PREROUTING and POSTROUTING.\r
++\r
++ Choosing this option will make IMQ hook like this:\r
++\r
++ PREROUTING: Before NAT\r
++ POSTROUTING: Before NAT\r
++\r
++ More information can be found at: www.linuximq.net\r
++\r
++ If not sure leave the default settings alone.\r
++\r
++endchoice\r
++\r
++config IMQ_NUM_DEVS\r
++\r
++ int "Number of IMQ devices"\r
++ range 2 16\r
++ depends on IMQ\r
++ default "2"\r
++ help\r
++\r
++ This settings defines how many IMQ devices will be \r
++ created.\r
++\r
++ The default value is 2.\r
++\r
++ More information can be found at: www.linuximq.net\r
++\r
++ If not sure leave the default settings alone.\r
++\r
+ config TUN\r
+ tristate "Universal TUN/TAP device driver support"\r
+ select CRC32\r
+--- linux-2.6.20.7-original/drivers/net/Makefile 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/drivers/net/Makefile 2007-04-19 16:22:34.000000000 +0300\r
+@@ -124,6 +124,7 @@\r
+ obj-$(CONFIG_SLHC) += slhc.o\r
+ \r
+ obj-$(CONFIG_DUMMY) += dummy.o\r
++obj-$(CONFIG_IMQ) += imq.o\r
+ obj-$(CONFIG_IFB) += ifb.o\r
+ obj-$(CONFIG_DE600) += de600.o\r
+ obj-$(CONFIG_DE620) += de620.o\r
+--- linux-2.6.20.7-original/include/linux/imq.h 1970-01-01 02:00:00.000000000 +0200\r
++++ linux-2.6.20.7/include/linux/imq.h 2007-04-19 16:22:34.000000000 +0300\r
+@@ -0,0 +1,9 @@\r
++#ifndef _IMQ_H\r
++#define _IMQ_H\r
++\r
++#define IMQ_MAX_DEVS 16\r
++\r
++#define IMQ_F_IFMASK 0x7f\r
++#define IMQ_F_ENQUEUE 0x80\r
++\r
++#endif /* _IMQ_H */\r
+--- linux-2.6.20.7-original/include/linux/netfilter_ipv4/ipt_IMQ.h 1970-01-01 02:00:00.000000000 +0200\r
++++ linux-2.6.20.7/include/linux/netfilter_ipv4/ipt_IMQ.h 2007-04-19 16:22:34.000000000 +0300\r
+@@ -0,0 +1,8 @@\r
++#ifndef _IPT_IMQ_H\r
++#define _IPT_IMQ_H\r
++\r
++struct ipt_imq_info {\r
++ unsigned int todev; /* target imq device */\r
++};\r
++\r
++#endif /* _IPT_IMQ_H */\r
+--- linux-2.6.20.7-original/include/linux/netfilter_ipv6/ip6t_IMQ.h 1970-01-01 02:00:00.000000000 +0200\r
++++ linux-2.6.20.7/include/linux/netfilter_ipv6/ip6t_IMQ.h 2007-04-19 16:22:34.000000000 +0300\r
+@@ -0,0 +1,8 @@\r
++#ifndef _IP6T_IMQ_H\r
++#define _IP6T_IMQ_H\r
++\r
++struct ip6t_imq_info {\r
++ unsigned int todev; /* target imq device */\r
++};\r
++\r
++#endif /* _IP6T_IMQ_H */\r
+--- linux-2.6.20.7-original/include/linux/skbuff.h 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/include/linux/skbuff.h 2007-04-19 16:22:34.000000000 +0300\r
+@@ -294,6 +294,10 @@\r
+ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)\r
+ struct sk_buff *nfct_reasm;\r
+ #endif\r
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)\r
++ unsigned char imq_flags;\r
++ struct nf_info *nf_info;\r
++#endif\r
+ #ifdef CONFIG_BRIDGE_NETFILTER\r
+ struct nf_bridge_info *nf_bridge;\r
+ #endif\r
+--- linux-2.6.20.7-original/net/core/dev.c 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/net/core/dev.c 2007-04-19 16:22:34.000000000 +0300\r
+@@ -94,6 +94,9 @@\r
+ #include <linux/skbuff.h>\r
+ #include <net/sock.h>\r
+ #include <linux/rtnetlink.h>\r
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)\r
++#include <linux/imq.h>\r
++#endif\r
+ #include <linux/proc_fs.h>\r
+ #include <linux/seq_file.h>\r
+ #include <linux/stat.h>\r
+@@ -1343,7 +1346,11 @@\r
+ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)\r
+ {\r
+ if (likely(!skb->next)) {\r
+- if (netdev_nit)\r
++ if (netdev_nit\r
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)\r
++ && !(skb->imq_flags & IMQ_F_ENQUEUE)\r
++#endif\r
++ )\r
+ dev_queue_xmit_nit(skb, dev);\r
+ \r
+ if (netif_needs_gso(dev, skb)) {\r
+--- linux-2.6.20.7-original/net/core/skbuff.c 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/net/core/skbuff.c 2007-04-19 16:22:34.000000000 +0300\r
+@@ -486,6 +486,10 @@\r
+ C(nfct_reasm);\r
+ nf_conntrack_get_reasm(skb->nfct_reasm);\r
+ #endif\r
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)\r
++ C(imq_flags);\r
++ C(nf_info);\r
++#endif /*CONFIG_IMQ*/\r
+ #ifdef CONFIG_BRIDGE_NETFILTER\r
+ C(nf_bridge);\r
+ nf_bridge_get(skb->nf_bridge);\r
+@@ -550,6 +554,10 @@\r
+ #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)\r
+ new->ipvs_property = old->ipvs_property;\r
+ #endif\r
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)\r
++ new->imq_flags = old->imq_flags;\r
++ new->nf_info = old->nf_info;\r
++#endif /*CONFIG_IMQ*/\r
+ #ifdef CONFIG_BRIDGE_NETFILTER\r
+ new->nf_bridge = old->nf_bridge;\r
+ nf_bridge_get(old->nf_bridge);\r
+--- linux-2.6.20.7-original/net/ipv4/netfilter/ipt_IMQ.c 1970-01-01 02:00:00.000000000 +0200\r
++++ linux-2.6.20.7/net/ipv4/netfilter/ipt_IMQ.c 2007-04-19 16:22:34.000000000 +0300\r
+@@ -0,0 +1,71 @@\r
++/*\r
++ * This target marks packets to be enqueued to an imq device\r
++ */\r
++#include <linux/module.h>\r
++#include <linux/skbuff.h>\r
++#include <linux/netfilter_ipv4/ip_tables.h>\r
++#include <linux/netfilter_ipv4/ipt_IMQ.h>\r
++#include <linux/imq.h>\r
++\r
++static unsigned int imq_target(struct sk_buff **pskb,\r
++ const struct net_device *in,\r
++ const struct net_device *out,\r
++ unsigned int hooknum,\r
++ const struct xt_target *target,\r
++ const void *targinfo)\r
++{\r
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;\r
++\r
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;\r
++\r
++ return IPT_CONTINUE;\r
++}\r
++\r
++static int imq_checkentry(const char *tablename,\r
++ const void *e,\r
++ const struct xt_target *target,\r
++ void *targinfo,\r
++ unsigned int hook_mask)\r
++{\r
++ struct ipt_imq_info *mr;\r
++\r
++ mr = (struct ipt_imq_info*)targinfo;\r
++\r
++ if (mr->todev > IMQ_MAX_DEVS) {\r
++ printk(KERN_WARNING\r
++ "IMQ: invalid device specified, highest is %u\n",\r
++ IMQ_MAX_DEVS);\r
++ return 0;\r
++ }\r
++\r
++ return 1;\r
++}\r
++\r
++static struct ipt_target ipt_imq_reg = {\r
++ .name = "IMQ",\r
++ .target = imq_target,\r
++ .targetsize = sizeof(struct ipt_imq_info),\r
++ .checkentry = imq_checkentry,\r
++ .me = THIS_MODULE,\r
++ .table = "mangle"\r
++};\r
++\r
++static int __init init(void)\r
++{\r
++ if (ipt_register_target(&ipt_imq_reg))\r
++ return -EINVAL;\r
++\r
++ return 0;\r
++}\r
++\r
++static void __exit fini(void)\r
++{\r
++ ipt_unregister_target(&ipt_imq_reg);\r
++}\r
++\r
++module_init(init);\r
++module_exit(fini);\r
++\r
++MODULE_AUTHOR("http://www.linuximq.net");\r
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");\r
++MODULE_LICENSE("GPL");\r
+--- linux-2.6.20.7-original/net/ipv4/netfilter/Kconfig 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/net/ipv4/netfilter/Kconfig 2007-04-19 16:22:34.000000000 +0300\r
+@@ -591,6 +591,17 @@\r
+ \r
+ To compile it as a module, choose M here. If unsure, say N.\r
+ \r
++config IP_NF_TARGET_IMQ\r
++ tristate "IMQ target support"\r
++ depends on IP_NF_MANGLE\r
++ help\r
++ This option adds a `IMQ' target which is used to specify if and\r
++ to which IMQ device packets should get enqueued/dequeued.\r
++\r
++ For more information visit: http://www.linuximq.net/\r
++\r
++ To compile it as a module, choose M here. If unsure, say N.\r
++\r
+ config IP_NF_TARGET_TOS\r
+ tristate "TOS target support"\r
+ depends on IP_NF_MANGLE\r
+--- linux-2.6.20.7-original/net/ipv4/netfilter/Makefile 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/net/ipv4/netfilter/Makefile 2007-04-19 16:22:34.000000000 +0300\r
+@@ -96,6 +96,7 @@\r
+ obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o\r
+ obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o\r
+ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o\r
++obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o\r
+ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o\r
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o\r
+ obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o\r
+--- linux-2.6.20.7-original/net/ipv6/netfilter/ip6t_IMQ.c 1970-01-01 02:00:00.000000000 +0200\r
++++ linux-2.6.20.7/net/ipv6/netfilter/ip6t_IMQ.c 2007-04-19 16:22:34.000000000 +0300\r
+@@ -0,0 +1,71 @@\r
++/*\r
++ * This target marks packets to be enqueued to an imq device\r
++ */\r
++#include <linux/module.h>\r
++#include <linux/skbuff.h>\r
++#include <linux/netfilter_ipv6/ip6_tables.h>\r
++#include <linux/netfilter_ipv6/ip6t_IMQ.h>\r
++#include <linux/imq.h>\r
++\r
++static unsigned int imq_target(struct sk_buff **pskb,\r
++ const struct net_device *in,\r
++ const struct net_device *out,\r
++ unsigned int hooknum,\r
++ const struct xt_target *target,\r
++ const void *targinfo)\r
++{\r
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;\r
++\r
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;\r
++\r
++ return IP6T_CONTINUE;\r
++}\r
++\r
++static int imq_checkentry(const char *tablename,\r
++ const void *entry,\r
++ const struct xt_target *target,\r
++ void *targinfo,\r
++ unsigned int hook_mask)\r
++{\r
++ struct ip6t_imq_info *mr;\r
++\r
++ mr = (struct ip6t_imq_info*)targinfo;\r
++\r
++ if (mr->todev > IMQ_MAX_DEVS) {\r
++ printk(KERN_WARNING\r
++ "IMQ: invalid device specified, highest is %u\n",\r
++ IMQ_MAX_DEVS);\r
++ return 0;\r
++ }\r
++\r
++ return 1;\r
++}\r
++\r
++static struct ip6t_target ip6t_imq_reg = {\r
++ .name = "IMQ",\r
++ .target = imq_target,\r
++ .targetsize = sizeof(struct ip6t_imq_info),\r
++ .table = "mangle",\r
++ .checkentry = imq_checkentry,\r
++ .me = THIS_MODULE\r
++};\r
++\r
++static int __init init(void)\r
++{\r
++ if (ip6t_register_target(&ip6t_imq_reg))\r
++ return -EINVAL;\r
++\r
++ return 0;\r
++}\r
++\r
++static void __exit fini(void)\r
++{\r
++ ip6t_unregister_target(&ip6t_imq_reg);\r
++}\r
++\r
++module_init(init);\r
++module_exit(fini);\r
++\r
++MODULE_AUTHOR("http://www.linuximq.net");\r
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");\r
++MODULE_LICENSE("GPL");\r
+--- linux-2.6.20.7-original/net/ipv6/netfilter/Kconfig 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/net/ipv6/netfilter/Kconfig 2007-04-19 16:22:34.000000000 +0300\r
+@@ -164,6 +164,15 @@\r
+ \r
+ To compile it as a module, choose M here. If unsure, say N.\r
+ \r
++config IP6_NF_TARGET_IMQ\r
++ tristate "IMQ target support"\r
++ depends on IP6_NF_MANGLE\r
++ help\r
++ This option adds a `IMQ' target which is used to specify if and\r
++ to which imq device packets should get enqueued/dequeued.\r
++\r
++ To compile it as a module, choose M here. If unsure, say N.\r
++\r
+ config IP6_NF_TARGET_HL\r
+ tristate 'HL (hoplimit) target support'\r
+ depends on IP6_NF_MANGLE\r
+--- linux-2.6.20.7-original/net/ipv6/netfilter/Makefile 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/net/ipv6/netfilter/Makefile 2007-04-19 16:22:34.000000000 +0300\r
+@@ -13,6 +13,7 @@\r
+ obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o\r
+ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o\r
+ obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o\r
++obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o\r
+ obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o\r
+ obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o\r
+ obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o\r
+--- linux-2.6.20.7-original/net/sched/sch_generic.c 2007-04-13 23:48:14.000000000 +0300\r
++++ linux-2.6.20.7/net/sched/sch_generic.c 2007-04-19 16:22:34.000000000 +0300\r
+@@ -87,7 +87,6 @@\r
+ \r
+ NOTE: Called under dev->queue_lock with locally disabled BH.\r
+ */\r
+-\r
+ static inline int qdisc_restart(struct net_device *dev)\r
+ {\r
+ struct Qdisc *q = dev->qdisc;\r
+@@ -181,6 +180,11 @@\r
+ return q->q.qlen;\r
+ }\r
+ \r
++int qdisc_restart1(struct net_device *dev)\r
++{\r
++ return qdisc_restart(dev);\r
++}\r
++\r
+ void __qdisc_run(struct net_device *dev)\r
+ {\r
+ if (unlikely(dev->qdisc == &noop_qdisc))\r
+@@ -617,3 +621,4 @@\r
+ EXPORT_SYMBOL(qdisc_reset);\r
+ EXPORT_SYMBOL(qdisc_lock_tree);\r
+ EXPORT_SYMBOL(qdisc_unlock_tree);\r
++EXPORT_SYMBOL(qdisc_restart1);\r