aboutsummaryrefslogtreecommitdiff
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-07-20 16:26:42 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-07-20 16:26:42 -0700
commit516bd664153d76f5c814633cee6500e2ff8e861b (patch)
treef67a1c70b013961849d3491ef22596cd0b0d9af9 /net/core/dev.c
parent844b9a8707f1fcf0482e0c52f44a555e799ccda6 (diff)
parent573201f36fd9c7c6d5218cdcd9948cee700b277d (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (24 commits) bridge: Partially disable netpoll support tcp: fix crash in tcp_xmit_retransmit_queue IPv6: fix CoA check in RH2 input handler (mip6_rthdr_input()) ibmveth: lost IRQ while closing/opening device leads to service loss rt2x00: Fix lockdep warning in rt2x00lib_probe_dev() vhost: avoid pr_err on condition guest can trigger ipmr: Don't leak memory if fib lookup fails. vhost-net: avoid flush under lock net: fix problem in reading sock TX queue net/core: neighbour update Oops net: skb_tx_hash() fix relative to skb_orphan_try() rfs: call sock_rps_record_flow() in tcp_splice_read() xfrm: do not assume that template resolving always returns xfrms hostap_pci: set dev->base_addr during probe axnet_cs: use spin_lock_irqsave in ax_interrupt dsa: Fix Kconfig dependencies. act_nat: not all of the ICMP packets need an IP header payload r8169: incorrect identifier for a 8168dp Phonet: fix skb leak in pipe endpoint accept() Bluetooth: Update sec_level/auth_type for already existing connections ...
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c20
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) {