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.
This commit is contained in:
Tomasz Torcz 2010-08-03 13:33:40 +02:00 committed by Lennart Poettering
parent 07424048b5
commit cebf8b2092
4 changed files with 26 additions and 2 deletions

View File

@ -437,6 +437,18 @@
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>

View 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" },

View 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) {

View 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;