Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp833565imm; Tue, 3 Jul 2018 00:23:18 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKu81S4yhO5Sd3EXeSwosOlpXiZqirUMjWvmZRPppvvk9sf0bQTE72i2jFPETBn6+WBG+HY X-Received: by 2002:a17:902:381:: with SMTP id d1-v6mr28907759pld.309.1530602598235; Tue, 03 Jul 2018 00:23:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530602598; cv=none; d=google.com; s=arc-20160816; b=t7+5cfzD4Pe+d1JcR1pWjqDh+iGqOgzssz91VhSM6/ILSNpYM15macsi5X2ShjzhTn iGof7y+N5OjuadnSn3hRLAVTROruxtAzGg8+IURlfx9VYRFt0HpmTeIYJ1sozqjAg3sr yns/M1UET8BBdyIvy2SjW0d83APY/DuyrkpdJxffSfaWTVJNil0dRxNxcUSw20Pbdf0e U7ZZJ1XQ2+ZHWCLyWOox1uDIVWr7kfMqSDNG1Z6UjRtwJ/HZtmQGktNomklGa7agf+Sb i9YwEi8wgaSqw/jzWMHad4lOdfUlfb9jkcVSNk2X5eaTWgiEc3X9Bbi+jxIYkzkMB1hj 3TYg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=x6HXHTplj+rIQX0w5BchTHnLTXNSal+2XrkPwJFDkPk=; b=MWwX9hUi6lrWLjCtbOoi0ojXl/7dazRuBWA959k1V3CAP6Du/ejrK+hMDYyK5OVG6p frKrAD4Nq+OhVVdne7k3AnAwMAKm0wiV1FoIz/qDK6XJNY3+pqPrhL0b4qeoSKIiarvh uqFoA8sxVLM9EHKtI0n+AXh0ab/o30L4nAmhjLdRjs/J/Gl4ObsFbX69nbmNX8IAqiOJ OgiF7dKWRCQpAbD59IraZsMxdG70Tg1x9pi/yNbdBgHLr/btKJ5SfGbCuu9fAc5XtDUC mqoIgB72KzsCIVEtFjfrOjpRWvFJToF0GAciid+jENMf5VP63D8V89VzeUJ4IDwyXYIo rkVg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=olwnib4u; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y11-v6si484667plg.301.2018.07.03.00.23.03; Tue, 03 Jul 2018 00:23:18 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=olwnib4u; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933398AbeGCHVs (ORCPT + 99 others); Tue, 3 Jul 2018 03:21:48 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:37777 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932802AbeGCHVp (ORCPT ); Tue, 3 Jul 2018 03:21:45 -0400 Received: by mail-pg0-f67.google.com with SMTP id n15-v6so544119pgv.4; Tue, 03 Jul 2018 00:21:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=x6HXHTplj+rIQX0w5BchTHnLTXNSal+2XrkPwJFDkPk=; b=olwnib4uXYIcpeIE99asw7gtl74LMiDTzTHQVn07ReXeJLnsQsRwELiJxKyxvCm5QZ gZqx3M36nn/NAUS50x6csBqdrsYKf/PRMT3x33X913hEQ2ntWLZu3dWh88m5/T0UnJxq Y31VyfjHHnk1XoAK584lIs13jqMIDg4gyeobNWcanEMJk2Phz1iXrLqUD+JxSzSozat1 qoRFI2PKJD1N5cBtY27pPdfpbfTs386i7/jmYtBphIV2HKD/Uj7cBgua4mMvkdgI7ZL+ OjNTZ3dbpssM4J4m/MhITeVP13gpZiOxWMTlmATsP06N/ELkewtqgVodaLuQyEc5Wpd4 2dDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=x6HXHTplj+rIQX0w5BchTHnLTXNSal+2XrkPwJFDkPk=; b=lItBXT2WiDESnjr/hE2xNEDvBrrJ6ujOiwuJWD29RrnFAXMQ5it8/ViNMpnEJhOvx7 LBZSvRp7C2Yff17vx4leCeDV/HndK94cHz1z4hNHdocvi8mtwZDs1lIFlSqIApafH02/ oIrmvsV7BeARaWKHaF6uPwwPxA2+/U/zxh3J17H0ZHm+mYuFPJPxZlgl1zq3Sr8P1WQI js8h2281VcJ23eewS6gf5m3vF8q2OERCl73aBFH8eZm/Yx7Im6uFr8C5qgRYt52EWhRI gIphWp9jvO6SrqNR06hs/rPSbcb0xRfGky6PZxemSbOi6LJkckrPVPXzSznjHKpsnw0Q 53Xg== X-Gm-Message-State: APt69E2VELt3kI596T1oCZ/0nNKzsjORd4xwmQiH8umkN21k01BvEDjI I9IvyYqfc0MjOIwEK3QouoQ= X-Received: by 2002:a63:8c5:: with SMTP id 188-v6mr24126309pgi.97.1530602505051; Tue, 03 Jul 2018 00:21:45 -0700 (PDT) Received: from 192-168-1-6.tpgi.com.com (110-175-8-199.static.tpgi.com.au. [110.175.8.199]) by smtp.gmail.com with ESMTPSA id i12-v6sm1040956pgr.64.2018.07.03.00.21.40 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 03 Jul 2018 00:21:43 -0700 (PDT) From: Jon Maxwell To: davem@davemloft.net Cc: ncardwell@google.com, edumazet@google.com, kuznet@ms2.inr.ac.ru, yoshfuji@linux-ipv6.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jmaxwell@redhat.com Subject: [net-next,v1] tcp: Improve setsockopt() TCP_USER_TIMEOUT accuracy Date: Tue, 3 Jul 2018 17:21:13 +1000 Message-Id: <20180703072113.19910-1-jmaxwell37@gmail.com> X-Mailer: git-send-email 2.13.6 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org v1 contains the following suggestions by Neal Cardwell: 1) Fix up units mismatch regarding msec/jiffies. 2) Address possiblility of time_remaining being negative. 3) Add a helper routine to do the rto calculation. Every time the TCP retransmission timer fires. It checks to see if there is a timeout before scheduling the next retransmit timer. The retransmit interval between each retransmission increases exponentially. The issue is that in order for the timeout to occur the retransmit timer needs to fire again. If the user timeout check happens after the 9th retransmit for example. It needs to wait for the 10th retransmit timer to fire in order to evaluate whether a timeout has occurred or not. If the interval is large enough then the timeout will be inaccurate. For example with a TCP_USER_TIMEOUT of 10 seconds without patch: 1st retransmit: 22:25:18.973488 IP host1.49310 > host2.search-agent: Flags [.] Last retransmit: 22:25:26.205499 IP host1.49310 > host2.search-agent: Flags [.] Timeout: send: Connection timed out Sun Jul 1 22:25:34 EDT 2018 We can see that last retransmit took ~7 seconds. Which pushed the total timeout to ~15 seconds instead of the expected 10 seconds. This gets more inaccurate the larger the TCP_USER_TIMEOUT value. As the interval increases. Add tcp_clamp_rto_to_user_timeout() to determine if the user rto has expired. Or whether the rto interval needs to be recalculated. Use the original interval if user rto is not set. Test results with the patch is the expected 10 second timeout: 1st retransmit: 01:37:59.022555 IP host1.49310 > host2.search-agent: Flags [.] Last retransmit: 01:38:06.486558 IP host1.49310 > host2.search-agent: Flags [.] Timeout: send: Connection timed out Mon Jul 2 01:38:09 EDT 2018 Signed-off-by: Jon Maxwell --- net/ipv4/tcp_timer.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 3b3611729928..82c2a3b3713c 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -22,6 +22,23 @@ #include #include +static __u32 tcp_clamp_rto_to_user_timeout(struct sock *sk) +{ + struct inet_connection_sock *icsk = inet_csk(sk); + __u32 rto = icsk->icsk_rto; + __u32 elapsed, user_timeout; + + if (!icsk->icsk_user_timeout) + return rto; + elapsed = tcp_time_stamp(tcp_sk(sk)) - tcp_sk(sk)->retrans_stamp; + user_timeout = jiffies_to_msecs(icsk->icsk_user_timeout); + if (elapsed >= user_timeout) + rto = 1; /* user timeout has passed; fire ASAP */ + else + rto = min(rto, (__u32)msecs_to_jiffies(user_timeout - elapsed)); + return rto; +} + /** * tcp_write_err() - close socket and save error info * @sk: The socket the error has appeared on. @@ -407,6 +424,7 @@ void tcp_retransmit_timer(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); struct net *net = sock_net(sk); struct inet_connection_sock *icsk = inet_csk(sk); + __u32 rto; if (tp->fastopen_rsk) { WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && @@ -535,7 +553,8 @@ void tcp_retransmit_timer(struct sock *sk) /* Use normal (exponential) backoff */ icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); } - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); + rto = tcp_clamp_rto_to_user_timeout(sk); + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto, TCP_RTO_MAX); if (retransmits_timed_out(sk, net->ipv4.sysctl_tcp_retries1 + 1, 0)) __sk_dst_reset(sk); -- 2.13.6