aboutsummaryrefslogtreecommitdiff
path: root/src/or/rephist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/rephist.c')
-rw-r--r--src/or/rephist.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 22b3ec5217..a0c9c9f39d 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -14,6 +14,7 @@
#include "circuitlist.h"
#include "circuituse.h"
#include "config.h"
+#include "networkstatus.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
@@ -73,6 +74,10 @@ typedef struct or_history_t {
/** If nonzero, we have been unable to connect since this time. */
time_t down_since;
+ /** The address at which we most recently connected to this OR
+ * sucessfully. */
+ tor_addr_t last_reached_addr;
+
/* === For MTBF tracking: */
/** Weighted sum total of all times that this router has been online.
*/
@@ -119,6 +124,7 @@ get_or_history(const char* id)
rephist_total_num++;
hist->link_history_map = digestmap_new();
hist->since = hist->changed = time(NULL);
+ tor_addr_make_unspec(&hist->last_reached_addr);
digestmap_set(history_map, id, hist);
}
return hist;
@@ -289,14 +295,19 @@ rep_hist_note_connection_died(const char* id, time_t when)
/** We have just decided that this router with identity digest <b>id</b> is
* reachable, meaning we will give it a "Running" flag for the next while. */
void
-rep_hist_note_router_reachable(const char *id, time_t when)
+rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr,
+ time_t when)
{
or_history_t *hist = get_or_history(id);
int was_in_run = 1;
char tbuf[ISO_TIME_LEN+1];
+ int addr_changed;
tor_assert(hist);
+ addr_changed = at_addr &&
+ tor_addr_compare(at_addr, &hist->last_reached_addr, CMP_EXACT) != 0;
+
if (!started_tracking_stability)
started_tracking_stability = time(NULL);
if (!hist->start_of_run) {
@@ -315,6 +326,29 @@ rep_hist_note_router_reachable(const char *id, time_t when)
down_length = when - hist->start_of_downtime;
hist->total_weighted_time += down_length;
hist->start_of_downtime = 0;
+ } else if (addr_changed) {
+ /* If we're reachable, but the address changed, treat this as some
+ * downtime. */
+#define MIN_DOWNTIME_FOR_ADDR_CHANGE 600
+ int penalty = get_options()->TestingTorNetwork ? 240 : 3600;
+ networkstatus_t *ns;
+ tor_assert(at_addr);
+
+ if ((ns = networkstatus_get_latest_consensus())) {
+ int fresh_interval = ns->fresh_until - ns->valid_after;
+ int live_interval = ns->valid_until - ns->valid_after;
+ /* on average, a descriptor addr change takes .5 intervals to make it
+ * into a consensus, and half a liveness period to make it to
+ * clients. */
+ penalty = (fresh_interval + live_interval) / 2;
+ }
+ format_local_iso_time(tbuf, hist->start_of_run);
+ log_info(LD_HIST,"Router %s still seems Running, but its address appears "
+ "to have changed since the last time it was reachable. I'm "
+ "going to treat it as having been down for %d seconds",
+ hex_str(id, DIGEST_LEN), penalty);
+ rep_hist_note_router_unreachable(id, when-penalty);
+ rep_hist_note_router_reachable(id, NULL, when);
} else {
format_local_iso_time(tbuf, hist->start_of_run);
if (was_in_run)
@@ -324,6 +358,8 @@ rep_hist_note_router_reachable(const char *id, time_t when)
log_info(LD_HIST,"Router %s is now Running; it was previously untracked",
hex_str(id, DIGEST_LEN));
}
+ if (at_addr)
+ tor_addr_copy(&hist->last_reached_addr, at_addr);
}
/** We have just decided that this router is unreachable, meaning