[tor-commits] [torflow/master] Implement per-class setpoints.

mikeperry at torproject.org mikeperry at torproject.org
Fri Dec 2 04:56:42 UTC 2011


commit 4f4bc10fba85adc877481e3fb4445847a208da12
Author: Mike Perry <mikeperry-git at fscked.org>
Date:   Thu Dec 1 20:09:25 2011 -0800

    Implement per-class setpoints.
    
    Governed by consensus param (off by default).
---
 NetworkScanners/BwAuthority/README.spec.txt |    5 ++
 NetworkScanners/BwAuthority/aggregate.py    |   65 ++++++++++++++++++++++-----
 2 files changed, 58 insertions(+), 12 deletions(-)

diff --git a/NetworkScanners/BwAuthority/README.spec.txt b/NetworkScanners/BwAuthority/README.spec.txt
index 81468b5..acce106 100644
--- a/NetworkScanners/BwAuthority/README.spec.txt
+++ b/NetworkScanners/BwAuthority/README.spec.txt
@@ -528,6 +528,11 @@
        accumulated in pid_error_sum as opposed to the consensus value
        itself.
 
+    "bwauthbyclass=1"
+       If present, computes F_avg (see Section 3.1) for each class
+       of Guard, Middle, Exit, and Guard+Exit nodes, and uses these
+       flag-specific averages to compute pid_error.
+
     "bwauthkp=N"
        Sets K_p to N/10000.0. If absent, K_p=1.0.
 
diff --git a/NetworkScanners/BwAuthority/aggregate.py b/NetworkScanners/BwAuthority/aggregate.py
index 6283f3f..120de07 100755
--- a/NetworkScanners/BwAuthority/aggregate.py
+++ b/NetworkScanners/BwAuthority/aggregate.py
@@ -92,6 +92,7 @@ class Node:
     self.new_bw = None
     self.change = None
     self.use_bw = -1
+    self.flags = ""
 
     # measurement vars from bwauth lines
     self.measured_at = 0
@@ -132,6 +133,16 @@ class Node:
                              + kd*self.use_bw*self.d_error_dt()
     return self.pid_bw
 
+  def node_class(self):
+    if "Guard" in self.flags and "Exit" in self.flags:
+      return "Guard+Exit"
+    elif "Guard" in self.flags:
+      return "Guard"
+    elif "Exit" in self.flags:
+      return "Exit"
+    else:
+      return "Middle"
+
   # Time-weighted sum of error per unit of time (measurement sample)
   def integral_error(self):
     if self.prev_error == 0:
@@ -222,6 +233,7 @@ class ConsensusJunk:
   def __init__(self, c):
     cs_bytes = c.sendAndRecv("GETINFO dir/status-vote/current/consensus\r\n")[0][2]
     self.bwauth_pid_control = True
+    self.group_by_class = False
     self.use_circ_fails = False
     self.use_best_ratio = True
     self.use_desc_bw = True
@@ -246,6 +258,9 @@ class ConsensusJunk:
         elif p == "bwauthbestratio=0":
           self.use_best_ratio = False
           plog("INFO", "Choosing larger of sbw vs fbw")
+        elif p == "bwauthbyclass=1":
+          self.group_by_class = True
+          plog("INFO", "Grouping nodes by flag-class")
         elif p.startswith("bwauthkp="):
           self.K_p = int(p.split("=")[1])/10000.0
           plog("INFO", "Got K_p=%f from consensus." % self.K_p)
@@ -439,23 +454,45 @@ def main(argv):
     for n in nodes.itervalues():
       n.circ_fail_rate = 0.0
 
+  for idhex in nodes.iterkeys():
+    if idhex in prev_consensus:
+      nodes[idhex].flags = prev_consensus[idhex].flags
+
+  true_filt_avg = {}
+  true_strm_avg = {}
+
   if cs_junk.bwauth_pid_control:
     # Penalize nodes for circuit failure: it indicates CPU pressure
     # TODO: Potentially penalize for stream failure, if we run into
     # socket exhaustion issues..
     plog("INFO", "PID control enabled")
-    true_filt_avg = sum(map(lambda n: n.filt_bw*(1.0-n.circ_fail_rate),
-                         nodes.itervalues()))/float(len(nodes))
-    true_strm_avg = sum(map(lambda n: n.strm_bw*(1.0-n.circ_fail_rate),
-                         nodes.itervalues()))/float(len(nodes))
+
+    if cs_junk.group_by_class:
+      for c in ["Guard+Exit", "Guard", "Exit", "Middle"]:
+        c_nodes = filter(lambda n: n.node_class() == c, nodes.itervalues())
+        true_filt_avg[c] = sum(map(lambda n: n.filt_bw*(1.0-n.circ_fail_rate),
+                             c_nodes))/float(len(c_nodes))
+        true_strm_avg[c] = sum(map(lambda n: n.strm_bw*(1.0-n.circ_fail_rate),
+                             c_nodes))/float(len(c_nodes))
+        plog("INFO", "Network true_filt_avg["+c+"]: "+str(true_filt_avg[c]))
+    else:
+      filt_avg = sum(map(lambda n: n.filt_bw*(1.0-n.circ_fail_rate),
+                      nodes.itervalues()))/float(len(nodes))
+      strm_avg = sum(map(lambda n: n.strm_bw*(1.0-n.circ_fail_rate),
+                           nodes.itervalues()))/float(len(nodes))
+      for c in ["Guard+Exit", "Guard", "Exit", "Middle"]:
+        true_filt_avg[c] = filt_avg
+        true_strm_avg[c] = strm_avg
   else:
     plog("INFO", "PID control disabled")
-    true_filt_avg = sum(map(lambda n: n.filt_bw,
-                         nodes.itervalues()))/float(len(nodes))
-    true_strm_avg = sum(map(lambda n: n.strm_bw,
+    filt_avg = sum(map(lambda n: n.filt_bw*(1.0-n.circ_fail_rate),
+                    nodes.itervalues()))/float(len(nodes))
+    strm_avg = sum(map(lambda n: n.strm_bw*(1.0-n.circ_fail_rate),
                          nodes.itervalues()))/float(len(nodes))
+    for c in ["Guard+Exit", "Guard", "Exit", "Middle"]:
+      true_filt_avg[c] = filt_avg
+      true_strm_avg[c] = strm_avg
 
-  plog("DEBUG", "Network true_filt_avg: "+str(true_filt_avg))
 
   prev_votes = None
   if cs_junk.bwauth_pid_control:
@@ -489,8 +526,8 @@ def main(argv):
 
   tot_net_bw = 0
   for n in nodes.itervalues():
-    n.fbw_ratio = n.filt_bw/true_filt_avg
-    n.sbw_ratio = n.strm_bw/true_strm_avg
+    n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()]
+    n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_clasS()]
 
     if cs_junk.bwauth_pid_control:
       if cs_junk.use_desc_bw:
@@ -500,9 +537,13 @@ def main(argv):
 
       # Penalize nodes for circ failure rate
       if cs_junk.use_best_ratio and n.sbw_ratio > n.fbw_ratio:
-        n.pid_error = (n.strm_bw*(1.0-n.circ_fail_rate) - true_strm_avg)/true_strm_avg
+        n.pid_error = (n.strm_bw*(1.0-n.circ_fail_rate) -
+                                  true_strm_avg[n.node_class()]) \
+                         / true_strm_avg[n.node_class()]
       else:
-        n.pid_error = (n.filt_bw*(1.0-n.circ_fail_rate) - true_filt_avg)/true_filt_avg
+        n.pid_error = (n.filt_bw*(1.0-n.circ_fail_rate) -
+                                  true_filt_avg[n.node_class()]) \
+                         / true_filt_avg[n.node_class()]
 
       if n.idhex in prev_votes.vote_map:
         # If there is a new sample, let's use it for all but guards





More information about the tor-commits mailing list