From 02ec9e701dbea5ad28fe2fcb2279c91b92498510 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 10 Jan 2013 08:56:51 +0000 Subject: [PATCH] --- yaml --- r: 351341 b: refs/heads/master c: 416186fbf8c5b4e4465a10c6ac7a45b6c47144b2 h: refs/heads/master i: 351339: 2ee764b2a195cd7c145c06d6b6b8918b3f1c6629 v: v3 --- [refs] | 2 +- trunk/include/linux/netdevice.h | 1 + trunk/net/core/dev.c | 57 ++++++++++++++++++--------------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/[refs] b/[refs] index f994888500c2..e9ded00dc906 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c10d73671ad30f54692f7f69f0e09e75d3a8926a +refs/heads/master: 416186fbf8c5b4e4465a10c6ac7a45b6c47144b2 diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 0209ac328e8a..608c3ac4d045 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -1403,6 +1403,7 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev, extern struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb); +extern u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb); /* * Net namespace inlines diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 4794cae84939..81ff67149f62 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2495,37 +2495,44 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) #endif } -struct netdev_queue *netdev_pick_tx(struct net_device *dev, - struct sk_buff *skb) +u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) { - int queue_index; - const struct net_device_ops *ops = dev->netdev_ops; - - if (dev->real_num_tx_queues == 1) - queue_index = 0; - else if (ops->ndo_select_queue) { - queue_index = ops->ndo_select_queue(dev, skb); - queue_index = dev_cap_txqueue(dev, queue_index); - } else { - struct sock *sk = skb->sk; - queue_index = sk_tx_queue_get(sk); + struct sock *sk = skb->sk; + int queue_index = sk_tx_queue_get(sk); - if (queue_index < 0 || skb->ooo_okay || - queue_index >= dev->real_num_tx_queues) { - int old_index = queue_index; + if (queue_index < 0 || skb->ooo_okay || + queue_index >= dev->real_num_tx_queues) { + int new_index = get_xps_queue(dev, skb); + if (new_index < 0) + new_index = skb_tx_hash(dev, skb); - queue_index = get_xps_queue(dev, skb); - if (queue_index < 0) - queue_index = skb_tx_hash(dev, skb); - - if (queue_index != old_index && sk) { - struct dst_entry *dst = + if (queue_index != new_index && sk) { + struct dst_entry *dst = rcu_dereference_check(sk->sk_dst_cache, 1); - if (dst && skb_dst(skb) == dst) - sk_tx_queue_set(sk, queue_index); - } + if (dst && skb_dst(skb) == dst) + sk_tx_queue_set(sk, queue_index); + } + + queue_index = new_index; + } + + return queue_index; +} + +struct netdev_queue *netdev_pick_tx(struct net_device *dev, + struct sk_buff *skb) +{ + int queue_index = 0; + + if (dev->real_num_tx_queues != 1) { + const struct net_device_ops *ops = dev->netdev_ops; + if (ops->ndo_select_queue) + queue_index = ops->ndo_select_queue(dev, skb); + else + queue_index = __netdev_pick_tx(dev, skb); + queue_index = dev_cap_txqueue(dev, queue_index); } skb_set_queue_mapping(skb, queue_index);