[tor-commits] [tor/master] Added AccountRule in and AccountingRule out options

nickm at torproject.org nickm at torproject.org
Fri Jan 8 23:56:02 UTC 2016


commit 4f0e28977d6376ccba599e7089aeb9e3b4f25e5f
Author: unixninja92 <charles at unixninja92.com>
Date:   Sun Jan 3 23:02:44 2016 -0500

    Added AccountRule in and AccountingRule out options
---
 changes/ticket15989        |    9 +++++++++
 doc/tor.1.txt              |    6 ++++--
 src/or/config.c            |    6 +++++-
 src/or/hibernate.c         |   20 ++++++++++++++++++--
 src/or/hibernate.h         |    1 +
 src/or/or.h                |    6 ++++--
 src/or/router.c            |    7 +++++--
 src/or/status.c            |   22 ++++++++++++++++++----
 src/test/test_accounting.c |   26 ++++++++++++++++++++++++++
 src/test/test_status.c     |    7 ++++---
 10 files changed, 94 insertions(+), 16 deletions(-)

diff --git a/changes/ticket15989 b/changes/ticket15989
new file mode 100644
index 0000000..1fd1fbb
--- /dev/null
+++ b/changes/ticket15989
@@ -0,0 +1,9 @@
+  o Minor enhancement (accounting):
+    - Added two modes to AccountingRule in torrc for
+      limiting just input or just output.
+      Closes ticket 15989; patch from "unixninja92".
+
+  o Minor bugfixe (accounting):
+    - The max bandwidth when using AccountRule sum
+      is now correctly logged.
+      Patch from "unixninja92".
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 3514c4d..0fea831 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1773,12 +1773,14 @@ is non-zero):
     of the time, which is more useful than a set of slow servers that are
     always "available".
 
-[[AccountingRule]] **AccountingRule** **sum**|**max**::
+[[AccountingRule]] **AccountingRule** **sum**|**max**|**in**|**out**::
     How we determine when our AccountingMax has been reached (when we
     should hibernate) during a time interval. Set to "max" to calculate
     using the higher of either the sent or received bytes (this is the
     default functionality). Set to "sum" to calculate using the sent
-    plus received bytes. (Default: max)
+    plus received bytes. Set to "in" to calculate using only the
+    received bytes. Set to "out" to calculate using only the sent bytes.
+    (Default: max)
 
 [[AccountingStart]] **AccountingStart** **day**|**week**|**month** [__day__] __HH:MM__::
     Specify how long accounting periods last. If **month** is given, each
diff --git a/src/or/config.c b/src/or/config.c
index a1f8e49..3ea1e1f 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -3454,8 +3454,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
       options->AccountingRule = ACCT_SUM;
     else if (!strcmp(options->AccountingRule_option, "max"))
       options->AccountingRule = ACCT_MAX;
+    else if (!strcmp(options->AccountingRule_option, "in"))
+      options->AccountingRule = ACCT_IN;
+    else if (!strcmp(options->AccountingRule_option, "out"))
+      options->AccountingRule = ACCT_OUT;
     else
