WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] Remus: IMQ patch for linux-2.6.18-xen.hg

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Remus: IMQ patch for linux-2.6.18-xen.hg
From: Brendan Cully <brendan@xxxxxxxxx>
Date: Thu, 12 Nov 2009 17:13:55 -0800
Cc: andy@xxxxxxxxx
Delivery-date: Thu, 12 Nov 2009 17:17:16 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.3.1+375-2dee9a359262
# HG changeset patch
# User Brendan Cully <brendan@xxxxxxxxx>
# Date 1258048720 28800
# Node ID 54a559a767055a765602f9b525bb5b43c7aae67e
# Parent  c317c41b1ac0d2241b7f40816f34b77bf3b1b168
IMQ allows the network buffer queuing discipline to block inbound
packets from the guest (normal queuing disciplines can only block
outbound packets).

>From http://www.linuximq.net/patchs/linux-2.6.18-imq.diff

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

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel