Fix patch conflict.
[rsync-patches.git] / congestion.diff
1 From: Dave Taht <d@taht.net>
2
3 In the bufferbloat age, anything that can make for a kinder, gentler bulk
4 transfer protocol seems desirable.
5
6 This add support for user and server selectable congestion control algorithms.
7
8 For example:
9     --congestion-alg=lp # For the tcp-lp algorithm on the command line
10
11 And diffserv support:
12     --diffserv=8 for setting the CS1 bit
13
14 Also available in rsync daemon modules:
15
16 [mystuff]
17     congestion alg = westwood # for a wireless connection
18     diffserv = 8
19
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.
23
24 To use this patch, run these commands for a successful build:
25
26     patch -p1 <patches/congestion.diff
27     ./configure                         (optional if already run)
28     make
29
30 based-on: 8695bcc2b140b2518254234659a03b96f04055fc
31 diff --git a/daemon-parm.txt b/daemon-parm.txt
32 --- a/daemon-parm.txt
33 +++ b/daemon-parm.txt
34 @@ -18,6 +18,7 @@ Locals: =================================================================
35  STRING auth_users              NULL
36  STRING charset                 NULL
37  STRING comment                 NULL
38 +STRING congestion_alg          NULL
39  STRING dont_compress           DEFAULT_DONT_COMPRESS
40  STRING early_exec              NULL
41  STRING exclude                 NULL
42 @@ -45,6 +46,7 @@ STRING        uid                     NULL
43  PATH   path                    NULL
44  PATH   temp_dir                NULL
45  
46 +INTEGER        diffserv                8
47  INTEGER        max_connections         0
48  INTEGER        max_verbosity           1
49  INTEGER        timeout                 0
50 diff --git a/options.c b/options.c
51 --- a/options.c
52 +++ b/options.c
53 @@ -75,6 +75,8 @@ int delete_during = 0;
54  int delete_before = 0;
55  int delete_after = 0;
56  int delete_excluded = 0;
57 +int diffserv = 8;
58 +char *congestion_alg = NULL;
59  int remove_source_files = 0;
60  int one_file_system = 0;
61  int protocol_version = PROTOCOL_VERSION;
62 @@ -1037,6 +1039,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
72 --- a/rsync.1.md
73 +++ b/rsync.1.md
74 @@ -443,6 +443,8 @@ detailed description below for a complete description.
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
84 --- a/socket.c
85 +++ 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;
90 +extern int diffserv;
91 +extern char *congestion_alg;
92  
93  #ifdef HAVE_SIGACTION
94  static struct sigaction sigact;
95 @@ -166,6 +168,37 @@ static void contimeout_handler(UNUSED(int val))
96         connect_timeout = -1;
97  }
98  
99 +/* Set special socket options
100 + *
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
105 + * or character.
106 +*/
107 +
108 +void set_special_sockopts(int s)
109 +{
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);
114 +       }
115 +#endif
116 +
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.
120 + */
121 +       if (diffserv) {
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));
126 +#endif
127 +       }
128 +}
129 +
130  /* Open a socket to a tcp remote host with the specified port.
131   *
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);
135                 }
136  
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,
142                         continue;
143                 }
144  
145 +               set_special_sockopts(s);
146                 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
147                            (char *)&one, sizeof one);
148                 if (sockopts)