rephist.c (101619B)
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 2 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 3 /* See LICENSE for licensing information */ 4 5 /** 6 * \file rephist.c 7 * \brief Basic history and performance-tracking functionality. 8 * 9 * Basic history and performance-tracking functionality to remember 10 * which servers have worked in the past, how much bandwidth we've 11 * been using, which ports we tend to want, and so on; further, 12 * exit port statistics, cell statistics, and connection statistics. 13 * 14 * The history and information tracked in this module could sensibly be 15 * divided into several categories: 16 * 17 * <ul><li>Statistics used by authorities to remember the uptime and 18 * stability information about various relays, including "uptime", 19 * "weighted fractional uptime" and "mean time between failures". 20 * 21 * <li>Predicted ports, used by clients to remember how long it's been 22 * since they opened an exit connection to each given target 23 * port. Clients use this information in order to try to keep circuits 24 * open to exit nodes that can connect to the ports that they care 25 * about. (The predicted ports mechanism also handles predicted circuit 26 * usage that _isn't_ port-specific, such as resolves, internal circuits, 27 * and so on.) 28 * 29 * <li>Public key operation counters, for tracking how many times we've 30 * done each public key operation. (This is unmaintained and we should 31 * remove it.) 32 * 33 * <li>Exit statistics by port, used by exits to keep track of the 34 * number of streams and bytes they've served at each exit port, so they 35 * can generate their exit-kibibytes-{read,written} and 36 * exit-streams-opened statistics. 37 * 38 * <li>Circuit stats, used by relays instances to tract circuit 39 * queue fullness and delay over time, and generate cell-processed-cells, 40 * cell-queued-cells, cell-time-in-queue, and cell-circuits-per-decile 41 * statistics. 42 * 43 * <li>Descriptor serving statistics, used by directory caches to track 44 * how many descriptors they've served. 45 * 46 * <li>Onion handshake statistics, used by relays to count how many 47 * TAP and ntor handshakes they've handled. 48 * 49 * <li>Hidden service statistics, used by relays to count rendezvous 50 * traffic and HSDir-stored descriptors. 51 * 52 * <li>Link protocol statistics, used by relays to count how many times 53 * each link protocol has been used. 54 * 55 * </ul> 56 * 57 * The entry points for this module are scattered throughout the 58 * codebase. Sending data, receiving data, connecting to a relay, 59 * losing a connection to a relay, and so on can all trigger a change in 60 * our current stats. Relays also invoke this module in order to 61 * extract their statistics when building routerinfo and extrainfo 62 * objects in router.c. 63 * 64 * TODO: This module should be broken up. 65 * 66 * (The "rephist" name originally stood for "reputation and history". ) 67 **/ 68 69 #define REPHIST_PRIVATE 70 #include "core/or/or.h" 71 #include "app/config/config.h" 72 #include "core/mainloop/connection.h" 73 #include "core/or/circuitlist.h" 74 #include "core/or/connection_or.h" 75 #include "feature/dirauth/authmode.h" 76 #include "feature/nodelist/networkstatus.h" 77 #include "feature/nodelist/nodelist.h" 78 #include "feature/stats/predict_ports.h" 79 #include "feature/stats/connstats.h" 80 #include "feature/stats/rephist.h" 81 #include "lib/container/order.h" 82 #include "lib/crypt_ops/crypto_rand.h" 83 #include "lib/math/laplace.h" 84 85 #include "feature/nodelist/networkstatus_st.h" 86 #include "core/or/or_circuit_st.h" 87 88 #include <event2/dns.h> 89 90 #ifdef HAVE_FCNTL_H 91 #include <fcntl.h> 92 #endif 93 94 /** Total number of bytes currently allocated in fields used by rephist.c. */ 95 uint64_t rephist_total_alloc=0; 96 /** Number of or_history_t objects currently allocated. */ 97 uint32_t rephist_total_num=0; 98 99 /** If the total weighted run count of all runs for a router ever falls 100 * below this amount, the router can be treated as having 0 MTBF. */ 101 #define STABILITY_EPSILON 0.0001 102 /** Value by which to discount all old intervals for MTBF purposes. This 103 * is compounded every STABILITY_INTERVAL. */ 104 #define STABILITY_ALPHA 0.95 105 /** Interval at which to discount all old intervals for MTBF purposes. */ 106 #define STABILITY_INTERVAL (12*60*60) 107 /* (This combination of ALPHA, INTERVAL, and EPSILON makes it so that an 108 * interval that just ended counts twice as much as one that ended a week ago, 109 * 20X as much as one that ended a month ago, and routers that have had no 110 * uptime data for about half a year will get forgotten.) */ 111 112 /** History of an OR. */ 113 typedef struct or_history_t { 114 /** When did we start tracking this OR? */ 115 time_t since; 116 /** When did we most recently note a change to this OR? */ 117 time_t changed; 118 119 /** The address at which we most recently connected to this OR 120 * successfully. */ 121 tor_addr_t last_reached_addr; 122 123 /** The port at which we most recently connected to this OR successfully */ 124 uint16_t last_reached_port; 125 126 /* === For MTBF tracking: */ 127 /** Weighted sum total of all times that this router has been online. 128 */ 129 unsigned long weighted_run_length; 130 /** If the router is now online (according to stability-checking rules), 131 * when did it come online? */ 132 time_t start_of_run; 133 /** Sum of weights for runs in weighted_run_length. */ 134 double total_run_weights; 135 /* === For fractional uptime tracking: */ 136 time_t start_of_downtime; 137 unsigned long weighted_uptime; 138 unsigned long total_weighted_time; 139 } or_history_t; 140 141 /** 142 * This structure holds accounting needed to calculate the padding overhead. 143 */ 144 typedef struct padding_counts_t { 145 /** Total number of cells we have received, including padding */ 146 uint64_t read_cell_count; 147 /** Total number of cells we have sent, including padding */ 148 uint64_t write_cell_count; 149 /** Total number of CELL_PADDING cells we have received */ 150 uint64_t read_pad_cell_count; 151 /** Total number of CELL_PADDING cells we have sent */ 152 uint64_t write_pad_cell_count; 153 /** Total number of read cells on padding-enabled conns */ 154 uint64_t enabled_read_cell_count; 155 /** Total number of sent cells on padding-enabled conns */ 156 uint64_t enabled_write_cell_count; 157 /** Total number of read CELL_PADDING cells on padding-enabled cons */ 158 uint64_t enabled_read_pad_cell_count; 159 /** Total number of sent CELL_PADDING cells on padding-enabled cons */ 160 uint64_t enabled_write_pad_cell_count; 161 /** Total number of RELAY_DROP cells we have received */ 162 uint64_t read_drop_cell_count; 163 /** Total number of RELAY_DROP cells we have sent */ 164 uint64_t write_drop_cell_count; 165 /** The maximum number of padding timers we've seen in 24 hours */ 166 uint64_t maximum_chanpad_timers; 167 /** When did we first copy padding_current into padding_published? */ 168 char first_published_at[ISO_TIME_LEN+1]; 169 } padding_counts_t; 170 171 /** Holds the current values of our padding statistics. 172 * It is not published until it is transferred to padding_published. */ 173 static padding_counts_t padding_current; 174 175 /** Remains fixed for a 24 hour period, and then is replaced 176 * by a redacted copy of padding_current */ 177 static padding_counts_t padding_published; 178 179 /** When did we last multiply all routers' weighted_run_length and 180 * total_run_weights by STABILITY_ALPHA? */ 181 static time_t stability_last_downrated = 0; 182 183 /** */ 184 static time_t started_tracking_stability = 0; 185 186 /** Map from hex OR identity digest to or_history_t. */ 187 static digestmap_t *history_map = NULL; 188 189 /** Represents a state of overload stats. 190 * 191 * All the timestamps in this structure have already been rounded down to the 192 * nearest hour. */ 193 typedef struct { 194 /* When did we last experience a general overload? */ 195 time_t overload_general_time; 196 197 /* When did we last experience a bandwidth-related overload? */ 198 time_t overload_ratelimits_time; 199 /* How many times have we gone off the our read limits? */ 200 uint64_t overload_read_count; 201 /* How many times have we gone off the our write limits? */ 202 uint64_t overload_write_count; 203 204 /* When did we last experience a file descriptor exhaustion? */ 205 time_t overload_fd_exhausted_time; 206 /* How many times have we experienced a file descriptor exhaustion? */ 207 uint64_t overload_fd_exhausted; 208 } overload_stats_t; 209 210 /** Current state of overload stats */ 211 static overload_stats_t overload_stats; 212 213 /** Counters to count the number of times we've reached an overload for the 214 * global connection read/write limit. Reported on the MetricsPort. */ 215 static uint64_t stats_n_read_limit_reached = 0; 216 static uint64_t stats_n_write_limit_reached = 0; 217 218 /** Total number of times we've reached TCP port exhaustion. */ 219 static uint64_t stats_n_tcp_exhaustion = 0; 220 221 /***** DNS statistics *****/ 222 223 /** Overload DNS statistics. The information in this object is used to assess 224 * if, due to DNS errors, we should emit a general overload signal or not. 225 * 226 * NOTE: This structure is _not_ per DNS query type like the statistics below 227 * because of a libevent bug 228 * (https://github.com/libevent/libevent/issues/1219), on error, the type is 229 * not propagated up back to the user and so we need to keep our own stats for 230 * the overload signal. */ 231 typedef struct { 232 /** Total number of DNS request seen at an Exit. They might not all end 233 * successfully or might even be lost by tor. This counter is incremented 234 * right before the DNS request is initiated. */ 235 uint64_t stats_n_request; 236 237 /** When is the next assessment time of the general overload for DNS errors. 238 * Once this time is reached, all stats are reset and this time is set to the 239 * next assessment time. */ 240 time_t next_assessment_time; 241 } overload_dns_stats_t; 242 243 /** Keep track of the DNS requests for the general overload state. */ 244 static overload_dns_stats_t overload_dns_stats; 245 246 /** Represents the statistics of DNS queries seen if it is an Exit. */ 247 typedef struct { 248 /* Total number of DNS errors found in RFC 1035 (from 0 to 5 code). */ 249 uint64_t stats_n_error_none; /* 0 */ 250 uint64_t stats_n_error_format; /* 1 */ 251 uint64_t stats_n_error_serverfailed; /* 2 */ 252 uint64_t stats_n_error_notexist; /* 3 */ 253 uint64_t stats_n_error_notimpl; /* 4 */ 254 uint64_t stats_n_error_refused; /* 5 */ 255 256 /* Total number of DNS errors specific to libevent. */ 257 uint64_t stats_n_error_truncated; /* 65 */ 258 uint64_t stats_n_error_unknown; /* 66 */ 259 uint64_t stats_n_error_tor_timeout; /* 67 */ 260 uint64_t stats_n_error_shutdown; /* 68 */ 261 uint64_t stats_n_error_cancel; /* 69 */ 262 uint64_t stats_n_error_nodata; /* 70 */ 263 264 /* Total number of DNS request seen at an Exit. They might not all end 265 * successfully or might even be lost by tor. This counter is incremented 266 * right before the DNS request is initiated. */ 267 uint64_t stats_n_request; 268 } dns_stats_t; 269 270 /* This is disabled because of the libevent bug where on error we don't get the 271 * DNS query type back. Once it is fixed, we can re-enable this. */ 272 #if 0 273 /** DNS statistics store for each DNS record type for which tor supports only 274 * three at the moment: A, PTR and AAAA. */ 275 static dns_stats_t dns_A_stats; 276 static dns_stats_t dns_PTR_stats; 277 static dns_stats_t dns_AAAA_stats; 278 #endif 279 280 /** DNS query statistics store. It covers all type of queries. */ 281 static dns_stats_t dns_all_stats; 282 283 /** Counter of the total number of DROP cell received. */ 284 static uint64_t relay_circ_n_drop_cell_received = 0; 285 286 /** Return the point to the DNS statistics store. Ignore the type for now 287 * because of a libevent problem. */ 288 static inline dns_stats_t * 289 get_dns_stats_by_type(const int type) 290 { 291 (void) type; 292 return &dns_all_stats; 293 } 294 295 #if 0 296 /** From a libevent record type, return a pointer to the corresponding DNS 297 * statistics store. NULL is returned if the type is unhandled. */ 298 static inline dns_stats_t * 299 get_dns_stats_by_type(const int type) 300 { 301 switch (type) { 302 case DNS_IPv4_A: 303 return &dns_A_stats; 304 case DNS_PTR: 305 return &dns_PTR_stats; 306 case DNS_IPv6_AAAA: 307 return &dns_AAAA_stats; 308 default: 309 return NULL; 310 } 311 } 312 #endif 313 314 /** Return the DNS error count for the given libevent DNS type and error code. 315 * The possible types are: DNS_IPv4_A, DNS_PTR, DNS_IPv6_AAAA. */ 316 uint64_t 317 rep_hist_get_n_dns_error(int type, uint8_t error) 318 { 319 dns_stats_t *dns_stats = get_dns_stats_by_type(type); 320 if (BUG(!dns_stats)) { 321 return 0; 322 } 323 324 switch (error) { 325 case DNS_ERR_NONE: 326 return dns_stats->stats_n_error_none; 327 case DNS_ERR_FORMAT: 328 return dns_stats->stats_n_error_format; 329 case DNS_ERR_SERVERFAILED: 330 return dns_stats->stats_n_error_serverfailed; 331 case DNS_ERR_NOTEXIST: 332 return dns_stats->stats_n_error_notexist; 333 case DNS_ERR_NOTIMPL: 334 return dns_stats->stats_n_error_notimpl; 335 case DNS_ERR_REFUSED: 336 return dns_stats->stats_n_error_refused; 337 case DNS_ERR_TRUNCATED: 338 return dns_stats->stats_n_error_truncated; 339 case DNS_ERR_UNKNOWN: 340 return dns_stats->stats_n_error_unknown; 341 case DNS_ERR_TIMEOUT: 342 return dns_stats->stats_n_error_tor_timeout; 343 case DNS_ERR_SHUTDOWN: 344 return dns_stats->stats_n_error_shutdown; 345 case DNS_ERR_CANCEL: 346 return dns_stats->stats_n_error_cancel; 347 case DNS_ERR_NODATA: 348 return dns_stats->stats_n_error_nodata; 349 default: 350 /* Unhandled code sent back by libevent. */ 351 return 0; 352 } 353 } 354 355 /** Return the total number of DNS request seen for the given libevent DNS 356 * record type. Possible types are: DNS_IPv4_A, DNS_PTR, DNS_IPv6_AAAA. */ 357 uint64_t 358 rep_hist_get_n_dns_request(int type) 359 { 360 dns_stats_t *dns_stats = get_dns_stats_by_type(type); 361 if (BUG(!dns_stats)) { 362 return 0; 363 } 364 return dns_stats->stats_n_request; 365 } 366 367 /** Note a DNS error for the given given libevent DNS record type and error 368 * code. Possible types are: DNS_IPv4_A, DNS_PTR, DNS_IPv6_AAAA. 369 * 370 * NOTE: Libevent is _not_ returning the type in case of an error and so if 371 * error is anything but DNS_ERR_NONE, the type is not usable and set to 0. 372 * 373 * See: https://gitlab.torproject.org/tpo/core/tor/-/issues/40490 */ 374 void 375 rep_hist_note_dns_error(int type, uint8_t error) 376 { 377 overload_dns_stats.stats_n_request++; 378 379 /* Again, the libevent bug (see function comment), for an error that is 380 * anything but DNS_ERR_NONE, the type is always 0 which means that we don't 381 * have a DNS stat object for it so this code will do nothing until libevent 382 * is fixed. */ 383 dns_stats_t *dns_stats = get_dns_stats_by_type(type); 384 /* Unsupported DNS query type. */ 385 if (!dns_stats) { 386 return; 387 } 388 389 switch (error) { 390 case DNS_ERR_NONE: 391 dns_stats->stats_n_error_none++; 392 break; 393 case DNS_ERR_FORMAT: 394 dns_stats->stats_n_error_format++; 395 break; 396 case DNS_ERR_SERVERFAILED: 397 dns_stats->stats_n_error_serverfailed++; 398 break; 399 case DNS_ERR_NOTEXIST: 400 dns_stats->stats_n_error_notexist++; 401 break; 402 case DNS_ERR_NOTIMPL: 403 dns_stats->stats_n_error_notimpl++; 404 break; 405 case DNS_ERR_REFUSED: 406 dns_stats->stats_n_error_refused++; 407 break; 408 case DNS_ERR_TRUNCATED: 409 dns_stats->stats_n_error_truncated++; 410 break; 411 case DNS_ERR_UNKNOWN: 412 dns_stats->stats_n_error_unknown++; 413 break; 414 case DNS_ERR_TIMEOUT: 415 dns_stats->stats_n_error_tor_timeout++; 416 break; 417 case DNS_ERR_SHUTDOWN: 418 dns_stats->stats_n_error_shutdown++; 419 break; 420 case DNS_ERR_CANCEL: 421 dns_stats->stats_n_error_cancel++; 422 break; 423 case DNS_ERR_NODATA: 424 dns_stats->stats_n_error_nodata++; 425 break; 426 default: 427 /* Unhandled code sent back by libevent. */ 428 break; 429 } 430 } 431 432 /** Note a DNS request for the given given libevent DNS record type. */ 433 void 434 rep_hist_note_dns_request(int type) 435 { 436 dns_stats_t *dns_stats = get_dns_stats_by_type(type); 437 if (BUG(!dns_stats)) { 438 return; 439 } 440 dns_stats->stats_n_request++; 441 } 442 443 /***** END of DNS statistics *****/ 444 445 /** Return true if this overload happened within the last `n_hours`. */ 446 static bool 447 overload_happened_recently(time_t overload_time, int n_hours) 448 { 449 /* An overload is relevant if it happened in the last 72 hours */ 450 if (overload_time > approx_time() - 3600 * n_hours) { 451 return true; 452 } 453 return false; 454 } 455 456 /* The current version of the overload stats version */ 457 #define OVERLOAD_STATS_VERSION 1 458 459 /** Return the stats_n_read_limit_reached counter. */ 460 uint64_t 461 rep_hist_get_n_read_limit_reached(void) 462 { 463 return stats_n_read_limit_reached; 464 } 465 466 /** Return the stats_n_write_limit_reached counter. */ 467 uint64_t 468 rep_hist_get_n_write_limit_reached(void) 469 { 470 return stats_n_write_limit_reached; 471 } 472 473 /** Returns an allocated string for server descriptor for publising information 474 * on whether we are overloaded or not. */ 475 char * 476 rep_hist_get_overload_general_line(void) 477 { 478 char *result = NULL; 479 char tbuf[ISO_TIME_LEN+1]; 480 481 /* Encode the general overload */ 482 if (overload_happened_recently(overload_stats.overload_general_time, 72)) { 483 format_iso_time(tbuf, overload_stats.overload_general_time); 484 tor_asprintf(&result, "overload-general %d %s\n", 485 OVERLOAD_STATS_VERSION, tbuf); 486 } 487 488 return result; 489 } 490 491 /** Returns an allocated string for extra-info documents for publishing 492 * overload statistics. */ 493 char * 494 rep_hist_get_overload_stats_lines(void) 495 { 496 char *result = NULL; 497 smartlist_t *chunks = smartlist_new(); 498 char tbuf[ISO_TIME_LEN+1]; 499 500 /* Add bandwidth-related overloads */ 501 if (overload_happened_recently(overload_stats.overload_ratelimits_time,24)) { 502 const or_options_t *options = get_options(); 503 format_iso_time(tbuf, overload_stats.overload_ratelimits_time); 504 smartlist_add_asprintf(chunks, 505 "overload-ratelimits %d %s %" PRIu64 " %" PRIu64 506 " %" PRIu64 " %" PRIu64 "\n", 507 OVERLOAD_STATS_VERSION, tbuf, 508 options->BandwidthRate, options->BandwidthBurst, 509 overload_stats.overload_read_count, 510 overload_stats.overload_write_count); 511 } 512 513 /* Finally file descriptor overloads */ 514 if (overload_happened_recently( 515 overload_stats.overload_fd_exhausted_time, 72)) { 516 format_iso_time(tbuf, overload_stats.overload_fd_exhausted_time); 517 smartlist_add_asprintf(chunks, "overload-fd-exhausted %d %s\n", 518 OVERLOAD_STATS_VERSION, tbuf); 519 } 520 521 /* Bail early if we had nothing to write */ 522 if (smartlist_len(chunks) == 0) { 523 goto done; 524 } 525 526 result = smartlist_join_strings(chunks, "", 0, NULL); 527 528 done: 529 SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); 530 smartlist_free(chunks); 531 return result; 532 } 533 534 /** Round down the time in `a` to the beginning of the current hour */ 535 #define SET_TO_START_OF_HOUR(a) STMT_BEGIN \ 536 (a) = approx_time() - (approx_time() % 3600); \ 537 STMT_END 538 539 /** Note down an overload event of type `overload`. */ 540 void 541 rep_hist_note_overload(overload_type_t overload) 542 { 543 static time_t last_read_counted = 0; 544 static time_t last_write_counted = 0; 545 546 switch (overload) { 547 case OVERLOAD_GENERAL: 548 SET_TO_START_OF_HOUR(overload_stats.overload_general_time); 549 break; 550 case OVERLOAD_READ: { 551 stats_n_read_limit_reached++; 552 SET_TO_START_OF_HOUR(overload_stats.overload_ratelimits_time); 553 if (approx_time() >= last_read_counted + 60) { /* Count once a minute */ 554 overload_stats.overload_read_count++; 555 last_read_counted = approx_time(); 556 } 557 break; 558 } 559 case OVERLOAD_WRITE: { 560 stats_n_write_limit_reached++; 561 SET_TO_START_OF_HOUR(overload_stats.overload_ratelimits_time); 562 if (approx_time() >= last_write_counted + 60) { /* Count once a minute */ 563 overload_stats.overload_write_count++; 564 last_write_counted = approx_time(); 565 } 566 break; 567 } 568 case OVERLOAD_FD_EXHAUSTED: 569 SET_TO_START_OF_HOUR(overload_stats.overload_fd_exhausted_time); 570 overload_stats.overload_fd_exhausted++; 571 break; 572 } 573 } 574 575 /** Note down that we've reached a TCP port exhaustion. This triggers an 576 * overload general event. */ 577 void 578 rep_hist_note_tcp_exhaustion(void) 579 { 580 stats_n_tcp_exhaustion++; 581 rep_hist_note_overload(OVERLOAD_GENERAL); 582 } 583 584 /** Return the total number of TCP exhaustion times we've reached. */ 585 uint64_t 586 rep_hist_get_n_tcp_exhaustion(void) 587 { 588 return stats_n_tcp_exhaustion; 589 } 590 591 /** Return the or_history_t for the OR with identity digest <b>id</b>, 592 * creating it if necessary. */ 593 static or_history_t * 594 get_or_history(const char* id) 595 { 596 or_history_t *hist; 597 598 if (tor_digest_is_zero(id)) 599 return NULL; 600 601 hist = digestmap_get(history_map, id); 602 if (!hist) { 603 hist = tor_malloc_zero(sizeof(or_history_t)); 604 rephist_total_alloc += sizeof(or_history_t); 605 rephist_total_num++; 606 hist->since = hist->changed = time(NULL); 607 tor_addr_make_unspec(&hist->last_reached_addr); 608 digestmap_set(history_map, id, hist); 609 } 610 return hist; 611 } 612 613 /** Helper: free storage held by a single OR history entry. */ 614 static void 615 free_or_history(void *_hist) 616 { 617 or_history_t *hist = _hist; 618 rephist_total_alloc -= sizeof(or_history_t); 619 rephist_total_num--; 620 tor_free(hist); 621 } 622 623 /** Initialize the static data structures for tracking history. */ 624 void 625 rep_hist_init(void) 626 { 627 history_map = digestmap_new(); 628 } 629 630 /** We have just decided that this router with identity digest <b>id</b> is 631 * reachable, meaning we will give it a "Running" flag for the next while. */ 632 void 633 rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr, 634 const uint16_t at_port, time_t when) 635 { 636 or_history_t *hist = get_or_history(id); 637 int was_in_run = 1; 638 char tbuf[ISO_TIME_LEN+1]; 639 int addr_changed, port_changed; 640 641 tor_assert(hist); 642 tor_assert((!at_addr && !at_port) || (at_addr && at_port)); 643 644 addr_changed = at_addr && !tor_addr_is_null(&hist->last_reached_addr) && 645 tor_addr_compare(at_addr, &hist->last_reached_addr, CMP_EXACT) != 0; 646 port_changed = at_port && hist->last_reached_port && 647 at_port != hist->last_reached_port; 648 649 if (!started_tracking_stability) 650 started_tracking_stability = time(NULL); 651 if (!hist->start_of_run) { 652 hist->start_of_run = when; 653 was_in_run = 0; 654 } 655 if (hist->start_of_downtime) { 656 long down_length; 657 658 format_local_iso_time(tbuf, hist->start_of_downtime); 659 log_info(LD_HIST, "Router %s is now Running; it had been down since %s.", 660 hex_str(id, DIGEST_LEN), tbuf); 661 if (was_in_run) 662 log_info(LD_HIST, " (Paradoxically, it was already Running too.)"); 663 664 down_length = when - hist->start_of_downtime; 665 hist->total_weighted_time += down_length; 666 hist->start_of_downtime = 0; 667 } else if (addr_changed || port_changed) { 668 /* If we're reachable, but the address changed, treat this as some 669 * downtime. */ 670 int penalty = get_options()->TestingTorNetwork ? 240 : 3600; 671 networkstatus_t *ns; 672 673 if ((ns = networkstatus_get_latest_consensus())) { 674 int fresh_interval = (int)(ns->fresh_until - ns->valid_after); 675 int live_interval = (int)(ns->valid_until - ns->valid_after); 676 /* on average, a descriptor addr change takes .5 intervals to make it 677 * into a consensus, and half a liveness period to make it to 678 * clients. */ 679 penalty = (int)(fresh_interval + live_interval) / 2; 680 } 681 format_local_iso_time(tbuf, hist->start_of_run); 682 log_info(LD_HIST,"Router %s still seems Running, but its address appears " 683 "to have changed since the last time it was reachable. I'm " 684 "going to treat it as having been down for %d seconds", 685 hex_str(id, DIGEST_LEN), penalty); 686 rep_hist_note_router_unreachable(id, when-penalty); 687 rep_hist_note_router_reachable(id, NULL, 0, when); 688 } else { 689 format_local_iso_time(tbuf, hist->start_of_run); 690 if (was_in_run) 691 log_debug(LD_HIST, "Router %s is still Running; it has been Running " 692 "since %s", hex_str(id, DIGEST_LEN), tbuf); 693 else 694 log_info(LD_HIST,"Router %s is now Running; it was previously untracked", 695 hex_str(id, DIGEST_LEN)); 696 } 697 if (at_addr) 698 tor_addr_copy(&hist->last_reached_addr, at_addr); 699 if (at_port) 700 hist->last_reached_port = at_port; 701 } 702 703 /** We have just decided that this router is unreachable, meaning 704 * we are taking away its "Running" flag. */ 705 void 706 rep_hist_note_router_unreachable(const char *id, time_t when) 707 { 708 or_history_t *hist = get_or_history(id); 709 char tbuf[ISO_TIME_LEN+1]; 710 int was_running = 0; 711 if (!started_tracking_stability) 712 started_tracking_stability = time(NULL); 713 714 tor_assert(hist); 715 if (hist->start_of_run) { 716 /*XXXX We could treat failed connections differently from failed 717 * connect attempts. */ 718 long run_length = when - hist->start_of_run; 719 format_local_iso_time(tbuf, hist->start_of_run); 720 721 hist->total_run_weights += 1.0; 722 hist->start_of_run = 0; 723 if (run_length < 0) { 724 unsigned long penalty = -run_length; 725 #define SUBTRACT_CLAMPED(var, penalty) \ 726 do { (var) = (var) < (penalty) ? 0 : (var) - (penalty); } while (0) 727 728 SUBTRACT_CLAMPED(hist->weighted_run_length, penalty); 729 SUBTRACT_CLAMPED(hist->weighted_uptime, penalty); 730 } else { 731 hist->weighted_run_length += run_length; 732 hist->weighted_uptime += run_length; 733 hist->total_weighted_time += run_length; 734 } 735 was_running = 1; 736 log_info(LD_HIST, "Router %s is now non-Running: it had previously been " 737 "Running since %s. Its total weighted uptime is %lu/%lu.", 738 hex_str(id, DIGEST_LEN), tbuf, hist->weighted_uptime, 739 hist->total_weighted_time); 740 } 741 if (!hist->start_of_downtime) { 742 hist->start_of_downtime = when; 743 744 if (!was_running) 745 log_info(LD_HIST, "Router %s is now non-Running; it was previously " 746 "untracked.", hex_str(id, DIGEST_LEN)); 747 } else { 748 if (!was_running) { 749 format_local_iso_time(tbuf, hist->start_of_downtime); 750 751 log_info(LD_HIST, "Router %s is still non-Running; it has been " 752 "non-Running since %s.", hex_str(id, DIGEST_LEN), tbuf); 753 } 754 } 755 } 756 757 /** Mark a router with ID <b>id</b> as non-Running, and retroactively declare 758 * that it has never been running: give it no stability and no WFU. */ 759 void 760 rep_hist_make_router_pessimal(const char *id, time_t when) 761 { 762 or_history_t *hist = get_or_history(id); 763 tor_assert(hist); 764 765 rep_hist_note_router_unreachable(id, when); 766 767 hist->weighted_run_length = 0; 768 hist->weighted_uptime = 0; 769 } 770 771 /** Helper: Discount all old MTBF data, if it is time to do so. Return 772 * the time at which we should next discount MTBF data. */ 773 time_t 774 rep_hist_downrate_old_runs(time_t now) 775 { 776 digestmap_iter_t *orhist_it; 777 const char *digest1; 778 or_history_t *hist; 779 void *hist_p; 780 double alpha = 1.0; 781 782 if (!history_map) 783 history_map = digestmap_new(); 784 if (!stability_last_downrated) 785 stability_last_downrated = now; 786 if (stability_last_downrated + STABILITY_INTERVAL > now) 787 return stability_last_downrated + STABILITY_INTERVAL; 788 789 /* Okay, we should downrate the data. By how much? */ 790 while (stability_last_downrated + STABILITY_INTERVAL <= now) { 791 stability_last_downrated += STABILITY_INTERVAL; 792 alpha *= STABILITY_ALPHA; 793 } 794 795 log_info(LD_HIST, "Discounting all old stability info by a factor of %f", 796 alpha); 797 798 /* Multiply every w_r_l, t_r_w pair by alpha. */ 799 for (orhist_it = digestmap_iter_init(history_map); 800 !digestmap_iter_done(orhist_it); 801 orhist_it = digestmap_iter_next(history_map,orhist_it)) { 802 digestmap_iter_get(orhist_it, &digest1, &hist_p); 803 hist = hist_p; 804 805 hist->weighted_run_length = 806 (unsigned long)(hist->weighted_run_length * alpha); 807 hist->total_run_weights *= alpha; 808 809 hist->weighted_uptime = (unsigned long)(hist->weighted_uptime * alpha); 810 hist->total_weighted_time = (unsigned long) 811 (hist->total_weighted_time * alpha); 812 } 813 814 return stability_last_downrated + STABILITY_INTERVAL; 815 } 816 817 /** Helper: Return the weighted MTBF of the router with history <b>hist</b>. */ 818 static double 819 get_stability(or_history_t *hist, time_t when) 820 { 821 long total = hist->weighted_run_length; 822 double total_weights = hist->total_run_weights; 823 824 if (hist->start_of_run) { 825 /* We're currently in a run. Let total and total_weights hold the values 826 * they would hold if the current run were to end now. */ 827 total += (when-hist->start_of_run); 828 total_weights += 1.0; 829 } 830 if (total_weights < STABILITY_EPSILON) { 831 /* Round down to zero, and avoid divide-by-zero. */ 832 return 0.0; 833 } 834 835 return total / total_weights; 836 } 837 838 /** Return the total amount of time we've been observing, with each run of 839 * time downrated by the appropriate factor. */ 840 static long 841 get_total_weighted_time(or_history_t *hist, time_t when) 842 { 843 long total = hist->total_weighted_time; 844 if (hist->start_of_run) { 845 total += (when - hist->start_of_run); 846 } else if (hist->start_of_downtime) { 847 total += (when - hist->start_of_downtime); 848 } 849 return total; 850 } 851 852 /** Helper: Return the weighted percent-of-time-online of the router with 853 * history <b>hist</b>. */ 854 static double 855 get_weighted_fractional_uptime(or_history_t *hist, time_t when) 856 { 857 long total = hist->total_weighted_time; 858 long up = hist->weighted_uptime; 859 860 if (hist->start_of_run) { 861 long run_length = (when - hist->start_of_run); 862 up += run_length; 863 total += run_length; 864 } else if (hist->start_of_downtime) { 865 total += (when - hist->start_of_downtime); 866 } 867 868 if (!total) { 869 /* Avoid calling anybody's uptime infinity (which should be impossible if 870 * the code is working), or NaN (which can happen for any router we haven't 871 * observed up or down yet). */ 872 return 0.0; 873 } 874 875 return ((double) up) / total; 876 } 877 878 /** Return how long the router whose identity digest is <b>id</b> has 879 * been reachable. Return 0 if the router is unknown or currently deemed 880 * unreachable. */ 881 long 882 rep_hist_get_uptime(const char *id, time_t when) 883 { 884 or_history_t *hist = get_or_history(id); 885 if (!hist) 886 return 0; 887 if (!hist->start_of_run || when < hist->start_of_run) 888 return 0; 889 return when - hist->start_of_run; 890 } 891 892 /** Return an estimated MTBF for the router whose identity digest is 893 * <b>id</b>. Return 0 if the router is unknown. */ 894 double 895 rep_hist_get_stability(const char *id, time_t when) 896 { 897 or_history_t *hist = get_or_history(id); 898 if (!hist) 899 return 0.0; 900 901 return get_stability(hist, when); 902 } 903 904 /** Return an estimated percent-of-time-online for the router whose identity 905 * digest is <b>id</b>. Return 0 if the router is unknown. */ 906 double 907 rep_hist_get_weighted_fractional_uptime(const char *id, time_t when) 908 { 909 or_history_t *hist = get_or_history(id); 910 if (!hist) 911 return 0.0; 912 913 return get_weighted_fractional_uptime(hist, when); 914 } 915 916 /** Return a number representing how long we've known about the router whose 917 * digest is <b>id</b>. Return 0 if the router is unknown. 918 * 919 * Be careful: this measure increases monotonically as we know the router for 920 * longer and longer, but it doesn't increase linearly. 921 */ 922 long 923 rep_hist_get_weighted_time_known(const char *id, time_t when) 924 { 925 or_history_t *hist = get_or_history(id); 926 if (!hist) 927 return 0; 928 929 return get_total_weighted_time(hist, when); 930 } 931 932 /** Return true if we've been measuring MTBFs for long enough to 933 * pronounce on Stability. */ 934 int 935 rep_hist_have_measured_enough_stability(void) 936 { 937 /* XXXX++ This doesn't do so well when we change our opinion 938 * as to whether we're tracking router stability. */ 939 return started_tracking_stability < time(NULL) - 4*60*60; 940 } 941 942 /** Log all the reliability data we have remembered, with the chosen 943 * severity. 944 */ 945 void 946 rep_hist_dump_stats(time_t now, int severity) 947 { 948 digestmap_iter_t *orhist_it; 949 const char *name1, *digest1; 950 char hexdigest1[HEX_DIGEST_LEN+1]; 951 or_history_t *or_history; 952 void *or_history_p; 953 const node_t *node; 954 955 rep_history_clean(now - get_options()->RephistTrackTime); 956 957 tor_log(severity, LD_HIST, "--------------- Dumping history information:"); 958 959 for (orhist_it = digestmap_iter_init(history_map); 960 !digestmap_iter_done(orhist_it); 961 orhist_it = digestmap_iter_next(history_map,orhist_it)) { 962 double s; 963 long stability; 964 digestmap_iter_get(orhist_it, &digest1, &or_history_p); 965 or_history = (or_history_t*) or_history_p; 966 967 if ((node = node_get_by_id(digest1)) && node_get_nickname(node)) 968 name1 = node_get_nickname(node); 969 else 970 name1 = "(unknown)"; 971 base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN); 972 s = get_stability(or_history, now); 973 stability = (long)s; 974 tor_log(severity, LD_HIST, 975 "OR %s [%s]: wmtbf %lu:%02lu:%02lu", 976 name1, hexdigest1, 977 stability/3600, (stability/60)%60, stability%60); 978 } 979 } 980 981 /** Remove history info for routers/links that haven't changed since 982 * <b>before</b>. 983 */ 984 void 985 rep_history_clean(time_t before) 986 { 987 int authority = authdir_mode(get_options()); 988 or_history_t *or_history; 989 void *or_history_p; 990 digestmap_iter_t *orhist_it; 991 const char *d1; 992 993 orhist_it = digestmap_iter_init(history_map); 994 while (!digestmap_iter_done(orhist_it)) { 995 int should_remove; 996 digestmap_iter_get(orhist_it, &d1, &or_history_p); 997 or_history = or_history_p; 998 999 should_remove = authority ? 1000 (or_history->total_run_weights < STABILITY_EPSILON && 1001 !or_history->start_of_run) 1002 : (or_history->changed < before); 1003 if (should_remove) { 1004 orhist_it = digestmap_iter_next_rmv(history_map, orhist_it); 1005 free_or_history(or_history); 1006 continue; 1007 } 1008 orhist_it = digestmap_iter_next(history_map, orhist_it); 1009 } 1010 } 1011 1012 /** Write MTBF data to disk. Return 0 on success, negative on failure. 1013 * 1014 * If <b>missing_means_down</b>, then if we're about to write an entry 1015 * that is still considered up but isn't in our routerlist, consider it 1016 * to be down. */ 1017 int 1018 rep_hist_record_mtbf_data(time_t now, int missing_means_down) 1019 { 1020 char time_buf[ISO_TIME_LEN+1]; 1021 1022 digestmap_iter_t *orhist_it; 1023 const char *digest; 1024 void *or_history_p; 1025 or_history_t *hist; 1026 open_file_t *open_file = NULL; 1027 FILE *f; 1028 1029 { 1030 char *filename = get_datadir_fname("router-stability"); 1031 f = start_writing_to_stdio_file(filename, OPEN_FLAGS_REPLACE|O_TEXT, 0600, 1032 &open_file); 1033 tor_free(filename); 1034 if (!f) 1035 return -1; 1036 } 1037 1038 /* File format is: 1039 * FormatLine *KeywordLine Data 1040 * 1041 * FormatLine = "format 1" NL 1042 * KeywordLine = Keyword SP Arguments NL 1043 * Data = "data" NL *RouterMTBFLine "." NL 1044 * RouterMTBFLine = Fingerprint SP WeightedRunLen SP 1045 * TotalRunWeights [SP S=StartRunTime] NL 1046 */ 1047 #define PUT(s) STMT_BEGIN if (fputs((s),f)<0) goto err; STMT_END 1048 #define PRINTF(args) STMT_BEGIN if (fprintf args <0) goto err; STMT_END 1049 1050 PUT("format 2\n"); 1051 1052 format_iso_time(time_buf, time(NULL)); 1053 PRINTF((f, "stored-at %s\n", time_buf)); 1054 1055 if (started_tracking_stability) { 1056 format_iso_time(time_buf, started_tracking_stability); 1057 PRINTF((f, "tracked-since %s\n", time_buf)); 1058 } 1059 if (stability_last_downrated) { 1060 format_iso_time(time_buf, stability_last_downrated); 1061 PRINTF((f, "last-downrated %s\n", time_buf)); 1062 } 1063 1064 PUT("data\n"); 1065 1066 /* XXX Nick: now bridge auths record this for all routers too. 1067 * Should we make them record it only for bridge routers? -RD 1068 * Not for 0.2.0. -NM */ 1069 for (orhist_it = digestmap_iter_init(history_map); 1070 !digestmap_iter_done(orhist_it); 1071 orhist_it = digestmap_iter_next(history_map,orhist_it)) { 1072 char dbuf[HEX_DIGEST_LEN+1]; 1073 const char *t = NULL; 1074 digestmap_iter_get(orhist_it, &digest, &or_history_p); 1075 hist = (or_history_t*) or_history_p; 1076 1077 base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN); 1078 1079 if (missing_means_down && hist->start_of_run && 1080 !connection_or_digest_is_known_relay(digest)) { 1081 /* We think this relay is running, but it's not listed in our 1082 * consensus. Somehow it fell out without telling us it went 1083 * down. Complain and also correct it. */ 1084 log_info(LD_HIST, 1085 "Relay '%s' is listed as up in rephist, but it's not in " 1086 "our routerlist. Correcting.", dbuf); 1087 rep_hist_note_router_unreachable(digest, now); 1088 } 1089 1090 PRINTF((f, "R %s\n", dbuf)); 1091 if (hist->start_of_run > 0) { 1092 format_iso_time(time_buf, hist->start_of_run); 1093 t = time_buf; 1094 } 1095 PRINTF((f, "+MTBF %lu %.5f%s%s\n", 1096 hist->weighted_run_length, hist->total_run_weights, 1097 t ? " S=" : "", t ? t : "")); 1098 t = NULL; 1099 if (hist->start_of_downtime > 0) { 1100 format_iso_time(time_buf, hist->start_of_downtime); 1101 t = time_buf; 1102 } 1103 PRINTF((f, "+WFU %lu %lu%s%s\n", 1104 hist->weighted_uptime, hist->total_weighted_time, 1105 t ? " S=" : "", t ? t : "")); 1106 } 1107 1108 PUT(".\n"); 1109 1110 #undef PUT 1111 #undef PRINTF 1112 1113 return finish_writing_to_file(open_file); 1114 err: 1115 abort_writing_to_file(open_file); 1116 return -1; 1117 } 1118 1119 /** Helper: return the first j >= i such that !strcmpstart(sl[j], prefix) and 1120 * such that no line sl[k] with i <= k < j starts with "R ". Return -1 if no 1121 * such line exists. */ 1122 static int 1123 find_next_with(smartlist_t *sl, int i, const char *prefix) 1124 { 1125 for ( ; i < smartlist_len(sl); ++i) { 1126 const char *line = smartlist_get(sl, i); 1127 if (!strcmpstart(line, prefix)) 1128 return i; 1129 if (!strcmpstart(line, "R ")) 1130 return -1; 1131 } 1132 return -1; 1133 } 1134 1135 /** How many bad times has parse_possibly_bad_iso_time() parsed? */ 1136 static int n_bogus_times = 0; 1137 /** Parse the ISO-formatted time in <b>s</b> into *<b>time_out</b>, but 1138 * round any pre-1970 date to Jan 1, 1970. */ 1139 static int 1140 parse_possibly_bad_iso_time(const char *s, time_t *time_out) 1141 { 1142 int year; 1143 char b[5]; 1144 strlcpy(b, s, sizeof(b)); 1145 b[4] = '\0'; 1146 year = (int)tor_parse_long(b, 10, 0, INT_MAX, NULL, NULL); 1147 if (year < 1970) { 1148 *time_out = 0; 1149 ++n_bogus_times; 1150 return 0; 1151 } else 1152 return parse_iso_time(s, time_out); 1153 } 1154 1155 /** We've read a time <b>t</b> from a file stored at <b>stored_at</b>, which 1156 * says we started measuring at <b>started_measuring</b>. Return a new number 1157 * that's about as much before <b>now</b> as <b>t</b> was before 1158 * <b>stored_at</b>. 1159 */ 1160 static inline time_t 1161 correct_time(time_t t, time_t now, time_t stored_at, time_t started_measuring) 1162 { 1163 if (t < started_measuring - 24*60*60*365) 1164 return 0; 1165 else if (t < started_measuring) 1166 return started_measuring; 1167 else if (t > stored_at) 1168 return 0; 1169 else { 1170 long run_length = stored_at - t; 1171 t = (time_t)(now - run_length); 1172 if (t < started_measuring) 1173 t = started_measuring; 1174 return t; 1175 } 1176 } 1177 1178 /** Load MTBF data from disk. Returns 0 on success or recoverable error, -1 1179 * on failure. */ 1180 int 1181 rep_hist_load_mtbf_data(time_t now) 1182 { 1183 /* XXXX won't handle being called while history is already populated. */ 1184 smartlist_t *lines; 1185 const char *line = NULL; 1186 int r=0, i; 1187 time_t last_downrated = 0, stored_at = 0, tracked_since = 0; 1188 time_t latest_possible_start = now; 1189 long format = -1; 1190 1191 { 1192 char *filename = get_datadir_fname("router-stability"); 1193 char *d = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL); 1194 tor_free(filename); 1195 if (!d) 1196 return -1; 1197 lines = smartlist_new(); 1198 smartlist_split_string(lines, d, "\n", SPLIT_SKIP_SPACE, 0); 1199 tor_free(d); 1200 } 1201 1202 { 1203 const char *firstline; 1204 if (smartlist_len(lines)>4) { 1205 firstline = smartlist_get(lines, 0); 1206 if (!strcmpstart(firstline, "format ")) 1207 format = tor_parse_long(firstline+strlen("format "), 1208 10, -1, LONG_MAX, NULL, NULL); 1209 } 1210 } 1211 if (format != 1 && format != 2) { 1212 log_warn(LD_HIST, 1213 "Unrecognized format in mtbf history file. Skipping."); 1214 goto err; 1215 } 1216 for (i = 1; i < smartlist_len(lines); ++i) { 1217 line = smartlist_get(lines, i); 1218 if (!strcmp(line, "data")) 1219 break; 1220 if (!strcmpstart(line, "last-downrated ")) { 1221 if (parse_iso_time(line+strlen("last-downrated "), &last_downrated)<0) 1222 log_warn(LD_HIST,"Couldn't parse downrate time in mtbf " 1223 "history file."); 1224 } 1225 if (!strcmpstart(line, "stored-at ")) { 1226 if (parse_iso_time(line+strlen("stored-at "), &stored_at)<0) 1227 log_warn(LD_HIST,"Couldn't parse stored time in mtbf " 1228 "history file."); 1229 } 1230 if (!strcmpstart(line, "tracked-since ")) { 1231 if (parse_iso_time(line+strlen("tracked-since "), &tracked_since)<0) 1232 log_warn(LD_HIST,"Couldn't parse started-tracking time in mtbf " 1233 "history file."); 1234 } 1235 } 1236 if (last_downrated > now) 1237 last_downrated = now; 1238 if (tracked_since > now) 1239 tracked_since = now; 1240 1241 if (!stored_at) { 1242 log_warn(LD_HIST, "No stored time recorded."); 1243 goto err; 1244 } 1245 1246 if (line && !strcmp(line, "data")) 1247 ++i; 1248 1249 n_bogus_times = 0; 1250 1251 for (; i < smartlist_len(lines); ++i) { 1252 char digest[DIGEST_LEN]; 1253 char hexbuf[HEX_DIGEST_LEN+1]; 1254 char mtbf_timebuf[ISO_TIME_LEN+1]; 1255 char wfu_timebuf[ISO_TIME_LEN+1]; 1256 time_t start_of_run = 0; 1257 time_t start_of_downtime = 0; 1258 int have_mtbf = 0, have_wfu = 0; 1259 long wrl = 0; 1260 double trw = 0; 1261 long wt_uptime = 0, total_wt_time = 0; 1262 int n; 1263 or_history_t *hist; 1264 line = smartlist_get(lines, i); 1265 if (!strcmp(line, ".")) 1266 break; 1267 1268 mtbf_timebuf[0] = '\0'; 1269 wfu_timebuf[0] = '\0'; 1270 1271 if (format == 1) { 1272 n = tor_sscanf(line, "%40s %ld %lf S=%10s %8s", 1273 hexbuf, &wrl, &trw, mtbf_timebuf, mtbf_timebuf+11); 1274 if (n != 3 && n != 5) { 1275 log_warn(LD_HIST, "Couldn't scan line %s", escaped(line)); 1276 continue; 1277 } 1278 have_mtbf = 1; 1279 } else { 1280 // format == 2. 1281 int mtbf_idx, wfu_idx; 1282 if (strcmpstart(line, "R ") || strlen(line) < 2+HEX_DIGEST_LEN) 1283 continue; 1284 strlcpy(hexbuf, line+2, sizeof(hexbuf)); 1285 mtbf_idx = find_next_with(lines, i+1, "+MTBF "); 1286 wfu_idx = find_next_with(lines, i+1, "+WFU "); 1287 if (mtbf_idx >= 0) { 1288 const char *mtbfline = smartlist_get(lines, mtbf_idx); 1289 n = tor_sscanf(mtbfline, "+MTBF %lu %lf S=%10s %8s", 1290 &wrl, &trw, mtbf_timebuf, mtbf_timebuf+11); 1291 if (n == 2 || n == 4) { 1292 have_mtbf = 1; 1293 } else { 1294 log_warn(LD_HIST, "Couldn't scan +MTBF line %s", 1295 escaped(mtbfline)); 1296 } 1297 } 1298 if (wfu_idx >= 0) { 1299 const char *wfuline = smartlist_get(lines, wfu_idx); 1300 n = tor_sscanf(wfuline, "+WFU %lu %lu S=%10s %8s", 1301 &wt_uptime, &total_wt_time, 1302 wfu_timebuf, wfu_timebuf+11); 1303 if (n == 2 || n == 4) { 1304 have_wfu = 1; 1305 } else { 1306 log_warn(LD_HIST, "Couldn't scan +WFU line %s", escaped(wfuline)); 1307 } 1308 } 1309 if (wfu_idx > i) 1310 i = wfu_idx; 1311 if (mtbf_idx > i) 1312 i = mtbf_idx; 1313 } 1314 if (base16_decode(digest, DIGEST_LEN, 1315 hexbuf, HEX_DIGEST_LEN) != DIGEST_LEN) { 1316 log_warn(LD_HIST, "Couldn't hex string %s", escaped(hexbuf)); 1317 continue; 1318 } 1319 hist = get_or_history(digest); 1320 if (!hist) 1321 continue; 1322 1323 if (have_mtbf) { 1324 if (mtbf_timebuf[0]) { 1325 mtbf_timebuf[10] = ' '; 1326 if (parse_possibly_bad_iso_time(mtbf_timebuf, &start_of_run)<0) 1327 log_warn(LD_HIST, "Couldn't parse time %s", 1328 escaped(mtbf_timebuf)); 1329 } 1330 hist->start_of_run = correct_time(start_of_run, now, stored_at, 1331 tracked_since); 1332 if (hist->start_of_run < latest_possible_start + wrl) 1333 latest_possible_start = (time_t)(hist->start_of_run - wrl); 1334 1335 hist->weighted_run_length = wrl; 1336 hist->total_run_weights = trw; 1337 } 1338 if (have_wfu) { 1339 if (wfu_timebuf[0]) { 1340 wfu_timebuf[10] = ' '; 1341 if (parse_possibly_bad_iso_time(wfu_timebuf, &start_of_downtime)<0) 1342 log_warn(LD_HIST, "Couldn't parse time %s", escaped(wfu_timebuf)); 1343 } 1344 } 1345 hist->start_of_downtime = correct_time(start_of_downtime, now, stored_at, 1346 tracked_since); 1347 hist->weighted_uptime = wt_uptime; 1348 hist->total_weighted_time = total_wt_time; 1349 } 1350 if (strcmp(line, ".")) 1351 log_warn(LD_HIST, "Truncated MTBF file."); 1352 1353 if (tracked_since < 86400*365) /* Recover from insanely early value. */ 1354 tracked_since = latest_possible_start; 1355 1356 stability_last_downrated = last_downrated; 1357 started_tracking_stability = tracked_since; 1358 1359 goto done; 1360 err: 1361 r = -1; 1362 done: 1363 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp)); 1364 smartlist_free(lines); 1365 return r; 1366 } 1367 1368 /*** Exit port statistics ***/ 1369 1370 /* Some constants */ 1371 /** To what multiple should byte numbers be rounded up? */ 1372 #define EXIT_STATS_ROUND_UP_BYTES 1024 1373 /** To what multiple should stream counts be rounded up? */ 1374 #define EXIT_STATS_ROUND_UP_STREAMS 4 1375 /** Number of TCP ports */ 1376 #define EXIT_STATS_NUM_PORTS 65536 1377 /** Top n ports that will be included in exit stats. */ 1378 #define EXIT_STATS_TOP_N_PORTS 10 1379 1380 /* The following data structures are arrays and no fancy smartlists or maps, 1381 * so that all write operations can be done in constant time. This comes at 1382 * the price of some memory (1.25 MB) and linear complexity when writing 1383 * stats for measuring relays. */ 1384 /** Number of bytes read in current period by exit port */ 1385 static uint64_t *exit_bytes_read = NULL; 1386 /** Number of bytes written in current period by exit port */ 1387 static uint64_t *exit_bytes_written = NULL; 1388 /** Number of streams opened in current period by exit port */ 1389 static uint32_t *exit_streams = NULL; 1390 1391 /** Start time of exit stats or 0 if we're not collecting exit stats. */ 1392 static time_t start_of_exit_stats_interval; 1393 1394 /** Initialize exit port stats. */ 1395 void 1396 rep_hist_exit_stats_init(time_t now) 1397 { 1398 start_of_exit_stats_interval = now; 1399 exit_bytes_read = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t)); 1400 exit_bytes_written = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint64_t)); 1401 exit_streams = tor_calloc(EXIT_STATS_NUM_PORTS, sizeof(uint32_t)); 1402 } 1403 1404 /** Reset counters for exit port statistics. */ 1405 void 1406 rep_hist_reset_exit_stats(time_t now) 1407 { 1408 start_of_exit_stats_interval = now; 1409 memset(exit_bytes_read, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t)); 1410 memset(exit_bytes_written, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t)); 1411 memset(exit_streams, 0, EXIT_STATS_NUM_PORTS * sizeof(uint32_t)); 1412 } 1413 1414 /** Stop collecting exit port stats in a way that we can re-start doing 1415 * so in rep_hist_exit_stats_init(). */ 1416 void 1417 rep_hist_exit_stats_term(void) 1418 { 1419 start_of_exit_stats_interval = 0; 1420 tor_free(exit_bytes_read); 1421 tor_free(exit_bytes_written); 1422 tor_free(exit_streams); 1423 } 1424 1425 /** Helper for qsort: compare two ints. Does not handle overflow properly, 1426 * but works fine for sorting an array of port numbers, which is what we use 1427 * it for. */ 1428 static int 1429 compare_int_(const void *x, const void *y) 1430 { 1431 return (*(int*)x - *(int*)y); 1432 } 1433 1434 /** Return a newly allocated string containing the exit port statistics 1435 * until <b>now</b>, or NULL if we're not collecting exit stats. Caller 1436 * must ensure start_of_exit_stats_interval is in the past. */ 1437 char * 1438 rep_hist_format_exit_stats(time_t now) 1439 { 1440 int i, j, top_elements = 0, cur_min_idx = 0, cur_port; 1441 uint64_t top_bytes[EXIT_STATS_TOP_N_PORTS]; 1442 int top_ports[EXIT_STATS_TOP_N_PORTS]; 1443 uint64_t cur_bytes = 0, other_read = 0, other_written = 0, 1444 total_read = 0, total_written = 0; 1445 uint32_t total_streams = 0, other_streams = 0; 1446 smartlist_t *written_strings, *read_strings, *streams_strings; 1447 char *written_string, *read_string, *streams_string; 1448 char t[ISO_TIME_LEN+1]; 1449 char *result; 1450 1451 if (!start_of_exit_stats_interval) 1452 return NULL; /* Not initialized. */ 1453 1454 tor_assert(now >= start_of_exit_stats_interval); 1455 1456 /* Go through all ports to find the n ports that saw most written and 1457 * read bytes. 1458 * 1459 * Invariant: at the end of the loop for iteration i, 1460 * total_read is the sum of all exit_bytes_read[0..i] 1461 * total_written is the sum of all exit_bytes_written[0..i] 1462 * total_stream is the sum of all exit_streams[0..i] 1463 * 1464 * top_elements = MAX(EXIT_STATS_TOP_N_PORTS, 1465 * #{j | 0 <= j <= i && volume(i) > 0}) 1466 * 1467 * For all 0 <= j < top_elements, 1468 * top_bytes[j] > 0 1469 * 0 <= top_ports[j] <= 65535 1470 * top_bytes[j] = volume(top_ports[j]) 1471 * 1472 * There is no j in 0..i and k in 0..top_elements such that: 1473 * volume(j) > top_bytes[k] AND j is not in top_ports[0..top_elements] 1474 * 1475 * There is no j!=cur_min_idx in 0..top_elements such that: 1476 * top_bytes[j] < top_bytes[cur_min_idx] 1477 * 1478 * where volume(x) == exit_bytes_read[x]+exit_bytes_written[x] 1479 * 1480 * Worst case: O(EXIT_STATS_NUM_PORTS * EXIT_STATS_TOP_N_PORTS) 1481 */ 1482 for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { 1483 total_read += exit_bytes_read[i]; 1484 total_written += exit_bytes_written[i]; 1485 total_streams += exit_streams[i]; 1486 cur_bytes = exit_bytes_read[i] + exit_bytes_written[i]; 1487 if (cur_bytes == 0) { 1488 continue; 1489 } 1490 if (top_elements < EXIT_STATS_TOP_N_PORTS) { 1491 top_bytes[top_elements] = cur_bytes; 1492 top_ports[top_elements++] = i; 1493 } else if (cur_bytes > top_bytes[cur_min_idx]) { 1494 top_bytes[cur_min_idx] = cur_bytes; 1495 top_ports[cur_min_idx] = i; 1496 } else { 1497 continue; 1498 } 1499 cur_min_idx = 0; 1500 for (j = 1; j < top_elements; j++) { 1501 if (top_bytes[j] < top_bytes[cur_min_idx]) { 1502 cur_min_idx = j; 1503 } 1504 } 1505 } 1506 1507 /* Add observations of top ports to smartlists. */ 1508 written_strings = smartlist_new(); 1509 read_strings = smartlist_new(); 1510 streams_strings = smartlist_new(); 1511 other_read = total_read; 1512 other_written = total_written; 1513 other_streams = total_streams; 1514 /* Sort the ports; this puts them out of sync with top_bytes, but we 1515 * won't be using top_bytes again anyway */ 1516 qsort(top_ports, top_elements, sizeof(int), compare_int_); 1517 for (j = 0; j < top_elements; j++) { 1518 cur_port = top_ports[j]; 1519 if (exit_bytes_written[cur_port] > 0) { 1520 uint64_t num = round_uint64_to_next_multiple_of( 1521 exit_bytes_written[cur_port], 1522 EXIT_STATS_ROUND_UP_BYTES); 1523 num /= 1024; 1524 smartlist_add_asprintf(written_strings, "%d=%"PRIu64, 1525 cur_port, (num)); 1526 other_written -= exit_bytes_written[cur_port]; 1527 } 1528 if (exit_bytes_read[cur_port] > 0) { 1529 uint64_t num = round_uint64_to_next_multiple_of( 1530 exit_bytes_read[cur_port], 1531 EXIT_STATS_ROUND_UP_BYTES); 1532 num /= 1024; 1533 smartlist_add_asprintf(read_strings, "%d=%"PRIu64, 1534 cur_port, (num)); 1535 other_read -= exit_bytes_read[cur_port]; 1536 } 1537 if (exit_streams[cur_port] > 0) { 1538 uint32_t num = round_uint32_to_next_multiple_of( 1539 exit_streams[cur_port], 1540 EXIT_STATS_ROUND_UP_STREAMS); 1541 smartlist_add_asprintf(streams_strings, "%d=%u", cur_port, num); 1542 other_streams -= exit_streams[cur_port]; 1543 } 1544 } 1545 1546 /* Add observations of other ports in a single element. */ 1547 other_written = round_uint64_to_next_multiple_of(other_written, 1548 EXIT_STATS_ROUND_UP_BYTES); 1549 other_written /= 1024; 1550 smartlist_add_asprintf(written_strings, "other=%"PRIu64, 1551 (other_written)); 1552 other_read = round_uint64_to_next_multiple_of(other_read, 1553 EXIT_STATS_ROUND_UP_BYTES); 1554 other_read /= 1024; 1555 smartlist_add_asprintf(read_strings, "other=%"PRIu64, 1556 (other_read)); 1557 other_streams = round_uint32_to_next_multiple_of(other_streams, 1558 EXIT_STATS_ROUND_UP_STREAMS); 1559 smartlist_add_asprintf(streams_strings, "other=%u", other_streams); 1560 1561 /* Join all observations in single strings. */ 1562 written_string = smartlist_join_strings(written_strings, ",", 0, NULL); 1563 read_string = smartlist_join_strings(read_strings, ",", 0, NULL); 1564 streams_string = smartlist_join_strings(streams_strings, ",", 0, NULL); 1565 SMARTLIST_FOREACH(written_strings, char *, cp, tor_free(cp)); 1566 SMARTLIST_FOREACH(read_strings, char *, cp, tor_free(cp)); 1567 SMARTLIST_FOREACH(streams_strings, char *, cp, tor_free(cp)); 1568 smartlist_free(written_strings); 1569 smartlist_free(read_strings); 1570 smartlist_free(streams_strings); 1571 1572 /* Put everything together. */ 1573 format_iso_time(t, now); 1574 tor_asprintf(&result, "exit-stats-end %s (%d s)\n" 1575 "exit-kibibytes-written %s\n" 1576 "exit-kibibytes-read %s\n" 1577 "exit-streams-opened %s\n", 1578 t, (unsigned) (now - start_of_exit_stats_interval), 1579 written_string, 1580 read_string, 1581 streams_string); 1582 tor_free(written_string); 1583 tor_free(read_string); 1584 tor_free(streams_string); 1585 return result; 1586 } 1587 1588 /** If 24 hours have passed since the beginning of the current exit port 1589 * stats period, write exit stats to $DATADIR/stats/exit-stats (possibly 1590 * overwriting an existing file) and reset counters. Return when we would 1591 * next want to write exit stats or 0 if we never want to write. */ 1592 time_t 1593 rep_hist_exit_stats_write(time_t now) 1594 { 1595 char *str = NULL; 1596 1597 if (!start_of_exit_stats_interval) 1598 return 0; /* Not initialized. */ 1599 if (start_of_exit_stats_interval + WRITE_STATS_INTERVAL > now) 1600 goto done; /* Not ready to write. */ 1601 1602 log_info(LD_HIST, "Writing exit port statistics to disk."); 1603 1604 /* Generate history string. */ 1605 str = rep_hist_format_exit_stats(now); 1606 1607 /* Reset counters. */ 1608 rep_hist_reset_exit_stats(now); 1609 1610 /* Try to write to disk. */ 1611 if (!check_or_create_data_subdir("stats")) { 1612 write_to_data_subdir("stats", "exit-stats", str, "exit port statistics"); 1613 } 1614 1615 done: 1616 tor_free(str); 1617 return start_of_exit_stats_interval + WRITE_STATS_INTERVAL; 1618 } 1619 1620 /** Note that we wrote <b>num_written</b> bytes and read <b>num_read</b> 1621 * bytes to/from an exit connection to <b>port</b>. */ 1622 void 1623 rep_hist_note_exit_bytes(uint16_t port, size_t num_written, 1624 size_t num_read) 1625 { 1626 if (!start_of_exit_stats_interval) 1627 return; /* Not initialized. */ 1628 exit_bytes_written[port] += num_written; 1629 exit_bytes_read[port] += num_read; 1630 log_debug(LD_HIST, "Written %lu bytes and read %lu bytes to/from an " 1631 "exit connection to port %d.", 1632 (unsigned long)num_written, (unsigned long)num_read, port); 1633 } 1634 1635 /** Note that we opened an exit stream to <b>port</b>. */ 1636 void 1637 rep_hist_note_exit_stream_opened(uint16_t port) 1638 { 1639 if (!start_of_exit_stats_interval) 1640 return; /* Not initialized. */ 1641 exit_streams[port]++; 1642 log_debug(LD_HIST, "Opened exit stream to port %d", port); 1643 } 1644 1645 /*** Exit streams statistics ***/ 1646 1647 /** Number of BEGIN streams seen. */ 1648 static uint64_t streams_begin_seen; 1649 /** Number of BEGIN_DIR streams seen. */ 1650 static uint64_t streams_begindir_seen; 1651 /** Number of RESOLVE streams seen. */ 1652 static uint64_t streams_resolve_seen; 1653 1654 /** Note a stream as seen for the given relay command. */ 1655 void 1656 rep_hist_note_exit_stream(unsigned int cmd) 1657 { 1658 switch (cmd) { 1659 case RELAY_COMMAND_BEGIN: 1660 streams_begin_seen++; 1661 break; 1662 case RELAY_COMMAND_BEGIN_DIR: 1663 streams_begindir_seen++; 1664 break; 1665 case RELAY_COMMAND_RESOLVE: 1666 streams_resolve_seen++; 1667 break; 1668 default: 1669 tor_assert_nonfatal_unreached_once(); 1670 break; 1671 } 1672 } 1673 1674 /** Return number of stream seen for the given command. */ 1675 uint64_t 1676 rep_hist_get_exit_stream_seen(unsigned int cmd) 1677 { 1678 switch (cmd) { 1679 case RELAY_COMMAND_BEGIN: 1680 return streams_begin_seen; 1681 case RELAY_COMMAND_BEGIN_DIR: 1682 return streams_begindir_seen; 1683 case RELAY_COMMAND_RESOLVE: 1684 return streams_resolve_seen; 1685 default: 1686 return 0; 1687 } 1688 } 1689 1690 /******* Connections statistics *******/ 1691 1692 #define CONN_DIRECTION_INITIATED 0 1693 #define CONN_DIRECTION_RECEIVED 1 1694 1695 #define CONN_DIRECTION(from_listener) \ 1696 (from_listener) ? CONN_DIRECTION_RECEIVED : CONN_DIRECTION_INITIATED 1697 1698 /** Number of connections created as in seen per direction per type. */ 1699 static uint64_t conn_num_created_v4[2][CONN_TYPE_MAX_]; 1700 static uint64_t conn_num_created_v6[2][CONN_TYPE_MAX_]; 1701 /** Number of connections opened per direction per type. */ 1702 static uint64_t conn_num_opened_v4[2][CONN_TYPE_MAX_]; 1703 static uint64_t conn_num_opened_v6[2][CONN_TYPE_MAX_]; 1704 /** Number of connections rejected per type. Always inbound. */ 1705 static uint64_t conn_num_rejected_v4[CONN_TYPE_MAX_]; 1706 static uint64_t conn_num_rejected_v6[CONN_TYPE_MAX_]; 1707 1708 /** Note that a connection has opened of the given type. */ 1709 void 1710 rep_hist_note_conn_opened(bool from_listener, unsigned int type, int af) 1711 { 1712 tor_assert(type <= CONN_TYPE_MAX_); 1713 1714 unsigned int dir = CONN_DIRECTION(from_listener); 1715 1716 switch (af) { 1717 case AF_INET: 1718 conn_num_created_v4[dir][type]++; 1719 conn_num_opened_v4[dir][type]++; 1720 break; 1721 case AF_INET6: 1722 conn_num_created_v6[dir][type]++; 1723 conn_num_opened_v6[dir][type]++; 1724 break; 1725 default: 1726 /* Ignore non IP connections at this point in time. */ 1727 break; 1728 } 1729 } 1730 1731 /** Note that a connection has closed of the given type. */ 1732 void 1733 rep_hist_note_conn_closed(bool from_listener, unsigned int type, int af) 1734 { 1735 tor_assert(type <= CONN_TYPE_MAX_); 1736 1737 unsigned int dir = CONN_DIRECTION(from_listener); 1738 1739 switch (af) { 1740 case AF_INET: 1741 if (conn_num_opened_v4[dir][type] > 0) { 1742 conn_num_opened_v4[dir][type]--; 1743 } 1744 break; 1745 case AF_INET6: 1746 if (conn_num_opened_v6[dir][type] > 0) { 1747 conn_num_opened_v6[dir][type]--; 1748 } 1749 break; 1750 default: 1751 /* Ignore non IP connections at this point in time. */ 1752 break; 1753 } 1754 } 1755 1756 /** Note that a connection has rejected of the given type. */ 1757 void 1758 rep_hist_note_conn_rejected(unsigned int type, int af) 1759 { 1760 tor_assert(type <= CONN_TYPE_MAX_); 1761 1762 switch (af) { 1763 case AF_INET: 1764 conn_num_rejected_v4[type]++; 1765 break; 1766 case AF_INET6: 1767 conn_num_rejected_v6[type]++; 1768 break; 1769 default: 1770 /* Ignore non IP connections at this point in time. */ 1771 break; 1772 } 1773 } 1774 1775 /** Return number of created connections of the given type. */ 1776 uint64_t 1777 rep_hist_get_conn_created(bool from_listener, unsigned int type, int af) 1778 { 1779 tor_assert(type <= CONN_TYPE_MAX_); 1780 unsigned int dir = CONN_DIRECTION(from_listener); 1781 switch (af) { 1782 case AF_INET: 1783 return conn_num_created_v4[dir][type]; 1784 case AF_INET6: 1785 return conn_num_created_v6[dir][type]; 1786 default: 1787 return 0; 1788 } 1789 } 1790 1791 /** Return number of opened connections of the given type. */ 1792 uint64_t 1793 rep_hist_get_conn_opened(bool from_listener, unsigned int type, int af) 1794 { 1795 tor_assert(type <= CONN_TYPE_MAX_); 1796 unsigned int dir = CONN_DIRECTION(from_listener); 1797 switch (af) { 1798 case AF_INET: 1799 return conn_num_opened_v4[dir][type]; 1800 case AF_INET6: 1801 return conn_num_opened_v6[dir][type]; 1802 default: 1803 return 0; 1804 } 1805 } 1806 1807 /** Return number of opened connections of the given type. */ 1808 uint64_t 1809 rep_hist_get_conn_rejected(unsigned int type, int af) 1810 { 1811 tor_assert(type <= CONN_TYPE_MAX_); 1812 switch (af) { 1813 case AF_INET: 1814 return conn_num_rejected_v4[type]; 1815 case AF_INET6: 1816 return conn_num_rejected_v6[type]; 1817 default: 1818 return 0; 1819 } 1820 } 1821 1822 /*** cell statistics ***/ 1823 1824 /** Start of the current buffer stats interval or 0 if we're not 1825 * collecting buffer statistics. */ 1826 static time_t start_of_buffer_stats_interval; 1827 1828 /** Initialize buffer stats. */ 1829 void 1830 rep_hist_buffer_stats_init(time_t now) 1831 { 1832 start_of_buffer_stats_interval = now; 1833 } 1834 1835 /** Statistics from a single circuit. Collected when the circuit closes, or 1836 * when we flush statistics to disk. */ 1837 typedef struct circ_buffer_stats_t { 1838 /** Average number of cells in the circuit's queue */ 1839 double mean_num_cells_in_queue; 1840 /** Average time a cell waits in the queue. */ 1841 double mean_time_cells_in_queue; 1842 /** Total number of cells sent over this circuit */ 1843 uint32_t processed_cells; 1844 } circ_buffer_stats_t; 1845 1846 /** List of circ_buffer_stats_t. */ 1847 static smartlist_t *circuits_for_buffer_stats = NULL; 1848 1849 /** Remember cell statistics <b>mean_num_cells_in_queue</b>, 1850 * <b>mean_time_cells_in_queue</b>, and <b>processed_cells</b> of a 1851 * circuit. */ 1852 void 1853 rep_hist_add_buffer_stats(double mean_num_cells_in_queue, 1854 double mean_time_cells_in_queue, uint32_t processed_cells) 1855 { 1856 circ_buffer_stats_t *stats; 1857 if (!start_of_buffer_stats_interval) 1858 return; /* Not initialized. */ 1859 stats = tor_malloc_zero(sizeof(circ_buffer_stats_t)); 1860 stats->mean_num_cells_in_queue = mean_num_cells_in_queue; 1861 stats->mean_time_cells_in_queue = mean_time_cells_in_queue; 1862 stats->processed_cells = processed_cells; 1863 if (!circuits_for_buffer_stats) 1864 circuits_for_buffer_stats = smartlist_new(); 1865 smartlist_add(circuits_for_buffer_stats, stats); 1866 } 1867 1868 /** Remember cell statistics for circuit <b>circ</b> at time 1869 * <b>end_of_interval</b> and reset cell counters in case the circuit 1870 * remains open in the next measurement interval. */ 1871 void 1872 rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) 1873 { 1874 time_t start_of_interval; 1875 int interval_length; 1876 or_circuit_t *orcirc; 1877 double mean_num_cells_in_queue, mean_time_cells_in_queue; 1878 uint32_t processed_cells; 1879 if (CIRCUIT_IS_ORIGIN(circ)) 1880 return; 1881 orcirc = TO_OR_CIRCUIT(circ); 1882 if (!orcirc->processed_cells) 1883 return; 1884 start_of_interval = (circ->timestamp_created.tv_sec > 1885 start_of_buffer_stats_interval) ? 1886 (time_t)circ->timestamp_created.tv_sec : 1887 start_of_buffer_stats_interval; 1888 interval_length = (int) (end_of_interval - start_of_interval); 1889 if (interval_length <= 0) 1890 return; 1891 processed_cells = orcirc->processed_cells; 1892 /* 1000.0 for s -> ms; 2.0 because of app-ward and exit-ward queues */ 1893 mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time / 1894 (double) interval_length / 1000.0 / 2.0; 1895 mean_time_cells_in_queue = 1896 (double) orcirc->total_cell_waiting_time / 1897 (double) orcirc->processed_cells; 1898 orcirc->total_cell_waiting_time = 0; 1899 orcirc->processed_cells = 0; 1900 rep_hist_add_buffer_stats(mean_num_cells_in_queue, 1901 mean_time_cells_in_queue, 1902 processed_cells); 1903 } 1904 1905 /** Sorting helper: return -1, 1, or 0 based on comparison of two 1906 * circ_buffer_stats_t */ 1907 static int 1908 buffer_stats_compare_entries_(const void **_a, const void **_b) 1909 { 1910 const circ_buffer_stats_t *a = *_a, *b = *_b; 1911 if (a->processed_cells < b->processed_cells) 1912 return 1; 1913 else if (a->processed_cells > b->processed_cells) 1914 return -1; 1915 else 1916 return 0; 1917 } 1918 1919 /** Stop collecting cell stats in a way that we can re-start doing so in 1920 * rep_hist_buffer_stats_init(). */ 1921 void 1922 rep_hist_buffer_stats_term(void) 1923 { 1924 rep_hist_reset_buffer_stats(0); 1925 } 1926 1927 /** Clear history of circuit statistics and set the measurement interval 1928 * start to <b>now</b>. */ 1929 void 1930 rep_hist_reset_buffer_stats(time_t now) 1931 { 1932 if (!circuits_for_buffer_stats) 1933 circuits_for_buffer_stats = smartlist_new(); 1934 SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, 1935 stats, tor_free(stats)); 1936 smartlist_clear(circuits_for_buffer_stats); 1937 start_of_buffer_stats_interval = now; 1938 } 1939 1940 /** Return a newly allocated string containing the buffer statistics until 1941 * <b>now</b>, or NULL if we're not collecting buffer stats. Caller must 1942 * ensure start_of_buffer_stats_interval is in the past. */ 1943 char * 1944 rep_hist_format_buffer_stats(time_t now) 1945 { 1946 #define SHARES 10 1947 uint64_t processed_cells[SHARES]; 1948 uint32_t circs_in_share[SHARES]; 1949 int number_of_circuits, i; 1950 double queued_cells[SHARES], time_in_queue[SHARES]; 1951 smartlist_t *processed_cells_strings, *queued_cells_strings, 1952 *time_in_queue_strings; 1953 char *processed_cells_string, *queued_cells_string, 1954 *time_in_queue_string; 1955 char t[ISO_TIME_LEN+1]; 1956 char *result; 1957 1958 if (!start_of_buffer_stats_interval) 1959 return NULL; /* Not initialized. */ 1960 1961 tor_assert(now >= start_of_buffer_stats_interval); 1962 1963 /* Calculate deciles if we saw at least one circuit. */ 1964 memset(processed_cells, 0, SHARES * sizeof(uint64_t)); 1965 memset(circs_in_share, 0, SHARES * sizeof(uint32_t)); 1966 memset(queued_cells, 0, SHARES * sizeof(double)); 1967 memset(time_in_queue, 0, SHARES * sizeof(double)); 1968 if (!circuits_for_buffer_stats) 1969 circuits_for_buffer_stats = smartlist_new(); 1970 number_of_circuits = smartlist_len(circuits_for_buffer_stats); 1971 if (number_of_circuits > 0) { 1972 smartlist_sort(circuits_for_buffer_stats, 1973 buffer_stats_compare_entries_); 1974 i = 0; 1975 SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats, 1976 circ_buffer_stats_t *, stats) 1977 { 1978 int share = i++ * SHARES / number_of_circuits; 1979 processed_cells[share] += stats->processed_cells; 1980 queued_cells[share] += stats->mean_num_cells_in_queue; 1981 time_in_queue[share] += stats->mean_time_cells_in_queue; 1982 circs_in_share[share]++; 1983 } 1984 SMARTLIST_FOREACH_END(stats); 1985 } 1986 1987 /* Write deciles to strings. */ 1988 processed_cells_strings = smartlist_new(); 1989 queued_cells_strings = smartlist_new(); 1990 time_in_queue_strings = smartlist_new(); 1991 for (i = 0; i < SHARES; i++) { 1992 smartlist_add_asprintf(processed_cells_strings, 1993 "%"PRIu64, !circs_in_share[i] ? 0 : 1994 (processed_cells[i] / 1995 circs_in_share[i])); 1996 } 1997 for (i = 0; i < SHARES; i++) { 1998 smartlist_add_asprintf(queued_cells_strings, "%.2f", 1999 circs_in_share[i] == 0 ? 0.0 : 2000 queued_cells[i] / (double) circs_in_share[i]); 2001 } 2002 for (i = 0; i < SHARES; i++) { 2003 smartlist_add_asprintf(time_in_queue_strings, "%.0f", 2004 circs_in_share[i] == 0 ? 0.0 : 2005 time_in_queue[i] / (double) circs_in_share[i]); 2006 } 2007 2008 /* Join all observations in single strings. */ 2009 processed_cells_string = smartlist_join_strings(processed_cells_strings, 2010 ",", 0, NULL); 2011 queued_cells_string = smartlist_join_strings(queued_cells_strings, 2012 ",", 0, NULL); 2013 time_in_queue_string = smartlist_join_strings(time_in_queue_strings, 2014 ",", 0, NULL); 2015 SMARTLIST_FOREACH(processed_cells_strings, char *, cp, tor_free(cp)); 2016 SMARTLIST_FOREACH(queued_cells_strings, char *, cp, tor_free(cp)); 2017 SMARTLIST_FOREACH(time_in_queue_strings, char *, cp, tor_free(cp)); 2018 smartlist_free(processed_cells_strings); 2019 smartlist_free(queued_cells_strings); 2020 smartlist_free(time_in_queue_strings); 2021 2022 /* Put everything together. */ 2023 format_iso_time(t, now); 2024 tor_asprintf(&result, "cell-stats-end %s (%d s)\n" 2025 "cell-processed-cells %s\n" 2026 "cell-queued-cells %s\n" 2027 "cell-time-in-queue %s\n" 2028 "cell-circuits-per-decile %d\n", 2029 t, (unsigned) (now - start_of_buffer_stats_interval), 2030 processed_cells_string, 2031 queued_cells_string, 2032 time_in_queue_string, 2033 CEIL_DIV(number_of_circuits, SHARES)); 2034 tor_free(processed_cells_string); 2035 tor_free(queued_cells_string); 2036 tor_free(time_in_queue_string); 2037 return result; 2038 #undef SHARES 2039 } 2040 2041 /** If 24 hours have passed since the beginning of the current buffer 2042 * stats period, write buffer stats to $DATADIR/stats/buffer-stats 2043 * (possibly overwriting an existing file) and reset counters. Return 2044 * when we would next want to write buffer stats or 0 if we never want to 2045 * write. */ 2046 time_t 2047 rep_hist_buffer_stats_write(time_t now) 2048 { 2049 char *str = NULL; 2050 2051 if (!start_of_buffer_stats_interval) 2052 return 0; /* Not initialized. */ 2053 if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now) 2054 goto done; /* Not ready to write */ 2055 2056 /* Add open circuits to the history. */ 2057 SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) { 2058 rep_hist_buffer_stats_add_circ(circ, now); 2059 } 2060 SMARTLIST_FOREACH_END(circ); 2061 2062 /* Generate history string. */ 2063 str = rep_hist_format_buffer_stats(now); 2064 2065 /* Reset both buffer history and counters of open circuits. */ 2066 rep_hist_reset_buffer_stats(now); 2067 2068 /* Try to write to disk. */ 2069 if (!check_or_create_data_subdir("stats")) { 2070 write_to_data_subdir("stats", "buffer-stats", str, "buffer statistics"); 2071 } 2072 2073 done: 2074 tor_free(str); 2075 return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL; 2076 } 2077 2078 /*** Descriptor serving statistics ***/ 2079 2080 /** Digestmap to track which descriptors were downloaded this stats 2081 * collection interval. It maps descriptor digest to pointers to 1, 2082 * effectively turning this into a list. */ 2083 static digestmap_t *served_descs = NULL; 2084 2085 /** Number of how many descriptors were downloaded in total during this 2086 * interval. */ 2087 static unsigned long total_descriptor_downloads; 2088 2089 /** Start time of served descs stats or 0 if we're not collecting those. */ 2090 static time_t start_of_served_descs_stats_interval; 2091 2092 /** Initialize descriptor stats. */ 2093 void 2094 rep_hist_desc_stats_init(time_t now) 2095 { 2096 if (served_descs) { 2097 log_warn(LD_BUG, "Called rep_hist_desc_stats_init() when desc stats were " 2098 "already initialized. This is probably harmless."); 2099 return; // Already initialized 2100 } 2101 served_descs = digestmap_new(); 2102 total_descriptor_downloads = 0; 2103 start_of_served_descs_stats_interval = now; 2104 } 2105 2106 /** Reset served descs stats to empty, starting a new interval <b>now</b>. */ 2107 static void 2108 rep_hist_reset_desc_stats(time_t now) 2109 { 2110 rep_hist_desc_stats_term(); 2111 rep_hist_desc_stats_init(now); 2112 } 2113 2114 /** Stop collecting served descs stats, so that rep_hist_desc_stats_init() is 2115 * safe to be called again. */ 2116 void 2117 rep_hist_desc_stats_term(void) 2118 { 2119 digestmap_free(served_descs, NULL); 2120 served_descs = NULL; 2121 start_of_served_descs_stats_interval = 0; 2122 total_descriptor_downloads = 0; 2123 } 2124 2125 /** Helper for rep_hist_desc_stats_write(). Return a newly allocated string 2126 * containing the served desc statistics until now, or NULL if we're not 2127 * collecting served desc stats. Caller must ensure that now is not before 2128 * start_of_served_descs_stats_interval. */ 2129 static char * 2130 rep_hist_format_desc_stats(time_t now) 2131 { 2132 char t[ISO_TIME_LEN+1]; 2133 char *result; 2134 2135 digestmap_iter_t *iter; 2136 const char *key; 2137 void *val; 2138 unsigned size; 2139 int *vals, max = 0, q3 = 0, md = 0, q1 = 0, min = 0; 2140 int n = 0; 2141 2142 if (!start_of_served_descs_stats_interval) 2143 return NULL; 2144 2145 size = digestmap_size(served_descs); 2146 if (size > 0) { 2147 vals = tor_calloc(size, sizeof(int)); 2148 for (iter = digestmap_iter_init(served_descs); 2149 !digestmap_iter_done(iter); 2150 iter = digestmap_iter_next(served_descs, iter)) { 2151 uintptr_t count; 2152 digestmap_iter_get(iter, &key, &val); 2153 count = (uintptr_t)val; 2154 vals[n++] = (int)count; 2155 (void)key; 2156 } 2157 max = find_nth_int(vals, size, size-1); 2158 q3 = find_nth_int(vals, size, (3*size-1)/4); 2159 md = find_nth_int(vals, size, (size-1)/2); 2160 q1 = find_nth_int(vals, size, (size-1)/4); 2161 min = find_nth_int(vals, size, 0); 2162 tor_free(vals); 2163 } 2164 2165 format_iso_time(t, now); 2166 2167 tor_asprintf(&result, 2168 "served-descs-stats-end %s (%d s) total=%lu unique=%u " 2169 "max=%d q3=%d md=%d q1=%d min=%d\n", 2170 t, 2171 (unsigned) (now - start_of_served_descs_stats_interval), 2172 total_descriptor_downloads, 2173 size, max, q3, md, q1, min); 2174 2175 return result; 2176 } 2177 2178 /** If WRITE_STATS_INTERVAL seconds have passed since the beginning of 2179 * the current served desc stats interval, write the stats to 2180 * $DATADIR/stats/served-desc-stats (possibly appending to an existing file) 2181 * and reset the state for the next interval. Return when we would next want 2182 * to write served desc stats or 0 if we won't want to write. */ 2183 time_t 2184 rep_hist_desc_stats_write(time_t now) 2185 { 2186 char *filename = NULL, *str = NULL; 2187 2188 if (!start_of_served_descs_stats_interval) 2189 return 0; /* We're not collecting stats. */ 2190 if (start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL > now) 2191 return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL; 2192 2193 str = rep_hist_format_desc_stats(now); 2194 tor_assert(str != NULL); 2195 2196 if (check_or_create_data_subdir("stats") < 0) { 2197 goto done; 2198 } 2199 filename = get_datadir_fname2("stats", "served-desc-stats"); 2200 if (append_bytes_to_file(filename, str, strlen(str), 0) < 0) 2201 log_warn(LD_HIST, "Unable to write served descs statistics to disk!"); 2202 2203 rep_hist_reset_desc_stats(now); 2204 2205 done: 2206 tor_free(filename); 2207 tor_free(str); 2208 return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL; 2209 } 2210 2211 /** Called to note that we've served a given descriptor (by 2212 * digest). Increments the count of descriptors served, and the number 2213 * of times we've served this descriptor. */ 2214 void 2215 rep_hist_note_desc_served(const char * desc) 2216 { 2217 void *val; 2218 uintptr_t count; 2219 if (!served_descs) 2220 return; // We're not collecting stats 2221 val = digestmap_get(served_descs, desc); 2222 count = (uintptr_t)val; 2223 if (count != INT_MAX) 2224 ++count; 2225 digestmap_set(served_descs, desc, (void*)count); 2226 total_descriptor_downloads++; 2227 } 2228 2229 /*** Connection statistics ***/ 2230 2231 /** Internal statistics to track how many requests of each type of 2232 * handshake we've received, and how many we've assigned to cpuworkers. 2233 * Useful for seeing trends in cpu load. 2234 * 2235 * They are reset at every heartbeat. 2236 * @{ */ 2237 STATIC int onion_handshakes_requested[MAX_ONION_STAT_TYPE+1] = {0}; 2238 STATIC int onion_handshakes_assigned[MAX_ONION_STAT_TYPE+1] = {0}; 2239 /**@}*/ 2240 2241 /** Counters keeping the same stats as above but for the entire duration of the 2242 * process (not reset). */ 2243 static uint64_t stats_n_onionskin_assigned[MAX_ONION_STAT_TYPE+1] = {0}; 2244 static uint64_t stats_n_onionskin_dropped[MAX_ONION_STAT_TYPE+1] = {0}; 2245 2246 /* We use a scale here so we can represent percentages with decimal points by 2247 * scaling the value by this factor and so 0.5% becomes a value of 500. 2248 * Default is 1% and thus min and max range is 0 to 100%. */ 2249 #define OVERLOAD_ONIONSKIN_NTOR_PERCENT_SCALE 1000.0 2250 #define OVERLOAD_ONIONSKIN_NTOR_PERCENT_DEFAULT 1000 2251 #define OVERLOAD_ONIONSKIN_NTOR_PERCENT_MIN 0 2252 #define OVERLOAD_ONIONSKIN_NTOR_PERCENT_MAX 100000 2253 2254 /** Consensus parameter: indicate what fraction of ntor onionskin drop over the 2255 * total number of requests must be reached before we trigger a general 2256 * overload signal.*/ 2257 static double overload_onionskin_ntor_fraction = 2258 OVERLOAD_ONIONSKIN_NTOR_PERCENT_DEFAULT / 2259 OVERLOAD_ONIONSKIN_NTOR_PERCENT_SCALE / 100.0; 2260 2261 /* Number of seconds for the assessment period. Default is 6 hours (21600) and 2262 * the min max range is within a 32bit value. We align this period to the 2263 * Heartbeat so the logs would match this period more or less. */ 2264 #define OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_DEFAULT (60 * 60 * 6) 2265 #define OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_MIN 0 2266 #define OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_MAX INT32_MAX 2267 2268 /** Consensus parameter: Period, in seconds, over which we count the number of 2269 * ntor onionskins requests and how many were dropped. After that period, we 2270 * assess if we trigger an overload or not. */ 2271 static int32_t overload_onionskin_ntor_period_secs = 2272 OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_DEFAULT; 2273 2274 /** Structure containing information for an assessment period of the onionskin 2275 * drop overload general signal. 2276 * 2277 * It is used to track, within a time period, how many requests we've gotten 2278 * and how many were dropped. The overload general signal is decided from these 2279 * depending on some consensus parameters. */ 2280 typedef struct { 2281 /** Total number of ntor onionskin requested for an assessment period. */ 2282 uint64_t n_ntor_requested; 2283 2284 /** Total number of dropped ntor onionskins for an assessment period. */ 2285 uint64_t n_ntor_dropped; 2286 2287 /** When is the next assessment time of the general overload for ntor 2288 * onionskin drop. Once this time is reached, all stats are reset and this 2289 * time is set to the next assessment time. */ 2290 time_t next_assessment_time; 2291 } overload_onionskin_assessment_t; 2292 2293 /** Keep track of the onionskin requests for an assessment period. */ 2294 static overload_onionskin_assessment_t overload_onionskin_assessment; 2295 2296 /** This function ensures that we clamp the maximum value of the given input 2297 * <b>type</b> to NTOR in case the input is out of range. 2298 */ 2299 static inline uint16_t 2300 onionskin_type_to_stat(uint16_t type) 2301 { 2302 if (BUG(type > MAX_ONION_STAT_TYPE)) { 2303 return MAX_ONION_STAT_TYPE; // use ntor_v3 if out of range 2304 } 2305 2306 return type; 2307 } 2308 2309 /** Assess our ntor handshake statistics and decide if we need to emit a 2310 * general overload signal. 2311 * 2312 * Regardless of overloaded or not, if the assessment time period has passed, 2313 * the stats are reset back to 0 and the assessment time period updated. 2314 * 2315 * This is called when a ntor handshake is _requested_ because we want to avoid 2316 * to have an asymmetric situation where requested counter is reset to 0 but 2317 * then a drop happens leading to the drop counter being incremented while the 2318 * requested counter is 0. */ 2319 static void 2320 overload_general_onionskin_assessment(void) 2321 { 2322 /* Initialize the time. Should be done once. */ 2323 if (overload_onionskin_assessment.next_assessment_time == 0) { 2324 goto reset; 2325 } 2326 2327 /* Not the time yet. */ 2328 if (overload_onionskin_assessment.next_assessment_time > approx_time()) { 2329 goto done; 2330 } 2331 2332 /* Make sure we have enough requests to be able to make a proper assessment. 2333 * We want to avoid 1 single request/drop to trigger an overload as we want 2334 * at least the number of requests to be above the scale of our fraction. */ 2335 if (overload_onionskin_assessment.n_ntor_requested < 2336 OVERLOAD_ONIONSKIN_NTOR_PERCENT_SCALE) { 2337 goto done; 2338 } 2339 2340 /* Lets see if we can signal a general overload. */ 2341 double fraction = (double) overload_onionskin_assessment.n_ntor_dropped / 2342 (double) overload_onionskin_assessment.n_ntor_requested; 2343 if (fraction >= overload_onionskin_ntor_fraction) { 2344 log_notice(LD_HIST, "General overload -> Ntor dropped (%" PRIu64 ") " 2345 "fraction %.4f%% is above threshold of %.4f%%", 2346 overload_onionskin_assessment.n_ntor_dropped, 2347 fraction * 100.0, 2348 overload_onionskin_ntor_fraction * 100.0); 2349 rep_hist_note_overload(OVERLOAD_GENERAL); 2350 } 2351 2352 reset: 2353 /* Reset counters for the next period. */ 2354 overload_onionskin_assessment.n_ntor_dropped = 0; 2355 overload_onionskin_assessment.n_ntor_requested = 0; 2356 overload_onionskin_assessment.next_assessment_time = 2357 approx_time() + overload_onionskin_ntor_period_secs; 2358 2359 done: 2360 return; 2361 } 2362 2363 /** A new onionskin (using the <b>type</b> handshake) has arrived. */ 2364 void 2365 rep_hist_note_circuit_handshake_requested(uint16_t type) 2366 { 2367 uint16_t stat = onionskin_type_to_stat(type); 2368 2369 onion_handshakes_requested[stat]++; 2370 2371 /* Only relays get to record requested onionskins. */ 2372 if (stat == ONION_HANDSHAKE_TYPE_NTOR || 2373 stat == ONION_HANDSHAKE_TYPE_NTOR_V3) { 2374 /* Assess if we've reached the overload general signal. */ 2375 overload_general_onionskin_assessment(); 2376 2377 overload_onionskin_assessment.n_ntor_requested++; 2378 } 2379 } 2380 2381 /** We've sent an onionskin (using the <b>type</b> handshake) to a 2382 * cpuworker. */ 2383 void 2384 rep_hist_note_circuit_handshake_assigned(uint16_t type) 2385 { 2386 onion_handshakes_assigned[onionskin_type_to_stat(type)]++; 2387 stats_n_onionskin_assigned[onionskin_type_to_stat(type)]++; 2388 } 2389 2390 /** We've just drop an onionskin (using the <b>type</b> handshake) due to being 2391 * overloaded. */ 2392 void 2393 rep_hist_note_circuit_handshake_dropped(uint16_t type) 2394 { 2395 uint16_t stat = onionskin_type_to_stat(type); 2396 2397 stats_n_onionskin_dropped[stat]++; 2398 2399 /* Only relays get to record requested onionskins. */ 2400 if (stat == ONION_HANDSHAKE_TYPE_NTOR || 2401 stat == ONION_HANDSHAKE_TYPE_NTOR_V3) { 2402 /* Note the dropped ntor in the overload assessment object. */ 2403 overload_onionskin_assessment.n_ntor_dropped++; 2404 } 2405 } 2406 2407 /** Get the circuit handshake value that is requested. */ 2408 MOCK_IMPL(int, 2409 rep_hist_get_circuit_handshake_requested, (uint16_t type)) 2410 { 2411 return onion_handshakes_requested[onionskin_type_to_stat(type)]; 2412 } 2413 2414 /** Get the circuit handshake value that is assigned. */ 2415 MOCK_IMPL(int, 2416 rep_hist_get_circuit_handshake_assigned, (uint16_t type)) 2417 { 2418 return onion_handshakes_assigned[onionskin_type_to_stat(type)]; 2419 } 2420 2421 /** Get the total number of circuit handshake value that is assigned. */ 2422 MOCK_IMPL(uint64_t, 2423 rep_hist_get_circuit_n_handshake_assigned, (uint16_t type)) 2424 { 2425 return stats_n_onionskin_assigned[onionskin_type_to_stat(type)]; 2426 } 2427 2428 /** Get the total number of circuit handshake value that is dropped. */ 2429 MOCK_IMPL(uint64_t, 2430 rep_hist_get_circuit_n_handshake_dropped, (uint16_t type)) 2431 { 2432 return stats_n_onionskin_dropped[onionskin_type_to_stat(type)]; 2433 } 2434 2435 /** Log our onionskin statistics since the last time we were called. */ 2436 void 2437 rep_hist_log_circuit_handshake_stats(time_t now) 2438 { 2439 (void)now; 2440 log_notice(LD_HEARTBEAT, "Circuit handshake stats since last time: " 2441 "%d/%d TAP, %d/%d NTor, %d/%d NTor (v3).", 2442 onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP], 2443 onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP], 2444 onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR], 2445 onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR], 2446 onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR_V3], 2447 onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR_V3]); 2448 memset(onion_handshakes_assigned, 0, sizeof(onion_handshakes_assigned)); 2449 memset(onion_handshakes_requested, 0, sizeof(onion_handshakes_requested)); 2450 } 2451 2452 /* Hidden service statistics section */ 2453 2454 /** Start of the current hidden service stats interval or 0 if we're 2455 * not collecting hidden service statistics. */ 2456 static time_t start_of_hs_v2_stats_interval; 2457 2458 /** Our v2 statistics structure singleton. */ 2459 static hs_v2_stats_t *hs_v2_stats = NULL; 2460 2461 /** HSv2 stats */ 2462 2463 /** Allocate, initialize and return an hs_v2_stats_t structure. */ 2464 static hs_v2_stats_t * 2465 hs_v2_stats_new(void) 2466 { 2467 hs_v2_stats_t *new_hs_v2_stats = tor_malloc_zero(sizeof(hs_v2_stats_t)); 2468 2469 return new_hs_v2_stats; 2470 } 2471 2472 #define hs_v2_stats_free(val) \ 2473 FREE_AND_NULL(hs_v2_stats_t, hs_v2_stats_free_, (val)) 2474 2475 /** Free an hs_v2_stats_t structure. */ 2476 static void 2477 hs_v2_stats_free_(hs_v2_stats_t *victim_hs_v2_stats) 2478 { 2479 if (!victim_hs_v2_stats) { 2480 return; 2481 } 2482 tor_free(victim_hs_v2_stats); 2483 } 2484 2485 /** Clear history of hidden service statistics and set the measurement 2486 * interval start to <b>now</b>. */ 2487 static void 2488 rep_hist_reset_hs_v2_stats(time_t now) 2489 { 2490 if (!hs_v2_stats) { 2491 hs_v2_stats = hs_v2_stats_new(); 2492 } 2493 2494 hs_v2_stats->rp_v2_relay_cells_seen = 0; 2495 2496 start_of_hs_v2_stats_interval = now; 2497 } 2498 2499 /*** HSv3 stats ******/ 2500 2501 /** Start of the current hidden service stats interval or 0 if we're not 2502 * collecting hidden service statistics. 2503 * 2504 * This is particularly important for v3 statistics since this variable 2505 * controls the start time of initial v3 stats collection. It's initialized by 2506 * rep_hist_hs_stats_init() to the next time period start (i.e. 12:00UTC), and 2507 * should_collect_v3_stats() ensures that functions that collect v3 stats do 2508 * not do so sooner than that. 2509 * 2510 * Collecting stats from 12:00UTC to 12:00UTC is extremely important for v3 2511 * stats because rep_hist_hsdir_stored_maybe_new_v3_onion() uses the blinded 2512 * key of each onion service as its double-counting index. Onion services 2513 * rotate their descriptor at around 00:00UTC which means that their blinded 2514 * key also changes around that time. However the precise time that onion 2515 * services rotate their descriptors is actually when they fetch a new 2516 * 00:00UTC consensus and that happens at a random time (e.g. it can even 2517 * happen at 02:00UTC). This means that if we started keeping v3 stats at 2518 * around 00:00UTC we wouldn't be able to tell when onion services change 2519 * their blinded key and hence we would double count an unpredictable amount 2520 * of them (for example, if an onion service fetches the 00:00UTC consensus at 2521 * 01:00UTC it would upload to its old HSDir at 00:45UTC, and then to a 2522 * different HSDir at 01:50UTC). 2523 * 2524 * For this reason, we start collecting statistics at 12:00UTC. This way we 2525 * know that by the time we stop collecting statistics for that time period 24 2526 * hours later, all the onion services have switched to their new blinded 2527 * key. This way we can predict much better how much double counting has been 2528 * performed. 2529 */ 2530 static time_t start_of_hs_v3_stats_interval; 2531 2532 /** Our v3 statistics structure singleton. */ 2533 static hs_v3_stats_t *hs_v3_stats = NULL; 2534 2535 /** Allocate, initialize and return an hs_v3_stats_t structure. */ 2536 static hs_v3_stats_t * 2537 hs_v3_stats_new(void) 2538 { 2539 hs_v3_stats_t *new_hs_v3_stats = tor_malloc_zero(sizeof(hs_v3_stats_t)); 2540 new_hs_v3_stats->v3_onions_seen_this_period = digest256map_new(); 2541 2542 return new_hs_v3_stats; 2543 } 2544 2545 #define hs_v3_stats_free(val) \ 2546 FREE_AND_NULL(hs_v3_stats_t, hs_v3_stats_free_, (val)) 2547 2548 /** Free an hs_v3_stats_t structure. */ 2549 static void 2550 hs_v3_stats_free_(hs_v3_stats_t *victim_hs_v3_stats) 2551 { 2552 if (!victim_hs_v3_stats) { 2553 return; 2554 } 2555 2556 digest256map_free(victim_hs_v3_stats->v3_onions_seen_this_period, NULL); 2557 tor_free(victim_hs_v3_stats); 2558 } 2559 2560 /** Clear history of hidden service statistics and set the measurement 2561 * interval start to <b>now</b>. */ 2562 static void 2563 rep_hist_reset_hs_v3_stats(time_t now) 2564 { 2565 if (!hs_v3_stats) { 2566 hs_v3_stats = hs_v3_stats_new(); 2567 } 2568 2569 digest256map_free(hs_v3_stats->v3_onions_seen_this_period, NULL); 2570 hs_v3_stats->v3_onions_seen_this_period = digest256map_new(); 2571 2572 hs_v3_stats->rp_v3_relay_cells_seen = 0; 2573 2574 start_of_hs_v3_stats_interval = now; 2575 } 2576 2577 /** Return true if it's a good time to collect v3 stats. 2578 * 2579 * v3 stats have a strict stats collection period (from 12:00UTC to 12:00UTC 2580 * on the real network). We don't want to collect statistics if (for example) 2581 * we just booted and it's 03:00UTC; we will wait until 12:00UTC before we 2582 * start collecting statistics to make sure that the final result represents 2583 * the whole collection period. This behavior is controlled by 2584 * rep_hist_hs_stats_init(). 2585 */ 2586 MOCK_IMPL(STATIC bool, 2587 should_collect_v3_stats,(void)) 2588 { 2589 return start_of_hs_v3_stats_interval <= approx_time(); 2590 } 2591 2592 /** We just received a new descriptor with <b>blinded_key</b>. See if we've 2593 * seen this blinded key before, and if not add it to the stats. */ 2594 void 2595 rep_hist_hsdir_stored_maybe_new_v3_onion(const uint8_t *blinded_key) 2596 { 2597 /* Return early if we don't collect HSv3 stats, or if it's not yet the time 2598 * to collect them. */ 2599 if (!hs_v3_stats || !should_collect_v3_stats()) { 2600 return; 2601 } 2602 2603 bool seen_before = 2604 !!digest256map_get(hs_v3_stats->v3_onions_seen_this_period, 2605 blinded_key); 2606 2607 log_info(LD_GENERAL, "Considering v3 descriptor with %s (%sseen before)", 2608 safe_str(hex_str((char*)blinded_key, 32)), 2609 seen_before ? "" : "not "); 2610 2611 /* Count it if we haven't seen it before. */ 2612 if (!seen_before) { 2613 digest256map_set(hs_v3_stats->v3_onions_seen_this_period, 2614 blinded_key, (void*)(uintptr_t)1); 2615 } 2616 } 2617 2618 /** We saw a new HS relay cell: count it! 2619 * If <b>is_v2</b> is set then it's a v2 RP cell, otherwise it's a v3. */ 2620 void 2621 rep_hist_seen_new_rp_cell(bool is_v2) 2622 { 2623 log_debug(LD_GENERAL, "New RP cell (%d)", is_v2); 2624 2625 if (is_v2 && hs_v2_stats) { 2626 hs_v2_stats->rp_v2_relay_cells_seen++; 2627 } else if (!is_v2 && hs_v3_stats && should_collect_v3_stats()) { 2628 hs_v3_stats->rp_v3_relay_cells_seen++; 2629 } 2630 } 2631 2632 /** Generic HS stats code */ 2633 2634 /** Initialize v2 and v3 hidden service statistics. */ 2635 void 2636 rep_hist_hs_stats_init(time_t now) 2637 { 2638 if (!hs_v2_stats) { 2639 hs_v2_stats = hs_v2_stats_new(); 2640 } 2641 2642 /* Start collecting v2 stats straight away */ 2643 start_of_hs_v2_stats_interval = now; 2644 2645 if (!hs_v3_stats) { 2646 hs_v3_stats = hs_v3_stats_new(); 2647 } 2648 2649 /* Start collecting v3 stats at the next 12:00 UTC */ 2650 start_of_hs_v3_stats_interval = hs_get_start_time_of_next_time_period(now); 2651 } 2652 2653 /** Stop collecting hidden service stats in a way that we can re-start 2654 * doing so in rep_hist_buffer_stats_init(). */ 2655 void 2656 rep_hist_hs_stats_term(void) 2657 { 2658 rep_hist_reset_hs_v2_stats(0); 2659 rep_hist_reset_hs_v3_stats(0); 2660 } 2661 2662 /** Stats reporting code */ 2663 2664 /* The number of cells that are supposed to be hidden from the adversary 2665 * by adding noise from the Laplace distribution. This value, divided by 2666 * EPSILON, is Laplace parameter b. It must be greater than 0. */ 2667 #define REND_CELLS_DELTA_F 2048 2668 /* Security parameter for obfuscating number of cells with a value between 2669 * ]0.0, 1.0]. Smaller values obfuscate observations more, but at the same 2670 * time make statistics less usable. */ 2671 #define REND_CELLS_EPSILON 0.3 2672 /* The number of cells that are supposed to be hidden from the adversary 2673 * by rounding up to the next multiple of this number. */ 2674 #define REND_CELLS_BIN_SIZE 1024 2675 /* The number of service identities that are supposed to be hidden from the 2676 * adversary by adding noise from the Laplace distribution. This value, 2677 * divided by EPSILON, is Laplace parameter b. It must be greater than 0. */ 2678 #define ONIONS_SEEN_DELTA_F 8 2679 /* Security parameter for obfuscating number of service identities with a 2680 * value between ]0.0, 1.0]. Smaller values obfuscate observations more, but 2681 * at the same time make statistics less usable. */ 2682 #define ONIONS_SEEN_EPSILON 0.3 2683 /* The number of service identities that are supposed to be hidden from 2684 * the adversary by rounding up to the next multiple of this number. */ 2685 #define ONIONS_SEEN_BIN_SIZE 8 2686 2687 /** Allocate and return a string containing hidden service stats that 2688 * are meant to be placed in the extra-info descriptor. 2689 * 2690 * Function works for both v2 and v3 stats depending on <b>is_v3</b>. */ 2691 STATIC char * 2692 rep_hist_format_hs_stats(time_t now, bool is_v3) 2693 { 2694 char t[ISO_TIME_LEN+1]; 2695 char *hs_stats_string; 2696 int64_t obfuscated_onions_seen, obfuscated_cells_seen; 2697 2698 uint64_t rp_cells_seen = is_v3 ? 2699 hs_v3_stats->rp_v3_relay_cells_seen : hs_v2_stats->rp_v2_relay_cells_seen; 2700 size_t onions_seen = is_v3 ? 2701 digest256map_size(hs_v3_stats->v3_onions_seen_this_period) : 0; 2702 time_t start_of_hs_stats_interval = is_v3 ? 2703 start_of_hs_v3_stats_interval : start_of_hs_v2_stats_interval; 2704 2705 uint64_t rounded_cells_seen 2706 = round_uint64_to_next_multiple_of(rp_cells_seen, REND_CELLS_BIN_SIZE); 2707 rounded_cells_seen = MIN(rounded_cells_seen, INT64_MAX); 2708 obfuscated_cells_seen = add_laplace_noise((int64_t)rounded_cells_seen, 2709 crypto_rand_double(), 2710 REND_CELLS_DELTA_F, REND_CELLS_EPSILON); 2711 2712 uint64_t rounded_onions_seen = 2713 round_uint64_to_next_multiple_of(onions_seen, ONIONS_SEEN_BIN_SIZE); 2714 rounded_onions_seen = MIN(rounded_onions_seen, INT64_MAX); 2715 obfuscated_onions_seen = add_laplace_noise((int64_t)rounded_onions_seen, 2716 crypto_rand_double(), ONIONS_SEEN_DELTA_F, 2717 ONIONS_SEEN_EPSILON); 2718 2719 format_iso_time(t, now); 2720 tor_asprintf(&hs_stats_string, "%s %s (%u s)\n" 2721 "%s %"PRId64" delta_f=%d epsilon=%.2f bin_size=%d\n" 2722 "%s %"PRId64" delta_f=%d epsilon=%.2f bin_size=%d\n", 2723 is_v3 ? "hidserv-v3-stats-end" : "hidserv-stats-end", 2724 t, (unsigned) (now - start_of_hs_stats_interval), 2725 is_v3 ? 2726 "hidserv-rend-v3-relayed-cells" : "hidserv-rend-relayed-cells", 2727 obfuscated_cells_seen, REND_CELLS_DELTA_F, 2728 REND_CELLS_EPSILON, REND_CELLS_BIN_SIZE, 2729 is_v3 ? "hidserv-dir-v3-onions-seen" :"hidserv-dir-onions-seen", 2730 obfuscated_onions_seen, ONIONS_SEEN_DELTA_F, 2731 ONIONS_SEEN_EPSILON, ONIONS_SEEN_BIN_SIZE); 2732 2733 return hs_stats_string; 2734 } 2735 2736 /** If 24 hours have passed since the beginning of the current HS 2737 * stats period, write buffer stats to $DATADIR/stats/hidserv-v3-stats 2738 * (possibly overwriting an existing file) and reset counters. Return 2739 * when we would next want to write buffer stats or 0 if we never want to 2740 * write. Function works for both v2 and v3 stats depending on <b>is_v3</b>. 2741 */ 2742 time_t 2743 rep_hist_hs_stats_write(time_t now, bool is_v3) 2744 { 2745 char *str = NULL; 2746 2747 time_t start_of_hs_stats_interval = is_v3 ? 2748 start_of_hs_v3_stats_interval : start_of_hs_v2_stats_interval; 2749 2750 if (!start_of_hs_stats_interval) { 2751 return 0; /* Not initialized. */ 2752 } 2753 2754 if (start_of_hs_stats_interval + WRITE_STATS_INTERVAL > now) { 2755 goto done; /* Not ready to write */ 2756 } 2757 2758 /* Generate history string. */ 2759 str = rep_hist_format_hs_stats(now, is_v3); 2760 2761 /* Reset HS history. */ 2762 if (is_v3) { 2763 rep_hist_reset_hs_v3_stats(now); 2764 } else { 2765 rep_hist_reset_hs_v2_stats(now); 2766 } 2767 2768 /* Try to write to disk. */ 2769 if (!check_or_create_data_subdir("stats")) { 2770 write_to_data_subdir("stats", 2771 is_v3 ? "hidserv-v3-stats" : "hidserv-stats", 2772 str, "hidden service stats"); 2773 } 2774 2775 done: 2776 tor_free(str); 2777 return start_of_hs_stats_interval + WRITE_STATS_INTERVAL; 2778 } 2779 2780 static uint64_t link_proto_count[MAX_LINK_PROTO+1][2]; 2781 2782 /** Note that we negotiated link protocol version <b>link_proto</b>, on 2783 * a connection that started here iff <b>started_here</b> is true. 2784 */ 2785 void 2786 rep_hist_note_negotiated_link_proto(unsigned link_proto, int started_here) 2787 { 2788 started_here = !!started_here; /* force to 0 or 1 */ 2789 if (link_proto > MAX_LINK_PROTO) { 2790 log_warn(LD_BUG, "Can't log link protocol %u", link_proto); 2791 return; 2792 } 2793 2794 link_proto_count[link_proto][started_here]++; 2795 } 2796 2797 /** 2798 * Update the maximum count of total pending channel padding timers 2799 * in this period. 2800 */ 2801 void 2802 rep_hist_padding_count_timers(uint64_t num_timers) 2803 { 2804 if (num_timers > padding_current.maximum_chanpad_timers) { 2805 padding_current.maximum_chanpad_timers = num_timers; 2806 } 2807 } 2808 2809 /** 2810 * Count a cell that we sent for padding overhead statistics. 2811 * 2812 * RELAY_COMMAND_DROP and CELL_PADDING are accounted separately. Both should be 2813 * counted for PADDING_TYPE_TOTAL. 2814 */ 2815 void 2816 rep_hist_padding_count_write(padding_type_t type) 2817 { 2818 switch (type) { 2819 case PADDING_TYPE_DROP: 2820 padding_current.write_drop_cell_count++; 2821 /* Padding stats get reset thus why we have two counters. */ 2822 relay_circ_n_drop_cell_received++; 2823 break; 2824 case PADDING_TYPE_CELL: 2825 padding_current.write_pad_cell_count++; 2826 break; 2827 case PADDING_TYPE_TOTAL: 2828 padding_current.write_cell_count++; 2829 break; 2830 case PADDING_TYPE_ENABLED_TOTAL: 2831 padding_current.enabled_write_cell_count++; 2832 break; 2833 case PADDING_TYPE_ENABLED_CELL: 2834 padding_current.enabled_write_pad_cell_count++; 2835 break; 2836 } 2837 } 2838 2839 /** 2840 * Count a cell that we've received for padding overhead statistics. 2841 * 2842 * RELAY_COMMAND_DROP and CELL_PADDING are accounted separately. Both should be 2843 * counted for PADDING_TYPE_TOTAL. 2844 */ 2845 void 2846 rep_hist_padding_count_read(padding_type_t type) 2847 { 2848 switch (type) { 2849 case PADDING_TYPE_DROP: 2850 padding_current.read_drop_cell_count++; 2851 break; 2852 case PADDING_TYPE_CELL: 2853 padding_current.read_pad_cell_count++; 2854 break; 2855 case PADDING_TYPE_TOTAL: 2856 padding_current.read_cell_count++; 2857 break; 2858 case PADDING_TYPE_ENABLED_TOTAL: 2859 padding_current.enabled_read_cell_count++; 2860 break; 2861 case PADDING_TYPE_ENABLED_CELL: 2862 padding_current.enabled_read_pad_cell_count++; 2863 break; 2864 } 2865 } 2866 2867 /** 2868 * Reset our current padding statistics. Called once every 24 hours. 2869 */ 2870 void 2871 rep_hist_reset_padding_counts(void) 2872 { 2873 memset(&padding_current, 0, sizeof(padding_current)); 2874 } 2875 2876 /** 2877 * Copy our current cell counts into a structure for listing in our 2878 * extra-info descriptor. Also perform appropriate rounding and redaction. 2879 * 2880 * This function is called once every 24 hours. 2881 */ 2882 #define MIN_CELL_COUNTS_TO_PUBLISH 1 2883 #define ROUND_CELL_COUNTS_TO 10000 2884 void 2885 rep_hist_prep_published_padding_counts(time_t now) 2886 { 2887 memcpy(&padding_published, &padding_current, sizeof(padding_published)); 2888 2889 if (padding_published.read_cell_count < MIN_CELL_COUNTS_TO_PUBLISH || 2890 padding_published.write_cell_count < MIN_CELL_COUNTS_TO_PUBLISH) { 2891 memset(&padding_published, 0, sizeof(padding_published)); 2892 return; 2893 } 2894 2895 format_iso_time(padding_published.first_published_at, now); 2896 #define ROUND_AND_SET_COUNT(x) (x) = round_uint64_to_next_multiple_of((x), \ 2897 ROUND_CELL_COUNTS_TO) 2898 ROUND_AND_SET_COUNT(padding_published.read_pad_cell_count); 2899 ROUND_AND_SET_COUNT(padding_published.write_pad_cell_count); 2900 ROUND_AND_SET_COUNT(padding_published.read_drop_cell_count); 2901 ROUND_AND_SET_COUNT(padding_published.write_drop_cell_count); 2902 ROUND_AND_SET_COUNT(padding_published.write_cell_count); 2903 ROUND_AND_SET_COUNT(padding_published.read_cell_count); 2904 ROUND_AND_SET_COUNT(padding_published.enabled_read_cell_count); 2905 ROUND_AND_SET_COUNT(padding_published.enabled_read_pad_cell_count); 2906 ROUND_AND_SET_COUNT(padding_published.enabled_write_cell_count); 2907 ROUND_AND_SET_COUNT(padding_published.enabled_write_pad_cell_count); 2908 #undef ROUND_AND_SET_COUNT 2909 } 2910 2911 /** 2912 * Returns an allocated string for extra-info documents for publishing 2913 * padding statistics from the last 24 hour interval. 2914 */ 2915 char * 2916 rep_hist_get_padding_count_lines(void) 2917 { 2918 char *result = NULL; 2919 2920 if (!padding_published.read_cell_count || 2921 !padding_published.write_cell_count) { 2922 return NULL; 2923 } 2924 2925 tor_asprintf(&result, "padding-counts %s (%d s)" 2926 " bin-size=%"PRIu64 2927 " write-drop=%"PRIu64 2928 " write-pad=%"PRIu64 2929 " write-total=%"PRIu64 2930 " read-drop=%"PRIu64 2931 " read-pad=%"PRIu64 2932 " read-total=%"PRIu64 2933 " enabled-read-pad=%"PRIu64 2934 " enabled-read-total=%"PRIu64 2935 " enabled-write-pad=%"PRIu64 2936 " enabled-write-total=%"PRIu64 2937 " max-chanpad-timers=%"PRIu64 2938 "\n", 2939 padding_published.first_published_at, 2940 REPHIST_CELL_PADDING_COUNTS_INTERVAL, 2941 (uint64_t)ROUND_CELL_COUNTS_TO, 2942 (padding_published.write_drop_cell_count), 2943 (padding_published.write_pad_cell_count), 2944 (padding_published.write_cell_count), 2945 (padding_published.read_drop_cell_count), 2946 (padding_published.read_pad_cell_count), 2947 (padding_published.read_cell_count), 2948 (padding_published.enabled_read_pad_cell_count), 2949 (padding_published.enabled_read_cell_count), 2950 (padding_published.enabled_write_pad_cell_count), 2951 (padding_published.enabled_write_cell_count), 2952 (padding_published.maximum_chanpad_timers) 2953 ); 2954 2955 return result; 2956 } 2957 2958 /** Log a heartbeat message explaining how many connections of each link 2959 * protocol version we have used. 2960 */ 2961 void 2962 rep_hist_log_link_protocol_counts(void) 2963 { 2964 smartlist_t *lines = smartlist_new(); 2965 2966 for (int i = 1; i <= MAX_LINK_PROTO; i++) { 2967 char *line = NULL; 2968 tor_asprintf(&line, "initiated %"PRIu64" and received " 2969 "%"PRIu64" v%d connections", link_proto_count[i][1], 2970 link_proto_count[i][0], i); 2971 smartlist_add(lines, line); 2972 } 2973 2974 char *log_line = smartlist_join_strings(lines, "; ", 0, NULL); 2975 2976 log_notice(LD_HEARTBEAT, "Since startup we %s.", log_line); 2977 2978 SMARTLIST_FOREACH(lines, char *, s, tor_free(s)); 2979 smartlist_free(lines); 2980 tor_free(log_line); 2981 } 2982 2983 /** Free all storage held by the OR/link history caches, by the 2984 * bandwidth history arrays, by the port history, or by statistics . */ 2985 void 2986 rep_hist_free_all(void) 2987 { 2988 hs_v2_stats_free(hs_v2_stats); 2989 hs_v3_stats_free(hs_v3_stats); 2990 digestmap_free(history_map, free_or_history); 2991 2992 tor_free(exit_bytes_read); 2993 tor_free(exit_bytes_written); 2994 tor_free(exit_streams); 2995 predicted_ports_free_all(); 2996 conn_stats_free_all(); 2997 2998 if (circuits_for_buffer_stats) { 2999 SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, s, 3000 tor_free(s)); 3001 smartlist_free(circuits_for_buffer_stats); 3002 circuits_for_buffer_stats = NULL; 3003 } 3004 rep_hist_desc_stats_term(); 3005 total_descriptor_downloads = 0; 3006 3007 tor_assert_nonfatal(rephist_total_alloc == 0); 3008 tor_assert_nonfatal_once(rephist_total_num == 0); 3009 } 3010 3011 /** Called just before the consensus will be replaced. Update the consensus 3012 * parameters in case they changed. */ 3013 void 3014 rep_hist_consensus_has_changed(const networkstatus_t *ns) 3015 { 3016 overload_onionskin_ntor_fraction = 3017 networkstatus_get_param(ns, "overload_onionskin_ntor_scale_percent", 3018 OVERLOAD_ONIONSKIN_NTOR_PERCENT_DEFAULT, 3019 OVERLOAD_ONIONSKIN_NTOR_PERCENT_MIN, 3020 OVERLOAD_ONIONSKIN_NTOR_PERCENT_MAX) / 3021 OVERLOAD_ONIONSKIN_NTOR_PERCENT_SCALE / 100.0; 3022 3023 overload_onionskin_ntor_period_secs = 3024 networkstatus_get_param(ns, "overload_onionskin_ntor_period_secs", 3025 OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_DEFAULT, 3026 OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_MIN, 3027 OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_MAX); 3028 } 3029 3030 /** Relay Only: return the total number of DROP cell received. */ 3031 uint64_t 3032 rep_hist_get_drop_cell_received_count(void) 3033 { 3034 return relay_circ_n_drop_cell_received; 3035 } 3036 3037 #ifdef TOR_UNIT_TESTS 3038 /* only exists for unit tests: get HSv2 stats object */ 3039 const hs_v2_stats_t * 3040 rep_hist_get_hs_v2_stats(void) 3041 { 3042 return hs_v2_stats; 3043 } 3044 3045 /* only exists for unit tests: get HSv2 stats object */ 3046 const hs_v3_stats_t * 3047 rep_hist_get_hs_v3_stats(void) 3048 { 3049 return hs_v3_stats; 3050 } 3051 #endif /* defined(TOR_UNIT_TESTS) */