From fc29b3ada6441caeff5e8f90fde4eefbdc82b1b5 Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Wed, 6 Mar 2019 07:11:43 -0800 Subject: [PATCH] mptcp: Don't update meta-RTO from subflows that are retransmitting Because, the RTO of these subflows is inflated. Thus, if you have one bad subflow hanging around, the MPTCP RTO-timer can blow up to the order of minutes. Better to ignore the RTO of these subflows. The following packet-drill script illustrates the behavior: --tolerance_usecs=100000 +0 `sysctl -w net.mptcp.mptcp_checksum=0` +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0 +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 +0 bind(3, {sa_family = AF_INET, sin_port = htons(13000), sin_addr = inet_addr("192.168.0.1")}, ...) = 0 +0 listen(3, 1) = 0 +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 5 +0 setsockopt(5, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0 bind(5, {sa_family = AF_INET, sin_port = htons(13001), sin_addr = inet_addr("192.168.0.1")}, ...) = 0 +0 listen(5,1) = 0 +0 < S 0:0(0) win 32792 sock(3) +0 > S. 0:0(0) ack 1 win 28800 sock(3) +0 < . 1:1(0) ack 1 win 257 sock(3) +0 accept(3, ..., ...) = 4 +0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0 +0 write(4, ..., 1000) = 1000 +0 > P. 1:1001(1000) ack 1 sock(4) +0 < . 1:1(0) ack 1001 win 4242 sock(4) +0 write(4, ..., 1000) = 1000 +0 > P. 1001:2001(1000) ack 1 sock(4) +0 write(4, ..., 1000) = 1000 +0 > P. 2001:3001(1000) ack 1 sock(4) +0 write(4, ..., 1000) = 1000 +0 > P. 3001:4001(1000) ack 1 sock(4) +0 write(4, ..., 1000) = 1000 +0 > P. 4001:5001(1000) ack 1 sock(4) +0 < . 1:1(0) ack 5001 win 4242 sock(4) /* ACK, without advencing dack: Now, the only way to recover is through a meta-retransmission timer */ /* Meta-level rexmit should fire in 400ms */ +0 write(4, ..., 1000) = 1000 +0 > P. 5001:6001(1000) ack 1 sock(4) +0.2 > P. 5001:6001(1000) ack 1 sock(4) /* Pushing out the timer */ +0.1 < . 1:1(0) ack 5001 win 4242 sock(4) +0.2 > P. 5001:6001(1000) ack 1 sock(4) /* This one reschedules the meta-timer */ +0.01 < . 1:1(0) ack 5001 win 4242 sock(4) +0 < S 0:0(0) win 32792 sock(5) +0 > S. 0:0(0) ack 1 win 28800 sock(5) +0 < . 1:1(0) ack 1 win 32792 sock(5) +0 mp_join_accept(5) = 6 +0 > . 1:1(0) ack 1 <...> sock(6) // reliably mp_join_ack /* This first one is a reinjection. */ +0 > P. 1:1001(1000) ack 1 sock(6) +0 < . 1:1(0) ack 1001 win 4242 sock(6) +0.4 > P. 5001:6001(1000) ack 1 sock(4) /* Fire, in 400ms after the above-mentioned ACK as the only working subflow has na RTO of 200ms */ +0 > P. 1001:2001(1000) ack 1 sock(6) +0 `sysctl -w net.mptcp.mptcp_checksum=1` Signed-off-by: Christoph Paasch Signed-off-by: Matthieu Baerts --- include/net/mptcp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/mptcp.h b/include/net/mptcp.h index a2b78a2e4101..57e8e020188d 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -1195,6 +1195,7 @@ static inline void mptcp_set_rto(struct sock *sk) struct sock *sk_it = mptcp_to_sock(mptcp); if ((mptcp_sk_can_send(sk_it) || sk_it->sk_state == TCP_SYN_RECV) && + inet_csk(sk_it)->icsk_retransmits == 0 && inet_csk(sk_it)->icsk_rto > max_rto) max_rto = inet_csk(sk_it)->icsk_rto; }