aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-04-19 17:56:38 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-20 04:18:06 -0400
commitb249dcb82d327e419d3cb45773b146ebb5faf419 (patch)
tree3424eac7e208c03a49ad182685f1ba3c836628b8 /net/core/dev.c
parente36fa2f7e92f25aab2e3d787dcfe3590817f19d3 (diff)
rps: consistent rxhash
In case we compute a software skb->rxhash, we can generate a consistent hash : Its value will be the same in both flow directions. This helps some workloads, like conntracking, since the same state needs to be accessed in both directions. tbench + RFS + this patch gives better results than tbench with default kernel configuration (no RPS, no RFS) Also fixed some sparse warnings. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 7f5755b0a57c..0d78e0454a6d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1974,7 +1974,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
1974 if (skb->sk && skb->sk->sk_hash) 1974 if (skb->sk && skb->sk->sk_hash)
1975 hash = skb->sk->sk_hash; 1975 hash = skb->sk->sk_hash;
1976 else 1976 else
1977 hash = skb->protocol; 1977 hash = (__force u16) skb->protocol;
1978 1978
1979 hash = jhash_1word(hash, hashrnd); 1979 hash = jhash_1word(hash, hashrnd);
1980 1980
@@ -2253,8 +2253,8 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
2253 2253
2254 ip = (struct iphdr *) skb->data; 2254 ip = (struct iphdr *) skb->data;
2255 ip_proto = ip->protocol; 2255 ip_proto = ip->protocol;
2256 addr1 = ip->saddr; 2256 addr1 = (__force u32) ip->saddr;
2257 addr2 = ip->daddr; 2257 addr2 = (__force u32) ip->daddr;
2258 ihl = ip->ihl; 2258 ihl = ip->ihl;
2259 break; 2259 break;
2260 case __constant_htons(ETH_P_IPV6): 2260 case __constant_htons(ETH_P_IPV6):
@@ -2263,8 +2263,8 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
2263 2263
2264 ip6 = (struct ipv6hdr *) skb->data; 2264 ip6 = (struct ipv6hdr *) skb->data;
2265 ip_proto = ip6->nexthdr; 2265 ip_proto = ip6->nexthdr;
2266 addr1 = ip6->saddr.s6_addr32[3]; 2266 addr1 = (__force u32) ip6->saddr.s6_addr32[3];
2267 addr2 = ip6->daddr.s6_addr32[3]; 2267 addr2 = (__force u32) ip6->daddr.s6_addr32[3];
2268 ihl = (40 >> 2); 2268 ihl = (40 >> 2);
2269 break; 2269 break;
2270 default: 2270 default:
@@ -2279,14 +2279,25 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
2279 case IPPROTO_AH: 2279 case IPPROTO_AH:
2280 case IPPROTO_SCTP: 2280 case IPPROTO_SCTP:
2281 case IPPROTO_UDPLITE: 2281 case IPPROTO_UDPLITE:
2282 if (pskb_may_pull(skb, (ihl * 4) + 4)) 2282 if (pskb_may_pull(skb, (ihl * 4) + 4)) {
2283 ports = *((u32 *) (skb->data + (ihl * 4))); 2283 __be16 *hports = (__be16 *) (skb->data + (ihl * 4));
2284 u32 sport, dport;
2285
2286 sport = (__force u16) hports[0];
2287 dport = (__force u16) hports[1];
2288 if (dport < sport)
2289 swap(sport, dport);
2290 ports = (sport << 16) + dport;
2291 }
2284 break; 2292 break;
2285 2293
2286 default: 2294 default:
2287 break; 2295 break;
2288 } 2296 }
2289 2297
2298 /* get a consistent hash (same value on both flow directions) */
2299 if (addr2 < addr1)
2300 swap(addr1, addr2);
2290 skb->rxhash = jhash_3words(addr1, addr2, ports, hashrnd); 2301 skb->rxhash = jhash_3words(addr1, addr2, ports, hashrnd);
2291 if (!skb->rxhash) 2302 if (!skb->rxhash)
2292 skb->rxhash = 1; 2303 skb->rxhash = 1;