mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Add new DirCache configuration option
This will give relay operators the ability of disabling the caching of directory data. In general, this should not be necessary, but on some lower-resource systems it may beneficial.
This commit is contained in:
committed by
Nick Mathewson
parent
e0bd6cdef2
commit
997f779a7f
@@ -1987,6 +1987,12 @@ if DirPort is non-zero):
|
||||
except that port specifiers are ignored. Any address not matched by
|
||||
some entry in the policy is accepted.
|
||||
|
||||
[[DirCache]] **DirCache** **0**|**1**::
|
||||
When this option is set, Tor caches all current directory documents and
|
||||
accepts client requests for them. Setting DirPort is not required for this,
|
||||
because clients connect via the ORPort by default. Setting either DirPort
|
||||
or BridgeRelay and setting DirCache to 0 is not supported. (Default: 1)
|
||||
|
||||
|
||||
DIRECTORY AUTHORITY SERVER OPTIONS
|
||||
----------------------------------
|
||||
|
||||
@@ -222,6 +222,7 @@ static config_var_t option_vars_[] = {
|
||||
V(DirPortFrontPage, FILENAME, NULL),
|
||||
VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"),
|
||||
VAR("DirAuthority", LINELIST, DirAuthorities, NULL),
|
||||
V(DirCache, BOOL, "1"),
|
||||
V(DirAuthorityFallbackRate, DOUBLE, "1.0"),
|
||||
V(DisableAllSwap, BOOL, "0"),
|
||||
V(DisableDebuggerAttachment, BOOL, "1"),
|
||||
@@ -3457,6 +3458,24 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
REJECT("AccountingRule must be 'sum' or 'max'");
|
||||
}
|
||||
|
||||
if (options->DirPort_set && !options->DirCache) {
|
||||
REJECT("DirPort configured but DirCache disabled. DirPort requires "
|
||||
"DirCache.");
|
||||
}
|
||||
|
||||
if (options->BridgeRelay && !options->DirCache) {
|
||||
REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires "
|
||||
"DirCache.");
|
||||
}
|
||||
|
||||
if (server_mode(options)) {
|
||||
char *msg = NULL;
|
||||
if (have_enough_mem_for_dircache(options, 0, &msg)) {
|
||||
log_warn(LD_CONFIG, "%s", msg);
|
||||
tor_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (options->HTTPProxy) { /* parse it now */
|
||||
if (tor_addr_port_lookup(options->HTTPProxy,
|
||||
&options->HTTPProxyAddr, &options->HTTPProxyPort) < 0)
|
||||
@@ -4065,6 +4084,48 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess)
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have less than 300 MB suggest disabling dircache */
|
||||
#define DIRCACHE_MIN_MB_BANDWIDTH 300
|
||||
#define DIRCACHE_MIN_BANDWIDTH (DIRCACHE_MIN_MB_BANDWIDTH*ONE_MEGABYTE)
|
||||
#define STRINGIFY(val) #val
|
||||
|
||||
/** Create a warning message for emitting if we are a dircache but may not have
|
||||
* enough system memory, or if we are not a dircache but probably should be.
|
||||
* Return -1 when a message is returned in *msg*, else return 0. */
|
||||
STATIC int
|
||||
have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem,
|
||||
char **msg)
|
||||
{
|
||||
*msg = NULL;
|
||||
if (total_mem == 0) {
|
||||
if (get_total_system_memory(&total_mem) < 0)
|
||||
total_mem = options->MaxMemInQueues;
|
||||
}
|
||||
if (options->DirCache) {
|
||||
if (total_mem < DIRCACHE_MIN_BANDWIDTH) {
|
||||
if (options->BridgeRelay) {
|
||||
*msg = strdup("Running a Bridge with less than "
|
||||
STRINGIFY(DIRCACHE_MIN_MB_BANDWIDTH) " MB of memory is "
|
||||
"not recommended.");
|
||||
} else {
|
||||
*msg = strdup("Being a directory cache (default) with less than "
|
||||
STRINGIFY(DIRCACHE_MIN_MB_BANDWIDTH) " MB of memory is "
|
||||
"not recommended and may consume most of the available "
|
||||
"resources, consider disabling this functionality by "
|
||||
"setting the DirCache option to 0.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (total_mem >= DIRCACHE_MIN_BANDWIDTH) {
|
||||
*msg = strdup("DirCache is disabled and we are configured as a "
|
||||
"relay. This may disqualify us from becoming a guard in the "
|
||||
"future.");
|
||||
}
|
||||
}
|
||||
return *msg == NULL ? 0 : -1;
|
||||
}
|
||||
#undef STRINGIFY
|
||||
|
||||
/** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
|
||||
* equal strings. */
|
||||
static int
|
||||
|
||||
@@ -158,6 +158,8 @@ STATIC int parse_dir_authority_line(const char *line,
|
||||
dirinfo_type_t required_type,
|
||||
int validate_only);
|
||||
STATIC int parse_dir_fallback_line(const char *line, int validate_only);
|
||||
STATIC int have_enough_mem_for_dircache(const or_options_t *options,
|
||||
size_t total_mem, char **msg);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3969,6 +3969,10 @@ typedef struct {
|
||||
/** Should we fetch our dir info at the start of the consensus period? */
|
||||
int FetchDirInfoExtraEarly;
|
||||
|
||||
int DirCache; /**< Cache all directory documents and accept requests via
|
||||
* tunnelled dir conns from clients. If 1, enabled (default);
|
||||
* If 0, disabled. */
|
||||
|
||||
char *VirtualAddrNetworkIPv4; /**< Address and mask to hand out for virtual
|
||||
* MAPADDRESS requests for IPv4 addresses */
|
||||
char *VirtualAddrNetworkIPv6; /**< Address and mask to hand out for virtual
|
||||
|
||||
+3
-1
@@ -1176,7 +1176,9 @@ router_should_be_directory_server(const or_options_t *options, int dir_port)
|
||||
int
|
||||
dir_server_mode(const or_options_t *options)
|
||||
{
|
||||
return (server_mode(options) || options->DirPort_set) &&
|
||||
if (!options->DirCache)
|
||||
return 0;
|
||||
return (server_mode(options) || options->DirPort_set) &&
|
||||
router_should_be_directory_server(options, 0);
|
||||
}
|
||||
|
||||
|
||||
+110
-5
@@ -69,22 +69,29 @@ clear_log_messages(void)
|
||||
messages = NULL;
|
||||
}
|
||||
|
||||
#define setup_options(opt,dflt) \
|
||||
do { \
|
||||
opt = options_new(); \
|
||||
opt->command = CMD_RUN_TOR; \
|
||||
options_init(opt); \
|
||||
\
|
||||
dflt = config_dup(&options_format, opt); \
|
||||
clear_log_messages(); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
test_options_validate_impl(const char *configuration,
|
||||
const char *expect_errmsg,
|
||||
int expect_log_severity,
|
||||
const char *expect_log)
|
||||
{
|
||||
or_options_t *opt = options_new();
|
||||
or_options_t *opt=NULL;
|
||||
or_options_t *dflt;
|
||||
config_line_t *cl=NULL;
|
||||
char *msg=NULL;
|
||||
int r;
|
||||
opt->command = CMD_RUN_TOR;
|
||||
options_init(opt);
|
||||
|
||||
dflt = config_dup(&options_format, opt);
|
||||
clear_log_messages();
|
||||
setup_options(opt, dflt);
|
||||
|
||||
r = config_get_lines(configuration, &cl, 1);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
@@ -159,12 +166,110 @@ test_options_validate(void *arg)
|
||||
"ServerTransportOptions did not parse",
|
||||
LOG_WARN, "\"slingsnappy\" is not a k=v");
|
||||
|
||||
WANT_ERR("DirPort 8080\nDirCache 0",
|
||||
"DirPort configured but DirCache disabled.");
|
||||
WANT_ERR("BridgeRelay 1\nDirCache 0",
|
||||
"We're a bridge but DirCache is disabled.");
|
||||
|
||||
clear_log_messages();
|
||||
return;
|
||||
}
|
||||
|
||||
#define MEGABYTEIFY(mb) (U64_LITERAL(mb) << 20)
|
||||
static void
|
||||
test_have_enough_mem_for_dircache(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
or_options_t *opt=NULL;
|
||||
or_options_t *dflt;
|
||||
config_line_t *cl=NULL;
|
||||
char *msg=NULL;;
|
||||
int r;
|
||||
const char *configuration = "ORPort 8080\nDirCache 1", *expect_errmsg;
|
||||
|
||||
setup_options(opt, dflt);
|
||||
setup_log_callback();
|
||||
(void)dflt;
|
||||
|
||||
r = config_get_lines(configuration, &cl, 1);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
|
||||
r = config_assign(&options_format, opt, cl, 0, 0, &msg);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
|
||||
/* 300 MB RAM available, DirCache enabled */
|
||||
r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
tt_assert(!msg);
|
||||
|
||||
/* 200 MB RAM available, DirCache enabled */
|
||||
r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg);
|
||||
tt_int_op(r, OP_EQ, -1);
|
||||
expect_errmsg = "Being a directory cache (default) with less than ";
|
||||
if (!strstr(msg, expect_errmsg)) {
|
||||
TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
|
||||
expect_errmsg, configuration, msg));
|
||||
}
|
||||
tor_free(msg);
|
||||
|
||||
configuration = "ORPort 8080\nDirCache 1\nBridgeRelay 1";
|
||||
r = config_get_lines(configuration, &cl, 1);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
|
||||
r = config_assign(&options_format, opt, cl, 0, 0, &msg);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
|
||||
/* 300 MB RAM available, DirCache enabled, Bridge */
|
||||
r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
tt_assert(!msg);
|
||||
|
||||
/* 200 MB RAM available, DirCache enabled, Bridge */
|
||||
r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg);
|
||||
tt_int_op(r, OP_EQ, -1);
|
||||
expect_errmsg = "Running a Bridge with less than ";
|
||||
if (!strstr(msg, expect_errmsg)) {
|
||||
TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
|
||||
expect_errmsg, configuration, msg));
|
||||
}
|
||||
tor_free(msg);
|
||||
|
||||
configuration = "ORPort 8080\nDirCache 0";
|
||||
r = config_get_lines(configuration, &cl, 1);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
|
||||
r = config_assign(&options_format, opt, cl, 0, 0, &msg);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
|
||||
/* 200 MB RAM available, DirCache disabled */
|
||||
r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg);
|
||||
tt_int_op(r, OP_EQ, 0);
|
||||
tt_assert(!msg);
|
||||
|
||||
/* 300 MB RAM available, DirCache disabled */
|
||||
r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg);
|
||||
tt_int_op(r, OP_EQ, -1);
|
||||
expect_errmsg = "DirCache is disabled and we are configured as a ";
|
||||
if (!strstr(msg, expect_errmsg)) {
|
||||
TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
|
||||
expect_errmsg, configuration, msg));
|
||||
}
|
||||
tor_free(msg);
|
||||
|
||||
clear_log_messages();
|
||||
|
||||
done:
|
||||
if (msg)
|
||||
tor_free(msg);
|
||||
tor_free(dflt);
|
||||
tor_free(opt);
|
||||
tor_free(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
struct testcase_t options_tests[] = {
|
||||
{ "validate", test_options_validate, TT_FORK, NULL, NULL },
|
||||
{ "mem_dircache", test_have_enough_mem_for_dircache, TT_FORK, NULL, NULL },
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user