chiark / gitweb /
socket: Allow selection of TCP Congestion Avoidance algorithm to socket
authorTomasz Torcz <tomek@pipebreaker.pl>
Tue, 3 Aug 2010 11:33:40 +0000 (13:33 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 3 Aug 2010 21:23:47 +0000 (23:23 +0200)
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.

man/systemd.socket.xml
src/load-fragment.c
src/socket.c
src/socket.h

index 20dc00ed0120a15f8f63830d021a5f418d213775..a7b8228aa0b6d7c5bb9fca0ba92052173a4e4c32 100644 (file)
                                 address. Defaults to <option>false</option>.</para></listitem>
                         </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>
index 98f16f9a23bf8b348991f047315d74b17ed0d37a..f2f2d72837b8b56a9fd45e8383a0faebd54b53b6 100644 (file)
@@ -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"   },
index 82a9348d13f2f8fa617991de3b92808e25f0aca5..2da3215a3d3ed12d76615bd2c35ad87818391ed5 100644 (file)
@@ -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) {
index 88ebf26f870b5db0713114dead3d0903f92b44fc..230dd200d5e423ebef41f869ec3f6555d5b0c0c1 100644 (file)
@@ -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;