]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-imq.patch
- one accounting system should be enough (xt_ACCOUNT).
[packages/kernel.git] / kernel-imq.patch
CommitLineData
76514441
AM
1diff -uNr linux-2.6.34/drivers/net/imq.c linux-2.6.34-imq/drivers/net/imq.c
2--- linux-2.6.34/drivers/net/imq.c 1970-01-01 02:00:00.000000000 +0200
3+++ linux-2.6.34-imq/drivers/net/imq.c 2010-06-02 10:05:45.752109073 +0300
4@@ -0,0 +1,635 @@
2380c486
JR
5+/*
6+ * Pseudo-driver for the intermediate queue device.
7+ *
8+ * This program is free software; you can redistribute it and/or
9+ * modify it under the terms of the GNU General Public License
10+ * as published by the Free Software Foundation; either version
11+ * 2 of the License, or (at your option) any later version.
12+ *
13+ * Authors: Patrick McHardy, <kaber@trash.net>
14+ *
15+ * The first version was written by Martin Devera, <devik@cdi.cz>
16+ *
17+ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
18+ * - Update patch to 2.4.21
19+ * Sebastian Strollo <sstrollo@nortelnetworks.com>
20+ * - Fix "Dead-loop on netdevice imq"-issue
21+ * Marcel Sebek <sebek64@post.cz>
22+ * - Update to 2.6.2-rc1
23+ *
24+ * After some time of inactivity there is a group taking care
25+ * of IMQ again: http://www.linuximq.net
26+ *
27+ *
28+ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7
29+ * including the following changes:
30+ *
31+ * - Correction of ipv6 support "+"s issue (Hasso Tepper)
32+ * - Correction of imq_init_devs() issue that resulted in
33+ * kernel OOPS unloading IMQ as module (Norbert Buchmuller)
34+ * - Addition of functionality to choose number of IMQ devices
35+ * during kernel config (Andre Correa)
36+ * - Addition of functionality to choose how IMQ hooks on
37+ * PRE and POSTROUTING (after or before NAT) (Andre Correa)
38+ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
39+ *
40+ *
41+ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
42+ * released with almost no problems. 2.6.14-x was released
43+ * with some important changes: nfcache was removed; After
44+ * some weeks of trouble we figured out that some IMQ fields
45+ * in skb were missing in skbuff.c - skb_clone and copy_skb_header.
46+ * These functions are correctly patched by this new patch version.
47+ *
48+ * Thanks for all who helped to figure out all the problems with
49+ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
50+ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
51+ * I didn't forget anybody). I apologize again for my lack of time.
52+ *
53+ *
54+ * 2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead
7f07242b 55+ * of qdisc_restart() and moved qdisc_run() to tasklet to avoid
2380c486
JR
56+ * recursive locking. New initialization routines to fix 'rmmod' not
57+ * working anymore. Used code from ifb.c. (Jussi Kivilinna)
7f07242b 58+ *
59+ * 2008/08/06 - 2.6.26 - (JK)
60+ * - Replaced tasklet with 'netif_schedule()'.
61+ * - Cleaned up and added comments for imq_nf_queue().
62+ *
63+ * 2009/04/12
64+ * - Add skb_save_cb/skb_restore_cb helper functions for backuping
65+ * control buffer. This is needed because qdisc-layer on kernels
66+ * 2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
67+ * - Add better locking for IMQ device. Hopefully this will solve
68+ * SMP issues. (Jussi Kivilinna)
69+ * - Port to 2.6.27
70+ * - Port to 2.6.28
71+ * - Port to 2.6.29 + fix rmmod not working
72+ *
73+ * 2009/04/20 - (Jussi Kivilinna)
74+ * - Use netdevice feature flags to avoid extra packet handling
75+ * by core networking layer and possibly increase performance.
76+ *
14f08cd0 77+ * 2009/09/26 - (Jussi Kivilinna)
78+ * - Add imq_nf_reinject_lockless to fix deadlock with
79+ * imq_nf_queue/imq_nf_reinject.
80+ *
81+ * 2009/12/08 - (Jussi Kivilinna)
82+ * - Port to 2.6.32
83+ * - Add check for skb->nf_queue_entry==NULL in imq_dev_xmit()
84+ * - Also add better error checking for skb->nf_queue_entry usage
85+ *
76514441
AM
86+ * 2010/02/25 - (Jussi Kivilinna)
87+ * - Port to 2.6.33
88+ *
2380c486
JR
89+ * Also, many thanks to pablo Sebastian Greco for making the initial
90+ * patch and to those who helped the testing.
91+ *
92+ * More info at: http://www.linuximq.net/ (Andre Correa)
93+ */
94+
95+#include <linux/module.h>
96+#include <linux/kernel.h>
97+#include <linux/moduleparam.h>
7f07242b 98+#include <linux/list.h>
2380c486
JR
99+#include <linux/skbuff.h>
100+#include <linux/netdevice.h>
7f07242b 101+#include <linux/etherdevice.h>
2380c486
JR
102+#include <linux/rtnetlink.h>
103+#include <linux/if_arp.h>
104+#include <linux/netfilter.h>
105+#include <linux/netfilter_ipv4.h>
106+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
107+ #include <linux/netfilter_ipv6.h>
108+#endif
109+#include <linux/imq.h>
110+#include <net/pkt_sched.h>
111+#include <net/netfilter/nf_queue.h>
112+
2380c486
JR
113+static nf_hookfn imq_nf_hook;
114+
115+static struct nf_hook_ops imq_ingress_ipv4 = {
116+ .hook = imq_nf_hook,
117+ .owner = THIS_MODULE,
118+ .pf = PF_INET,
119+ .hooknum = NF_INET_PRE_ROUTING,
120+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
121+ .priority = NF_IP_PRI_MANGLE + 1
122+#else
123+ .priority = NF_IP_PRI_NAT_DST + 1
124+#endif
125+};
126+
127+static struct nf_hook_ops imq_egress_ipv4 = {
128+ .hook = imq_nf_hook,
129+ .owner = THIS_MODULE,
130+ .pf = PF_INET,
131+ .hooknum = NF_INET_POST_ROUTING,
132+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
133+ .priority = NF_IP_PRI_LAST
134+#else
135+ .priority = NF_IP_PRI_NAT_SRC - 1
136+#endif
137+};
138+
139+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
140+static struct nf_hook_ops imq_ingress_ipv6 = {
141+ .hook = imq_nf_hook,
142+ .owner = THIS_MODULE,
143+ .pf = PF_INET6,
144+ .hooknum = NF_INET_PRE_ROUTING,
145+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
146+ .priority = NF_IP6_PRI_MANGLE + 1
147+#else
148+ .priority = NF_IP6_PRI_NAT_DST + 1
149+#endif
150+};
151+
152+static struct nf_hook_ops imq_egress_ipv6 = {
153+ .hook = imq_nf_hook,
154+ .owner = THIS_MODULE,
155+ .pf = PF_INET6,
156+ .hooknum = NF_INET_POST_ROUTING,
157+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
158+ .priority = NF_IP6_PRI_LAST
159+#else
160+ .priority = NF_IP6_PRI_NAT_SRC - 1
161+#endif
162+};
163+#endif
164+
165+#if defined(CONFIG_IMQ_NUM_DEVS)
166+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
167+#else
168+static unsigned int numdevs = IMQ_MAX_DEVS;
169+#endif
170+
7f07242b 171+static DEFINE_SPINLOCK(imq_nf_queue_lock);
172+
2380c486
JR
173+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
174+
7f07242b 175+
2380c486
JR
176+static struct net_device_stats *imq_get_stats(struct net_device *dev)
177+{
178+ return &dev->stats;
179+}
180+
181+/* called for packets kfree'd in qdiscs at places other than enqueue */
182+static void imq_skb_destructor(struct sk_buff *skb)
183+{
184+ struct nf_queue_entry *entry = skb->nf_queue_entry;
185+
14f08cd0 186+ skb->nf_queue_entry = NULL;
187+
2380c486 188+ if (entry) {
7f07242b 189+ nf_queue_entry_release_refs(entry);
190+ kfree(entry);
191+ }
192+
193+ skb_restore_cb(skb); /* kfree backup */
194+}
195+
14f08cd0 196+/* locking not needed when called from imq_nf_queue */
197+static void imq_nf_reinject_lockless(struct nf_queue_entry *entry,
198+ unsigned int verdict)
199+{
200+ int status;
201+
202+ if (!entry->next_outfn) {
203+ nf_reinject(entry, verdict);
204+ return;
205+ }
206+
207+ status = entry->next_outfn(entry, entry->next_queuenum);
208+ if (status < 0) {
209+ nf_queue_entry_release_refs(entry);
210+ kfree_skb(entry->skb);
211+ kfree(entry);
212+ }
213+}
214+
7f07242b 215+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
216+{
217+ int status;
218+
219+ if (!entry->next_outfn) {
220+ spin_lock_bh(&imq_nf_queue_lock);
221+ nf_reinject(entry, verdict);
222+ spin_unlock_bh(&imq_nf_queue_lock);
223+ return;
224+ }
225+
226+ rcu_read_lock();
227+ local_bh_disable();
228+ status = entry->next_outfn(entry, entry->next_queuenum);
229+ local_bh_enable();
230+ if (status < 0) {
231+ nf_queue_entry_release_refs(entry);
232+ kfree_skb(entry->skb);
2380c486
JR
233+ kfree(entry);
234+ }
7f07242b 235+
236+ rcu_read_unlock();
2380c486
JR
237+}
238+
14f08cd0 239+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
2380c486 240+{
14f08cd0 241+ struct nf_queue_entry *entry = skb->nf_queue_entry;
242+
243+ skb->nf_queue_entry = NULL;
244+ dev->trans_start = jiffies;
245+
2380c486
JR
246+ dev->stats.tx_bytes += skb->len;
247+ dev->stats.tx_packets++;
248+
14f08cd0 249+ if (entry == NULL) {
250+ /* We don't know what is going on here.. packet is queued for
251+ * imq device, but (probably) not by us.
252+ *
253+ * If this packet was not send here by imq_nf_queue(), then
254+ * skb_save_cb() was not used and skb_free() should not show:
255+ * WARNING: IMQ: kfree_skb: skb->cb_next:..
256+ * and/or
257+ * WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
258+ *
259+ * However if this message is shown, then IMQ is somehow broken
260+ * and you should report this to linuximq.net.
261+ */
262+
263+ /* imq_dev_xmit is black hole that eats all packets, report that
264+ * we eat this packet happily and increase dropped counters.
265+ */
266+
267+ dev->stats.tx_dropped++;
268+ dev_kfree_skb(skb);
269+
270+ return NETDEV_TX_OK;
271+ }
272+
273+ skb_restore_cb(skb); /* restore skb->cb */
274+
2380c486
JR
275+ skb->imq_flags = 0;
276+ skb->destructor = NULL;
277+
14f08cd0 278+ imq_nf_reinject(entry, NF_ACCEPT);
7f07242b 279+
14f08cd0 280+ return NETDEV_TX_OK;
2380c486
JR
281+}
282+
283+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
284+{
285+ struct net_device *dev;
7f07242b 286+ struct sk_buff *skb_orig, *skb, *skb_shared;
2380c486 287+ struct Qdisc *q;
7f07242b 288+ struct netdev_queue *txq;
289+ int users, index;
290+ int retval = -EINVAL;
291+
292+ index = entry->skb->imq_flags & IMQ_F_IFMASK;
293+ if (unlikely(index > numdevs - 1)) {
294+ if (net_ratelimit())
295+ printk(KERN_WARNING
296+ "IMQ: invalid device specified, highest is %u\n",
297+ numdevs - 1);
298+ retval = -EINVAL;
299+ goto out;
300+ }
2380c486
JR
301+
302+ /* check for imq device by index from cache */
303+ dev = imq_devs_cache[index];
7f07242b 304+ if (unlikely(!dev)) {
2380c486
JR
305+ char buf[8];
306+
307+ /* get device by name and cache result */
308+ snprintf(buf, sizeof(buf), "imq%d", index);
309+ dev = dev_get_by_name(&init_net, buf);
310+ if (!dev) {
311+ /* not found ?!*/
312+ BUG();
7f07242b 313+ retval = -ENODEV;
314+ goto out;
2380c486
JR
315+ }
316+
317+ imq_devs_cache[index] = dev;
7f07242b 318+ dev_put(dev);
2380c486
JR
319+ }
320+
7f07242b 321+ if (unlikely(!(dev->flags & IFF_UP))) {
2380c486 322+ entry->skb->imq_flags = 0;
14f08cd0 323+ imq_nf_reinject_lockless(entry, NF_ACCEPT);
7f07242b 324+ retval = 0;
325+ goto out;
2380c486
JR
326+ }
327+ dev->last_rx = jiffies;
328+
7f07242b 329+ skb = entry->skb;
330+ skb_orig = NULL;
331+
332+ /* skb has owner? => make clone */
333+ if (unlikely(skb->destructor)) {
334+ skb_orig = skb;
335+ skb = skb_clone(skb, GFP_ATOMIC);
336+ if (!skb) {
337+ retval = -ENOMEM;
338+ goto out;
339+ }
340+ entry->skb = skb;
2380c486 341+ }
2380c486 342+
7f07242b 343+ skb->nf_queue_entry = entry;
344+
345+ dev->stats.rx_bytes += skb->len;
2380c486
JR
346+ dev->stats.rx_packets++;
347+
7f07242b 348+ txq = dev_pick_tx(dev, skb);
2380c486 349+
7f07242b 350+ q = rcu_dereference(txq->qdisc);
351+ if (unlikely(!q->enqueue))
352+ goto packet_not_eaten_by_imq_dev;
2380c486 353+
7f07242b 354+ spin_lock_bh(qdisc_lock(q));
355+
356+ users = atomic_read(&skb->users);
357+
358+ skb_shared = skb_get(skb); /* increase reference count by one */
359+ skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
360+ overwrite it */
361+ qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
362+
363+ if (likely(atomic_read(&skb_shared->users) == users + 1)) {
364+ kfree_skb(skb_shared); /* decrease reference count by one */
365+
366+ skb->destructor = &imq_skb_destructor;
367+
368+ /* cloned? */
369+ if (skb_orig)
370+ kfree_skb(skb_orig); /* free original */
371+
372+ spin_unlock_bh(qdisc_lock(q));
373+
374+ /* schedule qdisc dequeue */
375+ __netif_schedule(q);
376+
377+ retval = 0;
378+ goto out;
379+ } else {
380+ skb_restore_cb(skb_shared); /* restore skb->cb */
14f08cd0 381+ skb->nf_queue_entry = NULL;
7f07242b 382+ /* qdisc dropped packet and decreased skb reference count of
383+ * skb, so we don't really want to and try refree as that would
384+ * actually destroy the skb. */
385+ spin_unlock_bh(qdisc_lock(q));
386+ goto packet_not_eaten_by_imq_dev;
387+ }
388+
389+packet_not_eaten_by_imq_dev:
390+ /* cloned? restore original */
391+ if (skb_orig) {
392+ kfree_skb(skb);
393+ entry->skb = skb_orig;
394+ }
395+ retval = -1;
396+out:
397+ return retval;
2380c486
JR
398+}
399+
400+static struct nf_queue_handler nfqh = {
401+ .name = "imq",
402+ .outfn = imq_nf_queue,
403+};
404+
2380c486
JR
405+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
406+ const struct net_device *indev,
407+ const struct net_device *outdev,
408+ int (*okfn)(struct sk_buff *))
409+{
410+ if (pskb->imq_flags & IMQ_F_ENQUEUE)
411+ return NF_QUEUE;
412+
413+ return NF_ACCEPT;
414+}
415+
416+static int imq_close(struct net_device *dev)
417+{
2380c486 418+ netif_stop_queue(dev);
2380c486
JR
419+ return 0;
420+}
421+
422+static int imq_open(struct net_device *dev)
423+{
2380c486 424+ netif_start_queue(dev);
2380c486
JR
425+ return 0;
426+}
427+
7f07242b 428+static const struct net_device_ops imq_netdev_ops = {
429+ .ndo_open = imq_open,
430+ .ndo_stop = imq_close,
431+ .ndo_start_xmit = imq_dev_xmit,
432+ .ndo_get_stats = imq_get_stats,
433+};
434+
2380c486
JR
435+static void imq_setup(struct net_device *dev)
436+{
7f07242b 437+ dev->netdev_ops = &imq_netdev_ops;
2380c486
JR
438+ dev->type = ARPHRD_VOID;
439+ dev->mtu = 16000;
440+ dev->tx_queue_len = 11000;
441+ dev->flags = IFF_NOARP;
7f07242b 442+ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
443+ NETIF_F_GSO | NETIF_F_HW_CSUM |
444+ NETIF_F_HIGHDMA;
14f08cd0 445+ dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
7f07242b 446+}
447+
448+static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
449+{
450+ int ret = 0;
451+
452+ if (tb[IFLA_ADDRESS]) {
453+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
454+ ret = -EINVAL;
455+ goto end;
456+ }
457+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
458+ ret = -EADDRNOTAVAIL;
459+ goto end;
460+ }
461+ }
462+ return 0;
463+end:
464+ printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
465+ return ret;
2380c486
JR
466+}
467+
468+static struct rtnl_link_ops imq_link_ops __read_mostly = {
469+ .kind = "imq",
7f07242b 470+ .priv_size = 0,
2380c486 471+ .setup = imq_setup,
7f07242b 472+ .validate = imq_validate,
2380c486
JR
473+};
474+
475+static int __init imq_init_hooks(void)
476+{
477+ int err;
478+
7f07242b 479+ nf_register_queue_imq_handler(&nfqh);
2380c486
JR
480+
481+ err = nf_register_hook(&imq_ingress_ipv4);
482+ if (err)
7f07242b 483+ goto err1;
2380c486
JR
484+
485+ err = nf_register_hook(&imq_egress_ipv4);
486+ if (err)
7f07242b 487+ goto err2;
2380c486
JR
488+
489+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2380c486
JR
490+ err = nf_register_hook(&imq_ingress_ipv6);
491+ if (err)
7f07242b 492+ goto err3;
2380c486
JR
493+
494+ err = nf_register_hook(&imq_egress_ipv6);
495+ if (err)
7f07242b 496+ goto err4;
2380c486
JR
497+#endif
498+
499+ return 0;
500+
501+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2380c486 502+err4:
7f07242b 503+ nf_unregister_hook(&imq_ingress_ipv6);
504+err3:
2380c486
JR
505+ nf_unregister_hook(&imq_egress_ipv4);
506+#endif
2380c486 507+err2:
7f07242b 508+ nf_unregister_hook(&imq_ingress_ipv4);
2380c486 509+err1:
7f07242b 510+ nf_unregister_queue_imq_handler();
2380c486
JR
511+ return err;
512+}
513+
514+static int __init imq_init_one(int index)
515+{
516+ struct net_device *dev;
517+ int ret;
518+
7f07242b 519+ dev = alloc_netdev(0, "imq%d", imq_setup);
2380c486
JR
520+ if (!dev)
521+ return -ENOMEM;
522+
523+ ret = dev_alloc_name(dev, dev->name);
524+ if (ret < 0)
525+ goto fail;
526+
527+ dev->rtnl_link_ops = &imq_link_ops;
528+ ret = register_netdevice(dev);
529+ if (ret < 0)
530+ goto fail;
531+
532+ return 0;
533+fail:
534+ free_netdev(dev);
535+ return ret;
536+}
537+
538+static int __init imq_init_devs(void)
539+{
540+ int err, i;
541+
7f07242b 542+ if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
2380c486
JR
543+ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
544+ IMQ_MAX_DEVS);
545+ return -EINVAL;
546+ }
547+
548+ rtnl_lock();
549+ err = __rtnl_link_register(&imq_link_ops);
550+
551+ for (i = 0; i < numdevs && !err; i++)
552+ err = imq_init_one(i);
553+
554+ if (err) {
555+ __rtnl_link_unregister(&imq_link_ops);
556+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
557+ }
558+ rtnl_unlock();
559+
560+ return err;
561+}
562+
563+static int __init imq_init_module(void)
564+{
565+ int err;
566+
7f07242b 567+#if defined(CONFIG_IMQ_NUM_DEVS)
568+ BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
569+ BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
570+ BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
571+#endif
572+
2380c486
JR
573+ err = imq_init_devs();
574+ if (err) {
575+ printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
576+ return err;
577+ }
578+
579+ err = imq_init_hooks();
580+ if (err) {
581+ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
582+ rtnl_link_unregister(&imq_link_ops);
583+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
584+ return err;
585+ }
586+
587+ printk(KERN_INFO "IMQ driver loaded successfully.\n");
588+
589+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
590+ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
591+#else
592+ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
593+#endif
594+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
595+ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
596+#else
597+ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
598+#endif
599+
600+ return 0;
601+}
602+
603+static void __exit imq_unhook(void)
604+{
605+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
606+ nf_unregister_hook(&imq_ingress_ipv6);
607+ nf_unregister_hook(&imq_egress_ipv6);
2380c486
JR
608+#endif
609+ nf_unregister_hook(&imq_ingress_ipv4);
610+ nf_unregister_hook(&imq_egress_ipv4);
7f07242b 611+
612+ nf_unregister_queue_imq_handler();
2380c486
JR
613+}
614+
615+static void __exit imq_cleanup_devs(void)
616+{
617+ rtnl_link_unregister(&imq_link_ops);
618+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
619+}
620+
621+static void __exit imq_exit_module(void)
622+{
623+ imq_unhook();
624+ imq_cleanup_devs();
625+ printk(KERN_INFO "IMQ driver unloaded successfully.\n");
626+}
627+
628+module_init(imq_init_module);
629+module_exit(imq_exit_module);
630+
631+module_param(numdevs, int, 0);
632+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
633+ "be created)");
634+MODULE_AUTHOR("http://www.linuximq.net");
635+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
636+ "http://www.linuximq.net/ for more information.");
637+MODULE_LICENSE("GPL");
638+MODULE_ALIAS_RTNL_LINK("imq");
639+
76514441
AM
640diff -uNr linux-2.6.34/drivers/net/Kconfig linux-2.6.34-imq/drivers/net/Kconfig
641--- linux-2.6.34/drivers/net/Kconfig 2010-05-17 00:17:36.000000000 +0300
642+++ linux-2.6.34-imq/drivers/net/Kconfig 2010-06-02 10:05:45.752109073 +0300
643@@ -121,6 +121,129 @@
2380c486
JR
644 To compile this driver as a module, choose M here: the module
645 will be called eql. If unsure, say N.
646
647+config IMQ
648+ tristate "IMQ (intermediate queueing device) support"
649+ depends on NETDEVICES && NETFILTER
650+ ---help---
651+ The IMQ device(s) is used as placeholder for QoS queueing
652+ disciplines. Every packet entering/leaving the IP stack can be
653+ directed through the IMQ device where it's enqueued/dequeued to the
654+ attached qdisc. This allows you to treat network devices as classes
655+ and distribute bandwidth among them. Iptables is used to specify
656+ through which IMQ device, if any, packets travel.
657+
658+ More information at: http://www.linuximq.net/
659+
660+ To compile this driver as a module, choose M here: the module
661+ will be called imq. If unsure, say N.
662+
663+choice
664+ prompt "IMQ behavior (PRE/POSTROUTING)"
665+ depends on IMQ
666+ default IMQ_BEHAVIOR_AB
667+ help
668+
669+ This settings defines how IMQ behaves in respect to its
670+ hooking in PREROUTING and POSTROUTING.
671+
672+ IMQ can work in any of the following ways:
673+
674+ PREROUTING | POSTROUTING
675+ -----------------|-------------------
676+ #1 After NAT | After NAT
677+ #2 After NAT | Before NAT
678+ #3 Before NAT | After NAT
679+ #4 Before NAT | Before NAT
680+
681+ The default behavior is to hook before NAT on PREROUTING
682+ and after NAT on POSTROUTING (#3).
683+
684+ This settings are specially usefull when trying to use IMQ
685+ to shape NATed clients.
686+
687+ More information can be found at: www.linuximq.net
688+
689+ If not sure leave the default settings alone.
690+
691+config IMQ_BEHAVIOR_AA
692+ bool "IMQ AA"
693+ help
694+ This settings defines how IMQ behaves in respect to its
695+ hooking in PREROUTING and POSTROUTING.
696+
697+ Choosing this option will make IMQ hook like this:
698+
699+ PREROUTING: After NAT
700+ POSTROUTING: After NAT
701+
702+ More information can be found at: www.linuximq.net
703+
704+ If not sure leave the default settings alone.
705+
706+config IMQ_BEHAVIOR_AB
707+ bool "IMQ AB"
708+ help
709+ This settings defines how IMQ behaves in respect to its
710+ hooking in PREROUTING and POSTROUTING.
711+
712+ Choosing this option will make IMQ hook like this:
713+
714+ PREROUTING: After NAT
715+ POSTROUTING: Before NAT
716+
717+ More information can be found at: www.linuximq.net
718+
719+ If not sure leave the default settings alone.
720+
721+config IMQ_BEHAVIOR_BA
722+ bool "IMQ BA"
723+ help
724+ This settings defines how IMQ behaves in respect to its
725+ hooking in PREROUTING and POSTROUTING.
726+
727+ Choosing this option will make IMQ hook like this:
728+
729+ PREROUTING: Before NAT
730+ POSTROUTING: After NAT
731+
732+ More information can be found at: www.linuximq.net
733+
734+ If not sure leave the default settings alone.
735+
736+config IMQ_BEHAVIOR_BB
737+ bool "IMQ BB"
738+ help
739+ This settings defines how IMQ behaves in respect to its
740+ hooking in PREROUTING and POSTROUTING.
741+
742+ Choosing this option will make IMQ hook like this:
743+
744+ PREROUTING: Before NAT
745+ POSTROUTING: Before NAT
746+
747+ More information can be found at: www.linuximq.net
748+
749+ If not sure leave the default settings alone.
750+
751+endchoice
752+
753+config IMQ_NUM_DEVS
754+
755+ int "Number of IMQ devices"
756+ range 2 16
757+ depends on IMQ
758+ default "16"
759+ help
760+
761+ This settings defines how many IMQ devices will be
762+ created.
763+
764+ The default value is 16.
765+
766+ More information can be found at: www.linuximq.net
767+
768+ If not sure leave the default settings alone.
769+
770 config TUN
771 tristate "Universal TUN/TAP device driver support"
772 select CRC32
76514441
AM
773diff -uNr linux-2.6.34/drivers/net/Makefile linux-2.6.34-imq/drivers/net/Makefile
774--- linux-2.6.34/drivers/net/Makefile 2010-05-17 00:17:36.000000000 +0300
775+++ linux-2.6.34-imq/drivers/net/Makefile 2010-06-02 10:05:45.752109073 +0300
776@@ -169,6 +169,7 @@
2380c486
JR
777 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
778
779 obj-$(CONFIG_DUMMY) += dummy.o
780+obj-$(CONFIG_IMQ) += imq.o
781 obj-$(CONFIG_IFB) += ifb.o
782 obj-$(CONFIG_MACVLAN) += macvlan.o
d031c9d6 783 obj-$(CONFIG_MACVTAP) += macvtap.o
76514441
AM
784diff -uNr linux-2.6.34/include/linux/imq.h linux-2.6.34-imq/include/linux/imq.h
785--- linux-2.6.34/include/linux/imq.h 1970-01-01 02:00:00.000000000 +0200
786+++ linux-2.6.34-imq/include/linux/imq.h 2010-06-02 10:05:45.752109073 +0300
7f07242b 787@@ -0,0 +1,13 @@
2380c486
JR
788+#ifndef _IMQ_H
789+#define _IMQ_H
790+
7f07242b 791+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
792+#define IMQ_F_BITS 5
793+
794+#define IMQ_F_IFMASK 0x0f
795+#define IMQ_F_ENQUEUE 0x10
2380c486 796+
7f07242b 797+#define IMQ_MAX_DEVS (IMQ_F_IFMASK + 1)
2380c486
JR
798+
799+#endif /* _IMQ_H */
2380c486 800+
76514441
AM
801diff -uNr linux-2.6.34/include/linux/netdevice.h linux-2.6.34-imq/include/linux/netdevice.h
802--- linux-2.6.34/include/linux/netdevice.h 2010-05-17 00:17:36.000000000 +0300
803+++ linux-2.6.34-imq/include/linux/netdevice.h 2010-06-02 10:05:45.752109073 +0300
804@@ -1203,6 +1203,7 @@
7f07242b 805 extern int dev_open(struct net_device *dev);
806 extern int dev_close(struct net_device *dev);
807 extern void dev_disable_lro(struct net_device *dev);
808+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
809 extern int dev_queue_xmit(struct sk_buff *skb);
810 extern int register_netdevice(struct net_device *dev);
5379d87d 811 extern void unregister_netdevice_queue(struct net_device *dev,
76514441
AM
812diff -uNr linux-2.6.34/include/linux/netfilter/xt_IMQ.h linux-2.6.34-imq/include/linux/netfilter/xt_IMQ.h
813--- linux-2.6.34/include/linux/netfilter/xt_IMQ.h 1970-01-01 02:00:00.000000000 +0200
814+++ linux-2.6.34-imq/include/linux/netfilter/xt_IMQ.h 2010-06-02 10:05:45.752109073 +0300
7f07242b 815@@ -0,0 +1,9 @@
816+#ifndef _XT_IMQ_H
817+#define _XT_IMQ_H
818+
819+struct xt_imq_info {
2380c486
JR
820+ unsigned int todev; /* target imq device */
821+};
822+
7f07242b 823+#endif /* _XT_IMQ_H */
824+
76514441
AM
825diff -uNr linux-2.6.34/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.6.34-imq/include/linux/netfilter_ipv4/ipt_IMQ.h
826--- linux-2.6.34/include/linux/netfilter_ipv4/ipt_IMQ.h 1970-01-01 02:00:00.000000000 +0200
827+++ linux-2.6.34-imq/include/linux/netfilter_ipv4/ipt_IMQ.h 2010-06-02 10:05:45.752109073 +0300
7f07242b 828@@ -0,0 +1,10 @@
829+#ifndef _IPT_IMQ_H
830+#define _IPT_IMQ_H
831+
832+/* Backwards compatibility for old userspace */
833+#include <linux/netfilter/xt_IMQ.h>
834+
835+#define ipt_imq_info xt_imq_info
836+
2380c486 837+#endif /* _IPT_IMQ_H */
7f07242b 838+
76514441
AM
839diff -uNr linux-2.6.34/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.6.34-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h
840--- linux-2.6.34/include/linux/netfilter_ipv6/ip6t_IMQ.h 1970-01-01 02:00:00.000000000 +0200
841+++ linux-2.6.34-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h 2010-06-02 10:05:45.752109073 +0300
7f07242b 842@@ -0,0 +1,10 @@
2380c486
JR
843+#ifndef _IP6T_IMQ_H
844+#define _IP6T_IMQ_H
845+
7f07242b 846+/* Backwards compatibility for old userspace */
847+#include <linux/netfilter/xt_IMQ.h>
848+
849+#define ip6t_imq_info xt_imq_info
2380c486
JR
850+
851+#endif /* _IP6T_IMQ_H */
7f07242b 852+
76514441
AM
853diff -uNr linux-2.6.34/include/linux/skbuff.h linux-2.6.34-imq/include/linux/skbuff.h
854--- linux-2.6.34/include/linux/skbuff.h 2010-05-17 00:17:36.000000000 +0300
855+++ linux-2.6.34-imq/include/linux/skbuff.h 2010-06-02 10:05:45.752109073 +0300
856@@ -29,6 +29,9 @@
7f07242b 857 #include <linux/rcupdate.h>
858 #include <linux/dmaengine.h>
859 #include <linux/hrtimer.h>
860+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
861+#include <linux/imq.h>
862+#endif
863
14f08cd0 864 /* Don't change this without changing skb_csum_unnecessary! */
865 #define CHECKSUM_NONE 0
76514441 866@@ -321,6 +324,9 @@
7f07242b 867 * first. This is owned by whoever has the skb queued ATM.
868 */
ca0faea1 869 char cb[48] __aligned(8);
7f07242b 870+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
871+ void *cb_next;
872+#endif
873
ca0faea1
AM
874 unsigned long _skb_dst;
875 #ifdef CONFIG_XFRM
76514441 876@@ -357,6 +363,9 @@
2380c486
JR
877 struct nf_conntrack *nfct;
878 struct sk_buff *nfct_reasm;
879 #endif
880+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
2380c486
JR
881+ struct nf_queue_entry *nf_queue_entry;
882+#endif
883 #ifdef CONFIG_BRIDGE_NETFILTER
884 struct nf_bridge_info *nf_bridge;
885 #endif
76514441 886@@ -378,6 +387,10 @@
14f08cd0 887
7e46296a 888 /* 0/14 bit hole */
14f08cd0 889
7f07242b 890+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
891+ __u8 imq_flags:IMQ_F_BITS;
892+#endif
14f08cd0 893+
7f07242b 894 #ifdef CONFIG_NET_DMA
895 dma_cookie_t dma_cookie;
7f07242b 896 #endif
76514441 897@@ -426,6 +439,12 @@
14f08cd0 898 return (struct rtable *)skb_dst(skb);
899 }
7f07242b 900
901+
902+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
903+extern int skb_save_cb(struct sk_buff *skb);
904+extern int skb_restore_cb(struct sk_buff *skb);
905+#endif
906+
907 extern void kfree_skb(struct sk_buff *skb);
14f08cd0 908 extern void consume_skb(struct sk_buff *skb);
7f07242b 909 extern void __kfree_skb(struct sk_buff *skb);
76514441 910@@ -1970,6 +1989,10 @@
2380c486
JR
911 dst->nfct_reasm = src->nfct_reasm;
912 nf_conntrack_get_reasm(src->nfct_reasm);
913 #endif
914+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
915+ dst->imq_flags = src->imq_flags;
916+ dst->nf_queue_entry = src->nf_queue_entry;
917+#endif
918 #ifdef CONFIG_BRIDGE_NETFILTER
919 dst->nf_bridge = src->nf_bridge;
920 nf_bridge_get(src->nf_bridge);
76514441
AM
921diff -uNr linux-2.6.34/include/net/netfilter/nf_queue.h linux-2.6.34-imq/include/net/netfilter/nf_queue.h
922--- linux-2.6.34/include/net/netfilter/nf_queue.h 2010-05-17 00:17:36.000000000 +0300
923+++ linux-2.6.34-imq/include/net/netfilter/nf_queue.h 2010-06-02 10:05:45.752109073 +0300
924@@ -13,6 +13,12 @@
7f07242b 925 struct net_device *indev;
926 struct net_device *outdev;
927 int (*okfn)(struct sk_buff *);
928+
929+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
930+ int (*next_outfn)(struct nf_queue_entry *entry,
931+ unsigned int queuenum);
932+ unsigned int next_queuenum;
933+#endif
934 };
935
936 #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
76514441 937@@ -30,5 +36,11 @@
7f07242b 938 const struct nf_queue_handler *qh);
939 extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
940 extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
941+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
942+
943+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
944+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
945+extern void nf_unregister_queue_imq_handler(void);
946+#endif
947
948 #endif /* _NF_QUEUE_H */
76514441
AM
949diff -uNr linux-2.6.34/net/core/dev.c linux-2.6.34-imq/net/core/dev.c
950--- linux-2.6.34/net/core/dev.c 2010-05-17 00:17:36.000000000 +0300
951+++ linux-2.6.34-imq/net/core/dev.c 2010-06-02 10:05:45.752109073 +0300
952@@ -98,6 +98,9 @@
2380c486
JR
953 #include <net/net_namespace.h>
954 #include <net/sock.h>
955 #include <linux/rtnetlink.h>
956+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
957+#include <linux/imq.h>
958+#endif
959 #include <linux/proc_fs.h>
960 #include <linux/seq_file.h>
961 #include <linux/stat.h>
76514441 962@@ -1859,7 +1862,11 @@
5379d87d 963 int rc = NETDEV_TX_OK;
7f07242b 964
2380c486
JR
965 if (likely(!skb->next)) {
966- if (!list_empty(&ptype_all))
967+ if (!list_empty(&ptype_all)
968+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
76514441 969+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
2380c486 970+#endif
76514441 971+ )
2380c486
JR
972 dev_queue_xmit_nit(skb, dev);
973
974 if (netif_needs_gso(dev, skb)) {
76514441 975@@ -1969,8 +1976,7 @@
5379d87d 976 return queue_index;
7f07242b 977 }
978
979-static struct netdev_queue *dev_pick_tx(struct net_device *dev,
76514441
AM
980- struct sk_buff *skb)
981+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
7f07242b 982 {
5379d87d 983 u16 queue_index;
76514441
AM
984 struct sock *sk = skb->sk;
985@@ -2000,6 +2006,7 @@
7f07242b 986 skb_set_queue_mapping(skb, queue_index);
987 return netdev_get_tx_queue(dev, queue_index);
988 }
989+EXPORT_SYMBOL(dev_pick_tx);
990
14f08cd0 991 static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
992 struct net_device *dev,
76514441
AM
993diff -uNr linux-2.6.34/net/core/skbuff.c linux-2.6.34-imq/net/core/skbuff.c
994--- linux-2.6.34/net/core/skbuff.c 2010-05-17 00:17:36.000000000 +0300
995+++ linux-2.6.34-imq/net/core/skbuff.c 2010-06-02 10:05:45.752109073 +0300
996@@ -72,6 +72,9 @@
7f07242b 997
998 static struct kmem_cache *skbuff_head_cache __read_mostly;
999 static struct kmem_cache *skbuff_fclone_cache __read_mostly;
1000+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1001+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
1002+#endif
1003
1004 static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
1005 struct pipe_buffer *buf)
76514441 1006@@ -91,6 +94,83 @@
7f07242b 1007 return 1;
1008 }
1009
1010+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1011+/* Control buffer save/restore for IMQ devices */
1012+struct skb_cb_table {
1013+ void *cb_next;
1014+ atomic_t refcnt;
1015+ char cb[48];
1016+};
2380c486 1017+
7f07242b 1018+static DEFINE_SPINLOCK(skb_cb_store_lock);
1019+
1020+int skb_save_cb(struct sk_buff *skb)
2380c486 1021+{
7f07242b 1022+ struct skb_cb_table *next;
1023+
1024+ next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
1025+ if (!next)
1026+ return -ENOMEM;
2380c486 1027+
7f07242b 1028+ BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
2380c486 1029+
7f07242b 1030+ memcpy(next->cb, skb->cb, sizeof(skb->cb));
1031+ next->cb_next = skb->cb_next;
1032+
1033+ atomic_set(&next->refcnt, 1);
1034+
1035+ skb->cb_next = next;
1036+ return 0;
2380c486 1037+}
7f07242b 1038+EXPORT_SYMBOL(skb_save_cb);
2380c486 1039+
7f07242b 1040+int skb_restore_cb(struct sk_buff *skb)
2380c486 1041+{
7f07242b 1042+ struct skb_cb_table *next;
2380c486 1043+
7f07242b 1044+ if (!skb->cb_next)
2380c486 1045+ return 0;
7f07242b 1046+
1047+ next = skb->cb_next;
1048+
1049+ BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
1050+
1051+ memcpy(skb->cb, next->cb, sizeof(skb->cb));
1052+ skb->cb_next = next->cb_next;
1053+
1054+ spin_lock(&skb_cb_store_lock);
1055+
1056+ if (atomic_dec_and_test(&next->refcnt)) {
1057+ kmem_cache_free(skbuff_cb_store_cache, next);
2380c486
JR
1058+ }
1059+
7f07242b 1060+ spin_unlock(&skb_cb_store_lock);
1061+
1062+ return 0;
2380c486 1063+}
7f07242b 1064+EXPORT_SYMBOL(skb_restore_cb);
2380c486 1065+
14f08cd0 1066+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
7f07242b 1067+{
1068+ struct skb_cb_table *next;
14f08cd0 1069+ struct sk_buff *old;
7f07242b 1070+
14f08cd0 1071+ if (!__old->cb_next) {
1072+ new->cb_next = NULL;
7f07242b 1073+ return;
1074+ }
1075+
1076+ spin_lock(&skb_cb_store_lock);
1077+
14f08cd0 1078+ old = (struct sk_buff *)__old;
1079+
7f07242b 1080+ next = old->cb_next;
1081+ atomic_inc(&next->refcnt);
1082+ new->cb_next = next;
1083+
1084+ spin_unlock(&skb_cb_store_lock);
1085+}
1086+#endif
1087
1088 /* Pipe buffer operations for a socket. */
5379d87d 1089 static const struct pipe_buf_operations sock_pipe_buf_ops = {
76514441 1090@@ -398,6 +478,26 @@
7f07242b 1091 WARN_ON(in_irq());
1092 skb->destructor(skb);
1093 }
1094+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1095+ /* This should not happen. When it does, avoid memleak by restoring
1096+ the chain of cb-backups. */
1097+ while(skb->cb_next != NULL) {
14f08cd0 1098+ if (net_ratelimit())
1099+ printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: "
1100+ "%08x\n", (unsigned int)skb->cb_next);
1101+
7f07242b 1102+ skb_restore_cb(skb);
1103+ }
14f08cd0 1104+ /* This should not happen either, nf_queue_entry is nullified in
1105+ * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
1106+ * leaking entry pointers, maybe memory. We don't know if this is
1107+ * pointer to already freed memory, or should this be freed.
1108+ * If this happens we need to add refcounting, etc for nf_queue_entry.
1109+ */
1110+ if (skb->nf_queue_entry && net_ratelimit())
1111+ printk(KERN_WARNING
1112+ "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
7f07242b 1113+#endif
1114 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
1115 nf_conntrack_put(skb->nfct);
1116 nf_conntrack_put_reasm(skb->nfct_reasm);
76514441 1117@@ -538,6 +638,9 @@
7f07242b 1118 new->sp = secpath_get(old->sp);
1119 #endif
1120 memcpy(new->cb, old->cb, sizeof(old->cb));
1121+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1122+ skb_copy_stored_cb(new, old);
1123+#endif
13e5c3b1 1124 new->csum = old->csum;
7f07242b 1125 new->local_df = old->local_df;
13e5c3b1 1126 new->pkt_type = old->pkt_type;
76514441 1127@@ -2779,6 +2882,13 @@
7f07242b 1128 0,
1129 SLAB_HWCACHE_ALIGN|SLAB_PANIC,
1130 NULL);
1131+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1132+ skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
1133+ sizeof(struct skb_cb_table),
1134+ 0,
1135+ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
1136+ NULL);
1137+#endif
1138 }
1139
1140 /**
76514441
AM
1141diff -uNr linux-2.6.34/net/netfilter/Kconfig linux-2.6.34-imq/net/netfilter/Kconfig
1142--- linux-2.6.34/net/netfilter/Kconfig 2010-05-17 00:17:36.000000000 +0300
1143+++ linux-2.6.34-imq/net/netfilter/Kconfig 2010-06-02 10:05:45.762097870 +0300
1144@@ -421,6 +421,18 @@
14f08cd0 1145 For more information on the LEDs available on your system, see
1146 Documentation/leds-class.txt
7f07242b 1147
1148+config NETFILTER_XT_TARGET_IMQ
1149+ tristate '"IMQ" target support'
1150+ depends on NETFILTER_XTABLES
1151+ depends on IP_NF_MANGLE || IP6_NF_MANGLE
1152+ select IMQ
1153+ default m if NETFILTER_ADVANCED=n
1154+ help
1155+ This option adds a `IMQ' target which is used to specify if and
1156+ to which imq device packets should get enqueued/dequeued.
2380c486 1157+
7f07242b 1158+ To compile it as a module, choose M here. If unsure, say N.
1159+
1160 config NETFILTER_XT_TARGET_MARK
1161 tristate '"MARK" target support'
1162 default m if NETFILTER_ADVANCED=n
76514441
AM
1163diff -uNr linux-2.6.34/net/netfilter/Makefile linux-2.6.34-imq/net/netfilter/Makefile
1164--- linux-2.6.34/net/netfilter/Makefile 2010-05-17 00:17:36.000000000 +0300
1165+++ linux-2.6.34-imq/net/netfilter/Makefile 2010-06-02 10:05:45.762097870 +0300
1166@@ -47,6 +47,7 @@
d031c9d6 1167 obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
7f07242b 1168 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
1169 obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
7f07242b 1170+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
14f08cd0 1171 obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
7f07242b 1172 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
1173 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
76514441
AM
1174diff -uNr linux-2.6.34/net/netfilter/nf_queue.c linux-2.6.34-imq/net/netfilter/nf_queue.c
1175--- linux-2.6.34/net/netfilter/nf_queue.c 2010-05-17 00:17:36.000000000 +0300
1176+++ linux-2.6.34-imq/net/netfilter/nf_queue.c 2010-06-02 10:05:45.762097870 +0300
1177@@ -21,6 +21,26 @@
7f07242b 1178
1179 static DEFINE_MUTEX(queue_handler_mutex);
1180
1181+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1182+static const struct nf_queue_handler *queue_imq_handler;
1183+
1184+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
2380c486 1185+{
7f07242b 1186+ mutex_lock(&queue_handler_mutex);
1187+ rcu_assign_pointer(queue_imq_handler, qh);
1188+ mutex_unlock(&queue_handler_mutex);
2380c486 1189+}
7f07242b 1190+EXPORT_SYMBOL(nf_register_queue_imq_handler);
2380c486 1191+
7f07242b 1192+void nf_unregister_queue_imq_handler(void)
2380c486 1193+{
7f07242b 1194+ mutex_lock(&queue_handler_mutex);
1195+ rcu_assign_pointer(queue_imq_handler, NULL);
1196+ mutex_unlock(&queue_handler_mutex);
2380c486 1197+}
7f07242b 1198+EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
1199+#endif
2380c486 1200+
7f07242b 1201 /* return EBUSY when somebody else is registered, return EEXIST if the
1202 * same handler is registered, return 0 in case of success. */
1203 int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
76514441 1204@@ -81,7 +101,7 @@
7f07242b 1205 }
1206 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
1207
1208-static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
1209+void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
1210 {
1211 /* Release those devices we held, or Alexey will kill me. */
1212 if (entry->indev)
76514441 1213@@ -101,6 +121,7 @@
7f07242b 1214 /* Drop reference to owner of hook which queued us. */
1215 module_put(entry->elem->owner);
1216 }
1217+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
1218
1219 /*
1220 * Any packet that leaves via this function must come back
76514441 1221@@ -122,12 +143,26 @@
7f07242b 1222 #endif
1223 const struct nf_afinfo *afinfo;
1224 const struct nf_queue_handler *qh;
1225+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1226+ const struct nf_queue_handler *qih = NULL;
1227+#endif
1228
1229 /* QUEUE == DROP if noone is waiting, to be safe. */
1230 rcu_read_lock();
1231
1232 qh = rcu_dereference(queue_handler[pf]);
1233+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1234+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1235+ if (pf == PF_INET || pf == PF_INET6)
1236+#else
1237+ if (pf == PF_INET)
1238+#endif
1239+ qih = rcu_dereference(queue_imq_handler);
2380c486 1240+
7f07242b 1241+ if (!qh && !qih)
1242+#else /* !IMQ */
1243 if (!qh)
1244+#endif
1245 goto err_unlock;
2380c486 1246
7f07242b 1247 afinfo = nf_get_afinfo(pf);
76514441 1248@@ -146,6 +181,10 @@
7f07242b 1249 .indev = indev,
1250 .outdev = outdev,
1251 .okfn = okfn,
1252+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1253+ .next_outfn = qh ? qh->outfn : NULL,
1254+ .next_queuenum = queuenum,
1255+#endif
1256 };
2380c486 1257
7f07242b 1258 /* If it's going away, ignore hook. */
76514441 1259@@ -171,8 +210,19 @@
7f07242b 1260 }
1261 #endif
1262 afinfo->saveroute(skb, entry);
1263+
1264+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1265+ if (qih) {
1266+ status = qih->outfn(entry, queuenum);
1267+ goto imq_skip_queue;
1268+ }
1269+#endif
1270+
1271 status = qh->outfn(entry, queuenum);
1272
1273+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1274+imq_skip_queue:
1275+#endif
1276 rcu_read_unlock();
1277
1278 if (status < 0) {
76514441
AM
1279diff -uNr linux-2.6.34/net/netfilter/xt_IMQ.c linux-2.6.34-imq/net/netfilter/xt_IMQ.c
1280--- linux-2.6.34/net/netfilter/xt_IMQ.c 1970-01-01 02:00:00.000000000 +0200
1281+++ linux-2.6.34-imq/net/netfilter/xt_IMQ.c 2010-06-02 10:05:45.762097870 +0300
7f07242b 1282@@ -0,0 +1,73 @@
2380c486
JR
1283+/*
1284+ * This target marks packets to be enqueued to an imq device
1285+ */
1286+#include <linux/module.h>
1287+#include <linux/skbuff.h>
7f07242b 1288+#include <linux/netfilter/x_tables.h>
1289+#include <linux/netfilter/xt_IMQ.h>
2380c486
JR
1290+#include <linux/imq.h>
1291+
1292+static unsigned int imq_target(struct sk_buff *pskb,
7f07242b 1293+ const struct xt_target_param *par)
2380c486 1294+{
7f07242b 1295+ const struct xt_imq_info *mr = par->targinfo;
2380c486 1296+
7f07242b 1297+ pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
2380c486
JR
1298+
1299+ return XT_CONTINUE;
1300+}
1301+
7f07242b 1302+static bool imq_checkentry(const struct xt_tgchk_param *par)
2380c486 1303+{
7f07242b 1304+ struct xt_imq_info *mr = par->targinfo;
2380c486 1305+
7f07242b 1306+ if (mr->todev > IMQ_MAX_DEVS - 1) {
2380c486
JR
1307+ printk(KERN_WARNING
1308+ "IMQ: invalid device specified, highest is %u\n",
7f07242b 1309+ IMQ_MAX_DEVS - 1);
2380c486
JR
1310+ return 0;
1311+ }
1312+
1313+ return 1;
1314+}
1315+
7f07242b 1316+static struct xt_target xt_imq_reg[] __read_mostly = {
1317+ {
1318+ .name = "IMQ",
1319+ .family = AF_INET,
1320+ .checkentry = imq_checkentry,
1321+ .target = imq_target,
1322+ .targetsize = sizeof(struct xt_imq_info),
1323+ .table = "mangle",
1324+ .me = THIS_MODULE
1325+ },
1326+ {
1327+ .name = "IMQ",
1328+ .family = AF_INET6,
1329+ .checkentry = imq_checkentry,
1330+ .target = imq_target,
1331+ .targetsize = sizeof(struct xt_imq_info),
1332+ .table = "mangle",
1333+ .me = THIS_MODULE
1334+ },
2380c486
JR
1335+};
1336+
7f07242b 1337+static int __init imq_init(void)
2380c486 1338+{
7f07242b 1339+ return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
2380c486
JR
1340+}
1341+
7f07242b 1342+static void __exit imq_fini(void)
2380c486 1343+{
7f07242b 1344+ xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
2380c486
JR
1345+}
1346+
7f07242b 1347+module_init(imq_init);
1348+module_exit(imq_fini);
2380c486
JR
1349+
1350+MODULE_AUTHOR("http://www.linuximq.net");
1351+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
1352+MODULE_LICENSE("GPL");
7f07242b 1353+MODULE_ALIAS("ipt_IMQ");
1354+MODULE_ALIAS("ip6t_IMQ");
2380c486 1355+
This page took 0.329038 seconds and 4 git commands to generate.