[RFC mptcp-next 5/6] mptcp: add MP_FAIL retrans support

Geliang Tang posted 6 patches 3 years, 11 months ago
There is a newer version of this series
[RFC mptcp-next 5/6] mptcp: add MP_FAIL retrans support
Posted by Geliang Tang 3 years, 11 months ago
Add MP_FAIL retrans support.

Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
 net/mptcp/pm.c       |  3 +++
 net/mptcp/protocol.c |  1 +
 net/mptcp/protocol.h |  3 +++
 net/mptcp/subflow.c  | 25 +++++++++++++++++++++++++
 4 files changed, 32 insertions(+)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 5e133b249492..e85acdf49d95 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -311,11 +311,14 @@ void mptcp_pm_mp_fail_echoed(struct sock *sk, u64 fail_seq)
 			if (tmp != subflow && tmp->fail_seq == fail_seq) {
 				struct sock *ssk = mptcp_subflow_tcp_sock(tmp);
 
+				sk_stop_timer_sync(ssk, &tmp->mp_fail_timer);
 				ssk->sk_err = EBADMSG;
 				tcp_set_state(ssk, TCP_CLOSE);
 				subflow_sched_work_if_closed(msk, ssk);
 			}
 		}
+	} else {
+		sk_stop_timer_sync(sk, &subflow->mp_fail_timer);
 	}
 }
 
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 4599bde215b2..85f7c76aeb90 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2307,6 +2307,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
 		sock_orphan(ssk);
 
 	subflow->disposable = 1;
+	sk_stop_timer_sync(ssk, &subflow->mp_fail_timer);
 
 	/* if ssk hit tcp_done(), tcp_cleanup_ulp() cleared the related ops
 	 * the ssk has been already destroyed, we just need to release the
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 595222b08fbd..9f6e8774b069 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -467,6 +467,7 @@ struct mptcp_subflow_context {
 	u8	reset_transient:1;
 	u8	reset_reason:4;
 	u8	stale_count;
+	u8	retrans_times;
 
 	long	delegated_status;
 
@@ -483,6 +484,8 @@ struct mptcp_subflow_context {
 	void	(*tcp_state_change)(struct sock *sk);
 	void	(*tcp_error_report)(struct sock *sk);
 
+	struct	timer_list mp_fail_timer;
+
 	struct	rcu_head rcu;
 };
 
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index a8b5b8bf45e5..9bbc157fd713 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -27,6 +27,8 @@
 
 #include <trace/events/mptcp.h>
 
+#define MP_FAIL_RETRANS_MAX	3
+
 static void mptcp_subflow_ops_undo_override(struct sock *ssk);
 
 static void SUBFLOW_REQ_INC_STATS(struct request_sock *req,
@@ -1099,9 +1101,29 @@ void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)
 	}
 }
 
+static void mptcp_mp_fail_timer(struct timer_list *timer)
+{
+	struct mptcp_subflow_context *subflow = from_timer(subflow, timer, mp_fail_timer);
+	struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+	struct net *net = sock_net(ssk);
+
+	if (inet_sk_state_load(ssk) == TCP_CLOSE)
+		return;
+
+	subflow->fail_seq = subflow->map_seq;
+	subflow->send_mp_fail = 1;
+	MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
+	pr_debug("retransmit MP_FAIL %u fail_seq=%llu",
+		 subflow->retrans_times++, subflow->fail_seq);
+
+	if (subflow->retrans_times < MP_FAIL_RETRANS_MAX)
+		sk_reset_timer(ssk, timer, jiffies + mptcp_get_mp_fail_timeout(net));
+}
+
 static bool subflow_check_data_avail(struct sock *ssk)
 {
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+	struct net *net = sock_net(ssk);
 	enum mapping_status status;
 	struct mptcp_sock *msk;
 	struct sk_buff *skb;
@@ -1173,6 +1195,9 @@ static bool subflow_check_data_avail(struct sock *ssk)
 					sk_eat_skb(ssk, skb);
 			}
 			WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
+			timer_setup(&subflow->mp_fail_timer, mptcp_mp_fail_timer, 0);
+			sk_reset_timer(ssk, &subflow->mp_fail_timer,
+				       jiffies + mptcp_get_mp_fail_timeout(net));
 			return true;
 		}
 
-- 
2.34.1