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",
                .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),
        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));
 
 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);
 
        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)