diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 20dc00ed01..a7b8228aa0 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -437,6 +437,18 @@ address. Defaults to . + + TCPCongestion= + Takes a string + value. Controls the TCP congestion + algorithm used by this socket. Should + be one of "westwood", "veno", "cubic", + "lp" or any other available algorithm + supported by the IP stack. This + setting applies only to stream + sockets. + + ExecStartPre= ExecStartPost= diff --git a/src/load-fragment.c b/src/load-fragment.c index 98f16f9a23..f2f2d72837 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -1616,6 +1616,7 @@ static int load_from_path(Unit *u, const char *path) { { "Mark", config_parse_int, &u->socket.mark, "Socket" }, { "PipeSize", config_parse_size, &u->socket.pipe_size, "Socket" }, { "FreeBind", config_parse_bool, &u->socket.free_bind, "Socket" }, + { "TCPCongestion", config_parse_string, &u->socket.tcp_congestion, "Socket" }, EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"), { "What", config_parse_string, &u->mount.parameters_fragment.what, "Mount" }, diff --git a/src/socket.c b/src/socket.c index 82a9348d13..2da3215a3d 100644 --- a/src/socket.c +++ b/src/socket.c @@ -31,6 +31,7 @@ #include "unit.h" #include "socket.h" +#include "netinet/tcp.h" #include "log.h" #include "load-dropin.h" #include "load-fragment.h" @@ -116,6 +117,9 @@ static void socket_done(Unit *u) { s->service = NULL; + free(s->tcp_congestion); + s->tcp_congestion = NULL; + free(s->bind_to_device); s->bind_to_device = NULL; @@ -371,14 +375,16 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { "%sSocketMode: %04o\n" "%sDirectoryMode: %04o\n" "%sKeepAlive: %s\n" - "%sFreeBind: %s\n", + "%sFreeBind: %s\n" + "%sTCPCongestion: %s\n", prefix, socket_state_to_string(s->state), prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only), prefix, s->backlog, prefix, s->socket_mode, prefix, s->directory_mode, prefix, yes_no(s->keep_alive), - prefix, yes_no(s->free_bind)); + prefix, yes_no(s->free_bind), + prefix, s->tcp_congestion); if (s->control_pid > 0) fprintf(f, @@ -632,6 +638,10 @@ static void socket_apply_socket_options(Socket *s, int fd) { if (r < 0 && x < 0) log_warning("IP_TTL/IPV6_UNICAST_HOPS failed: %m"); } + + if (s->tcp_congestion) + if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0) + log_warning("TCP_CONGESTION failed: %m"); } static void socket_apply_fifo_options(Socket *s, int fd) { diff --git a/src/socket.h b/src/socket.h index 88ebf26f87..230dd200d5 100644 --- a/src/socket.h +++ b/src/socket.h @@ -114,6 +114,7 @@ struct Socket { int mark; bool free_bind; char *bind_to_device; + char *tcp_congestion; /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */ SocketAddressBindIPv6Only bind_ipv6_only;