diff options
author | Neal Cardwell <ncardwell@google.com> | 2012-09-22 00:18:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-22 15:47:10 -0400 |
commit | 016818d076871c4ee34db1e8d74dc17ac1de626a (patch) | |
tree | 60d0f20afb0937f61b5fc4611e53a2ac411a0646 /net/ipv4 | |
parent | 623df484a777f3c00c1ea3d6a7565b8d8ac688a1 (diff) |
tcp: TCP Fast Open Server - take SYNACK RTT after completing 3WHS
When taking SYNACK RTT samples for servers using TCP Fast Open, fix
the code to ensure that we only call tcp_valid_rtt_meas() after we
receive the ACK that completes the 3-way handshake.
Previously we were always taking an RTT sample in
tcp_v4_syn_recv_sock(). However, for TCP Fast Open connections
tcp_v4_conn_req_fastopen() calls tcp_v4_syn_recv_sock() at the time we
receive the SYN. So for TFO we must wait until tcp_rcv_state_process()
to take the RTT sample.
To fix this, we wait until after TFO calls tcp_v4_syn_recv_sock()
before we set the snt_synack timestamp, since tcp_synack_rtt_meas()
already ensures that we only take a SYNACK RTT sample if snt_synack is
non-zero. To be careful, we only take a snt_synack timestamp when
a SYNACK transmit or retransmit succeeds.
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_input.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 12 |
2 files changed, 10 insertions, 3 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e2bec815ff23..bb326684495b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5983,6 +5983,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5983 | * need req so release it. | 5983 | * need req so release it. |
5984 | */ | 5984 | */ |
5985 | if (req) { | 5985 | if (req) { |
5986 | tcp_synack_rtt_meas(sk, req); | ||
5986 | reqsk_fastopen_remove(sk, req, false); | 5987 | reqsk_fastopen_remove(sk, req, false); |
5987 | } else { | 5988 | } else { |
5988 | /* Make sure socket is routed, for | 5989 | /* Make sure socket is routed, for |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1e66f7fb4fe6..0a7e020f16b5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -868,6 +868,8 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
868 | ireq->rmt_addr, | 868 | ireq->rmt_addr, |
869 | ireq->opt); | 869 | ireq->opt); |
870 | err = net_xmit_eval(err); | 870 | err = net_xmit_eval(err); |
871 | if (!tcp_rsk(req)->snt_synack && !err) | ||
872 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
871 | } | 873 | } |
872 | 874 | ||
873 | return err; | 875 | return err; |
@@ -1382,6 +1384,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, | |||
1382 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; | 1384 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; |
1383 | const struct inet_request_sock *ireq = inet_rsk(req); | 1385 | const struct inet_request_sock *ireq = inet_rsk(req); |
1384 | struct sock *child; | 1386 | struct sock *child; |
1387 | int err; | ||
1385 | 1388 | ||
1386 | req->retrans = 0; | 1389 | req->retrans = 0; |
1387 | req->sk = NULL; | 1390 | req->sk = NULL; |
@@ -1393,8 +1396,11 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, | |||
1393 | kfree_skb(skb_synack); | 1396 | kfree_skb(skb_synack); |
1394 | return -1; | 1397 | return -1; |
1395 | } | 1398 | } |
1396 | ip_build_and_send_pkt(skb_synack, sk, ireq->loc_addr, | 1399 | err = ip_build_and_send_pkt(skb_synack, sk, ireq->loc_addr, |
1397 | ireq->rmt_addr, ireq->opt); | 1400 | ireq->rmt_addr, ireq->opt); |
1401 | err = net_xmit_eval(err); | ||
1402 | if (!err) | ||
1403 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1398 | /* XXX (TFO) - is it ok to ignore error and continue? */ | 1404 | /* XXX (TFO) - is it ok to ignore error and continue? */ |
1399 | 1405 | ||
1400 | spin_lock(&queue->fastopenq->lock); | 1406 | spin_lock(&queue->fastopenq->lock); |
@@ -1612,7 +1618,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1612 | isn = tcp_v4_init_sequence(skb); | 1618 | isn = tcp_v4_init_sequence(skb); |
1613 | } | 1619 | } |
1614 | tcp_rsk(req)->snt_isn = isn; | 1620 | tcp_rsk(req)->snt_isn = isn; |
1615 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1616 | 1621 | ||
1617 | if (dst == NULL) { | 1622 | if (dst == NULL) { |
1618 | dst = inet_csk_route_req(sk, &fl4, req); | 1623 | dst = inet_csk_route_req(sk, &fl4, req); |
@@ -1650,6 +1655,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1650 | if (err || want_cookie) | 1655 | if (err || want_cookie) |
1651 | goto drop_and_free; | 1656 | goto drop_and_free; |
1652 | 1657 | ||
1658 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1653 | tcp_rsk(req)->listener = NULL; | 1659 | tcp_rsk(req)->listener = NULL; |
1654 | /* Add the request_sock to the SYN table */ | 1660 | /* Add the request_sock to the SYN table */ |
1655 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1661 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |