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