Commit cacaddf5 authored by Tommy S. Christensen's avatar Tommy S. Christensen Committed by David S. Miller

[NET]: Disable queueing when carrier is lost.

Some network drivers call netif_stop_queue() when detecting loss of
carrier. This leads to packets being queued up at the qdisc level for
an unbound period of time. In order to prevent this effect, the core
networking stack will now cease to queue packets for any device, that
is operationally down (i.e. the queue is flushed and disabled).
Signed-off-by: default avatarTommy S. Christensen <tommy.christensen@tpack.net>
Acked-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0f4821e7
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/if.h> #include <linux/if.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/pkt_sched.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -74,6 +75,12 @@ void linkwatch_run_queue(void) ...@@ -74,6 +75,12 @@ void linkwatch_run_queue(void)
clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state); clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
if (netif_carrier_ok(dev)) {
WARN_ON(dev->qdisc_sleeping == &noop_qdisc);
dev_activate(dev);
} else
dev_deactivate(dev);
netdev_state_change(dev); netdev_state_change(dev);
} }
......
...@@ -539,6 +539,10 @@ void dev_activate(struct net_device *dev) ...@@ -539,6 +539,10 @@ void dev_activate(struct net_device *dev)
write_unlock_bh(&qdisc_tree_lock); write_unlock_bh(&qdisc_tree_lock);
} }
if (!netif_carrier_ok(dev))
/* Delay activation until next carrier-on event */
return;
spin_lock_bh(&dev->queue_lock); spin_lock_bh(&dev->queue_lock);
rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping); rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping);
if (dev->qdisc != &noqueue_qdisc) { if (dev->qdisc != &noqueue_qdisc) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment