[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r9170: reinstate the most important dead chickens for limiting impa (in tor/trunk: doc src/or)
- To: or-cvs@xxxxxxxxxxxxx
- Subject: [or-cvs] r9170: reinstate the most important dead chickens for limiting impa (in tor/trunk: doc src/or)
- From: arma@xxxxxxxx
- Date: Sat, 23 Dec 2006 03:48:19 -0500 (EST)
- Delivered-to: archiver@seul.org
- Delivered-to: or-cvs-outgoing@seul.org
- Delivered-to: or-cvs@seul.org
- Delivery-date: Sat, 23 Dec 2006 03:48:38 -0500
- Reply-to: or-talk@xxxxxxxxxxxxx
- Sender: owner-or-cvs@xxxxxxxxxxxxx
Author: arma
Date: 2006-12-23 03:48:16 -0500 (Sat, 23 Dec 2006)
New Revision: 9170
Modified:
tor/trunk/doc/TODO
tor/trunk/doc/dir-spec.txt
tor/trunk/src/or/connection.c
tor/trunk/src/or/directory.c
tor/trunk/src/or/dirserv.c
tor/trunk/src/or/or.h
Log:
reinstate the most important dead chickens for limiting
impact of directory writes now that we're write limiting.
a few more dead chickens remain.
Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO 2006-12-21 17:38:15 UTC (rev 9169)
+++ tor/trunk/doc/TODO 2006-12-23 08:48:16 UTC (rev 9170)
@@ -183,7 +183,8 @@
R - "bandwidth classes", for incoming vs initiated-here conns,
and to give dir conns lower priority.
. Write limiting; separate token bucket for write
- - preemptively give a 503 to some dir requests
+ o preemptively give a 503 to some v1 dir requests
+ - preemptively give a 503 to some v2 dir requests
- per-conn write buckets
- separate config options for read vs write limiting
Modified: tor/trunk/doc/dir-spec.txt
===================================================================
--- tor/trunk/doc/dir-spec.txt 2006-12-21 17:38:15 UTC (rev 9169)
+++ tor/trunk/doc/dir-spec.txt 2006-12-23 08:48:16 UTC (rev 9170)
@@ -215,10 +215,10 @@
"accept" exitpattern
"reject" exitpattern
- These lines, in order, describe the rules that an OR follows when
+ These lines describe the rules that an OR follows when
deciding whether to allow a new stream to a given address. The
'exitpattern' syntax is described below. The rules are considered in
- order; if no rule matches, the address will be accept. For clarity,
+ order; if no rule matches, the address will be accepted. For clarity,
the last such entry SHOULD be accept *:* or reject *:*.
"router-signature" NL Signature NL
Modified: tor/trunk/src/or/connection.c
===================================================================
--- tor/trunk/src/or/connection.c 2006-12-21 17:38:15 UTC (rev 9169)
+++ tor/trunk/src/or/connection.c 2006-12-23 08:48:16 UTC (rev 9170)
@@ -1104,19 +1104,22 @@
extern int global_read_bucket, global_write_bucket;
static int
-connection_bucket_round_robin(int base, int global_bucket, int conn_bucket)
+connection_bucket_round_robin(int base, int priority,
+ int global_bucket, int conn_bucket)
{
int at_most;
+ int num_bytes_high = (priority ? 32 : 16) * base;
+ int num_bytes_low = (priority ? 4 : 2) * base;
/* Do a rudimentary round-robin so one circuit can't hog a connection.
* Pick at most 32 cells, at least 4 cells if possible, and if we're in
* the middle pick 1/8 of the available bandwidth. */
at_most = global_bucket / 8;
at_most -= (at_most % base); /* round down */
- if (at_most > 32*base) /* 16 KB */
- at_most = 32*base;
- else if (at_most < 4*base) /* 2 KB */
- at_most = 4*base;
+ if (at_most > num_bytes_high) /* 16 KB, or 8 KB for low-priority */
+ at_most = num_bytes_high;
+ else if (at_most < num_bytes_low) /* 2 KB, or 1 KB for low-priority */
+ at_most = num_bytes_low;
if (at_most > global_bucket)
at_most = global_bucket;
@@ -1135,12 +1138,14 @@
{
int base = connection_speaks_cells(conn) ?
CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE;
+ int priority = conn->type != CONN_TYPE_DIR;
int conn_bucket = -1;
if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) {
or_connection_t *or_conn = TO_OR_CONN(conn);
conn_bucket = or_conn->read_bucket;
}
- return connection_bucket_round_robin(base, global_read_bucket, conn_bucket);
+ return connection_bucket_round_robin(base, priority,
+ global_read_bucket, conn_bucket);
}
/** How many bytes at most can we write onto this connection? */
@@ -1149,17 +1154,44 @@
{
int base = connection_speaks_cells(conn) ?
CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE;
+ int priority = conn->type != CONN_TYPE_DIR;
- return connection_bucket_round_robin(base, global_write_bucket,
+ return connection_bucket_round_robin(base, priority, global_write_bucket,
conn->outbuf_flushlen);
}
-/** Return 1 if the global write bucket has no bytes in it,
- * or return 0 if it does. */
+/** Return 1 if the global write bucket is low enough that we shouldn't
+ * send <b>attempt</b> bytes of low-priority directory stuff out.
+ * Else return 0.
+
+ * Priority is 1 for v1 requests (directories and running-routers),
+ * and 2 for v2 requests (statuses and descriptors). But see FFFF in
+ * directory_handle_command_get() for why we don't use priority 2 yet.
+ *
+ * There are a lot of parameters we could use here:
+ * - global_write_bucket. Low is bad.
+ * - bandwidthrate. Low is bad.
+ * - bandwidthburst. Not a big factor?
+ * - attempt. High is bad.
+ * - total bytes queued on outbufs. High is bad. But I'm wary of
+ * using this, since a few slow-flushing queues will pump up the
+ * number without meaning what we meant to mean. What we really
+ * mean is "total directory bytes added to outbufs recently", but
+ * that's harder to quantify and harder to keep track of.
+ */
int
-global_write_bucket_empty(void)
+global_write_bucket_low(size_t attempt, int priority)
{
- return global_write_bucket <= 0;
+ if (global_write_bucket < (int)attempt) /* not enough space no matter what */
+ return 1;
+
+ if (priority == 1) { /* old-style v1 query */
+ if (global_write_bucket-attempt < 2*get_options()->BandwidthRate)
+ return 1;
+ } else { /* v2 query */
+ /* no further constraints yet */
+ }
+ return 0;
}
/** We just read num_read onto conn. Decrement buckets appropriately. */
Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c 2006-12-21 17:38:15 UTC (rev 9169)
+++ tor/trunk/src/or/directory.c 2006-12-23 08:48:16 UTC (rev 9170)
@@ -1510,7 +1510,7 @@
}
dlen = deflated ? d->dir_z_len : d->dir_len;
- if (global_write_bucket_empty()) {
+ if (global_write_bucket_low(dlen, 1)) {
log_info(LD_DIRSERV,
"Client asked for the mirrored directory, but we've been "
"writing too many bytes lately. Sending 503 Dir busy.");
@@ -1544,16 +1544,24 @@
!strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
int deflated = !strcmp(url,"/tor/running-routers.z");
dlen = dirserv_get_runningrouters(&cp, deflated);
- note_request(url, dlen);
- tor_free(url);
if (!dlen) { /* we failed to create/cache cp */
write_http_status_line(conn, 503, "Directory unavailable");
/* try to get a new one now */
if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
+ tor_free(url);
return 0;
}
-
+ if (global_write_bucket_low(dlen, 1)) {
+ log_info(LD_DIRSERV,
+ "Client asked for running-routers, but we've been "
+ "writing too many bytes lately. Sending 503 Dir busy.");
+ write_http_status_line(conn, 503, "Directory busy, try again later");
+ tor_free(url);
+ return 0;
+ }
+ note_request(url, dlen);
+ tor_free(url);
write_http_response_header(conn, dlen,
deflated?"application/octet-stream":"text/plain",
deflated?"deflate":"identity",
@@ -1562,6 +1570,10 @@
return 0;
}
+ /* FFFF for status/ and server/ requests, we don't have a good
+ * guess of the length we're going to be writing out, so it's hard
+ * to call global_write_bucket_low(). How to proceed? */
+
if (!strcmpstart(url,"/tor/status/")) {
/* v2 network status fetch. */
size_t url_len = strlen(url);
Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c 2006-12-21 17:38:15 UTC (rev 9169)
+++ tor/trunk/src/or/dirserv.c 2006-12-23 08:48:16 UTC (rev 9170)
@@ -1101,7 +1101,7 @@
/** Helper: If we're an authority for the right directory version (the
* directory version is determined by <b>is_v1_object</b>), try to regenerate
* auth_src as appropriate and return it, falling back to cache_src on
- * failure. If we're a cache, return cach_src.
+ * failure. If we're a cache, return cache_src.
*/
static cached_dir_t *
dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2006-12-21 17:38:15 UTC (rev 9169)
+++ tor/trunk/src/or/or.h 2006-12-23 08:48:16 UTC (rev 9170)
@@ -1976,7 +1976,7 @@
smartlist_t *new_conns);
int connection_bucket_write_limit(connection_t *conn);
-int global_write_bucket_empty(void);
+int global_write_bucket_low(size_t attempt, int priority);
void connection_bucket_init(void);
void connection_bucket_refill(int seconds_elapsed);