diff options
author | Felix Fietkau <nbd@openwrt.org> | 2009-02-21 16:33:24 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2009-02-21 16:33:24 +0000 |
commit | 0e461e45dbd71b34ab409034b3c09520aeaea431 (patch) | |
tree | f7744aedcd15d214c9c505e6e7db05aa61fbf179 | |
parent | 2fc5d9bb16e2c15a0c454533e26b019b48ec6d58 (diff) | |
download | upstream-0e461e45dbd71b34ab409034b3c09520aeaea431.tar.gz upstream-0e461e45dbd71b34ab409034b3c09520aeaea431.tar.bz2 upstream-0e461e45dbd71b34ab409034b3c09520aeaea431.zip |
fix IMQ on linux 2.6.27 and 2.6.28
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@14599 3c298f89-4303-0410-b956-a3cf2f4a3e73
3 files changed, 190 insertions, 1 deletions
diff --git a/package/kernel/modules/netfilter.mk b/package/kernel/modules/netfilter.mk index d757b9e976..5817595649 100644 --- a/package/kernel/modules/netfilter.mk +++ b/package/kernel/modules/netfilter.mk @@ -237,7 +237,7 @@ define KernelPackage/ipt-imq imq \ $(IPT_IMQ-m) \ )) - DEPENDS:= kmod-ipt-core @!LINUX_2_6_27 @!LINUX_2_6_28 + DEPENDS:= kmod-ipt-core endef define KernelPackage/ipt-imq/description diff --git a/target/linux/generic-2.6/patches-2.6.27/151-netfilter_imq_2.6.27.patch b/target/linux/generic-2.6/patches-2.6.27/151-netfilter_imq_2.6.27.patch new file mode 100644 index 0000000000..9390db7424 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.27/151-netfilter_imq_2.6.27.patch @@ -0,0 +1,75 @@ +--- a/drivers/net/imq.c ++++ b/drivers/net/imq.c +@@ -178,10 +178,11 @@ static int imq_nf_queue(struct nf_queue_ + struct sk_buff *skb2 = NULL; + struct Qdisc *q; + unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK; +- int ret = -1; ++ struct netdev_queue *txq; ++ int ret = -EINVAL; + + if (index > numdevs) +- return -1; ++ return ret; + + /* check for imq device by index from cache */ + dev = imq_devs_cache[index]; +@@ -194,7 +195,7 @@ static int imq_nf_queue(struct nf_queue_ + if (!dev) { + /* not found ?!*/ + BUG(); +- return -1; ++ return ret; + } + + imq_devs_cache[index] = dev; +@@ -212,17 +213,19 @@ static int imq_nf_queue(struct nf_queue_ + skb2 = entry->skb; + entry->skb = skb_clone(entry->skb, GFP_ATOMIC); + if (!entry->skb) +- return -1; ++ return -ENOMEM; + } + entry->skb->nf_queue_entry = entry; + + dev->stats.rx_bytes += entry->skb->len; + dev->stats.rx_packets++; + +- spin_lock_bh(&dev->queue_lock); +- q = dev->qdisc; ++ txq = netdev_get_tx_queue(dev, 0); ++ __netif_tx_lock_bh(txq); ++ q = txq->qdisc; ++ + if (q->enqueue) { +- q->enqueue(skb_get(entry->skb), q); ++ qdisc_enqueue_root(skb_get(entry->skb), q); + if (skb_shared(entry->skb)) { + entry->skb->destructor = imq_skb_destructor; + kfree_skb(entry->skb); +@@ -231,7 +234,7 @@ static int imq_nf_queue(struct nf_queue_ + } + if (!test_and_set_bit(1, &priv->tasklet_pending)) + tasklet_schedule(&priv->tasklet); +- spin_unlock_bh(&dev->queue_lock); ++ __netif_tx_unlock_bh(txq); + + if (skb2) + kfree_skb(ret ? entry->skb : skb2); +@@ -248,11 +251,13 @@ static void qdisc_run_tasklet(unsigned l + { + struct net_device *dev = (struct net_device *)arg; + struct imq_private *priv = netdev_priv(dev); ++ struct netdev_queue *txq; + +- spin_lock(&dev->queue_lock); +- qdisc_run(dev); ++ netif_tx_lock(dev); ++ txq = netdev_get_tx_queue(dev, 0); ++ qdisc_run(txq->qdisc); + clear_bit(1, &priv->tasklet_pending); +- spin_unlock(&dev->queue_lock); ++ netif_tx_unlock(dev); + } + + static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, diff --git a/target/linux/generic-2.6/patches-2.6.28/151-netfilter_imq_2.6.28.patch b/target/linux/generic-2.6/patches-2.6.28/151-netfilter_imq_2.6.28.patch new file mode 100644 index 0000000000..c531042444 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.28/151-netfilter_imq_2.6.28.patch @@ -0,0 +1,114 @@ +--- a/drivers/net/imq.c ++++ b/drivers/net/imq.c +@@ -178,10 +178,11 @@ static int imq_nf_queue(struct nf_queue_ + struct sk_buff *skb2 = NULL; + struct Qdisc *q; + unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK; +- int ret = -1; ++ struct netdev_queue *txq; ++ int ret = -EINVAL; + + if (index > numdevs) +- return -1; ++ return ret; + + /* check for imq device by index from cache */ + dev = imq_devs_cache[index]; +@@ -194,7 +195,7 @@ static int imq_nf_queue(struct nf_queue_ + if (!dev) { + /* not found ?!*/ + BUG(); +- return -1; ++ return ret; + } + + imq_devs_cache[index] = dev; +@@ -212,17 +213,19 @@ static int imq_nf_queue(struct nf_queue_ + skb2 = entry->skb; + entry->skb = skb_clone(entry->skb, GFP_ATOMIC); + if (!entry->skb) +- return -1; ++ return -ENOMEM; + } + entry->skb->nf_queue_entry = entry; + + dev->stats.rx_bytes += entry->skb->len; + dev->stats.rx_packets++; + +- spin_lock_bh(&dev->queue_lock); +- q = dev->qdisc; ++ txq = netdev_get_tx_queue(dev, 0); ++ __netif_tx_lock_bh(txq); ++ q = txq->qdisc; ++ + if (q->enqueue) { +- q->enqueue(skb_get(entry->skb), q); ++ qdisc_enqueue_root(skb_get(entry->skb), q); + if (skb_shared(entry->skb)) { + entry->skb->destructor = imq_skb_destructor; + kfree_skb(entry->skb); +@@ -231,7 +234,7 @@ static int imq_nf_queue(struct nf_queue_ + } + if (!test_and_set_bit(1, &priv->tasklet_pending)) + tasklet_schedule(&priv->tasklet); +- spin_unlock_bh(&dev->queue_lock); ++ __netif_tx_unlock_bh(txq); + + if (skb2) + kfree_skb(ret ? entry->skb : skb2); +@@ -248,11 +253,13 @@ static void qdisc_run_tasklet(unsigned l + { + struct net_device *dev = (struct net_device *)arg; + struct imq_private *priv = netdev_priv(dev); ++ struct netdev_queue *txq; + +- spin_lock(&dev->queue_lock); +- qdisc_run(dev); ++ netif_tx_lock(dev); ++ txq = netdev_get_tx_queue(dev, 0); ++ qdisc_run(txq->qdisc); + clear_bit(1, &priv->tasklet_pending); +- spin_unlock(&dev->queue_lock); ++ netif_tx_unlock(dev); + } + + static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, +--- a/net/ipv4/netfilter/ipt_IMQ.c ++++ b/net/ipv4/netfilter/ipt_IMQ.c +@@ -7,29 +7,23 @@ + #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) ++static unsigned int ++imq_target(struct sk_buff *pskb, ++ const struct xt_target_param *par) + { +- struct ipt_imq_info *mr = (struct ipt_imq_info *)targinfo; ++ struct ipt_imq_info *mr = (struct ipt_imq_info *)par->targinfo; + + pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; + + return XT_CONTINUE; + } + +-static bool imq_checkentry(const char *tablename, +- const void *e, +- const struct xt_target *target, +- void *targinfo, +- unsigned int hook_mask) ++static bool ++imq_checkentry(const struct xt_tgchk_param *par) + { + struct ipt_imq_info *mr; + +- mr = (struct ipt_imq_info *)targinfo; ++ mr = (struct ipt_imq_info *)par->targinfo; + + if (mr->todev > IMQ_MAX_DEVS) { + printk(KERN_WARNING |