summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2008-09-20 22:05:50 -0700
committerDavid S. Miller <davem@davemloft.net>2008-09-20 22:05:50 -0700
commitad55dcaff0e34269f86975ce2ea0da22e9eb74a1 (patch)
tree9fdf5c6c3feaf0197e684eab9eb84b4333284962
parente7272403d2f9be3dbb7cc185fcc390e781b1af6b (diff)
downloadlinux-3.10-ad55dcaff0e34269f86975ce2ea0da22e9eb74a1.tar.gz
linux-3.10-ad55dcaff0e34269f86975ce2ea0da22e9eb74a1.tar.bz2
linux-3.10-ad55dcaff0e34269f86975ce2ea0da22e9eb74a1.zip
netdev: simple_tx_hash shouldn't hash inside fragments
Currently simple_tx_hash is hashing inside of udp fragments. As a result packets are getting getting sent to all queues when they shouldn't be. This causes a serious performance regression which can be seen by sending UDP frames larger than mtu on multiqueue devices. This change will make it so that fragments are hashed only as IP datagrams w/o any protocol information. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/dev.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index e719ed29310..e8eb2b47834 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -122,6 +122,7 @@
#include <linux/if_arp.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
+#include <net/ip.h>
#include <linux/ipv6.h>
#include <linux/in.h>
#include <linux/jhash.h>
@@ -1667,7 +1668,7 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
{
u32 addr1, addr2, ports;
u32 hash, ihl;
- u8 ip_proto;
+ u8 ip_proto = 0;
if (unlikely(!simple_tx_hashrnd_initialized)) {
get_random_bytes(&simple_tx_hashrnd, 4);
@@ -1676,7 +1677,8 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
switch (skb->protocol) {
case __constant_htons(ETH_P_IP):
- ip_proto = ip_hdr(skb)->protocol;
+ if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)))
+ ip_proto = ip_hdr(skb)->protocol;
addr1 = ip_hdr(skb)->saddr;
addr2 = ip_hdr(skb)->daddr;
ihl = ip_hdr(skb)->ihl;