Ticket #961: fix_961_v2.patch

File fix_961_v2.patch, 8.7 KB (added by chobe, 4 years ago)
  • doc/tor.1.txt

    diff --git a/doc/tor.1.txt b/doc/tor.1.txt
    index a997bc3..89523aa 100644
    a b is non-zero): 
    16351635    to 0 will disable the heartbeat. (Default: 6 hours)
    16361636
    16371637[[AccountingMax]] **AccountingMax** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**KBits**|**MBits**|**GBits**|**TBytes**::
    1638     Never send more than the specified number of bytes in a given accounting
    1639     period, or receive more than that number in the period. For example, with
    1640     AccountingMax set to 1 GByte, a server could send 900 MBytes and
    1641     receive 800 MBytes and continue running. It will only hibernate once
    1642     one of the two reaches 1 GByte. When the number of bytes gets low,
    1643     Tor will stop accepting new connections and circuits.  When the
    1644     number of bytes is exhausted, Tor will hibernate until some
    1645     time in the next accounting period. To prevent all servers from waking at
    1646     the same time, Tor will also wait until a random point in each period
    1647     before waking up. If you have bandwidth cost issues, enabling hibernation
    1648     is preferable to setting a low bandwidth, since it provides users with a
    1649     collection of fast servers that are up some of the time, which is more
    1650     useful than a set of slow servers that are always "available".
     1638    Limits the max number of bytes sent and received within a set time period
     1639    using a given calculation rule (see: AccountingStart, AccountingRule).
     1640    Useful if you need to stay under a specific bandwidth. By default, the
     1641    number used for calculation is the max of either the bytes sent or
     1642    received. For example, with AccountingMax set to 1 GByte, a server
     1643    could send 900 MBytes and receive 800 MBytes and continue running.
     1644    It will only hibernate once one of the two reaches 1 GByte. This can
     1645    be changed to use the sum of the both bytes received and sent by setting
     1646    the AccountingRule option to "sum" (total bandwidth in/out). When the
     1647    number of bytes remaining gets low, Tor will stop accepting new connections
     1648    and circuits. When the number of bytes is exhausted, Tor will hibernate
     1649    until some time in the next accounting period. To prevent all servers
     1650    from waking at the same time, Tor will also wait until a random point
     1651    in each period before waking up. If you have bandwidth cost issues,
     1652    enabling hibernation is preferable to setting a low bandwidth, since
     1653    it provides users with a collection of fast servers that are up some
     1654    of the time, which is more useful than a set of slow servers that are
     1655    always "available".
     1656
     1657[[AccountingRule]] **AccountingRule** **sum**|**max**::
     1658    How we determine when our AccountingMax has been reached (when we
     1659    should hibernate) during a time interval. Set to "max" to calculate
     1660    using the higher of either the sent or received bytes (this is the
     1661    default functionality). Set to "sum" to calculate using the sent
     1662    plus received bytes.
    16511663
    16521664[[AccountingStart]] **AccountingStart** **day**|**week**|**month** [__day__] __HH:MM__::
    16531665    Specify how long accounting periods last. If **month** is given, each
  • src/or/config.c

    diff --git a/src/or/config.c b/src/or/config.c
    index 7800ec1..c1f93f8 100644
    a b static config_abbrev_t option_abbrevs_[] = { 
    129129static config_var_t option_vars_[] = {
    130130  OBSOLETE("AccountingMaxKB"),
    131131  V(AccountingMax,               MEMUNIT,  "0 bytes"),
     132  V(AccountingRule,              STRING,  "max"),
    132133  V(AccountingStart,             STRING,   NULL),
    133134  V(Address,                     STRING,   NULL),
    134135  V(AllowDotExit,                BOOL,     "0"),
    options_validate(or_options_t *old_options, or_options_t *options, 
    31373138               "risky: they will all turn off at the same time, which may "
    31383139               "alert observers that they are being run by the same party.");
    31393140    }
     3141    if (options->AccountingRule &&
     3142      strcmp(options->AccountingRule, "sum") != 0 &&
     3143      strcmp(options->AccountingRule, "max") != 0)
     3144      REJECT("AccountingRule must be 'sum' or 'max'");
    31403145  }
    31413146
    31423147  if (options->HTTPProxy) { /* parse it now */
  • src/or/hibernate.c

    diff --git a/src/or/hibernate.c b/src/or/hibernate.c
    index c433ac1..1cf3bd9 100644
    a b configure_accounting(time_t now) 
    410410  accounting_set_wakeup_time();
    411411}
    412412
     413/** Return the relevant number of bytes sent/received this interval
     414 * based on the set AccountingRule */
     415static uint64_t
     416get_accounting_bytes()
     417{
     418  if (strcmp(get_options()->AccountingRule, "sum") == 0)
     419    return n_bytes_read_in_interval+n_bytes_written_in_interval;
     420  return MAX(n_bytes_read_in_interval, n_bytes_written_in_interval);
     421}
     422
    413423/** Set expected_bandwidth_usage based on how much we sent/received
    414424 * per minute last interval (if we were up for at least 30 minutes),
    415425 * or based on our declared bandwidth otherwise. */
    update_expected_bandwidth(void) 
    439449     * doesn't know to store soft-limit info.  Just take rate at which
    440450     * we were reading/writing in the last interval as our expected rate.
    441451     */
    442     uint64_t used = MAX(n_bytes_written_in_interval,
    443                         n_bytes_read_in_interval);
     452    uint64_t used = get_accounting_bytes();
    444453    expected = used / (n_seconds_active_in_interval / 60);
    445454  } else {
    446455    /* If we haven't gotten enough data last interval, set 'expected'
    hibernate_hard_limit_reached(void) 
    715724  uint64_t hard_limit = get_options()->AccountingMax;
    716725  if (!hard_limit)
    717726    return 0;
    718   return n_bytes_read_in_interval >= hard_limit
    719     || n_bytes_written_in_interval >= hard_limit;
     727  return get_accounting_bytes() >= hard_limit;
    720728}
    721729
    722730/** Return true iff we have sent/received almost all the bytes we are willing
    hibernate_soft_limit_reached(void) 
    747755
    748756  if (!soft_limit)
    749757    return 0;
    750   return n_bytes_read_in_interval >= soft_limit
    751     || n_bytes_written_in_interval >= soft_limit;
     758  return get_accounting_bytes() >= soft_limit;
    752759}
    753760
    754761/** Called when we get a SIGINT, or when bandwidth soft limit is
    hibernate_begin(hibernate_state_t new_state, time_t now) 
    772779      hibernate_state == HIBERNATE_STATE_LIVE) {
    773780    soft_limit_hit_at = now;
    774781    n_seconds_to_hit_soft_limit = n_seconds_active_in_interval;
    775     n_bytes_at_soft_limit = MAX(n_bytes_read_in_interval,
    776                                 n_bytes_written_in_interval);
     782    n_bytes_at_soft_limit = get_accounting_bytes();
    777783  }
    778784
    779785  /* close listeners. leave control listener(s). */
    getinfo_helper_accounting(control_connection_t *conn, 
    10031009                 U64_PRINTF_ARG(n_bytes_written_in_interval));
    10041010  } else if (!strcmp(question, "accounting/bytes-left")) {
    10051011    uint64_t limit = get_options()->AccountingMax;
    1006     uint64_t read_left = 0, write_left = 0;
    1007     if (n_bytes_read_in_interval < limit)
    1008       read_left = limit - n_bytes_read_in_interval;
    1009     if (n_bytes_written_in_interval < limit)
    1010       write_left = limit - n_bytes_written_in_interval;
    1011     tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
    1012                  U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left));
     1012    if (strcmp(get_options()->AccountingRule, "sum") == 0)
     1013    {
     1014      uint64_t total_left = 0;
     1015      uint64_t total_bytes = get_accounting_bytes();
     1016      if (total_bytes < limit)
     1017        total_left = limit - total_bytes;
     1018      tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
     1019                   U64_PRINTF_ARG(total_left), U64_PRINTF_ARG(total_left));
     1020    }else
     1021    {
     1022      uint64_t read_left = 0, write_left = 0;
     1023      if (n_bytes_read_in_interval < limit)
     1024        read_left = limit - n_bytes_read_in_interval;
     1025      if (n_bytes_written_in_interval < limit)
     1026        write_left = limit - n_bytes_written_in_interval;
     1027      tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
     1028                   U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left));
     1029    }
    10131030  } else if (!strcmp(question, "accounting/interval-start")) {
    10141031    *answer = tor_malloc(ISO_TIME_LEN+1);
    10151032    format_iso_time(*answer, interval_start_time);
  • src/or/or.h

    diff --git a/src/or/or.h b/src/or/or.h
    index 3683607..6d98c99 100644
    a b typedef struct { 
    37903790  uint64_t AccountingMax; /**< How many bytes do we allow per accounting
    37913791                           * interval before hibernation?  0 for "never
    37923792                           * hibernate." */
     3793  char *AccountingRule; /**< How do we determine when our AccountingMax
     3794                         * has been reached?
     3795                         * "max" for when in or out reaches AccountingMax
     3796                         * "sum for when in plus out reaches AccountingMax */
    37933797
    37943798  /** Base64-encoded hash of accepted passwords for the control system. */
    37953799  config_line_t *HashedControlPassword;