aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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
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')
-rw-r--r--net/ipv4/datagram.c1
-rw-r--r--net/ipv4/tcp_ipv4.c3
-rw-r--r--net/ipv4/tcp_output.c1
3 files changed, 5 insertions, 0 deletions
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. */