]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/core/dev.c
net: add a recursion limit in xmit path
[net-next-2.6.git] / net / core / dev.c
index 48ad47f402ad1de8297a8c29ef4954f9e4cb8d9e..50daccad6a53a01a628c09e5f6109ac9961fc8cf 100644 (file)
@@ -2177,6 +2177,9 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
        return rc;
 }
 
+static DEFINE_PER_CPU(int, xmit_recursion);
+#define RECURSION_LIMIT 3
+
 /**
  *     dev_queue_xmit - transmit a buffer
  *     @skb: buffer to transmit
@@ -2242,10 +2245,15 @@ int dev_queue_xmit(struct sk_buff *skb)
 
                if (txq->xmit_lock_owner != cpu) {
 
+                       if (__this_cpu_read(xmit_recursion) > RECURSION_LIMIT)
+                               goto recursion_alert;
+
                        HARD_TX_LOCK(dev, txq, cpu);
 
                        if (!netif_tx_queue_stopped(txq)) {
+                               __this_cpu_inc(xmit_recursion);
                                rc = dev_hard_start_xmit(skb, dev, txq);
+                               __this_cpu_dec(xmit_recursion);
                                if (dev_xmit_complete(rc)) {
                                        HARD_TX_UNLOCK(dev, txq);
                                        goto out;
@@ -2257,7 +2265,9 @@ int dev_queue_xmit(struct sk_buff *skb)
                                       "queue packet!\n", dev->name);
                } else {
                        /* Recursion is detected! It is possible,
-                        * unfortunately */
+                        * unfortunately
+                        */
+recursion_alert:
                        if (net_ratelimit())
                                printk(KERN_CRIT "Dead loop on virtual device "
                                       "%s, fix it urgently!\n", dev->name);