summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt6
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--include/net/tcp.h4
-rw-r--r--net/ipv4/sysctl_net_ipv4.c24
-rw-r--r--net/ipv4/tcp_cong.c16
5 files changed, 51 insertions, 0 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index fd3c0c012351..db4280856588 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -351,10 +351,16 @@ tcp_frto - BOOLEAN
where packet loss is typically due to random radio interference
rather than intermediate router congestion.
+tcp_available_congestion_control - STRING
+ Shows the available congestion control choices that are registered.
+ More congestion control algorithms may be available as modules,
+ but not loaded.
+
tcp_congestion_control - STRING
Set the congestion control algorithm to be used for new
connections. The algorithm "reno" is always available, but
additional choices may be available based on kernel configuration.
+ Default is set as part of kernel configuration.
somaxconn - INTEGER
Limit of socket listen() backlog, known in userspace as SOMAXCONN.
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index d98562f1df76..28a48279654d 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -426,6 +426,7 @@ enum
NET_CIPSOV4_CACHE_BUCKET_SIZE=119,
NET_CIPSOV4_RBM_OPTFMT=120,
NET_CIPSOV4_RBM_STRICTVALID=121,
+ NET_TCP_AVAIL_CONG_CONTROL=122,
};
enum {
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 246916c2321e..6af4baf5b769 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -620,6 +620,9 @@ enum tcp_ca_event {
* Interface for adding new TCP congestion control handlers
*/
#define TCP_CA_NAME_MAX 16
+#define TCP_CA_MAX 128
+#define TCP_CA_BUF_MAX (TCP_CA_NAME_MAX*TCP_CA_MAX)
+
struct tcp_congestion_ops {
struct list_head list;
@@ -659,6 +662,7 @@ extern void tcp_init_congestion_control(struct sock *sk);
extern void tcp_cleanup_congestion_control(struct sock *sk);
extern int tcp_set_default_congestion_control(const char *name);
extern void tcp_get_default_congestion_control(char *name);
+extern void tcp_get_available_congestion_control(char *buf, size_t len);
extern int tcp_set_congestion_control(struct sock *sk, const char *name);
extern void tcp_slow_start(struct tcp_sock *tp);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 15061b314411..2e770f45d829 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -129,6 +129,23 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
return ret;
}
+static int proc_tcp_available_congestion_control(ctl_table *ctl,
+ int write, struct file * filp,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, };
+ int ret;
+
+ tbl.data = kmalloc(tbl.maxlen, GFP_USER);
+ if (!tbl.data)
+ return -ENOMEM;
+ tcp_get_available_congestion_control(tbl.data, TCP_CA_BUF_MAX);
+ ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
+ kfree(tbl.data);
+ return ret;
+}
+
ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_TCP_TIMESTAMPS,
@@ -731,6 +748,13 @@ ctl_table ipv4_table[] = {
.proc_handler = &proc_dointvec,
},
#endif /* CONFIG_NETLABEL */
+ {
+ .ctl_name = NET_TCP_AVAIL_CONG_CONTROL,
+ .procname = "tcp_available_congestion_control",
+ .maxlen = TCP_CA_BUF_MAX,
+ .mode = 0444,
+ .proc_handler = &proc_tcp_available_congestion_control,
+ },
{ .ctl_name = 0 }
};
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 1e2982f4acd4..d846d7b95e1f 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -139,6 +139,22 @@ static int __init tcp_congestion_default(void)
late_initcall(tcp_congestion_default);
+/* Build string with list of available congestion control values */
+void tcp_get_available_congestion_control(char *buf, size_t maxlen)
+{
+ struct tcp_congestion_ops *ca;
+ size_t offs = 0;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
+ offs += snprintf(buf + offs, maxlen - offs,
+ "%s%s",
+ offs == 0 ? "" : " ", ca->name);
+
+ }
+ rcu_read_unlock();
+}
+
/* Get current default congestion control */
void tcp_get_default_congestion_control(char *name)
{