mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-03 00:53:32 +01:00
Add Maxima lists to bandwidth state.
Right now, Tor routers don't save the maxima values from the bw_history_t between sessions. That's no good, since we use those values to determine bandwidth. This code adds a new BWHist.*Maximum set of values to the state file. If they're not present, we estimate them by taking the observed total bandwidth and dividing it by the period length, which provides a lower bound. This should fix bug 1863. I'm calling it a feature.
This commit is contained in:
parent
28844c8403
commit
105b94b75b
@ -1,3 +1,10 @@
|
|||||||
|
o Minor features
|
||||||
|
- Servers now save observed maximum bandwidth throughput rates
|
||||||
|
to their state file (along with total usage, which was already
|
||||||
|
saved) so that they can determine their correct estimated
|
||||||
|
bandwidth on restart. Resolves bug 1863, where Tor servers
|
||||||
|
would reset their estimated bandwidth to 0 after restarting.
|
||||||
|
|
||||||
o Minor bugfixes
|
o Minor bugfixes
|
||||||
- Fix a bug in banwidth history state parsing that could have been
|
- Fix a bug in banwidth history state parsing that could have been
|
||||||
triggered if a future version of Tor ever changed the timing
|
triggered if a future version of Tor ever changed the timing
|
||||||
@ -7,4 +14,3 @@
|
|||||||
error parsing any bw history value from the state file. Bugfix on
|
error parsing any bw history value from the state file. Bugfix on
|
||||||
Tor 0.2.2.15-alpha.
|
Tor 0.2.2.15-alpha.
|
||||||
|
|
||||||
|
|
||||||
|
@ -443,15 +443,19 @@ static config_var_t _state_vars[] = {
|
|||||||
V(BWHistoryReadEnds, ISOTIME, NULL),
|
V(BWHistoryReadEnds, ISOTIME, NULL),
|
||||||
V(BWHistoryReadInterval, UINT, "900"),
|
V(BWHistoryReadInterval, UINT, "900"),
|
||||||
V(BWHistoryReadValues, CSV, ""),
|
V(BWHistoryReadValues, CSV, ""),
|
||||||
|
V(BWHistoryReadMaxima, CSV, ""),
|
||||||
V(BWHistoryWriteEnds, ISOTIME, NULL),
|
V(BWHistoryWriteEnds, ISOTIME, NULL),
|
||||||
V(BWHistoryWriteInterval, UINT, "900"),
|
V(BWHistoryWriteInterval, UINT, "900"),
|
||||||
V(BWHistoryWriteValues, CSV, ""),
|
V(BWHistoryWriteValues, CSV, ""),
|
||||||
|
V(BWHistoryWriteMaxima, CSV, ""),
|
||||||
V(BWHistoryDirReadEnds, ISOTIME, NULL),
|
V(BWHistoryDirReadEnds, ISOTIME, NULL),
|
||||||
V(BWHistoryDirReadInterval, UINT, "900"),
|
V(BWHistoryDirReadInterval, UINT, "900"),
|
||||||
V(BWHistoryDirReadValues, CSV, ""),
|
V(BWHistoryDirReadValues, CSV, ""),
|
||||||
|
V(BWHistoryDirReadMaxima, CSV, ""),
|
||||||
V(BWHistoryDirWriteEnds, ISOTIME, NULL),
|
V(BWHistoryDirWriteEnds, ISOTIME, NULL),
|
||||||
V(BWHistoryDirWriteInterval, UINT, "900"),
|
V(BWHistoryDirWriteInterval, UINT, "900"),
|
||||||
V(BWHistoryDirWriteValues, CSV, ""),
|
V(BWHistoryDirWriteValues, CSV, ""),
|
||||||
|
V(BWHistoryDirWriteMaxima, CSV, ""),
|
||||||
|
|
||||||
V(TorVersion, STRING, NULL),
|
V(TorVersion, STRING, NULL),
|
||||||
|
|
||||||
|
@ -2856,19 +2856,25 @@ typedef struct {
|
|||||||
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
|
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
|
||||||
* of the entries of Values. The "Values" lists hold decimal string
|
* of the entries of Values. The "Values" lists hold decimal string
|
||||||
* representations of the number of bytes read or written in each
|
* representations of the number of bytes read or written in each
|
||||||
* interval. */
|
* interval. The "Maxima" list holds decimal strings describing the highest
|
||||||
|
* rate achieved during the interval.
|
||||||
|
*/
|
||||||
time_t BWHistoryReadEnds;
|
time_t BWHistoryReadEnds;
|
||||||
int BWHistoryReadInterval;
|
int BWHistoryReadInterval;
|
||||||
smartlist_t *BWHistoryReadValues;
|
smartlist_t *BWHistoryReadValues;
|
||||||
|
smartlist_t *BWHistoryReadMaxima;
|
||||||
time_t BWHistoryWriteEnds;
|
time_t BWHistoryWriteEnds;
|
||||||
int BWHistoryWriteInterval;
|
int BWHistoryWriteInterval;
|
||||||
smartlist_t *BWHistoryWriteValues;
|
smartlist_t *BWHistoryWriteValues;
|
||||||
|
smartlist_t *BWHistoryWriteMaxima;
|
||||||
time_t BWHistoryDirReadEnds;
|
time_t BWHistoryDirReadEnds;
|
||||||
int BWHistoryDirReadInterval;
|
int BWHistoryDirReadInterval;
|
||||||
smartlist_t *BWHistoryDirReadValues;
|
smartlist_t *BWHistoryDirReadValues;
|
||||||
|
smartlist_t *BWHistoryDirReadMaxima;
|
||||||
time_t BWHistoryDirWriteEnds;
|
time_t BWHistoryDirWriteEnds;
|
||||||
int BWHistoryDirWriteInterval;
|
int BWHistoryDirWriteInterval;
|
||||||
smartlist_t *BWHistoryDirWriteValues;
|
smartlist_t *BWHistoryDirWriteValues;
|
||||||
|
smartlist_t *BWHistoryDirWriteMaxima;
|
||||||
|
|
||||||
/** Build time histogram */
|
/** Build time histogram */
|
||||||
config_line_t * BuildtimeHistogram;
|
config_line_t * BuildtimeHistogram;
|
||||||
|
@ -1261,8 +1261,12 @@ add_obs(bw_array_t *b, time_t when, uint64_t n)
|
|||||||
/* If we're currently adding observations for an earlier second than
|
/* If we're currently adding observations for an earlier second than
|
||||||
* 'when', advance b->cur_obs_time and b->cur_obs_idx by an
|
* 'when', advance b->cur_obs_time and b->cur_obs_idx by an
|
||||||
* appropriate number of seconds, and do all the other housekeeping */
|
* appropriate number of seconds, and do all the other housekeeping */
|
||||||
while (when>b->cur_obs_time)
|
while (when>b->cur_obs_time) {
|
||||||
|
/* Doing this one second at a time is potentially inefficient, if we start
|
||||||
|
with a state file that is very old. Fortunately, it doesn't seem to
|
||||||
|
show up in profiles, so we can just ignore it for now. */
|
||||||
advance_obs(b);
|
advance_obs(b);
|
||||||
|
}
|
||||||
|
|
||||||
b->obs[b->cur_obs_idx] += n;
|
b->obs[b->cur_obs_idx] += n;
|
||||||
b->total_in_period += n;
|
b->total_in_period += n;
|
||||||
@ -1497,15 +1501,21 @@ static void
|
|||||||
rep_hist_update_bwhist_state_section(or_state_t *state,
|
rep_hist_update_bwhist_state_section(or_state_t *state,
|
||||||
const bw_array_t *b,
|
const bw_array_t *b,
|
||||||
smartlist_t **s_values,
|
smartlist_t **s_values,
|
||||||
|
smartlist_t **s_maxima,
|
||||||
time_t *s_begins,
|
time_t *s_begins,
|
||||||
int *s_interval)
|
int *s_interval)
|
||||||
{
|
{
|
||||||
char buf[20*NUM_TOTALS + 1], *cp;
|
char *cp;
|
||||||
|
int i,j;
|
||||||
|
|
||||||
if (*s_values) {
|
if (*s_values) {
|
||||||
SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
|
SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
|
||||||
smartlist_free(*s_values);
|
smartlist_free(*s_values);
|
||||||
}
|
}
|
||||||
|
if (*s_maxima) {
|
||||||
|
SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
|
||||||
|
smartlist_free(*s_maxima);
|
||||||
|
}
|
||||||
if (! server_mode(get_options())) {
|
if (! server_mode(get_options())) {
|
||||||
/* Clients don't need to store bandwidth history persistently;
|
/* Clients don't need to store bandwidth history persistently;
|
||||||
* force these values to the defaults. */
|
* force these values to the defaults. */
|
||||||
@ -1519,18 +1529,30 @@ rep_hist_update_bwhist_state_section(or_state_t *state,
|
|||||||
*s_begins = 0;
|
*s_begins = 0;
|
||||||
*s_interval = 900;
|
*s_interval = 900;
|
||||||
*s_values = smartlist_create();
|
*s_values = smartlist_create();
|
||||||
|
*s_maxima = smartlist_create();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*s_begins = b->next_period;
|
*s_begins = b->next_period;
|
||||||
*s_interval = NUM_SECS_BW_SUM_INTERVAL;
|
*s_interval = NUM_SECS_BW_SUM_INTERVAL;
|
||||||
cp = buf;
|
|
||||||
cp += rep_hist_fill_bandwidth_history(cp, sizeof(buf), b);
|
|
||||||
tor_snprintf(cp, sizeof(buf)-(cp-buf),
|
|
||||||
cp == buf ? U64_FORMAT : ","U64_FORMAT,
|
|
||||||
U64_PRINTF_ARG(b->total_in_period));
|
|
||||||
*s_values = smartlist_create();
|
*s_values = smartlist_create();
|
||||||
if (server_mode(get_options()))
|
*s_maxima = smartlist_create();
|
||||||
smartlist_split_string(*s_values, buf, ",", SPLIT_SKIP_SPACE, 0);
|
/* Set i to first position in circular array */
|
||||||
|
i = (b->num_maxes_set <= b->next_max_idx) ? 0 : b->next_max_idx;
|
||||||
|
for (j=0; j < b->num_maxes_set; ++j,++i) {
|
||||||
|
uint64_t maxval;
|
||||||
|
if (i > NUM_TOTALS)
|
||||||
|
i = 0;
|
||||||
|
tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(b->totals[i] & ~0x3ff));
|
||||||
|
smartlist_add(*s_values, cp);
|
||||||
|
maxval = b->maxima[i] / NUM_SECS_ROLLING_MEASURE;
|
||||||
|
tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(maxval & ~0x3ff));
|
||||||
|
smartlist_add(*s_maxima, cp);
|
||||||
|
}
|
||||||
|
tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(b->total_in_period & ~0x3ff));
|
||||||
|
smartlist_add(*s_values, cp);
|
||||||
|
tor_asprintf(&cp, U64_FORMAT, U64_PRINTF_ARG(b->max_total & ~0x3ff));
|
||||||
|
smartlist_add(*s_maxima, cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update <b>state</b> with the newest bandwidth history. */
|
/** Update <b>state</b> with the newest bandwidth history. */
|
||||||
@ -1541,6 +1563,7 @@ rep_hist_update_state(or_state_t *state)
|
|||||||
rep_hist_update_bwhist_state_section(state,\
|
rep_hist_update_bwhist_state_section(state,\
|
||||||
(arrname),\
|
(arrname),\
|
||||||
&state->BWHistory ## st ## Values, \
|
&state->BWHistory ## st ## Values, \
|
||||||
|
&state->BWHistory ## st ## Maxima, \
|
||||||
&state->BWHistory ## st ## Ends, \
|
&state->BWHistory ## st ## Ends, \
|
||||||
&state->BWHistory ## st ## Interval)
|
&state->BWHistory ## st ## Interval)
|
||||||
|
|
||||||
@ -1560,6 +1583,7 @@ rep_hist_update_state(or_state_t *state)
|
|||||||
static int
|
static int
|
||||||
rep_hist_load_bwhist_state_section(bw_array_t *b,
|
rep_hist_load_bwhist_state_section(bw_array_t *b,
|
||||||
const smartlist_t *s_values,
|
const smartlist_t *s_values,
|
||||||
|
const smartlist_t *s_maxima,
|
||||||
const time_t s_begins,
|
const time_t s_begins,
|
||||||
const int s_interval)
|
const int s_interval)
|
||||||
{
|
{
|
||||||
@ -1567,8 +1591,9 @@ rep_hist_load_bwhist_state_section(bw_array_t *b,
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
time_t start;
|
time_t start;
|
||||||
|
|
||||||
uint64_t v;
|
uint64_t v, mv;
|
||||||
int i,ok;
|
int i,ok,ok_m;
|
||||||
|
int have_maxima = (smartlist_len(s_values) == smartlist_len(s_maxima));
|
||||||
|
|
||||||
if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
|
if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
|
||||||
start = s_begins - s_interval*(smartlist_len(s_values));
|
start = s_begins - s_interval*(smartlist_len(s_values));
|
||||||
@ -1578,12 +1603,22 @@ rep_hist_load_bwhist_state_section(bw_array_t *b,
|
|||||||
b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
|
b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
|
||||||
SMARTLIST_FOREACH_BEGIN(s_values, const char *, cp) {
|
SMARTLIST_FOREACH_BEGIN(s_values, const char *, cp) {
|
||||||
v = tor_parse_uint64(cp, 10, 0, UINT64_MAX, &ok, NULL);
|
v = tor_parse_uint64(cp, 10, 0, UINT64_MAX, &ok, NULL);
|
||||||
if (!ok) {
|
if (have_maxima) {
|
||||||
|
const char *maxstr = smartlist_get(s_maxima, cp_sl_idx);
|
||||||
|
mv = tor_parse_uint64(maxstr, 10, 0, UINT64_MAX, &ok_m, NULL);
|
||||||
|
mv *= NUM_SECS_ROLLING_MEASURE;
|
||||||
|
} else {
|
||||||
|
/* No maxima known; guess average rate to be conservative. */
|
||||||
|
mv = v / s_interval;
|
||||||
|
}
|
||||||
|
if (!ok || !ok_m) {
|
||||||
retval = -1;
|
retval = -1;
|
||||||
log_notice(LD_HIST, "Could not parse '%s' into a number.'", cp);
|
log_notice(LD_HIST, "Could not parse '%s' into a number.'", cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start < now) {
|
if (start < now) {
|
||||||
add_obs(b, start, v);
|
add_obs(b, start, v);
|
||||||
|
b->max_total = mv;
|
||||||
/* This will result in some fairly choppy history if s_interval
|
/* This will result in some fairly choppy history if s_interval
|
||||||
* is notthe same as NUM_SECS_BW_SUM_INTERVAL. XXXX */
|
* is notthe same as NUM_SECS_BW_SUM_INTERVAL. XXXX */
|
||||||
start += s_interval;
|
start += s_interval;
|
||||||
@ -1592,15 +1627,10 @@ rep_hist_load_bwhist_state_section(bw_array_t *b,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up maxima and observed */
|
/* Clean up maxima and observed */
|
||||||
/* Do we really want to zero this for the purpose of max capacity? */
|
|
||||||
for (i=0; i<NUM_SECS_ROLLING_MEASURE; ++i) {
|
for (i=0; i<NUM_SECS_ROLLING_MEASURE; ++i) {
|
||||||
b->obs[i] = 0;
|
b->obs[i] = 0;
|
||||||
}
|
}
|
||||||
b->total_obs = 0;
|
b->total_obs = 0;
|
||||||
for (i=0; i<NUM_TOTALS; ++i) {
|
|
||||||
b->maxima[i] = 0;
|
|
||||||
}
|
|
||||||
b->max_total = 0;
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -1619,6 +1649,7 @@ rep_hist_load_state(or_state_t *state, char **err)
|
|||||||
if (rep_hist_load_bwhist_state_section( \
|
if (rep_hist_load_bwhist_state_section( \
|
||||||
(arrname), \
|
(arrname), \
|
||||||
state->BWHistory ## st ## Values, \
|
state->BWHistory ## st ## Values, \
|
||||||
|
state->BWHistory ## st ## Maxima, \
|
||||||
state->BWHistory ## st ## Ends, \
|
state->BWHistory ## st ## Ends, \
|
||||||
state->BWHistory ## st ## Interval)<0) \
|
state->BWHistory ## st ## Interval)<0) \
|
||||||
all_ok = 0
|
all_ok = 0
|
||||||
|
Loading…
Reference in New Issue
Block a user