diff options
-rw-r--r-- | include/net/ip.h | 14 | ||||
-rw-r--r-- | include/net/ipv6.h | 15 | ||||
-rw-r--r-- | include/net/sock.h | 11 | ||||
-rw-r--r-- | net/ipv4/datagram.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 1 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 1 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 4 |
8 files changed, 50 insertions, 0 deletions
diff --git a/include/net/ip.h b/include/net/ip.h index 0e795df05ec9..2e8f055989c3 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <net/route.h> | 31 | #include <net/route.h> |
32 | #include <net/snmp.h> | 32 | #include <net/snmp.h> |
33 | #include <net/flow.h> | 33 | #include <net/flow.h> |
34 | #include <net/flow_keys.h> | ||
34 | 35 | ||
35 | struct sock; | 36 | struct sock; |
36 | 37 | ||
@@ -353,6 +354,19 @@ static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto) | |||
353 | skb->len, proto, 0); | 354 | skb->len, proto, 0); |
354 | } | 355 | } |
355 | 356 | ||
357 | static inline void inet_set_txhash(struct sock *sk) | ||
358 | { | ||
359 | struct inet_sock *inet = inet_sk(sk); | ||
360 | struct flow_keys keys; | ||
361 | |||
362 | keys.src = inet->inet_saddr; | ||
363 | keys.dst = inet->inet_daddr; | ||
364 | keys.port16[0] = inet->inet_sport; | ||
365 | keys.port16[1] = inet->inet_dport; | ||
366 | |||
367 | sk->sk_txhash = flow_hash_from_keys(&keys); | ||
368 | } | ||
369 | |||
356 | /* | 370 | /* |
357 | * Map a multicast IP onto multicast MAC for type ethernet. | 371 | * Map a multicast IP onto multicast MAC for type ethernet. |
358 | */ | 372 | */ |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 574337fe72dd..2aa86e1135a1 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <net/if_inet6.h> | 19 | #include <net/if_inet6.h> |
20 | #include <net/ndisc.h> | 20 | #include <net/ndisc.h> |
21 | #include <net/flow.h> | 21 | #include <net/flow.h> |
22 | #include <net/flow_keys.h> | ||
22 | #include <net/snmp.h> | 23 | #include <net/snmp.h> |
23 | 24 | ||
24 | #define SIN6_LEN_RFC2133 24 | 25 | #define SIN6_LEN_RFC2133 24 |
@@ -684,6 +685,20 @@ static inline int ip6_sk_dst_hoplimit(struct ipv6_pinfo *np, struct flowi6 *fl6, | |||
684 | return hlimit; | 685 | return hlimit; |
685 | } | 686 | } |
686 | 687 | ||
688 | static inline void ip6_set_txhash(struct sock *sk) | ||
689 | { | ||
690 | struct inet_sock *inet = inet_sk(sk); | ||
691 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
692 | struct flow_keys keys; | ||
693 | |||
694 | keys.src = (__force __be32)ipv6_addr_hash(&np->saddr); | ||
695 | keys.dst = (__force __be32)ipv6_addr_hash(&sk->sk_v6_daddr); | ||
696 | keys.port16[0] = inet->inet_sport; | ||
697 | keys.port16[1] = inet->inet_dport; | ||
698 | |||
699 | sk->sk_txhash = flow_hash_from_keys(&keys); | ||
700 | } | ||
701 | |||
687 | /* | 702 | /* |
688 | * Header manipulation | 703 | * Header manipulation |
689 | */ | 704 | */ |
diff --git a/include/net/sock.h b/include/net/sock.h index 8d4c9473e7d7..cb84b2f1ad8f 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -273,6 +273,7 @@ struct cg_proto; | |||
273 | * @sk_rcvtimeo: %SO_RCVTIMEO setting | 273 | * @sk_rcvtimeo: %SO_RCVTIMEO setting |
274 | * @sk_sndtimeo: %SO_SNDTIMEO setting | 274 | * @sk_sndtimeo: %SO_SNDTIMEO setting |
275 | * @sk_rxhash: flow hash received from netif layer | 275 | * @sk_rxhash: flow hash received from netif layer |
276 | * @sk_txhash: computed flow hash for use on transmit | ||
276 | * @sk_filter: socket filtering instructions | 277 | * @sk_filter: socket filtering instructions |
277 | * @sk_protinfo: private area, net family specific, when not using slab | 278 | * @sk_protinfo: private area, net family specific, when not using slab |
278 | * @sk_timer: sock cleanup timer | 279 | * @sk_timer: sock cleanup timer |
@@ -347,6 +348,7 @@ struct sock { | |||
347 | #ifdef CONFIG_RPS | 348 | #ifdef CONFIG_RPS |
348 | __u32 sk_rxhash; | 349 | __u32 sk_rxhash; |
349 | #endif | 350 | #endif |
351 | __u32 sk_txhash; | ||
350 | #ifdef CONFIG_NET_RX_BUSY_POLL | 352 | #ifdef CONFIG_NET_RX_BUSY_POLL |
351 | unsigned int sk_napi_id; | 353 | unsigned int sk_napi_id; |
352 | unsigned int sk_ll_usec; | 354 | unsigned int sk_ll_usec; |
@@ -1980,6 +1982,14 @@ static inline void sock_poll_wait(struct file *filp, | |||
1980 | } | 1982 | } |
1981 | } | 1983 | } |
1982 | 1984 | ||
1985 | static inline void skb_set_hash_from_sk(struct sk_buff *skb, struct sock *sk) | ||
1986 | { | ||
1987 | if (sk->sk_txhash) { | ||
1988 | skb->l4_hash = 1; | ||
1989 | skb->hash = sk->sk_txhash; | ||
1990 | } | ||
1991 | } | ||
1992 | |||
1983 | /* | 1993 | /* |
1984 | * Queue a received datagram if it will fit. Stream and sequenced | 1994 | * Queue a received datagram if it will fit. Stream and sequenced |
1985 | * protocols can't normally use this as they need to fit buffers in | 1995 | * protocols can't normally use this as they need to fit buffers in |
@@ -1994,6 +2004,7 @@ static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | |||
1994 | skb_orphan(skb); | 2004 | skb_orphan(skb); |
1995 | skb->sk = sk; | 2005 | skb->sk = sk; |
1996 | skb->destructor = sock_wfree; | 2006 | skb->destructor = sock_wfree; |
2007 | skb_set_hash_from_sk(skb, sk); | ||
1997 | /* | 2008 | /* |
1998 | * We used to take a refcount on sk, but following operation | 2009 | * We used to take a refcount on sk, but following operation |
1999 | * is enough to guarantee sk_free() wont free this sock until | 2010 | * is enough to guarantee sk_free() wont free this sock until |
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index a3095fdefbed..90c0e8386116 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c | |||
@@ -76,6 +76,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
76 | inet->inet_daddr = fl4->daddr; | 76 | inet->inet_daddr = fl4->daddr; |
77 | inet->inet_dport = usin->sin_port; | 77 | inet->inet_dport = usin->sin_port; |
78 | sk->sk_state = TCP_ESTABLISHED; | 78 | sk->sk_state = TCP_ESTABLISHED; |
79 | inet_set_txhash(sk); | ||
79 | inet->inet_id = jiffies; | 80 | inet->inet_id = jiffies; |
80 | 81 | ||
81 | sk_dst_set(sk, &rt->dst); | 82 | sk_dst_set(sk, &rt->dst); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 52d0f6a1ec2c..1edc739b9da5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -208,6 +208,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
208 | inet->inet_dport = usin->sin_port; | 208 | inet->inet_dport = usin->sin_port; |
209 | inet->inet_daddr = daddr; | 209 | inet->inet_daddr = daddr; |
210 | 210 | ||
211 | inet_set_txhash(sk); | ||
212 | |||
211 | inet_csk(sk)->icsk_ext_hdr_len = 0; | 213 | inet_csk(sk)->icsk_ext_hdr_len = 0; |
212 | if (inet_opt) | 214 | if (inet_opt) |
213 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; | 215 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
@@ -1334,6 +1336,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1334 | newinet->mc_ttl = ip_hdr(skb)->ttl; | 1336 | newinet->mc_ttl = ip_hdr(skb)->ttl; |
1335 | newinet->rcv_tos = ip_hdr(skb)->tos; | 1337 | newinet->rcv_tos = ip_hdr(skb)->tos; |
1336 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 1338 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
1339 | inet_set_txhash(newsk); | ||
1337 | if (inet_opt) | 1340 | if (inet_opt) |
1338 | inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; | 1341 | inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
1339 | newinet->inet_id = newtp->write_seq ^ jiffies; | 1342 | newinet->inet_id = newtp->write_seq ^ jiffies; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f8f2a944a1ce..bcee13c4627c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -916,6 +916,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
916 | skb_orphan(skb); | 916 | skb_orphan(skb); |
917 | skb->sk = sk; | 917 | skb->sk = sk; |
918 | skb->destructor = tcp_wfree; | 918 | skb->destructor = tcp_wfree; |
919 | skb_set_hash_from_sk(skb, sk); | ||
919 | atomic_add(skb->truesize, &sk->sk_wmem_alloc); | 920 | atomic_add(skb->truesize, &sk->sk_wmem_alloc); |
920 | 921 | ||
921 | /* Build TCP header and checksum it. */ | 922 | /* Build TCP header and checksum it. */ |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index c3bf2d2e519e..2753319524f1 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -199,6 +199,7 @@ ipv4_connected: | |||
199 | NULL); | 199 | NULL); |
200 | 200 | ||
201 | sk->sk_state = TCP_ESTABLISHED; | 201 | sk->sk_state = TCP_ESTABLISHED; |
202 | ip6_set_txhash(sk); | ||
202 | out: | 203 | out: |
203 | fl6_sock_release(flowlabel); | 204 | fl6_sock_release(flowlabel); |
204 | return err; | 205 | return err; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index a97c95585da8..22055b098428 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -198,6 +198,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
198 | sk->sk_v6_daddr = usin->sin6_addr; | 198 | sk->sk_v6_daddr = usin->sin6_addr; |
199 | np->flow_label = fl6.flowlabel; | 199 | np->flow_label = fl6.flowlabel; |
200 | 200 | ||
201 | ip6_set_txhash(sk); | ||
202 | |||
201 | /* | 203 | /* |
202 | * TCP over IPv4 | 204 | * TCP over IPv4 |
203 | */ | 205 | */ |
@@ -1132,6 +1134,8 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1132 | newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; | 1134 | newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; |
1133 | newsk->sk_bound_dev_if = ireq->ir_iif; | 1135 | newsk->sk_bound_dev_if = ireq->ir_iif; |
1134 | 1136 | ||
1137 | ip6_set_txhash(newsk); | ||
1138 | |||
1135 | /* Now IPv6 options... | 1139 | /* Now IPv6 options... |
1136 | 1140 | ||
1137 | First: no IPv4 options. | 1141 | First: no IPv4 options. |