mptcp: add net.mptcp.available_schedulers
authorGregory Detal <gregory.detal@gmail.com>
Tue, 14 May 2024 01:13:28 +0000 (18:13 -0700)
committerJakub Kicinski <kuba@kernel.org>
Tue, 14 May 2024 01:29:23 +0000 (18:29 -0700)
The sysctl lists the available schedulers that can be set using
net.mptcp.scheduler similarly to net.ipv4.tcp_available_congestion_control.

Signed-off-by: Gregory Detal <gregory.detal@gmail.com>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Tested-by: Geliang Tang <geliang@kernel.org>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Mat Martineau <martineau@kernel.org>
Link: https://lore.kernel.org/r/20240514011335.176158-5-martineau@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/mptcp.h
net/mptcp/ctrl.c
net/mptcp/protocol.h
net/mptcp/sched.c

index fb996124b3d5cf6b4bd27f88be3388978b7027da..0bc4ab03f48786a11ee6be2b7aac60c0d8d176cb 100644 (file)
@@ -97,6 +97,9 @@ struct mptcp_out_options {
 };
 
 #define MPTCP_SCHED_NAME_MAX   16
+#define MPTCP_SCHED_MAX                128
+#define MPTCP_SCHED_BUF_MAX    (MPTCP_SCHED_NAME_MAX * MPTCP_SCHED_MAX)
+
 #define MPTCP_SUBFLOWS_MAX     8
 
 struct mptcp_sched_data {
index 49abf80b3fad8e68885409c0080c0f8584aa51d6..542555ba474cb9b9337e3036671b9f43fd9dd9d1 100644 (file)
@@ -133,6 +133,24 @@ static int proc_scheduler(struct ctl_table *ctl, int write,
        return ret;
 }
 
+static int proc_available_schedulers(struct ctl_table *ctl,
+                                    int write, void *buffer,
+                                    size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table tbl = { .maxlen = MPTCP_SCHED_BUF_MAX, };
+       int ret;
+
+       tbl.data = kmalloc(tbl.maxlen, GFP_USER);
+       if (!tbl.data)
+               return -ENOMEM;
+
+       mptcp_get_available_schedulers(tbl.data, MPTCP_SCHED_BUF_MAX);
+       ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
+       kfree(tbl.data);
+
+       return ret;
+}
+
 static struct ctl_table mptcp_sysctl_table[] = {
        {
                .procname = "enabled",
@@ -187,6 +205,12 @@ static struct ctl_table mptcp_sysctl_table[] = {
                .mode = 0644,
                .proc_handler = proc_scheduler,
        },
+       {
+               .procname = "available_schedulers",
+               .maxlen = MPTCP_SCHED_BUF_MAX,
+               .mode = 0644,
+               .proc_handler = proc_available_schedulers,
+       },
        {
                .procname = "close_timeout",
                .maxlen = sizeof(unsigned int),
@@ -214,7 +238,8 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
        table[4].data = &pernet->stale_loss_cnt;
        table[5].data = &pernet->pm_type;
        table[6].data = &pernet->scheduler;
-       table[7].data = &pernet->close_timeout;
+       /* table[7] is for available_schedulers which is read-only info */
+       table[8].data = &pernet->close_timeout;
 
        hdr = register_net_sysctl_sz(net, MPTCP_SYSCTL_PATH, table,
                                     ARRAY_SIZE(mptcp_sysctl_table));
index 4dcce3641d1d95609a7f335c077e0415f7643636..39fc47e6b88ad0723a1bf7ad71b2c86b264cebfe 100644 (file)
@@ -686,6 +686,7 @@ unsigned int mptcp_stale_loss_cnt(const struct net *net);
 unsigned int mptcp_close_timeout(const struct sock *sk);
 int mptcp_get_pm_type(const struct net *net);
 const char *mptcp_get_scheduler(const struct net *net);
+void mptcp_get_available_schedulers(char *buf, size_t maxlen);
 void __mptcp_subflow_fully_established(struct mptcp_sock *msk,
                                       struct mptcp_subflow_context *subflow,
                                       const struct mptcp_options_received *mp_opt);
index 4ab0693c069c0fb0725372f17df62d87e859820c..4a7fd0508ad28497463f1e40ec2b95c555249969 100644 (file)
@@ -51,6 +51,28 @@ struct mptcp_sched_ops *mptcp_sched_find(const char *name)
        return ret;
 }
 
+/* Build string with list of available scheduler values.
+ * Similar to tcp_get_available_congestion_control()
+ */
+void mptcp_get_available_schedulers(char *buf, size_t maxlen)
+{
+       struct mptcp_sched_ops *sched;
+       size_t offs = 0;
+
+       rcu_read_lock();
+       spin_lock(&mptcp_sched_list_lock);
+       list_for_each_entry_rcu(sched, &mptcp_sched_list, list) {
+               offs += snprintf(buf + offs, maxlen - offs,
+                                "%s%s",
+                                offs == 0 ? "" : " ", sched->name);
+
+               if (WARN_ON_ONCE(offs >= maxlen))
+                       break;
+       }
+       spin_unlock(&mptcp_sched_list_lock);
+       rcu_read_unlock();
+}
+
 int mptcp_register_scheduler(struct mptcp_sched_ops *sched)
 {
        if (!sched->get_subflow)