From 1ffbe0ef6810a280417ceb0fc083b36a6f1043f3 Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Wed, 6 Mar 2019 07:11:44 -0800 Subject: [PATCH] mptcp: Reevalute and reschedule meta-level RTO for new subflows When a new subflow comes in, he might reduce the meta-level RTO significantly. E.g., because the other subflow is non-functional but *had* a huge RTO. In that case, we should reschedule the timer so that it fires earlier and we are able to recover quickly. --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.4 < . 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.4 < . 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.4 < . 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) +1.1 > P. 5001:6001(1000) ack 1 sock(4) /* Pushing out the timer */ +0.1 < . 1:1(0) ack 5001 win 4242 sock(4) +1.1 > 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) /* Fire, in 400ms after the subflow got established */ +0.4 > 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 --- net/ipv4/tcp_input.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ca947519027f..6b270eb90cca 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6286,8 +6286,19 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) if (is_master_tp(tp)) { mptcp_update_metasocket(mptcp_meta_sk(sk)); } else { + struct sock *meta_sk = mptcp_meta_sk(sk); + tcp_send_ack(sk); + /* Update RTO as it might be worse/better */ + mptcp_set_rto(sk); + + /* If the new RTO would fire earlier, pull it in! */ + if (tcp_sk(meta_sk)->packets_out && + icsk->icsk_timeout > inet_csk(meta_sk)->icsk_rto + jiffies) { + tcp_rearm_rto(meta_sk); + } + mptcp_push_pending_frames(mptcp_meta_sk(sk)); } }