summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Torcz <tomek@pipebreaker.pl>2010-08-03 13:33:40 +0200
committerLennart Poettering <lennart@poettering.net>2010-08-03 23:23:47 +0200
commitcebf8b209237db381a504c50eeba76c4c28fb677 (patch)
tree9dcbfd743121a2327ecd3f1cb7af9b703ffa8652
parent07424048b52f8b22b472bf0370a185c1eb443417 (diff)
socket: Allow selection of TCP Congestion Avoidance algorithm to socket
Hi, attached path extends socket configurables with another knob - TCP Congestion Avoidance selection. Linux implements handful of those, useful in various situations. For example, TCP Low Priority may be used by FTP service to gracefully yield bandwidth for more important TCP/IP streams. Until recently TCP_CONGESTION was Linux-specific, recently FreeBSD 8 and OpenSolaris gained compatible support.
-rw-r--r--man/systemd.socket.xml12
-rw-r--r--src/load-fragment.c1
-rw-r--r--src/socket.c14
-rw-r--r--src/socket.h1
4 files changed, 26 insertions, 2 deletions
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
@@ -438,6 +438,18 @@
</varlistentry>
<varlistentry>
+ <term><varname>TCPCongestion=</varname></term>
+ <listitem><para>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.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>ExecStartPre=</varname></term>
<term><varname>ExecStartPost=</varname></term>
<listitem><para>Takes one or more
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;