1 From: Dave Taht <d@taht.net>
3 In the bufferbloat age, anything that can make for a kinder, gentler bulk
4 transfer protocol seems desirable.
6 This add support for user and server selectable congestion control algorithms.
9 --congestion-alg=lp # For the tcp-lp algorithm on the command line
12 --diffserv=8 for setting the CS1 bit
14 Also available in rsync daemon modules:
17 congestion alg = westwood # for a wireless connection
20 This could be improved by being able to specify a list of congestion algorithms
21 to try, symbolic names for diffserv (CS1), a better name than 'congestion-alg',
22 and some error checking.
24 To use this patch, run these commands for a successful build:
26 patch -p1 <patches/congestion.diff
27 ./configure (optional if already run)
30 based-on: 4c0a4067df2516ce50e12a7d3ae572275fa9fc0b
31 diff --git a/daemon-parm.txt b/daemon-parm.txt
34 @@ -18,6 +18,7 @@ Locals: =================================================================
35 STRING auth_users NULL
38 +STRING congestion_alg NULL
39 STRING dont_compress DEFAULT_DONT_COMPRESS
40 STRING early_exec NULL
42 @@ -45,6 +46,7 @@ STRING uid NULL
47 INTEGER max_connections 0
48 INTEGER max_verbosity 1
50 diff --git a/options.c b/options.c
53 @@ -79,6 +79,8 @@ int delete_during = 0;
54 int delete_before = 0;
56 int delete_excluded = 0;
58 +char *congestion_alg = NULL;
59 int remove_source_files = 0;
60 int one_file_system = 0;
61 int protocol_version = PROTOCOL_VERSION;
62 @@ -829,6 +831,8 @@ static struct poptOption long_options[] = {
63 {"outbuf", 0, POPT_ARG_STRING, &outbuf_mode, 0, 0, 0 },
64 {"remote-option", 'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
65 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
66 + {"congestion-alg", 0, POPT_ARG_STRING, &congestion_alg, 0, 0, 0 },
67 + {"diffserv", 0, POPT_ARG_INT, &diffserv, 0, 0, 0 },
68 {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 },
69 {"server", 0, POPT_ARG_NONE, 0, OPT_SERVER, 0, 0 },
70 {"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 },
71 diff --git a/rsync.1.md b/rsync.1.md
74 @@ -470,6 +470,8 @@ has its own detailed description later in this manpage.
75 --address=ADDRESS bind address for outgoing socket to daemon
76 --port=PORT specify double-colon alternate port number
77 --sockopts=OPTIONS specify custom TCP options
78 +--diffserv=[0-63] specify diffserv setting
79 +--congestion-alg=STRING choose a congestion algo
80 --blocking-io use blocking I/O for the remote shell
81 --outbuf=N|L|B set out buffering to None, Line, or Block
82 --stats give some file-transfer stats
83 diff --git a/socket.c b/socket.c
86 @@ -40,6 +40,8 @@ extern char *sockopts;
87 extern int default_af_hint;
88 extern int connect_timeout;
89 extern int pid_file_fd;
91 +extern char *congestion_alg;
94 static struct sigaction sigact;
95 @@ -166,6 +168,37 @@ static void contimeout_handler(UNUSED(int val))
99 +/* Set special socket options
101 + * Diffserv is a value in the range of 0-63, and needs to be shifted left
102 + * 2 places AND treated differently for ipv4 and ipv6.
103 + * Setting TCP congestion control is rather Linux specific (at the moment)
104 + * and sends a varying length string to setsockopt rather than an integer
108 +void set_special_sockopts(int s)
110 +#if defined(TCP_CONGESTION)
111 + if (congestion_alg) {
112 + if (setsockopt(s, SOL_TCP, TCP_CONGESTION, congestion_alg, strlen(congestion_alg)) == -1)
113 + rprintf(FINFO, "Couldn't set %s congestion algorithm\n", congestion_alg);
117 +/* setting the diffserv/tos bits is different on ipv6 and
118 + * ipv4, so we just hammer down on both and ignore the result
119 + * And ipv6 demands an int for v. I didn't write the spec.
122 + int v = (diffserv & 63) <<2;
123 + setsockopt(s,IPPROTO_IP, IP_TOS, &v, sizeof(v));
124 +#if defined(IPV6_TCLASS)
125 + setsockopt(s,IPPROTO_IPV6, IPV6_TCLASS, &v, sizeof(v));
130 /* Open a socket to a tcp remote host with the specified port.
132 * Based on code from Warren. Proxy support by Stephen Rothwell.
133 @@ -272,6 +305,7 @@ int open_socket_out(char *host, int port, const char *bind_addr, int af_hint)
134 alarm(connect_timeout);
137 + set_special_sockopts(s);
138 set_socket_options(s, sockopts);
139 while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
140 if (connect_timeout < 0)
141 @@ -440,6 +474,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
145 + set_special_sockopts(s);
146 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
147 (char *)&one, sizeof one);