mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Tweak CELL_STATS event based on comments by nickm.
- Move cell_command_to_string from control.c to command.c. - Use accessor for global_circuitlist instead of extern. - Add a struct for cell statistics by command instead of six arrays. - Split up control_event_circuit_cell_stats by using two helper functions. - Add TestingEnableCellStatsEvent option. - Prepare functions for testing. - Rename a few variables and document a few things better.
This commit is contained in:
parent
2f893624ab
commit
26b49f525d
@ -2006,6 +2006,7 @@ The following options are used for running a testing Tor network.
|
|||||||
TestingAuthDirTimeToLearnReachability 0 minutes
|
TestingAuthDirTimeToLearnReachability 0 minutes
|
||||||
TestingEstimatedDescriptorPropagationTime 0 minutes
|
TestingEstimatedDescriptorPropagationTime 0 minutes
|
||||||
TestingEnableConnBwEvent 1
|
TestingEnableConnBwEvent 1
|
||||||
|
TestingEnableCellStatsEvent 1
|
||||||
|
|
||||||
**TestingV3AuthInitialVotingInterval** __N__ **minutes**|**hours**::
|
**TestingV3AuthInitialVotingInterval** __N__ **minutes**|**hours**::
|
||||||
Like V3AuthVotingInterval, but for initial voting interval before the first
|
Like V3AuthVotingInterval, but for initial voting interval before the first
|
||||||
@ -2041,6 +2042,11 @@ The following options are used for running a testing Tor network.
|
|||||||
events. Changing this requires that **TestingTorNetwork** is set.
|
events. Changing this requires that **TestingTorNetwork** is set.
|
||||||
(Default: 0)
|
(Default: 0)
|
||||||
|
|
||||||
|
**TestingEnableCellStatsEvent** **0**|**1**::
|
||||||
|
If this option is set, then Tor controllers may register for CELL_STATS
|
||||||
|
events. Changing this requires that **TestingTorNetwork** is set.
|
||||||
|
(Default: 0)
|
||||||
|
|
||||||
|
|
||||||
SIGNALS
|
SIGNALS
|
||||||
-------
|
-------
|
||||||
|
@ -52,6 +52,33 @@ static void command_process_created_cell(cell_t *cell, channel_t *chan);
|
|||||||
static void command_process_relay_cell(cell_t *cell, channel_t *chan);
|
static void command_process_relay_cell(cell_t *cell, channel_t *chan);
|
||||||
static void command_process_destroy_cell(cell_t *cell, channel_t *chan);
|
static void command_process_destroy_cell(cell_t *cell, channel_t *chan);
|
||||||
|
|
||||||
|
/** Convert the cell <b>command</b> into a lower-case, human-readable
|
||||||
|
* string. */
|
||||||
|
const char *
|
||||||
|
cell_command_to_string(uint8_t command)
|
||||||
|
{
|
||||||
|
switch (command) {
|
||||||
|
case CELL_PADDING: return "padding";
|
||||||
|
case CELL_CREATE: return "create";
|
||||||
|
case CELL_CREATED: return "created";
|
||||||
|
case CELL_RELAY: return "relay";
|
||||||
|
case CELL_DESTROY: return "destroy";
|
||||||
|
case CELL_CREATE_FAST: return "create_fast";
|
||||||
|
case CELL_CREATED_FAST: return "created_fast";
|
||||||
|
case CELL_VERSIONS: return "versions";
|
||||||
|
case CELL_NETINFO: return "netinfo";
|
||||||
|
case CELL_RELAY_EARLY: return "relay_early";
|
||||||
|
case CELL_CREATE2: return "create2";
|
||||||
|
case CELL_CREATED2: return "created2";
|
||||||
|
case CELL_VPADDING: return "vpadding";
|
||||||
|
case CELL_CERTS: return "certs";
|
||||||
|
case CELL_AUTH_CHALLENGE: return "auth_challenge";
|
||||||
|
case CELL_AUTHENTICATE: return "authenticate";
|
||||||
|
case CELL_AUTHORIZE: return "authorize";
|
||||||
|
default: return "unrecognized";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef KEEP_TIMING_STATS
|
#ifdef KEEP_TIMING_STATS
|
||||||
/** This is a wrapper function around the actual function that processes the
|
/** This is a wrapper function around the actual function that processes the
|
||||||
* <b>cell</b> that just arrived on <b>conn</b>. Increment <b>*time</b>
|
* <b>cell</b> that just arrived on <b>conn</b>. Increment <b>*time</b>
|
||||||
|
@ -19,6 +19,8 @@ void command_process_var_cell(channel_t *chan, var_cell_t *cell);
|
|||||||
void command_setup_channel(channel_t *chan);
|
void command_setup_channel(channel_t *chan);
|
||||||
void command_setup_listener(channel_listener_t *chan_l);
|
void command_setup_listener(channel_listener_t *chan_l);
|
||||||
|
|
||||||
|
const char *cell_command_to_string(uint8_t command);
|
||||||
|
|
||||||
extern uint64_t stats_n_padding_cells_processed;
|
extern uint64_t stats_n_padding_cells_processed;
|
||||||
extern uint64_t stats_n_create_cells_processed;
|
extern uint64_t stats_n_create_cells_processed;
|
||||||
extern uint64_t stats_n_created_cells_processed;
|
extern uint64_t stats_n_created_cells_processed;
|
||||||
|
@ -219,6 +219,7 @@ static config_var_t option_vars_[] = {
|
|||||||
V(DNSListenAddress, LINELIST, NULL),
|
V(DNSListenAddress, LINELIST, NULL),
|
||||||
V(DownloadExtraInfo, BOOL, "0"),
|
V(DownloadExtraInfo, BOOL, "0"),
|
||||||
V(TestingEnableConnBwEvent, BOOL, "0"),
|
V(TestingEnableConnBwEvent, BOOL, "0"),
|
||||||
|
V(TestingEnableCellStatsEvent, BOOL, "0"),
|
||||||
V(EnforceDistinctSubnets, BOOL, "1"),
|
V(EnforceDistinctSubnets, BOOL, "1"),
|
||||||
V(EntryNodes, ROUTERSET, NULL),
|
V(EntryNodes, ROUTERSET, NULL),
|
||||||
V(EntryStatistics, BOOL, "0"),
|
V(EntryStatistics, BOOL, "0"),
|
||||||
@ -463,6 +464,7 @@ static const config_var_t testing_tor_network_defaults[] = {
|
|||||||
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
|
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
|
||||||
V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
|
V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
|
||||||
V(TestingEnableConnBwEvent, BOOL, "1"),
|
V(TestingEnableConnBwEvent, BOOL, "1"),
|
||||||
|
V(TestingEnableCellStatsEvent, BOOL, "1"),
|
||||||
VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "1"),
|
VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "1"),
|
||||||
|
|
||||||
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
|
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
|
||||||
@ -3244,6 +3246,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||||||
"Tor networks!");
|
"Tor networks!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options->TestingEnableCellStatsEvent &&
|
||||||
|
!options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
|
||||||
|
REJECT("TestingEnableCellStatsEvent may only be changed in testing "
|
||||||
|
"Tor networks!");
|
||||||
|
}
|
||||||
|
|
||||||
if (options->TestingTorNetwork) {
|
if (options->TestingTorNetwork) {
|
||||||
log_warn(LD_CONFIG, "TestingTorNetwork is set. This will make your node "
|
log_warn(LD_CONFIG, "TestingTorNetwork is set. This will make your node "
|
||||||
"almost unusable in the public Tor network, and is "
|
"almost unusable in the public Tor network, and is "
|
||||||
|
225
src/or/control.c
225
src/or/control.c
@ -19,6 +19,7 @@
|
|||||||
#include "circuitlist.h"
|
#include "circuitlist.h"
|
||||||
#include "circuitstats.h"
|
#include "circuitstats.h"
|
||||||
#include "circuituse.h"
|
#include "circuituse.h"
|
||||||
|
#include "command.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "confparse.h"
|
#include "confparse.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
@ -46,8 +47,6 @@
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern circuit_t *global_circuitlist; /* from circuitlist.c */
|
|
||||||
|
|
||||||
#include "procmon.h"
|
#include "procmon.h"
|
||||||
|
|
||||||
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
|
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
|
||||||
@ -279,7 +278,7 @@ control_update_global_event_mask(void)
|
|||||||
(new_mask & EVENT_CIRC_BANDWIDTH_USED)) {
|
(new_mask & EVENT_CIRC_BANDWIDTH_USED)) {
|
||||||
circuit_t *circ;
|
circuit_t *circ;
|
||||||
origin_circuit_t *ocirc;
|
origin_circuit_t *ocirc;
|
||||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
for (circ = circuit_get_global_list_(); circ; circ = circ->next) {
|
||||||
if (!CIRCUIT_IS_ORIGIN(circ))
|
if (!CIRCUIT_IS_ORIGIN(circ))
|
||||||
continue;
|
continue;
|
||||||
ocirc = TO_ORIGIN_CIRCUIT(circ);
|
ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||||
@ -3944,7 +3943,7 @@ control_event_circ_bandwidth_used(void)
|
|||||||
if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED))
|
if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
for (circ = circuit_get_global_list_(); circ; circ = circ->next) {
|
||||||
if (!CIRCUIT_IS_ORIGIN(circ))
|
if (!CIRCUIT_IS_ORIGIN(circ))
|
||||||
continue;
|
continue;
|
||||||
ocirc = TO_ORIGIN_CIRCUIT(circ);
|
ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||||
@ -4009,162 +4008,150 @@ control_event_conn_bandwidth_used(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert the cell <b>command</b> into a lower-case, human-readable
|
/** Helper structure: temporarily stores cell statistics for a circuit. */
|
||||||
* string. */
|
typedef struct cell_stats_t {
|
||||||
static const char *
|
/** Number of cells added in app-ward direction by command. */
|
||||||
cell_command_to_string(uint8_t command)
|
uint64_t added_cells_appward[CELL_COMMAND_MAX_ + 1];
|
||||||
|
/** Number of cells added in exit-ward direction by command. */
|
||||||
|
uint64_t added_cells_exitward[CELL_COMMAND_MAX_ + 1];
|
||||||
|
/** Number of cells removed in app-ward direction by command. */
|
||||||
|
uint64_t removed_cells_appward[CELL_COMMAND_MAX_ + 1];
|
||||||
|
/** Number of cells removed in exit-ward direction by command. */
|
||||||
|
uint64_t removed_cells_exitward[CELL_COMMAND_MAX_ + 1];
|
||||||
|
/** Total waiting time of cells in app-ward direction by command. */
|
||||||
|
uint64_t total_time_appward[CELL_COMMAND_MAX_ + 1];
|
||||||
|
/** Total waiting time of cells in exit-ward direction by command. */
|
||||||
|
uint64_t total_time_exitward[CELL_COMMAND_MAX_ + 1];
|
||||||
|
} cell_stats_t;
|
||||||
|
|
||||||
|
/** Helper: iterate over cell statistics of <b>circ</b> and sum up added
|
||||||
|
* cells, removed cells, and waiting times by cell command and direction.
|
||||||
|
* Store results in <b>cell_stats</b>. Free cell statistics of the
|
||||||
|
* circuit afterwards. */
|
||||||
|
static void
|
||||||
|
sum_up_cell_stats_by_command(circuit_t *circ, cell_stats_t *cell_stats)
|
||||||
{
|
{
|
||||||
switch (command) {
|
memset(cell_stats, 0, sizeof(cell_stats_t));
|
||||||
case CELL_PADDING: return "padding";
|
SMARTLIST_FOREACH_BEGIN(circ->testing_cell_stats,
|
||||||
case CELL_CREATE: return "create";
|
testing_cell_stats_entry_t *, ent) {
|
||||||
case CELL_CREATED: return "created";
|
tor_assert(ent->command <= CELL_COMMAND_MAX_);
|
||||||
case CELL_RELAY: return "relay";
|
if (!ent->removed && !ent->exitward) {
|
||||||
case CELL_DESTROY: return "destroy";
|
cell_stats->added_cells_appward[ent->command] += 1;
|
||||||
case CELL_CREATE_FAST: return "create_fast";
|
} else if (!ent->removed && ent->exitward) {
|
||||||
case CELL_CREATED_FAST: return "created_fast";
|
cell_stats->added_cells_exitward[ent->command] += 1;
|
||||||
case CELL_VERSIONS: return "versions";
|
} else if (!ent->exitward) {
|
||||||
case CELL_NETINFO: return "netinfo";
|
cell_stats->removed_cells_appward[ent->command] += 1;
|
||||||
case CELL_RELAY_EARLY: return "relay_early";
|
cell_stats->total_time_appward[ent->command] += ent->waiting_time * 10;
|
||||||
case CELL_CREATE2: return "create2";
|
} else {
|
||||||
case CELL_CREATED2: return "created2";
|
cell_stats->removed_cells_exitward[ent->command] += 1;
|
||||||
case CELL_VPADDING: return "vpadding";
|
cell_stats->total_time_exitward[ent->command] += ent->waiting_time * 10;
|
||||||
case CELL_CERTS: return "certs";
|
}
|
||||||
case CELL_AUTH_CHALLENGE: return "auth_challenge";
|
tor_free(ent);
|
||||||
case CELL_AUTHENTICATE: return "authenticate";
|
} SMARTLIST_FOREACH_END(ent);
|
||||||
case CELL_AUTHORIZE: return "authorize";
|
smartlist_free(circ->testing_cell_stats);
|
||||||
default: return "unrecognized";
|
circ->testing_cell_stats = NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Helper: append a cell statistics string to <code>event_parts</code>,
|
/** Helper: append a cell statistics string to <code>event_parts</code>,
|
||||||
* prefixed with <code>key</code>=. Statistics consist of comma-separated
|
* prefixed with <code>key</code>=. Statistics consist of comma-separated
|
||||||
* key:value pairs with lower-case command strings as keys and cell
|
* key:value pairs with lower-case command strings as keys and cell
|
||||||
* numbers or total waiting times as values. A key:value pair is included
|
* numbers or total waiting times as values. A key:value pair is included
|
||||||
* if the entry in <code>include_if_positive</code> is positive, but with
|
* if the entry in <code>include_if_non_zero</code> is not zero, but with
|
||||||
* the (possibly zero) entry from <code>number_to_include</code>. If no
|
* the (possibly zero) entry from <code>number_to_include</code>. If no
|
||||||
* entry in <code>include_if_positive</code> is positive, no string will
|
* entry in <code>include_if_non_zero</code> is positive, no string will
|
||||||
* be added to <code>event_parts</code>. */
|
* be added to <code>event_parts</code>. */
|
||||||
static void
|
static void
|
||||||
append_cell_stats_by_command(smartlist_t *event_parts, const char *key,
|
append_cell_stats_by_command(smartlist_t *event_parts, const char *key,
|
||||||
uint64_t *include_if_positive,
|
uint64_t *include_if_non_zero,
|
||||||
uint64_t *number_to_include)
|
uint64_t *number_to_include)
|
||||||
{
|
{
|
||||||
smartlist_t *key_value_strings = smartlist_new();
|
smartlist_t *key_value_strings = smartlist_new();
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i <= CELL_MAX_; i++) {
|
for (i = 0; i <= CELL_COMMAND_MAX_; i++) {
|
||||||
if (include_if_positive[i] > 0) {
|
if (include_if_non_zero[i] > 0) {
|
||||||
smartlist_add_asprintf(key_value_strings, "%s:"U64_FORMAT,
|
smartlist_add_asprintf(key_value_strings, "%s:"U64_FORMAT,
|
||||||
cell_command_to_string(i),
|
cell_command_to_string(i),
|
||||||
U64_PRINTF_ARG(number_to_include[i]));
|
U64_PRINTF_ARG(number_to_include[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key_value_strings->num_used > 0) {
|
if (smartlist_len(key_value_strings) > 0) {
|
||||||
char *joined = smartlist_join_strings(key_value_strings, ",", 0, NULL);
|
char *joined = smartlist_join_strings(key_value_strings, ",", 0, NULL);
|
||||||
char *result;
|
smartlist_add_asprintf(event_parts, "%s=%s", key, joined);
|
||||||
tor_asprintf(&result, "%s=%s", key, joined);
|
|
||||||
smartlist_add(event_parts, result);
|
|
||||||
SMARTLIST_FOREACH(key_value_strings, char *, cp, tor_free(cp));
|
SMARTLIST_FOREACH(key_value_strings, char *, cp, tor_free(cp));
|
||||||
tor_free(joined);
|
tor_free(joined);
|
||||||
}
|
}
|
||||||
smartlist_free(key_value_strings);
|
smartlist_free(key_value_strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Helper: format <b>cell_stats</b> for <b>circ</b> for inclusion in a
|
||||||
|
* CELL_STATS event and write result string to <b>event_string</b>. */
|
||||||
|
static void
|
||||||
|
format_cell_stats(char **event_string, circuit_t *circ,
|
||||||
|
cell_stats_t *cell_stats)
|
||||||
|
{
|
||||||
|
smartlist_t *event_parts = smartlist_new();
|
||||||
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
|
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||||
|
smartlist_add_asprintf(event_parts, "ID=%lu",
|
||||||
|
(unsigned long)ocirc->global_identifier);
|
||||||
|
} else {
|
||||||
|
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||||
|
smartlist_add_asprintf(event_parts, "InboundQueue=%lu",
|
||||||
|
(unsigned long)or_circ->p_circ_id);
|
||||||
|
smartlist_add_asprintf(event_parts, "InboundConn="U64_FORMAT,
|
||||||
|
U64_PRINTF_ARG(or_circ->p_chan->global_identifier));
|
||||||
|
append_cell_stats_by_command(event_parts, "InboundAdded",
|
||||||
|
cell_stats->added_cells_appward,
|
||||||
|
cell_stats->added_cells_appward);
|
||||||
|
append_cell_stats_by_command(event_parts, "InboundRemoved",
|
||||||
|
cell_stats->removed_cells_appward,
|
||||||
|
cell_stats->removed_cells_appward);
|
||||||
|
append_cell_stats_by_command(event_parts, "InboundTime",
|
||||||
|
cell_stats->removed_cells_appward,
|
||||||
|
cell_stats->total_time_appward);
|
||||||
|
}
|
||||||
|
if (circ->n_chan) {
|
||||||
|
smartlist_add_asprintf(event_parts, "OutboundQueue=%lu",
|
||||||
|
(unsigned long)circ->n_circ_id);
|
||||||
|
smartlist_add_asprintf(event_parts, "OutboundConn="U64_FORMAT,
|
||||||
|
U64_PRINTF_ARG(circ->n_chan->global_identifier));
|
||||||
|
append_cell_stats_by_command(event_parts, "OutboundAdded",
|
||||||
|
cell_stats->added_cells_exitward,
|
||||||
|
cell_stats->added_cells_exitward);
|
||||||
|
append_cell_stats_by_command(event_parts, "OutboundRemoved",
|
||||||
|
cell_stats->removed_cells_exitward,
|
||||||
|
cell_stats->removed_cells_exitward);
|
||||||
|
append_cell_stats_by_command(event_parts, "OutboundTime",
|
||||||
|
cell_stats->removed_cells_exitward,
|
||||||
|
cell_stats->total_time_exitward);
|
||||||
|
}
|
||||||
|
*event_string = smartlist_join_strings(event_parts, " ", 0, NULL);
|
||||||
|
SMARTLIST_FOREACH(event_parts, char *, cp, tor_free(cp));
|
||||||
|
smartlist_free(event_parts);
|
||||||
|
}
|
||||||
|
|
||||||
/** A second or more has elapsed: tell any interested control connection
|
/** A second or more has elapsed: tell any interested control connection
|
||||||
* how many cells have been processed for a given circuit. */
|
* how many cells have been processed for a given circuit. */
|
||||||
int
|
int
|
||||||
control_event_circuit_cell_stats(void)
|
control_event_circuit_cell_stats(void)
|
||||||
{
|
{
|
||||||
/* These arrays temporarily consume slightly over 6 KiB on the stack
|
|
||||||
* every second, most of which are wasted for the non-existant commands
|
|
||||||
* between CELL_RELAY_EARLY (9) and CELL_VPADDING (128). But nothing
|
|
||||||
* beats the stack when it comes to performance. */
|
|
||||||
uint64_t added_cells_appward[CELL_MAX_ + 1],
|
|
||||||
added_cells_exitward[CELL_MAX_ + 1],
|
|
||||||
removed_cells_appward[CELL_MAX_ + 1],
|
|
||||||
removed_cells_exitward[CELL_MAX_ + 1],
|
|
||||||
total_time_appward[CELL_MAX_ + 1],
|
|
||||||
total_time_exitward[CELL_MAX_ + 1];
|
|
||||||
circuit_t *circ;
|
circuit_t *circ;
|
||||||
if (!get_options()->TestingTorNetwork ||
|
cell_stats_t *cell_stats;
|
||||||
|
char *event_string;
|
||||||
|
if (!get_options()->TestingEnableCellStatsEvent ||
|
||||||
!EVENT_IS_INTERESTING(EVENT_CELL_STATS))
|
!EVENT_IS_INTERESTING(EVENT_CELL_STATS))
|
||||||
return 0;
|
return 0;
|
||||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
cell_stats = tor_malloc(sizeof(cell_stats_t));;
|
||||||
smartlist_t *event_parts;
|
for (circ = circuit_get_global_list_(); circ; circ = circ->next) {
|
||||||
char *event_string;
|
|
||||||
|
|
||||||
if (!circ->testing_cell_stats)
|
if (!circ->testing_cell_stats)
|
||||||
continue;
|
continue;
|
||||||
|
sum_up_cell_stats_by_command(circ, cell_stats);
|
||||||
memset(added_cells_appward, 0, (CELL_MAX_ + 1) * sizeof(uint64_t));
|
format_cell_stats(&event_string, circ, cell_stats);
|
||||||
memset(added_cells_exitward, 0, (CELL_MAX_ + 1) * sizeof(uint64_t));
|
|
||||||
memset(removed_cells_appward, 0, (CELL_MAX_ + 1) * sizeof(uint64_t));
|
|
||||||
memset(removed_cells_exitward, 0, (CELL_MAX_ + 1) * sizeof(uint64_t));
|
|
||||||
memset(total_time_appward, 0, (CELL_MAX_ + 1) * sizeof(uint64_t));
|
|
||||||
memset(total_time_exitward, 0, (CELL_MAX_ + 1) * sizeof(uint64_t));
|
|
||||||
SMARTLIST_FOREACH_BEGIN(circ->testing_cell_stats,
|
|
||||||
testing_cell_stats_entry_t *, ent) {
|
|
||||||
tor_assert(ent->command <= CELL_MAX_);
|
|
||||||
if (!ent->removed && !ent->exit_ward) {
|
|
||||||
added_cells_appward[ent->command] += 1;
|
|
||||||
} else if (!ent->removed && ent->exit_ward) {
|
|
||||||
added_cells_exitward[ent->command] += 1;
|
|
||||||
} else if (!ent->exit_ward) {
|
|
||||||
removed_cells_appward[ent->command] += 1;
|
|
||||||
total_time_appward[ent->command] += ent->waiting_time * 10;
|
|
||||||
} else {
|
|
||||||
removed_cells_exitward[ent->command] += 1;
|
|
||||||
total_time_exitward[ent->command] += ent->waiting_time * 10;
|
|
||||||
}
|
|
||||||
tor_free(ent);
|
|
||||||
} SMARTLIST_FOREACH_END(ent);
|
|
||||||
smartlist_free(circ->testing_cell_stats);
|
|
||||||
circ->testing_cell_stats = NULL;
|
|
||||||
|
|
||||||
event_parts = smartlist_new();
|
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
|
||||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
|
||||||
char *id_string;
|
|
||||||
tor_asprintf(&id_string, "ID=%lu",
|
|
||||||
(unsigned long)ocirc->global_identifier);
|
|
||||||
smartlist_add(event_parts, id_string);
|
|
||||||
} else {
|
|
||||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
|
||||||
char *queue_string, *conn_string;
|
|
||||||
tor_asprintf(&queue_string, "InboundQueue=%lu",
|
|
||||||
(unsigned long)or_circ->p_circ_id);
|
|
||||||
tor_asprintf(&conn_string, "InboundConn="U64_FORMAT,
|
|
||||||
U64_PRINTF_ARG(or_circ->p_chan->global_identifier));
|
|
||||||
smartlist_add(event_parts, queue_string);
|
|
||||||
smartlist_add(event_parts, conn_string);
|
|
||||||
append_cell_stats_by_command(event_parts, "InboundAdded",
|
|
||||||
added_cells_appward, added_cells_appward);
|
|
||||||
append_cell_stats_by_command(event_parts, "InboundRemoved",
|
|
||||||
removed_cells_appward, removed_cells_appward);
|
|
||||||
append_cell_stats_by_command(event_parts, "InboundTime",
|
|
||||||
removed_cells_appward, total_time_appward);
|
|
||||||
}
|
|
||||||
if (circ->n_chan) {
|
|
||||||
char *queue_string, *conn_string;
|
|
||||||
tor_asprintf(&queue_string, "OutboundQueue=%lu",
|
|
||||||
(unsigned long)circ->n_circ_id);
|
|
||||||
tor_asprintf(&conn_string, "OutboundConn="U64_FORMAT,
|
|
||||||
U64_PRINTF_ARG(circ->n_chan->global_identifier));
|
|
||||||
smartlist_add(event_parts, queue_string);
|
|
||||||
smartlist_add(event_parts, conn_string);
|
|
||||||
append_cell_stats_by_command(event_parts, "OutboundAdded",
|
|
||||||
added_cells_exitward, added_cells_exitward);
|
|
||||||
append_cell_stats_by_command(event_parts, "OutboundRemoved",
|
|
||||||
removed_cells_exitward, removed_cells_exitward);
|
|
||||||
append_cell_stats_by_command(event_parts, "OutboundTime",
|
|
||||||
removed_cells_exitward, total_time_exitward);
|
|
||||||
}
|
|
||||||
event_string = smartlist_join_strings(event_parts, " ", 0, NULL);
|
|
||||||
send_control_event(EVENT_CELL_STATS, ALL_FORMATS,
|
send_control_event(EVENT_CELL_STATS, ALL_FORMATS,
|
||||||
"650 CELL_STATS %s\r\n", event_string);
|
"650 CELL_STATS %s\r\n", event_string);
|
||||||
SMARTLIST_FOREACH(event_parts, char *, cp, tor_free(cp));
|
|
||||||
smartlist_free(event_parts);
|
|
||||||
tor_free(event_string);
|
tor_free(event_string);
|
||||||
}
|
}
|
||||||
|
tor_free(cell_stats);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
src/or/or.h
17
src/or/or.h
@ -839,7 +839,7 @@ typedef enum {
|
|||||||
#define CELL_AUTH_CHALLENGE 130
|
#define CELL_AUTH_CHALLENGE 130
|
||||||
#define CELL_AUTHENTICATE 131
|
#define CELL_AUTHENTICATE 131
|
||||||
#define CELL_AUTHORIZE 132
|
#define CELL_AUTHORIZE 132
|
||||||
#define CELL_MAX_ 132
|
#define CELL_COMMAND_MAX_ 132
|
||||||
|
|
||||||
/** How long to test reachability before complaining to the user. */
|
/** How long to test reachability before complaining to the user. */
|
||||||
#define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
|
#define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
|
||||||
@ -1089,7 +1089,7 @@ typedef struct insertion_time_queue_t {
|
|||||||
} insertion_time_queue_t;
|
} insertion_time_queue_t;
|
||||||
|
|
||||||
/** Number of cells with the same command consecutively added to a circuit
|
/** Number of cells with the same command consecutively added to a circuit
|
||||||
* queue; used for cell statistics only in TestingTorNetwork mode. */
|
* queue; used for cell statistics only if CELL_STATS events are enabled. */
|
||||||
typedef struct insertion_command_elem_t {
|
typedef struct insertion_command_elem_t {
|
||||||
struct insertion_command_elem_t *next; /**< Next element in queue. */
|
struct insertion_command_elem_t *next; /**< Next element in queue. */
|
||||||
/** Which command did these consecutively added cells have? */
|
/** Which command did these consecutively added cells have? */
|
||||||
@ -2756,8 +2756,8 @@ typedef struct {
|
|||||||
|
|
||||||
struct create_cell_t;
|
struct create_cell_t;
|
||||||
|
|
||||||
/** Entry in the cell stats list of a circuit; used only when
|
/** Entry in the cell stats list of a circuit; used only if CELL_STATS
|
||||||
* TestingTorNetwork is set. */
|
* events are enabled. */
|
||||||
typedef struct testing_cell_stats_entry_t {
|
typedef struct testing_cell_stats_entry_t {
|
||||||
uint8_t command; /**< cell command number. */
|
uint8_t command; /**< cell command number. */
|
||||||
/** Waiting time in centiseconds if this event is for a removed cell,
|
/** Waiting time in centiseconds if this event is for a removed cell,
|
||||||
@ -2766,7 +2766,7 @@ typedef struct testing_cell_stats_entry_t {
|
|||||||
* delay would long have been closed. */
|
* delay would long have been closed. */
|
||||||
unsigned int waiting_time:22;
|
unsigned int waiting_time:22;
|
||||||
unsigned int removed:1; /**< 0 for added to, 1 for removed from queue. */
|
unsigned int removed:1; /**< 0 for added to, 1 for removed from queue. */
|
||||||
unsigned int exit_ward:1; /**< 0 for app-ward, 1 for exit-ward. */
|
unsigned int exitward:1; /**< 0 for app-ward, 1 for exit-ward. */
|
||||||
} testing_cell_stats_entry_t;
|
} testing_cell_stats_entry_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2896,8 +2896,8 @@ typedef struct circuit_t {
|
|||||||
struct circuit_t *prev_active_on_n_chan;
|
struct circuit_t *prev_active_on_n_chan;
|
||||||
|
|
||||||
/** Various statistics about cells being added to or removed from this
|
/** Various statistics about cells being added to or removed from this
|
||||||
* circuit's queues; used only when TestingTorNetwork is set and cleared
|
* circuit's queues; used only if CELL_STATS events are enabled and
|
||||||
* after being sent to control port. */
|
* cleared after being sent to control port. */
|
||||||
smartlist_t *testing_cell_stats;
|
smartlist_t *testing_cell_stats;
|
||||||
} circuit_t;
|
} circuit_t;
|
||||||
|
|
||||||
@ -3988,6 +3988,9 @@ typedef struct {
|
|||||||
/** Enable CONN_BW events. Only altered on testing networks. */
|
/** Enable CONN_BW events. Only altered on testing networks. */
|
||||||
int TestingEnableConnBwEvent;
|
int TestingEnableConnBwEvent;
|
||||||
|
|
||||||
|
/** Enable CELL_STATS events. Only altered on testing networks. */
|
||||||
|
int TestingEnableCellStatsEvent;
|
||||||
|
|
||||||
/** If true, and we have GeoIP data, and we're a bridge, keep a per-country
|
/** If true, and we have GeoIP data, and we're a bridge, keep a per-country
|
||||||
* count of how many client addresses have contacted us so that we can help
|
* count of how many client addresses have contacted us so that we can help
|
||||||
* the bridge authority guess which countries have blocked access to us. */
|
* the bridge authority guess which countries have blocked access to us. */
|
||||||
|
122
src/or/relay.c
122
src/or/relay.c
@ -2046,7 +2046,7 @@ static mp_pool_t *cell_pool = NULL;
|
|||||||
static mp_pool_t *it_pool = NULL;
|
static mp_pool_t *it_pool = NULL;
|
||||||
|
|
||||||
/** Memory pool to allocate insertion_command_elem_t objects used for cell
|
/** Memory pool to allocate insertion_command_elem_t objects used for cell
|
||||||
* statistics in TestingTorNetwork mode. */
|
* statistics if CELL_STATS events are enabled. */
|
||||||
static mp_pool_t *ic_pool = NULL;
|
static mp_pool_t *ic_pool = NULL;
|
||||||
|
|
||||||
/** Allocate structures to hold cells. */
|
/** Allocate structures to hold cells. */
|
||||||
@ -2058,7 +2058,7 @@ init_cell_pool(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Free all storage used to hold cells (and insertion times/commands if we
|
/** Free all storage used to hold cells (and insertion times/commands if we
|
||||||
* measure cell statistics and/or are in TestingTorNetwork mode). */
|
* measure cell statistics and/or if CELL_STATS events are enabled). */
|
||||||
void
|
void
|
||||||
free_cell_pool(void)
|
free_cell_pool(void)
|
||||||
{
|
{
|
||||||
@ -2153,16 +2153,68 @@ cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
|
|||||||
++queue->n;
|
++queue->n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Append command of type <b>command</b> in direction to <b>queue</b> for
|
||||||
|
* CELL_STATS event. */
|
||||||
|
static void
|
||||||
|
cell_command_queue_append(cell_queue_t *queue, uint8_t command)
|
||||||
|
{
|
||||||
|
insertion_command_queue_t *ic_queue = queue->insertion_commands;
|
||||||
|
if (!ic_pool)
|
||||||
|
ic_pool = mp_pool_new(sizeof(insertion_command_elem_t), 1024);
|
||||||
|
if (!ic_queue) {
|
||||||
|
ic_queue = tor_malloc_zero(sizeof(insertion_command_queue_t));
|
||||||
|
queue->insertion_commands = ic_queue;
|
||||||
|
}
|
||||||
|
if (ic_queue->last && ic_queue->last->command == command) {
|
||||||
|
ic_queue->last->counter++;
|
||||||
|
} else {
|
||||||
|
insertion_command_elem_t *elem = mp_pool_get(ic_pool);
|
||||||
|
elem->next = NULL;
|
||||||
|
elem->command = command;
|
||||||
|
elem->counter = 1;
|
||||||
|
if (ic_queue->last) {
|
||||||
|
ic_queue->last->next = elem;
|
||||||
|
ic_queue->last = elem;
|
||||||
|
} else {
|
||||||
|
ic_queue->first = ic_queue->last = elem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieve oldest command from <b>queue</b> and write it to
|
||||||
|
* <b>command</b> for CELL_STATS event. Return 0 for success, -1
|
||||||
|
* otherwise. */
|
||||||
|
static int
|
||||||
|
cell_command_queue_pop(uint8_t *command, cell_queue_t *queue)
|
||||||
|
{
|
||||||
|
int res = -1;
|
||||||
|
insertion_command_queue_t *ic_queue = queue->insertion_commands;
|
||||||
|
if (ic_queue && ic_queue->first) {
|
||||||
|
insertion_command_elem_t *ic_elem = ic_queue->first;
|
||||||
|
ic_elem->counter--;
|
||||||
|
if (ic_elem->counter < 1) {
|
||||||
|
ic_queue->first = ic_elem->next;
|
||||||
|
if (ic_elem == ic_queue->last)
|
||||||
|
ic_queue->last = NULL;
|
||||||
|
mp_pool_release(ic_elem);
|
||||||
|
}
|
||||||
|
*command = ic_elem->command;
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/** Append a newly allocated copy of <b>cell</b> to the end of the
|
/** Append a newly allocated copy of <b>cell</b> to the end of the
|
||||||
* <b>exit_ward</b> (or app-ward) <b>queue</b> of <b>circ</b>. */
|
* <b>exitward</b> (or app-ward) <b>queue</b> of <b>circ</b>. */
|
||||||
void
|
void
|
||||||
cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
||||||
int exit_ward, const cell_t *cell,
|
int exitward, const cell_t *cell,
|
||||||
int wide_circ_ids)
|
int wide_circ_ids)
|
||||||
{
|
{
|
||||||
packed_cell_t *copy = packed_cell_copy(cell, wide_circ_ids);
|
packed_cell_t *copy = packed_cell_copy(cell, wide_circ_ids);
|
||||||
/* Remember the time when this cell was put in the queue. */
|
/* Remember the time when this cell was put in the queue. */
|
||||||
if (get_options()->CellStatistics || get_options()->TestingTorNetwork) {
|
if (get_options()->CellStatistics ||
|
||||||
|
get_options()->TestingEnableCellStatsEvent) {
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
uint32_t added;
|
uint32_t added;
|
||||||
insertion_time_queue_t *it_queue = queue->insertion_times;
|
insertion_time_queue_t *it_queue = queue->insertion_times;
|
||||||
@ -2193,35 +2245,15 @@ cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
|||||||
}
|
}
|
||||||
/* Remember that we added a cell to the queue, and remember the cell
|
/* Remember that we added a cell to the queue, and remember the cell
|
||||||
* command. */
|
* command. */
|
||||||
if (get_options()->TestingTorNetwork) {
|
if (get_options()->TestingEnableCellStatsEvent) {
|
||||||
insertion_command_queue_t *ic_queue = queue->insertion_commands;
|
|
||||||
testing_cell_stats_entry_t *ent =
|
testing_cell_stats_entry_t *ent =
|
||||||
tor_malloc_zero(sizeof(testing_cell_stats_entry_t));
|
tor_malloc_zero(sizeof(testing_cell_stats_entry_t));
|
||||||
ent->command = cell->command;
|
ent->command = cell->command;
|
||||||
ent->exit_ward = exit_ward;
|
ent->exitward = exitward;
|
||||||
if (!circ->testing_cell_stats)
|
if (!circ->testing_cell_stats)
|
||||||
circ->testing_cell_stats = smartlist_new();
|
circ->testing_cell_stats = smartlist_new();
|
||||||
smartlist_add(circ->testing_cell_stats, ent);
|
smartlist_add(circ->testing_cell_stats, ent);
|
||||||
if (!ic_pool)
|
cell_command_queue_append(queue, cell->command);
|
||||||
ic_pool = mp_pool_new(sizeof(insertion_command_elem_t), 1024);
|
|
||||||
if (!ic_queue) {
|
|
||||||
ic_queue = tor_malloc_zero(sizeof(insertion_command_queue_t));
|
|
||||||
queue->insertion_commands = ic_queue;
|
|
||||||
}
|
|
||||||
if (ic_queue->last && ic_queue->last->command == cell->command) {
|
|
||||||
ic_queue->last->counter++;
|
|
||||||
} else {
|
|
||||||
insertion_command_elem_t *elem = mp_pool_get(ic_pool);
|
|
||||||
elem->next = NULL;
|
|
||||||
elem->command = cell->command;
|
|
||||||
elem->counter = 1;
|
|
||||||
if (ic_queue->last) {
|
|
||||||
ic_queue->last->next = elem;
|
|
||||||
ic_queue->last = elem;
|
|
||||||
} else {
|
|
||||||
ic_queue->first = ic_queue->last = elem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cell_queue_append(queue, copy);
|
cell_queue_append(queue, copy);
|
||||||
}
|
}
|
||||||
@ -2429,7 +2461,7 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
|
|||||||
|
|
||||||
/* Calculate the exact time that this cell has spent in the queue. */
|
/* Calculate the exact time that this cell has spent in the queue. */
|
||||||
if (get_options()->CellStatistics ||
|
if (get_options()->CellStatistics ||
|
||||||
get_options()->TestingTorNetwork) {
|
get_options()->TestingEnableCellStatsEvent) {
|
||||||
struct timeval tvnow;
|
struct timeval tvnow;
|
||||||
uint32_t flushed;
|
uint32_t flushed;
|
||||||
uint32_t cell_waiting_time;
|
uint32_t cell_waiting_time;
|
||||||
@ -2460,28 +2492,20 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
|
|||||||
or_circ->total_cell_waiting_time += cell_waiting_time;
|
or_circ->total_cell_waiting_time += cell_waiting_time;
|
||||||
or_circ->processed_cells++;
|
or_circ->processed_cells++;
|
||||||
}
|
}
|
||||||
if (get_options()->TestingTorNetwork) {
|
if (get_options()->TestingEnableCellStatsEvent) {
|
||||||
insertion_command_queue_t *ic_queue = queue->insertion_commands;
|
uint8_t command;
|
||||||
if (!ic_queue || !ic_queue->first) {
|
if (cell_command_queue_pop(&command, queue) < 0) {
|
||||||
log_info(LD_BUG, "Cannot determine command of cell, which "
|
log_info(LD_GENERAL, "Cannot determine command of cell. "
|
||||||
"is a bug, because TestingTorNetwork cannot "
|
"Looks like the CELL_STATS event was "
|
||||||
"be enabled while running.");
|
"recently enabled.");
|
||||||
} else {
|
} else {
|
||||||
testing_cell_stats_entry_t *ent =
|
testing_cell_stats_entry_t *ent =
|
||||||
tor_malloc_zero(sizeof(testing_cell_stats_entry_t));
|
tor_malloc_zero(sizeof(testing_cell_stats_entry_t));
|
||||||
insertion_command_elem_t *ic_elem = ic_queue->first;
|
ent->command = command;
|
||||||
ent->command = ic_elem->command;
|
|
||||||
ic_elem->counter--;
|
|
||||||
if (ic_elem->counter < 1) {
|
|
||||||
ic_queue->first = ic_elem->next;
|
|
||||||
if (ic_elem == ic_queue->last)
|
|
||||||
ic_queue->last = NULL;
|
|
||||||
mp_pool_release(ic_elem);
|
|
||||||
}
|
|
||||||
ent->waiting_time = (unsigned int)cell_waiting_time / 10;
|
ent->waiting_time = (unsigned int)cell_waiting_time / 10;
|
||||||
ent->removed = 1;
|
ent->removed = 1;
|
||||||
if (circ->n_chan == chan)
|
if (circ->n_chan == chan)
|
||||||
ent->exit_ward = 1;
|
ent->exitward = 1;
|
||||||
if (!circ->testing_cell_stats)
|
if (!circ->testing_cell_stats)
|
||||||
circ->testing_cell_stats = smartlist_new();
|
circ->testing_cell_stats = smartlist_new();
|
||||||
smartlist_add(circ->testing_cell_stats, ent);
|
smartlist_add(circ->testing_cell_stats, ent);
|
||||||
@ -2542,12 +2566,12 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
|||||||
{
|
{
|
||||||
cell_queue_t *queue;
|
cell_queue_t *queue;
|
||||||
int streams_blocked;
|
int streams_blocked;
|
||||||
int exit_ward;
|
int exitward;
|
||||||
if (circ->marked_for_close)
|
if (circ->marked_for_close)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
exit_ward = (direction == CELL_DIRECTION_OUT);
|
exitward = (direction == CELL_DIRECTION_OUT);
|
||||||
if (exit_ward) {
|
if (exitward) {
|
||||||
queue = &circ->n_chan_cells;
|
queue = &circ->n_chan_cells;
|
||||||
streams_blocked = circ->streams_blocked_on_n_chan;
|
streams_blocked = circ->streams_blocked_on_n_chan;
|
||||||
} else {
|
} else {
|
||||||
@ -2556,7 +2580,7 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
|||||||
streams_blocked = circ->streams_blocked_on_p_chan;
|
streams_blocked = circ->streams_blocked_on_p_chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_queue_append_packed_copy(circ, queue, exit_ward, cell,
|
cell_queue_append_packed_copy(circ, queue, exitward, cell,
|
||||||
chan->wide_circ_ids);
|
chan->wide_circ_ids);
|
||||||
|
|
||||||
/* If we have too many cells on the circuit, we should stop reading from
|
/* If we have too many cells on the circuit, we should stop reading from
|
||||||
|
@ -53,7 +53,7 @@ void packed_cell_free(packed_cell_t *cell);
|
|||||||
void cell_queue_clear(cell_queue_t *queue);
|
void cell_queue_clear(cell_queue_t *queue);
|
||||||
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
|
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
|
||||||
void cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
void cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
||||||
int exit_ward, const cell_t *cell,
|
int exitward, const cell_t *cell,
|
||||||
int wide_circ_ids);
|
int wide_circ_ids);
|
||||||
|
|
||||||
void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
||||||
|
Loading…
Reference in New Issue
Block a user