mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
r13773@catbus: nickm | 2007-07-16 11:58:25 -0400
Initial "constrained socket buffers" patch from coderman. needs tweaking. svn:r10842
This commit is contained in:
parent
6d2cb32d10
commit
f4a6673758
27
doc/tor.1.in
27
doc/tor.1.in
@ -101,6 +101,33 @@ You probably don't need to adjust this. It has no effect on
|
|||||||
Windows since that platform lacks getrlimit(). (Default: 1000)
|
Windows since that platform lacks getrlimit(). (Default: 1000)
|
||||||
.LP
|
.LP
|
||||||
.TP
|
.TP
|
||||||
|
\fBConstrainedSockets \fR\fB0\fR|\fB1\fR\fP
|
||||||
|
If set, Tor will attempt to shrink the recv and xmit buffers for all
|
||||||
|
sockets to the size specified in \fBConstrainedSockSize\fP. This is useful
|
||||||
|
for virtual servers and other environments where system level TCP
|
||||||
|
buffers may be limited. If you encounter the "Error creating network
|
||||||
|
socket: No buffer space available" message you are likely experiencing
|
||||||
|
this problem.
|
||||||
|
|
||||||
|
The preferred solution is to have the admin increase the buffer pool for
|
||||||
|
the host itself via /proc/sys/net/ipv4/tcp_mem or equivalent facility.
|
||||||
|
|
||||||
|
The DirPort option should also not be used if TCP buffers are scarce. The
|
||||||
|
cached directory requests consume additional sockets which exacerbates the
|
||||||
|
problem.
|
||||||
|
|
||||||
|
You should \fBnot\fP enable this feature unless you encounter the no buffer
|
||||||
|
space available issue. Reducing the TCP buffers affects window size for
|
||||||
|
for the TCP stream and will reduce throughput in proportion to round trip
|
||||||
|
time on long paths.
|
||||||
|
.LP
|
||||||
|
.TP
|
||||||
|
\fBConstrainedSockSize \fR\fINUM\fP
|
||||||
|
When \fBConstrainedSockets\fP is enabled the recv and xmit buffers for
|
||||||
|
all sockets will be set to this limit. Must be a value between 2048
|
||||||
|
and 262144 in 1024 byte increments. Default of 8192 is recommended.
|
||||||
|
.LP
|
||||||
|
.TP
|
||||||
\fBControlPort \fR\fIPort\fP
|
\fBControlPort \fR\fIPort\fP
|
||||||
If set, Tor will accept connections on this port and allow those
|
If set, Tor will accept connections on this port and allow those
|
||||||
connections to control the Tor process using the Tor Control Protocol
|
connections to control the Tor process using the Tor Control Protocol
|
||||||
|
@ -146,6 +146,8 @@ static config_var_t _option_vars[] = {
|
|||||||
VAR("CircuitIdleTimeout", INTERVAL, CircuitIdleTimeout, "1 hour"),
|
VAR("CircuitIdleTimeout", INTERVAL, CircuitIdleTimeout, "1 hour"),
|
||||||
VAR("ClientOnly", BOOL, ClientOnly, "0"),
|
VAR("ClientOnly", BOOL, ClientOnly, "0"),
|
||||||
VAR("ConnLimit", UINT, ConnLimit, "1000"),
|
VAR("ConnLimit", UINT, ConnLimit, "1000"),
|
||||||
|
VAR("ConstrainedSockets", BOOL, ConstrainedSockets, "0"),
|
||||||
|
VAR("ConstrainedSockSize", UINT, ConstrainedSockSize, "8192"),
|
||||||
VAR("ContactInfo", STRING, ContactInfo, NULL),
|
VAR("ContactInfo", STRING, ContactInfo, NULL),
|
||||||
VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
|
VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
|
||||||
VAR("ControlPort", UINT, ControlPort, "0"),
|
VAR("ControlPort", UINT, ControlPort, "0"),
|
||||||
@ -330,6 +332,11 @@ static config_var_description_t options_description[] = {
|
|||||||
{ "BandwidthBurst", "Limit the maximum token buffer size (also known as "
|
{ "BandwidthBurst", "Limit the maximum token buffer size (also known as "
|
||||||
"burst) to the given number of bytes." },
|
"burst) to the given number of bytes." },
|
||||||
{ "ConnLimit", "Maximum number of simultaneous sockets allowed." },
|
{ "ConnLimit", "Maximum number of simultaneous sockets allowed." },
|
||||||
|
{ "ConstrainedSockets", "Shrink tx and rx buffers for sockets to avoid "
|
||||||
|
"system limits on vservers and related environments. See man page for "
|
||||||
|
"more information regarding this option." },
|
||||||
|
{ "ConstrainedSockSize", "Limit socket buffers to this size when "
|
||||||
|
"ConstrainedSockets is enabled." },
|
||||||
/* ControlListenAddress */
|
/* ControlListenAddress */
|
||||||
{ "ControlPort", "If set, Tor will accept connections from the same machine "
|
{ "ControlPort", "If set, Tor will accept connections from the same machine "
|
||||||
"(localhost only) on this port, and allow those connections to control "
|
"(localhost only) on this port, and allow those connections to control "
|
||||||
@ -2925,6 +2932,29 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options->ConstrainedSockets) {
|
||||||
|
/* If the user wants to constrain socket buffer use, make sure the desired
|
||||||
|
* limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
|
||||||
|
if (options->ConstrainedSockSize < MIN_TCPSOCK_BUFFER ||
|
||||||
|
options->ConstrainedSockSize > MAX_TCPSOCK_BUFFER ||
|
||||||
|
options->ConstrainedSockSize % 1024 ) {
|
||||||
|
r = tor_snprintf(buf, sizeof(buf),
|
||||||
|
"ConstrainedSockSize is invalid. Must be a value between %d and %d "
|
||||||
|
"in 1024 byte increments.",
|
||||||
|
MIN_TCPSOCK_BUFFER, MAX_TCPSOCK_BUFFER);
|
||||||
|
*msg = tor_strdup(r >= 0 ? buf : "internal error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (options->DirPort) {
|
||||||
|
/* Providing cached directory entries while system TCP buffers are scarce
|
||||||
|
* will exacerbate the socket errors. Suggest that this be disabled. */
|
||||||
|
COMPLAIN("You have requested constrained socket buffers while also "
|
||||||
|
"serving directory entries via DirPort. It is strongly "
|
||||||
|
"suggested that you disable serving directory requests when "
|
||||||
|
"system TCP buffer resources are scarce.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rend_config_services(options, 1) < 0)
|
if (rend_config_services(options, 1) < 0)
|
||||||
REJECT("Failed to configure rendezvous options. See logs for details.");
|
REJECT("Failed to configure rendezvous options. See logs for details.");
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ static int connection_reached_eof(connection_t *conn);
|
|||||||
static int connection_read_to_buf(connection_t *conn, int *max_to_read);
|
static int connection_read_to_buf(connection_t *conn, int *max_to_read);
|
||||||
static int connection_process_inbuf(connection_t *conn, int package_partial);
|
static int connection_process_inbuf(connection_t *conn, int package_partial);
|
||||||
static void client_check_address_changed(int sock);
|
static void client_check_address_changed(int sock);
|
||||||
|
static void set_constrained_socket_buffers(int sock, int size);
|
||||||
|
|
||||||
static uint32_t last_interface_ip = 0;
|
static uint32_t last_interface_ip = 0;
|
||||||
static smartlist_t *outgoing_addrs = NULL;
|
static smartlist_t *outgoing_addrs = NULL;
|
||||||
@ -898,6 +899,8 @@ connection_handle_listener_read(connection_t *conn, int new_type)
|
|||||||
/* length of the remote address. Must be whatever accept() needs. */
|
/* length of the remote address. Must be whatever accept() needs. */
|
||||||
socklen_t remotelen = 256;
|
socklen_t remotelen = 256;
|
||||||
char tmpbuf[INET_NTOA_BUF_LEN];
|
char tmpbuf[INET_NTOA_BUF_LEN];
|
||||||
|
or_options_t *options = get_options();
|
||||||
|
|
||||||
tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in));
|
tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in));
|
||||||
memset(addrbuf, 0, sizeof(addrbuf));
|
memset(addrbuf, 0, sizeof(addrbuf));
|
||||||
|
|
||||||
@ -923,6 +926,10 @@ connection_handle_listener_read(connection_t *conn, int new_type)
|
|||||||
|
|
||||||
set_socket_nonblocking(news);
|
set_socket_nonblocking(news);
|
||||||
|
|
||||||
|
if (options->ConstrainedSockets) {
|
||||||
|
set_constrained_socket_buffers (news, options->ConstrainedSockSize);
|
||||||
|
}
|
||||||
|
|
||||||
tor_assert(((struct sockaddr*)addrbuf)->sa_family == conn->socket_family);
|
tor_assert(((struct sockaddr*)addrbuf)->sa_family == conn->socket_family);
|
||||||
|
|
||||||
if (conn->socket_family == AF_INET) {
|
if (conn->socket_family == AF_INET) {
|
||||||
@ -1096,6 +1103,10 @@ connection_connect(connection_t *conn, const char *address,
|
|||||||
|
|
||||||
set_socket_nonblocking(s);
|
set_socket_nonblocking(s);
|
||||||
|
|
||||||
|
if (options->ConstrainedSockets) {
|
||||||
|
set_constrained_socket_buffers (s, options->ConstrainedSockSize);
|
||||||
|
}
|
||||||
|
|
||||||
memset(&dest_addr,0,sizeof(dest_addr));
|
memset(&dest_addr,0,sizeof(dest_addr));
|
||||||
dest_addr.sin_family = AF_INET;
|
dest_addr.sin_family = AF_INET;
|
||||||
dest_addr.sin_port = htons(port);
|
dest_addr.sin_port = htons(port);
|
||||||
@ -2540,6 +2551,29 @@ client_check_address_changed(int sock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Some systems have limited system buffers for recv and xmit on
|
||||||
|
* sockets allocated in a virtual server or similar environment. For a Tor
|
||||||
|
* server this can produce the "Error creating network socket: No buffer
|
||||||
|
* space available" error once all available TCP buffer space is consumed.
|
||||||
|
* This method will attempt to constrain the buffers allocated for the socket
|
||||||
|
* to the desired size to stay below system TCP buffer limits.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_constrained_socket_buffers(int sock, int size)
|
||||||
|
{
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (const char *)&size, sizeof(size)) < 0) {
|
||||||
|
int e = tor_socket_errno(sock);
|
||||||
|
log_warn(LD_NET, "setsockopt() to constrain send buffer to %d bytes failed: %s",
|
||||||
|
size, tor_socket_strerror(e));
|
||||||
|
}
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (const char *)&size, sizeof(size)) < 0) {
|
||||||
|
int e = tor_socket_errno(sock);
|
||||||
|
log_warn(LD_NET, "setsockopt() to constrain recv buffer to %d bytes failed: %s",
|
||||||
|
size, tor_socket_strerror(e));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/** Process new bytes that have arrived on conn-\>inbuf.
|
/** Process new bytes that have arrived on conn-\>inbuf.
|
||||||
*
|
*
|
||||||
* This function just passes conn to the connection-specific
|
* This function just passes conn to the connection-specific
|
||||||
|
@ -1748,6 +1748,10 @@ typedef struct exit_redirect_t {
|
|||||||
unsigned is_redirect:1;
|
unsigned is_redirect:1;
|
||||||
} exit_redirect_t;
|
} exit_redirect_t;
|
||||||
|
|
||||||
|
/* limits for TCP send and recv buffer size used for constrained sockets */
|
||||||
|
#define MIN_TCPSOCK_BUFFER 2048
|
||||||
|
#define MAX_TCPSOCK_BUFFER 262144 /* 256k */
|
||||||
|
|
||||||
/** A linked list of lines in a config file. */
|
/** A linked list of lines in a config file. */
|
||||||
typedef struct config_line_t {
|
typedef struct config_line_t {
|
||||||
char *key;
|
char *key;
|
||||||
@ -1889,6 +1893,9 @@ typedef struct {
|
|||||||
config_line_t *ReachableORAddresses; /**< IP:ports for OR conns. */
|
config_line_t *ReachableORAddresses; /**< IP:ports for OR conns. */
|
||||||
config_line_t *ReachableDirAddresses; /**< IP:ports for Dir conns. */
|
config_line_t *ReachableDirAddresses; /**< IP:ports for Dir conns. */
|
||||||
|
|
||||||
|
int ConstrainedSockets; /**< Shrink xmit and recv socket buffers. */
|
||||||
|
int ConstrainedSockSize; /**< Size of constrained buffers. */
|
||||||
|
|
||||||
/** Application ports that require all nodes in circ to have sufficient
|
/** Application ports that require all nodes in circ to have sufficient
|
||||||
* uptime. */
|
* uptime. */
|
||||||
smartlist_t *LongLivedPorts;
|
smartlist_t *LongLivedPorts;
|
||||||
|
Loading…
Reference in New Issue
Block a user