net: check the return value of ndo_select_queue()
authorEric Dumazet <eric.dumazet@gmail.com>
Fri, 13 Nov 2009 21:54:04 +0000 (21:54 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Nov 2009 06:08:05 +0000 (22:08 -0800)
Check the return value of ndo_select_queue(). If the value isn't smaller
than the real_num_tx_queues, print a warning message, and reset it to zero.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
----
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/dev.c

index 548340b..32045df 100644 (file)
@@ -1848,6 +1848,20 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(skb_tx_hash);
 
+static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
+{
+       if (unlikely(queue_index >= dev->real_num_tx_queues)) {
+               if (net_ratelimit()) {
+                       WARN(1, "%s selects TX queue %d, but "
+                            "real number of TX queues is %d\n",
+                            dev->name, queue_index,
+                            dev->real_num_tx_queues);
+               }
+               return 0;
+       }
+       return queue_index;
+}
+
 static struct netdev_queue *dev_pick_tx(struct net_device *dev,
                                        struct sk_buff *skb)
 {
@@ -1861,6 +1875,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
 
                if (ops->ndo_select_queue) {
                        queue_index = ops->ndo_select_queue(dev, skb);
+                       queue_index = dev_cap_txqueue(dev, queue_index);
                } else {
                        queue_index = 0;
                        if (dev->real_num_tx_queues > 1)