The core benches a subflow via the "stale" bit after
net.mptcp.stale_loss_cnt retransmission intervals without progress.
That bit belongs to the core and is tightly coupled to the RTO: it
gets cleared the moment a packet is acked on the subflow. A packet
scheduler has no way to bench a subflow for its own reasons, such as
too high latency or instability, and keep it benched independently of
ack traffic.
Reusing "stale" doesn't work, and "scheduled" doesn't either: the core
clears it right after every send/retrans pass, so it can't express a
standing "leave this subflow alone for now" decision, and nothing
outside the scheduler that set it can ever see it.
This adds a scheduler-owned "avoid" bool that stays set until the
scheduler clears it, is honoured by the default in-kernel subflow
picker on both the send and retransmit paths, and is visible through
MPTCP diag alongside the existing BKUP/FULLY_ESTABLISHED flags.
The avoid state is kept as a standalone bool instead of using the
adjacent flag bitfield. This avoids a race with
mptcp_subflow_data_available(), which clears map_valid in the same
bitfield from the receive path while the scheduler can update avoid
from BPF context. The avoid accesses use READ_ONCE()/WRITE_ONCE().
The default in-kernel subflow picker skips avoided subflows for both
send and retransmit operations. Custom schedulers can explicitly
honour the avoid state according to their own scheduling policy.
The avoid state is exposed to BPF struct_ops schedulers through
mptcp_subflow_set_avoid(), and is also exposed through MPTCP diag as
MPTCP_SUBFLOW_FLAG_AVOID. The kfunc is marked __bpf_kfunc so it remains
available for BPF BTF resolution.
The BPF selftest uses per-socket BPF storage to track whether the
avoid transition has already been performed. It waits until a second
subflow is available before marking it avoided, then relies on that
state remaining set across subsequent scheduler rounds without
calling mptcp_subflow_set_avoid() again. The test validates the
avoided-subflow behaviour through the existing data-transfer and
per-address byte-count checks.
Probing an avoided subflow to decide when to clear it (mentioned in
issue 348) is left out on purpose: that's scheduler policy, not core
mechanism, and belongs to whoever writes the actual latency/stability
heuristics on top of this.
Patch 1 adds the flag, the kfunc, the default-scheduler enforcement,
and diag support.
Patch 2 adds the BPF selftest exercising persistence of the avoid state
across scheduler rounds.
Link: https://github.com/multipath-tcp/mptcp_net-next/issues/349
Kalpan Jani (2):
mptcp: sched: add subflow avoid flag and enforce it in default sched
selftests: mptcp: bpf: exercise the subflow avoid flag across rounds
---
include/uapi/linux/mptcp.h | 1 +
net/mptcp/bpf.c | 1 +
net/mptcp/diag.c | 2 +
net/mptcp/protocol.c | 4 +-
net/mptcp/protocol.h | 3 +
net/mptcp/sched.c | 6 ++
.../testing/selftests/bpf/prog_tests/mptcp.c | 15 ++++
.../selftests/bpf/progs/mptcp_bpf_avoid.c | 87 +++++++++++++++++++
8 files changed, 117 insertions(+), 2 deletions(-)
create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_avoid.c
--
2.43.0