Message ID | 95d450f9694cf9d95081a77db529db2181d0d3b3.1631011068.git.geliangtang@xiaomi.com (mailing list archive) |
---|---|
State | RFC, archived |
Headers | show |
Series | round-robin packet scheduler support | expand |
On Tue, 2021-09-07 at 18:41 +0800, Geliang Tang wrote: > From: Geliang Tang <geliangtang@xiaomi.com> > > Implement the round-robin packet scheduler like on the mptcp.org kernel. > > Signed-off-by: Geliang Tang <geliangtang@xiaomi.com> > --- > net/mptcp/Kconfig | 7 +++++++ > net/mptcp/protocol.c | 26 ++++++++++++++++++++++++++ > 2 files changed, 33 insertions(+) > > diff --git a/net/mptcp/Kconfig b/net/mptcp/Kconfig > index 10c97e19a7da..0df36991566a 100644 > --- a/net/mptcp/Kconfig > +++ b/net/mptcp/Kconfig > @@ -23,6 +23,13 @@ config MPTCP_IPV6 > depends on IPV6=y > default y > > +config MPTCP_ROUNDROBIN > + tristate "MPTCP Round-Robin" > + default n > + help > + This is a very simple round-robin scheduler. Probably has bad performance > + but might be interesting for researchers. > + > config MPTCP_KUNIT_TEST > tristate "This builds the MPTCP KUnit tests" if !KUNIT_ALL_TESTS > depends on KUNIT > diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c > index ab72a3950f2b..b78c4eb4947f 100644 > --- a/net/mptcp/protocol.c > +++ b/net/mptcp/protocol.c > @@ -1521,6 +1521,29 @@ static struct mptcp_sched_ops mptcp_sched_default = { > .owner = THIS_MODULE, > }; > > +#if IS_ENABLED(CONFIG_MPTCP_ROUNDROBIN) > +static struct sock *rr_get_subflow(struct mptcp_sock *msk) > +{ > + struct mptcp_subflow_context *subflow; > + struct sock *ssk; > + > + mptcp_for_each_subflow(msk, subflow) { > + ssk = mptcp_subflow_tcp_sock(subflow); > + if (ssk != msk->last_snd) { > + pr_debug("msk=%p ssk=%p last_snd=%p", msk, ssk, msk->last_snd); > + msk->last_snd = ssk; > + } This needs some more logic: - it must take in account backup vs non backup - it should consider if the given subflow has available write space/snd_wnd - it should move from the 'last_snd' subflow to the 'next' one, instead of always selecting the fist subflow other then 'last_snd'. Otherwise with 3 non backup subflow active we will never pick the last created one. There is an import side question, already asked by Christoph, why the round robin? perhpas we should consider instead some different scheduler, known to perform well. @Christoph: which is the 'best' mptcp.org scheduler out there? blest? Thanks! Paolo
On Tue, 7 Sep 2021, Paolo Abeni wrote: > There is an import side question, already asked by Christoph, why the > round robin? perhpas we should consider instead some different > scheduler, known to perform well. @Christoph: which is the 'best' > mptcp.org scheduler out there? blest? > This is the main question I have! We've also discussed the idea of eBPF-based schedulers, so I've been thinking we would have one built-in scheduler and then allow alternatives (like round robin) via eBPF. If there's a good use case for round robin maybe there's a solution here similar to what we did with the fullmesh path manager: could there be a configuration knob for the existing scheduler that makes it try to *not* use the last-used subflow, instead of favoring the last-used subflow? -- Mat Martineau Intel
diff --git a/net/mptcp/Kconfig b/net/mptcp/Kconfig index 10c97e19a7da..0df36991566a 100644 --- a/net/mptcp/Kconfig +++ b/net/mptcp/Kconfig @@ -23,6 +23,13 @@ config MPTCP_IPV6 depends on IPV6=y default y +config MPTCP_ROUNDROBIN + tristate "MPTCP Round-Robin" + default n + help + This is a very simple round-robin scheduler. Probably has bad performance + but might be interesting for researchers. + config MPTCP_KUNIT_TEST tristate "This builds the MPTCP KUnit tests" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index ab72a3950f2b..b78c4eb4947f 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1521,6 +1521,29 @@ static struct mptcp_sched_ops mptcp_sched_default = { .owner = THIS_MODULE, }; +#if IS_ENABLED(CONFIG_MPTCP_ROUNDROBIN) +static struct sock *rr_get_subflow(struct mptcp_sock *msk) +{ + struct mptcp_subflow_context *subflow; + struct sock *ssk; + + mptcp_for_each_subflow(msk, subflow) { + ssk = mptcp_subflow_tcp_sock(subflow); + if (ssk != msk->last_snd) { + pr_debug("msk=%p ssk=%p last_snd=%p", msk, ssk, msk->last_snd); + msk->last_snd = ssk; + } + } + return msk->last_snd; +} + +static struct mptcp_sched_ops mptcp_sched_rr = { + .get_subflow = rr_get_subflow, + .name = "roundrobin", + .owner = THIS_MODULE, +}; +#endif + static DEFINE_SPINLOCK(mptcp_sched_list_lock); static LIST_HEAD(mptcp_sched_list); @@ -1565,6 +1588,9 @@ static void mptcp_sched_data_init(struct mptcp_sock *msk) static void mptcp_sched_init(void) { mptcp_register_scheduler(&mptcp_sched_default); +#if IS_ENABLED(CONFIG_MPTCP_ROUNDROBIN) + mptcp_register_scheduler(&mptcp_sched_rr); +#endif } static void mptcp_push_release(struct sock *sk, struct sock *ssk,