diff --git a/include/net/tcp.h b/include/net/tcp.h index 5b2b04835688..2bc55f0eaca6 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -341,6 +341,9 @@ void tcp_release_cb(struct sock *sk); void tcp_wfree(struct sk_buff *skb); void tcp_write_timer_handler(struct sock *sk); void tcp_delack_timer_handler(struct sock *sk); +bool retransmits_timed_out(struct sock *sk, + unsigned int boundary, + unsigned int timeout); int tcp_ioctl(struct sock *sk, int cmd, int *karg); enum skb_drop_reason tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb); void tcp_rcv_established(struct sock *sk, struct sk_buff *skb); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index b412ed88ccd9..685aa718acfb 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -210,9 +210,9 @@ static unsigned int tcp_model_timeout(struct sock *sk, * after "boundary" unsuccessful, exponentially backed-off * retransmissions with an initial RTO of TCP_RTO_MIN. */ -static bool retransmits_timed_out(struct sock *sk, - unsigned int boundary, - unsigned int timeout) +bool retransmits_timed_out(struct sock *sk, + unsigned int boundary, + unsigned int timeout) { struct tcp_sock *tp = tcp_sk(sk); unsigned int start_ts, delta; diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 8319a4bc86e3..03b175f4146c 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -423,6 +423,26 @@ static long mptcp_timeout_from_subflow(const struct mptcp_subflow_context *subfl inet_csk(ssk)->icsk_timeout - jiffies : 0; } +static void __mptcp_subflow_timeout(struct sock *sk, struct sock *ssk, long tout) +{ + unsigned int boundary = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_retries1) + 1; + + if (retransmits_timed_out(ssk, boundary, tout)) + __mptcp_check_push(sk, ssk); +} + +static void mptcp_subflow_timeout(struct sock *sk) +{ + struct mptcp_subflow_context *subflow; + + mptcp_for_each_subflow(mptcp_sk(sk), subflow) { + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); + long tout = mptcp_timeout_from_subflow(subflow); + + __mptcp_subflow_timeout(sk, ssk, tout); + } +} + void mptcp_set_timeout(struct sock *sk) { struct mptcp_subflow_context *subflow; @@ -2673,6 +2693,7 @@ static void mptcp_worker(struct work_struct *work) mptcp_check_fastclose(msk); mptcp_pm_nl_work(msk); + mptcp_subflow_timeout(sk); mptcp_check_send_data_fin(sk); mptcp_check_data_fin_ack(sk);