-      REJECT("AccountingRule must be 'sum' or 'max'");
+      REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'");
   }
 
   if (options->DirPort_set && !options->DirCache) {
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 5f727e2..7f8530b 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -412,11 +412,15 @@ configure_accounting(time_t now)
 
 /** Return the relevant number of bytes sent/received this interval
  * based on the set AccountingRule */
-static uint64_t
+uint64_t
 get_accounting_bytes(void)
 {
   if (get_options()->AccountingRule == ACCT_SUM)
     return n_bytes_read_in_interval+n_bytes_written_in_interval;
+  else if (get_options()->AccountingRule == ACCT_IN)
+    return n_bytes_read_in_interval;
+  else if (get_options()->AccountingRule == ACCT_OUT)
+    return n_bytes_written_in_interval;
   else
     return MAX(n_bytes_read_in_interval, n_bytes_written_in_interval);
 }
@@ -1010,7 +1014,7 @@ getinfo_helper_accounting(control_connection_t *conn,
     else
       *answer = tor_strdup("awake");
   } else if (!strcmp(question, "accounting/bytes")) {
-    tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
+      tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
                  U64_PRINTF_ARG(n_bytes_read_in_interval),
                  U64_PRINTF_ARG(n_bytes_written_in_interval));
   } else if (!strcmp(question, "accounting/bytes-left")) {
@@ -1022,6 +1026,18 @@ getinfo_helper_accounting(control_connection_t *conn,
         total_left = limit - total_bytes;
       tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
                    U64_PRINTF_ARG(total_left), U64_PRINTF_ARG(total_left));
+    } else if (get_options()->AccountingRule == ACCT_IN) {
+      uint64_t read_left = 0;
+      if (n_bytes_read_in_interval < limit)
+        read_left = limit - n_bytes_read_in_interval;
+      tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
+                   U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(limit));
+    } else if (get_options()->AccountingRule == ACCT_OUT) {
+      uint64_t write_left = 0;
+      if (n_bytes_written_in_interval < limit)
+        write_left = limit - n_bytes_written_in_interval;
+      tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
+                   U64_PRINTF_ARG(limit), U64_PRINTF_ARG(write_left));
     } else {
       uint64_t read_left = 0, write_left = 0;
       if (n_bytes_read_in_interval < limit)
diff --git a/src/or/hibernate.h b/src/or/hibernate.h
index b9e619c..e0d0c29 100644
--- a/src/or/hibernate.h
+++ b/src/or/hibernate.h
@@ -19,6 +19,7 @@ MOCK_DECL(int, accounting_is_enabled, (const or_options_t *options));
 int accounting_get_interval_length(void);
 MOCK_DECL(time_t, accounting_get_end_time, (void));
 void configure_accounting(time_t now);
+uint64_t get_accounting_bytes(void);
 void accounting_run_housekeeping(time_t now);
 void accounting_add_bytes(size_t n_read, size_t n_written, int seconds);
 int accounting_record_bandwidth_usage(time_t now, or_state_t *state);
diff --git a/src/or/or.h b/src/or/or.h
index 89c5398..3178fda 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3893,9 +3893,11 @@ typedef struct {
                            * hibernate." */
   /** How do we determine when our AccountingMax has been reached?
    * "max" for when in or out reaches AccountingMax
-   * "sum" for when in plus out reaches AccountingMax */
+   * "sum" for when in plus out reaches AccountingMax
+   * "in"  for when in reaches AccountingMax
+   * "out" for when out reaches AccountingMax */
   char *AccountingRule_option;
-  enum { ACCT_MAX, ACCT_SUM } AccountingRule;
+  enum { ACCT_MAX, ACCT_SUM, ACCT_IN, ACCT_OUT } AccountingRule;
 
   /** Base64-encoded hash of accepted passwords for the control system. */
   config_line_t *HashedControlPassword;
diff --git a/src/or/router.c b/src/or/router.c
index 2081bdb..c94dca9 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1133,10 +1133,13 @@ router_should_be_directory_server(const or_options_t *options, int dir_port)
   int new_choice=1;
   const char *reason = NULL;
 
-  if (accounting_is_enabled(options)) {
+  if (accounting_is_enabled(options) &&
+    get_options()->AccountingRule != ACCT_IN) {
     /* Don't spend bytes for directory traffic if we could end up hibernating,
      * but allow DirPort otherwise. Some people set AccountingMax because
-     * they're confused or to get statistics. */
+     * they're confused or to get statistics. Directory traffic has a much
+     * larger effect on output than input so there is no reason to turn it
+     * off if using AccountingRule in. */
     int interval_length = accounting_get_interval_length();
     uint32_t effective_bw = get_effective_bwrate(options);
     uint64_t acc_bytes;
diff --git a/src/or/status.c b/src/or/status.c
index 8f7be0a..69d1072 100644
--- a/src/or/status.c
+++ b/src/or/status.c
@@ -164,24 +164,38 @@ log_accounting(const time_t now, const or_options_t *options)
   or_state_t *state = get_or_state();
   char *acc_rcvd = bytes_to_usage(state->AccountingBytesReadInInterval);
   char *acc_sent = bytes_to_usage(state->AccountingBytesWrittenInInterval);
+  char *acc_used = bytes_to_usage(get_accounting_bytes());
   uint64_t acc_bytes = options->AccountingMax;
   char *acc_max;
   time_t interval_end = accounting_get_end_time();
   char end_buf[ISO_TIME_LEN + 1];
   char *remaining = NULL;
-  if (options->AccountingRule == ACCT_SUM)
-    acc_bytes *= 2;
   acc_max = bytes_to_usage(acc_bytes);
   format_local_iso_time(end_buf, interval_end);
   remaining = secs_to_uptime(interval_end - now);
 
+  const char *acc_rule;
+  switch (options->AccountingRule) {
+    case ACCT_MAX: acc_rule = "max";
+    break;
+    case ACCT_SUM: acc_rule = "sum";
+    break;
+    case ACCT_OUT: acc_rule = "out";
+    break;
+    case ACCT_IN: acc_rule = "in";
+    break;
+    default: acc_rule = "max";
+    break;
+  }
+
   log_notice(LD_HEARTBEAT, "Heartbeat: Accounting enabled. "
-      "Sent: %s / %s, Received: %s / %s. The "
+      "Sent: %s, Received: %s, Used: %s / %s, Rule: %s. The "
       "current accounting interval ends on %s, in %s.",
-      acc_sent, acc_max, acc_rcvd, acc_max, end_buf, remaining);
+      acc_sent, acc_rcvd, acc_used, acc_max, acc_rule, end_buf, remaining);
 
   tor_free(acc_rcvd);
   tor_free(acc_sent);
+  tor_free(acc_used);
   tor_free(acc_max);
   tor_free(remaining);
 }
diff --git a/src/test/test_accounting.c b/src/test/test_accounting.c
index 25908e9..7edba98 100644
--- a/src/test/test_accounting.c
+++ b/src/test/test_accounting.c
@@ -61,6 +61,32 @@ test_accounting_limits(void *arg)
   fake_time += 1;
   consider_hibernation(fake_time);
   tor_assert(we_are_hibernating() == 1);
+
+  options->AccountingRule = ACCT_OUT;
+
+  accounting_add_bytes(100, 10, 1);
+  fake_time += 1;
+  consider_hibernation(fake_time);
+  tor_assert(we_are_hibernating() == 0);
+
+  accounting_add_bytes(0, 90, 1);
+  fake_time += 1;
+  consider_hibernation(fake_time);
+  tor_assert(we_are_hibernating() == 1);
+
+  options->AccountingMax = 300;
+  options->AccountingRule = ACCT_IN;
+
+  accounting_add_bytes(10, 100, 1);
+  fake_time += 1;
+  consider_hibernation(fake_time);
+  tor_assert(we_are_hibernating() == 0);
+
+  accounting_add_bytes(90, 0, 1);
+  fake_time += 1;
+  consider_hibernation(fake_time);
+  tor_assert(we_are_hibernating() == 1);
+
   goto done;
  done:
   NS_UNMOCK(get_or_state);
diff --git a/src/test/test_status.c b/src/test/test_status.c
index cbc8af1..57d69b1 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -707,12 +707,13 @@ NS(logv)(int severity, log_domain_mask_t domain,
       tt_ptr_op(strstr(funcname, "log_accounting"), OP_NE, NULL);
       tt_ptr_op(suffix, OP_EQ, NULL);
       tt_str_op(format, OP_EQ,
-          "Heartbeat: Accounting enabled. Sent: %s / %s, Received: %s / %s. "
-          "The current accounting interval ends on %s, in %s.");
+          "Heartbeat: Accounting enabled. Sent: %s, Received: %s, Used: %s / "
+          "%s, Rule: %s. The current accounting interval ends on %s, in %s.");
       tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB");  /* acc_sent */
-      tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB");  /* acc_max */
       tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB");  /* acc_rcvd */
+      tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB");  /* acc_used */
       tt_str_op(va_arg(ap, char *), OP_EQ, "0 kB");  /* acc_max */
+      tt_str_op(va_arg(ap, char *), OP_EQ, "max");  /* acc_rule */
       /* format_local_iso_time uses local tz, just check mins and secs. */
       tt_ptr_op(strstr(va_arg(ap, char *), ":01:00"),
                 OP_NE, NULL); /* end_buf */





More information about the tor-commits mailing list