diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-12-13 09:34:20 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-12-13 09:46:58 -0500 |
commit | 219c969d7bf858c4df5fc6ee9b0c472a525b6b2a (patch) | |
tree | 2b3aa9585fe033c4c2a9a074e8ad90f5d0bead05 /src/or/channelpadding.c | |
parent | dd6dec2665af9964d8f940c27f3f0815a649424a (diff) | |
download | tor-219c969d7bf858c4df5fc6ee9b0c472a525b6b2a.tar.gz tor-219c969d7bf858c4df5fc6ee9b0c472a525b6b2a.zip |
Use monotime_coarse for transfer times and padding times
Using absolute_msec requires a 64-bit division operation every time
we calculate it, which gets expensive on 32-bit architectures.
Instead, just use the lazy "monotime_coarse_get()" operation, and
don't convert to milliseconds until we absolutely must.
In this case, it seemed fine to use a full monotime_coarse_t rather
than a truncated "stamp" as we did to solve this problem for the
timerstamps in buf_t and packed_cell_t: There are vastly more cells
and buffer chunks than there are channels, and using 16 bytes per
channel in the worst case is not a big deal.
There are still more millisecond operations here than strictly
necessary; let's see any divisions show up in profiles.
Diffstat (limited to 'src/or/channelpadding.c')
-rw-r--r-- | src/or/channelpadding.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/src/or/channelpadding.c b/src/or/channelpadding.c index 435436c45c..70a906d232 100644 --- a/src/or/channelpadding.c +++ b/src/or/channelpadding.c @@ -23,7 +23,8 @@ #include <event2/event.h> #include "rendservice.h" -STATIC int channelpadding_get_netflow_inactive_timeout_ms(const channel_t *); +STATIC int32_t channelpadding_get_netflow_inactive_timeout_ms( + const channel_t *); STATIC int channelpadding_send_disable_command(channel_t *); STATIC int64_t channelpadding_compute_time_until_pad_for_netflow(channel_t *); @@ -165,7 +166,7 @@ channelpadding_new_consensus_params(networkstatus_t *ns) * Returns the next timeout period (in milliseconds) after which we should * send a padding packet, or 0 if padding is disabled. */ -STATIC int +STATIC int32_t channelpadding_get_netflow_inactive_timeout_ms(const channel_t *chan) { int low_timeout = consensus_nf_ito_low; @@ -377,15 +378,16 @@ channelpadding_send_padding_cell_for_callback(channel_t *chan) chan->pending_padding_callback = 0; - if (!chan->next_padding_time_ms || + if (monotime_coarse_is_zero(&chan->next_padding_time) || chan->has_queued_writes(chan)) { /* We must have been active before the timer fired */ - chan->next_padding_time_ms = 0; + monotime_coarse_zero(&chan->next_padding_time); return; } { - uint64_t now = monotime_coarse_absolute_msec(); + monotime_coarse_t now; + monotime_coarse_get(&now); log_fn(LOG_INFO,LD_OR, "Sending netflow keepalive on "U64_FORMAT" to %s (%s) after " @@ -393,12 +395,13 @@ channelpadding_send_padding_cell_for_callback(channel_t *chan) U64_PRINTF_ARG(chan->global_identifier), safe_str_client(chan->get_remote_descr(chan, 0)), safe_str_client(hex_str(chan->identity_digest, DIGEST_LEN)), - U64_PRINTF_ARG(now - chan->timestamp_xfer_ms), - U64_PRINTF_ARG(now - chan->next_padding_time_ms)); + I64_PRINTF_ARG(monotime_coarse_diff_msec(&chan->timestamp_xfer,&now)), + I64_PRINTF_ARG( + monotime_coarse_diff_msec(&chan->next_padding_time,&now))); } /* Clear the timer */ - chan->next_padding_time_ms = 0; + monotime_coarse_zero(&chan->next_padding_time); /* Send the padding cell. This will cause the channel to get a * fresh timestamp_active */ @@ -500,38 +503,42 @@ channelpadding_schedule_padding(channel_t *chan, int in_ms) STATIC int64_t channelpadding_compute_time_until_pad_for_netflow(channel_t *chan) { - uint64_t long_now = monotime_coarse_absolute_msec(); + monotime_coarse_t now; + monotime_coarse_get(&now); - if (!chan->next_padding_time_ms) { + if (monotime_coarse_is_zero(&chan->next_padding_time)) { /* If the below line or crypto_rand_int() shows up on a profile, * we can avoid getting a timeout until we're at least nf_ito_lo * from a timeout window. That will prevent us from setting timers * on connections that were active up to 1.5 seconds ago. * Idle connections should only call this once every 5.5s on average * though, so that might be a micro-optimization for little gain. */ - int64_t padding_timeout = + int32_t padding_timeout = channelpadding_get_netflow_inactive_timeout_ms(chan); if (!padding_timeout) return CHANNELPADDING_TIME_DISABLED; - chan->next_padding_time_ms = padding_timeout - + chan->timestamp_xfer_ms; + monotime_coarse_add_msec(&chan->next_padding_time, + &chan->timestamp_xfer, + padding_timeout); } + const int64_t ms_till_pad = + monotime_coarse_diff_msec(&now, &chan->next_padding_time); + /* If the next padding time is beyond the maximum possible consensus value, * then this indicates a clock jump, so just send padding now. This is * better than using monotonic time because we want to avoid the situation * where we wait around forever for monotonic time to move forward after * a clock jump far into the past. */ - if (chan->next_padding_time_ms > long_now + - DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX) { + if (ms_till_pad > DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX) { tor_fragile_assert(); log_warn(LD_BUG, "Channel padding timeout scheduled "I64_FORMAT"ms in the future. " "Did the monotonic clock just jump?", - I64_PRINTF_ARG(chan->next_padding_time_ms - long_now)); + I64_PRINTF_ARG(ms_till_pad)); return 0; /* Clock jumped: Send padding now */ } @@ -540,11 +547,8 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan) from now which we should send padding, so we can schedule a callback then. */ - if (long_now + - (TOR_HOUSEKEEPING_CALLBACK_MSEC + TOR_HOUSEKEEPING_CALLBACK_SLACK_MSEC) - >= chan->next_padding_time_ms) { - int64_t ms_until_pad_for_netflow = chan->next_padding_time_ms - - long_now; + if (ms_till_pad < (TOR_HOUSEKEEPING_CALLBACK_MSEC + + TOR_HOUSEKEEPING_CALLBACK_SLACK_MSEC)) { /* If the padding time is in the past, that means that libevent delayed * calling the once-per-second callback due to other work taking too long. * See https://bugs.torproject.org/22212 and @@ -554,16 +558,16 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan) * and allowed a router to emit a netflow frame, just so we don't forget * about it entirely.. */ #define NETFLOW_MISSED_WINDOW (150000 - DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH) - if (ms_until_pad_for_netflow < 0) { - int severity = (ms_until_pad_for_netflow < -NETFLOW_MISSED_WINDOW) + if (ms_till_pad < 0) { + int severity = (ms_till_pad < -NETFLOW_MISSED_WINDOW) ? LOG_NOTICE : LOG_INFO; log_fn(severity, LD_OR, "Channel padding timeout scheduled "I64_FORMAT"ms in the past. ", - I64_PRINTF_ARG(-ms_until_pad_for_netflow)); + I64_PRINTF_ARG(-ms_till_pad)); return 0; /* Clock jumped: Send padding now */ } - return ms_until_pad_for_netflow; + return ms_till_pad; } return CHANNELPADDING_TIME_LATER; } |