diff options
author | Yuchung Cheng <ycheng@google.com> | 2015-09-18 14:36:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-09-21 19:19:01 -0400 |
commit | 0f1c28ae74bb1a34d36fca2db5161611d58b3148 (patch) | |
tree | a525dec074bcb7f5bdb79e17bdc0162637b9164a /net/ipv4/tcp_input.c | |
parent | 21fe8af40024c49af37124bc7b19c5836d25695e (diff) |
tcp: usec resolution SYN/ACK RTT
Currently SYN/ACK RTT is measured in jiffies. For LAN the SYN/ACK
RTT is often measured as 0ms or sometimes 1ms, which would affect
RTT estimation and min RTT samping used by some congestion control.
This patch improves SYN/ACK RTT to be usec resolution if platform
supports it. While the timestamping of SYN/ACK is done in request
sock, the RTT measurement is carefully arranged to avoid storing
another u64 timestamp in tcp_sock.
For regular handshake w/o SYNACK retransmission, the RTT is sampled
right after the child socket is created and right before the request
sock is released (tcp_check_req() in tcp_minisocks.c)
For Fast Open the child socket is already created when SYN/ACK was
sent, the RTT is sampled in tcp_rcv_state_process() after processing
the final ACK an right before the request socket is released.
If the SYN/ACK was retransmistted or SYN-cookie was used, we rely
on TCP timestamps to measure the RTT. The sample is taken at the
same place in tcp_rcv_state_process() after the timestamp values
are validated in tcp_validate_incoming(). Note that we do not store
TS echo value in request_sock for SYN-cookies, because the value
is already stored in tp->rx_opt used by tcp_ack_update_rtt().
One side benefit is that the RTT measurement now happens before
initializing congestion control (of the passive side). Therefore
the congestion control can use the SYN/ACK RTT.
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 29 |
1 files changed, 14 insertions, 15 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a62e9c76d485..497adf58a6b8 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2953,21 +2953,21 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, | |||
2953 | } | 2953 | } |
2954 | 2954 | ||
2955 | /* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */ | 2955 | /* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */ |
2956 | static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp) | 2956 | void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req) |
2957 | { | 2957 | { |
2958 | struct tcp_sock *tp = tcp_sk(sk); | 2958 | long rtt_us = -1L; |
2959 | long seq_rtt_us = -1L; | ||
2960 | 2959 | ||
2961 | if (synack_stamp && !tp->total_retrans) | 2960 | if (req && !req->num_retrans && tcp_rsk(req)->snt_synack.v64) { |
2962 | seq_rtt_us = jiffies_to_usecs(tcp_time_stamp - synack_stamp); | 2961 | struct skb_mstamp now; |
2963 | 2962 | ||
2964 | /* If the ACK acks both the SYNACK and the (Fast Open'd) data packets | 2963 | skb_mstamp_get(&now); |
2965 | * sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack() | 2964 | rtt_us = skb_mstamp_us_delta(&now, &tcp_rsk(req)->snt_synack); |
2966 | */ | 2965 | } |
2967 | if (!tp->srtt_us) | 2966 | |
2968 | tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt_us, -1L); | 2967 | tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, rtt_us, -1L); |
2969 | } | 2968 | } |
2970 | 2969 | ||
2970 | |||
2971 | static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) | 2971 | static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) |
2972 | { | 2972 | { |
2973 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2973 | const struct inet_connection_sock *icsk = inet_csk(sk); |
@@ -5706,7 +5706,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5706 | struct request_sock *req; | 5706 | struct request_sock *req; |
5707 | int queued = 0; | 5707 | int queued = 0; |
5708 | bool acceptable; | 5708 | bool acceptable; |
5709 | u32 synack_stamp; | ||
5710 | 5709 | ||
5711 | tp->rx_opt.saw_tstamp = 0; | 5710 | tp->rx_opt.saw_tstamp = 0; |
5712 | 5711 | ||
@@ -5785,15 +5784,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5785 | if (!acceptable) | 5784 | if (!acceptable) |
5786 | return 1; | 5785 | return 1; |
5787 | 5786 | ||
5787 | if (!tp->srtt_us) | ||
5788 | tcp_synack_rtt_meas(sk, req); | ||
5789 | |||
5788 | /* Once we leave TCP_SYN_RECV, we no longer need req | 5790 | /* Once we leave TCP_SYN_RECV, we no longer need req |
5789 | * so release it. | 5791 | * so release it. |
5790 | */ | 5792 | */ |
5791 | if (req) { | 5793 | if (req) { |
5792 | synack_stamp = tcp_rsk(req)->snt_synack; | ||
5793 | tp->total_retrans = req->num_retrans; | 5794 | tp->total_retrans = req->num_retrans; |
5794 | reqsk_fastopen_remove(sk, req, false); | 5795 | reqsk_fastopen_remove(sk, req, false); |
5795 | } else { | 5796 | } else { |
5796 | synack_stamp = tp->lsndtime; | ||
5797 | /* Make sure socket is routed, for correct metrics. */ | 5797 | /* Make sure socket is routed, for correct metrics. */ |
5798 | icsk->icsk_af_ops->rebuild_header(sk); | 5798 | icsk->icsk_af_ops->rebuild_header(sk); |
5799 | tcp_init_congestion_control(sk); | 5799 | tcp_init_congestion_control(sk); |
@@ -5816,7 +5816,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5816 | tp->snd_una = TCP_SKB_CB(skb)->ack_seq; | 5816 | tp->snd_una = TCP_SKB_CB(skb)->ack_seq; |
5817 | tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; | 5817 | tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; |
5818 | tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); | 5818 | tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); |
5819 | tcp_synack_rtt_meas(sk, synack_stamp); | ||
5820 | 5819 | ||
5821 | if (tp->rx_opt.tstamp_ok) | 5820 | if (tp->rx_opt.tstamp_ok) |
5822 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; | 5821 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; |
@@ -6027,7 +6026,7 @@ static void tcp_openreq_init(struct request_sock *req, | |||
6027 | req->cookie_ts = 0; | 6026 | req->cookie_ts = 0; |
6028 | tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq; | 6027 | tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq; |
6029 | tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; | 6028 | tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; |
6030 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | 6029 | skb_mstamp_get(&tcp_rsk(req)->snt_synack); |
6031 | tcp_rsk(req)->last_oow_ack_time = 0; | 6030 | tcp_rsk(req)->last_oow_ack_time = 0; |
6032 | req->mss = rx_opt->mss_clamp; | 6031 | req->mss = rx_opt->mss_clamp; |
6033 | req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0; | 6032 | req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0; |