aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-07-02 00:32:17 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-08 00:14:21 -0400
commitb73c3d0e4f0e1961e15bec18720e48aabebe2109 (patch)
tree84bba82f2bb8dda790d4cea90eb698a5442d36b4 /net/ipv4/tcp_ipv4.c
parent5ed20a68cd6ca4adc0aa2d240913d604a2eb3e25 (diff)
net: Save TX flow hash in sock and set in skbuf on xmit
For a connected socket we can precompute the flow hash for setting in skb->hash on output. This is a performance advantage over calculating the skb->hash for every packet on the connection. The computation is done using the common hash algorithm to be consistent with computations done for packets of the connection in other states where thers is no socket (e.g. time-wait, syn-recv, syn-cookies). This patch adds sk_txhash to the sock structure. inet_set_txhash and ip6_set_txhash functions are added which are called from points in TCP and UDP where socket moves to established state. skb_set_hash_from_sk is a function which sets skb->hash from the sock txhash value. This is called in UDP and TCP transmit path when transmitting within the context of a socket. Tested: ran super_netperf with 200 TCP_RR streams over a vxlan interface (in this case skb_get_hash called on every TX packet to create a UDP source port). Before fix: 95.02% CPU utilization 154/256/505 90/95/99% latencies 1.13042e+06 tps Time in functions: 0.28% skb_flow_dissect 0.21% __skb_get_hash After fix: 94.95% CPU utilization 156/254/485 90/95/99% latencies 1.15447e+06 Neither __skb_get_hash nor skb_flow_dissect appear in perf Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r--net/ipv4/tcp_ipv4.c3
1 files changed, 3 insertions, 0 deletions
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;