aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeliang Tang <tanggeliang@kylinos.cn>2024-03-06 10:51:29 +0800
committerGeliang Tang <tanggeliang@kylinos.cn>2024-04-22 10:56:52 +0800
commita1889c8f06ce4ab910b13217d53fa44846b9a5a5 (patch)
treedd1f89330b769f04f302e7a93d9899fc908a7002
parent6149d0f9118ac779eaa1a025edf7db813106c1f4 (diff)
downloadmptcp_net-next-a1889c8f06ce4ab910b13217d53fa44846b9a5a5.tar.gz
mptcp: react scheduler when subflow events pop up
The current packet scheduler will not react by queuing more packets if some subflows only events are emitted, e.g. new TCP ACKs are received only acking things at TCP-level but not at MPTCP level. The scheduler should be called when such events happen. ack_update_msk() is invoked when an ACK is received, so it's the right place to call the scheduler by invoking __mptcp_check_push(). mptcp_subflow_timeout() is implemented to call the scheduler when a subflow timeout happens. But I'm not sure where is the right place to invoke it. I mean where is the right place when a RTO is fired. So I temporarily do it in mptcp_worker(). Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/343 Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
-rw-r--r--include/net/tcp.h3
-rw-r--r--net/ipv4/tcp_timer.c6
-rw-r--r--net/mptcp/protocol.c21
3 files changed, 27 insertions, 3 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index b935e1ae4caf8..29a564228a2d0 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -349,6 +349,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 976db57b95d40..6673ef832f539 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -212,9 +212,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 4ffd607455d4d..c33fc9968c0f8 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -486,6 +486,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;
@@ -2745,6 +2765,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);