[PATCH mptcp-next 1/2] mptcp: sched: add subflow avoid flag and kfunc
Kalpan Jani <[email protected]> Wed, 15 Jul 2026 15:41:47 +0530
| Newsgroups | dev.linux.lists.mptcp |
|---|---|
| Message-ID | <[email protected]> |
The core benches a subflow via the "stale" bit after net.mptcp.stale_loss_cnt retransmission intervals without progress. That bit is owned by the core and tightly coupled to the RTO: it is cleared automatically as soon as a packet is acked on the subflow (mptcp_subflow_active() calls mptcp_subflow_set_active() when rcv_tstamp advances). A packet scheduler may want to bench a subflow for unrelated reasons (too high latency, too unstable) and keep it benched until it decides otherwise. Reusing the stale bit does not work: the core would clear it on the next incoming ack. Add a separate, scheduler-owned "avoid" flag to mptcp_subflow_context: - it is never set or cleared by the core, only through mptcp_subflow_set_avoid(), exposed to BPF struct_ops schedulers as a kfunc, with the same registration and filter as mptcp_subflow_set_scheduled() so only schedulers can call it; - it lives in the struct_group(reset) block and is therefore cleared when the subflow is reset, so a re-established path is re-evaluated. The flag is scheduler-local state: a scheduler sets it to remember that a subflow should be skipped, and consults it when picking a subflow to send on. The core send and retransmit paths are left unchanged. Link: https://github.com/multipath-tcp/mptcp_net-next/issues/349 Signed-off-by: Kalpan Jani <[email protected]> --- net/mptcp/bpf.c | 1 + net/mptcp/protocol.h | 3 +++ net/mptcp/sched.c | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index 0845061ddc65..ca6e3e2c3c60 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -318,6 +318,7 @@ BTF_KFUNCS_START(bpf_mptcp_common_kfunc_ids) BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx, KF_RET_NULL) BTF_ID_FLAGS(func, bpf_mptcp_subflow_tcp_sock, KF_RET_NULL) BTF_ID_FLAGS(func, mptcp_subflow_set_scheduled) +BTF_ID_FLAGS(func, mptcp_subflow_set_avoid) BTF_ID_FLAGS(func, mptcp_subflow_active) BTF_ID_FLAGS(func, mptcp_set_timeout) BTF_ID_FLAGS(func, mptcp_wnd_end) diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index da40c6f3705f..6485629acd63 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -587,6 +587,7 @@ struct mptcp_subflow_context { __unused : 8; bool data_avail; bool scheduled; + bool avoid; /* pkt scheduler: skip subflow if possible */ bool pm_listener; /* a listener managed by the kernel PM? */ bool fully_established; /* path validated */ u32 lent_mem_frag; @@ -897,6 +898,8 @@ static inline bool __mptcp_subflow_active(struct mptcp_subflow_context *subflow) void mptcp_subflow_set_active(struct mptcp_subflow_context *subflow); +void mptcp_subflow_set_avoid(struct mptcp_subflow_context *subflow, bool avoid); + bool mptcp_subflow_active(struct mptcp_subflow_context *subflow); void mptcp_subflow_drop_ctx(struct sock *ssk); diff --git a/net/mptcp/sched.c b/net/mptcp/sched.c index 1e59072d478c..09163f9742b9 100644 --- a/net/mptcp/sched.c +++ b/net/mptcp/sched.c @@ -165,6 +165,12 @@ void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow, WRITE_ONCE(subflow->scheduled, scheduled); } +void mptcp_subflow_set_avoid(struct mptcp_subflow_context *subflow, + bool avoid) +{ + WRITE_ONCE(subflow->avoid, avoid); +} + int mptcp_sched_get_send(struct mptcp_sock *msk) { struct mptcp_subflow_context *subflow; -- 2.43.0