diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-08-04 10:26:03 +1000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-08-04 10:26:03 +1000 |
commit | 412a4ac5e9cf7fdeb6af562c25547a9b9da7674f (patch) | |
tree | a8ce13cbc9c47c99799e5e3e3ad26ba78274ee73 /net/core/dev.c | |
parent | e8e5c2155b0035b6e04f29be67f6444bc914005b (diff) | |
parent | 0c2daaafcdec726e89cbccca61d576de8429c537 (diff) |
Merge commit 'gcl/next' into next
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 723a34710ad..0ea10f849be 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1911,8 +1911,16 @@ static int dev_gso_segment(struct sk_buff *skb) */ static inline void skb_orphan_try(struct sk_buff *skb) { - if (!skb_tx(skb)->flags) + struct sock *sk = skb->sk; + + if (sk && !skb_tx(skb)->flags) { + /* skb_tx_hash() wont be able to get sk. + * We copy sk_hash into skb->rxhash + */ + if (!skb->rxhash) + skb->rxhash = sk->sk_hash; skb_orphan(skb); + } } int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, @@ -1998,8 +2006,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) if (skb->sk && skb->sk->sk_hash) hash = skb->sk->sk_hash; else - hash = (__force u16) skb->protocol; - + hash = (__force u16) skb->protocol ^ skb->rxhash; hash = jhash_1word(hash, hashrnd); return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); @@ -2022,12 +2029,11 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) static struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb) { - u16 queue_index; + int queue_index; struct sock *sk = skb->sk; - if (sk_tx_queue_recorded(sk)) { - queue_index = sk_tx_queue_get(sk); - } else { + queue_index = sk_tx_queue_get(sk); + if (queue_index < 0) { const struct net_device_ops *ops = dev->netdev_ops; if (ops->ndo_select_queue) { |