fix IMQ on linux 2.6.27 and 2.6.28
authorFelix Fietkau <nbd@openwrt.org>
Sat, 21 Feb 2009 16:33:24 +0000 (16:33 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 21 Feb 2009 16:33:24 +0000 (16:33 +0000)
SVN-Revision: 14599

package/kernel/modules/netfilter.mk
target/linux/generic-2.6/patches-2.6.27/151-netfilter_imq_2.6.27.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.28/151-netfilter_imq_2.6.28.patch [new file with mode: 0644]

index d757b9e..5817595 100644 (file)
@@ -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 (file)
index 0000000..9390db7
--- /dev/null
@@ -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 (file)
index 0000000..c531042
--- /dev/null
@@ -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