[or-cvs] r21363: {} Initial commit of CBT stress testing tools. (in torflow/trunk/CircuitAnalysis/BuildTimes: . CBT-Test CBT-Test/tor-data)

mikeperry at seul.org mikeperry at seul.org
Wed Dec 30 16:19:40 UTC 2009


Author: mikeperry
Date: 2009-12-30 11:19:40 -0500 (Wed, 30 Dec 2009)
New Revision: 21363

Added:
   torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/
   torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbt.cfg
   torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbttest.py
   torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/run_test.sh
   torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/tor-data/
   torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/tor-data/torrc
Log:

Initial commit of CBT stress testing tools.



Added: torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbt.cfg
===================================================================
--- torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbt.cfg	                        (rev 0)
+++ torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbt.cfg	2009-12-30 16:19:40 UTC (rev 21363)
@@ -0,0 +1,10 @@
+[TorCtl]
+loglevel=DEBUG
+tor_host = 127.0.0.1
+tor_port = 9550
+control_host = 127.0.0.1
+control_port = 9551
+control_pass =#
+# XXX: Unused
+meta_host = 127.0.0.1
+meta_port = 9552

Added: torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbttest.py
===================================================================
--- torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbttest.py	                        (rev 0)
+++ torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbttest.py	2009-12-30 16:19:40 UTC (rev 21363)
@@ -0,0 +1,229 @@
+#!/usr/bin/python
+
+try:
+  import psyco
+  psyco.full()
+except ImportError:
+  #print 'Psyco not installed, the program will just run slower'
+  pass
+
+#import profile
+
+import socket,sys,time,getopt,os,threading,atexit
+sys.path.append("../../../")
+sys.path.append("../")
+from TorCtl import TorUtil
+import TorCtl
+from TorCtl.TorCtl import EventHandler, PreEventListener
+from TorCtl import PathSupport, TorCtl
+from TorCtl.PathSupport import ExitPolicyRestriction,OrNodeRestriction,RestrictionError
+from TorCtl.TorUtil import plog
+
+# XXX: Add to config
+MAX_CIRCUITS = 5
+STREAK_RATIO = 0.5
+FUZZY_RATIO = 0.5
+
+# Original value of FetchUselessDescriptors
+FUDValue = None
+
+class CircTime:
+  def __init__(self, start_time):
+    self.start_time = start_time
+    self.end_time = 0
+
+class CircHandler(EventHandler):
+  def __init__(self, c):
+    EventHandler.__init__(self)
+    self.c = c
+    self.circs = {}
+    self.live_circs = {}
+    self.timeout_circs = {}
+    self.closed_circs = {}
+    self.circ_times = {}
+
+  def heartbeat_event(self, event):
+    if len(self.live_circs) < MAX_CIRCUITS:
+       circ_id = self.c.extend_circuit()
+       plog("INFO", "Launched circuit: "+str(circ_id))
+
+  def close_all_circs(self):
+    lines = self.c.sendAndRecv("GETINFO circuit-status\r\n")[0][2]
+    if lines: lines = lines.split("\n")
+    else: return
+    for l in lines:
+      if l:
+        line_parts = l.split(" ")
+        plog("INFO", "Closing aleady built circuit "+str(line_parts[0]))
+        self.live_circs[int(line_parts[0])] = True
+        self.circs[int(line_parts[0])] = True
+        self.c.close_circuit(int(line_parts[0]))
+
+  # XXX: Also time circs...
+  def circ_status_event(self, circ_event):
+    if circ_event.status == 'LAUNCHED':
+      self.circs[circ_event.circ_id] = circ_event.status
+      self.circ_times[circ_event.circ_id] = CircTime(circ_event.arrived_at)
+      self.live_circs[circ_event.circ_id] = True
+    elif circ_event.status == 'BUILT':
+      self.circs[circ_event.circ_id] = circ_event.status
+      self.c.close_circuit(circ_event.circ_id)
+      if circ_event.circ_id in self.circ_times:
+        self.circ_times[circ_event.circ_id].end_time = circ_event.arrived_at
+        plog("INFO", "Closing circuit "+str(circ_event.circ_id)+" with build time of "+str(self.circ_times[circ_event.circ_id].end_time-self.circ_times[circ_event.circ_id].start_time))
+    elif circ_event.status == 'FAILED' or circ_event.status == 'CLOSED':
+      plog("INFO", circ_event.status+" circuit "+str(circ_event.circ_id))
+      self.circs[circ_event.circ_id] = circ_event.status
+      # XXX: Record this differently..
+      #if circ_event.circ_id in self.circ_times:
+      #  self.circ_times[circ_event.circ_id].end_time = circ_event.arrived_at
+      del self.live_circs[circ_event.circ_id]
+      if circ_event.reason == 'TIMEOUT':
+        self.timeout_circs[circ_event.circ_id] = True
+      else:
+        self.closed_circs[circ_event.circ_id] = True
+
+class BuildTimeoutTracker(PreEventListener):
+  def __init__(self):
+    PreEventListener.__init__(self)
+    self.last_timeout = 0
+    self.timeout_streak = 0
+    self.timeout_fuzzy_streak = 0
+    self.buildtimeout_fuzzy = None
+    self.buildtimeout_strict = None
+    self.fuzzy_streak_count = 0
+    self.strict_streak_count = 0
+    self.total_times = 0
+
+  def buildtimeout_set_event(self, bt_event):
+    plog("INFO", "Got buildtimeout event: "+bt_event.set_type+" TOTAL_TIMES="
+                 +str(bt_event.total_times)+" TIMEOUT_MS="
+                 +str(bt_event.timeout_ms))
+    if not self.total_times:
+      self.total_times = bt_event.total_times-1
+    self.total_times +=1
+    # Ensure we don't wrap during testing:
+    assert(self.total_times == bt_event.total_times)
+
+    if not self.buildtimeout_strict:
+      self.buildtimeout_strict = bt_event
+    if not self.buildtimeout_fuzzy:
+      self.buildtimeout_fuzzy = bt_event
+
+    strict_last = int(round(self.buildtimeout_strict.timeout_ms, -3))
+    strict_curr = int(round(bt_event.timeout_ms, -3))
+    strict_diff = abs(strict_last-strict_curr)
+    if strict_diff > 0:
+      self.buildtimeout_strict = bt_event
+      self.strict_streak_count = 0
+    else:
+      if (self.strict_streak_count != (bt_event.total_times -
+                 self.buildtimeout_strict.total_times)):
+        plog("WARN",
+             "Streak count doesn't match: "+str(self.strict_streak_count)+
+             " != "+str(bt_event.total_times)
+                     +"-"+str(self.buildtimeout_strict.total_times))
+        assert(self.strict_streak_count ==
+              (bt_event.total_times - self.buildtimeout_strict.total_times))
+      self.strict_streak_count += 1
+      if (self.strict_streak_count >= self.total_times*STREAK_RATIO):
+        plog("NOTICE",
+             "Strict termination condition reached at "
+             +str(self.total_times-self.strict_streak_count)
+             +" with streak of "+str(self.strict_streak_count))
+        # XXX: Signal termination condition
+
+    fuzzy_last = int(round(self.buildtimeout_fuzzy.timeout_ms, -3))
+    fuzzy_curr = int(round(bt_event.timeout_ms, -3))
+    fuzzy_diff = abs(fuzzy_last-fuzzy_curr)
+    if fuzzy_diff > 1000:
+      self.buildtimeout_fuzzy = bt_event
+      self.fuzzy_streak_count = 0
+    else:
+      assert(self.fuzzy_streak_count ==
+              (bt_event.total_times - self.buildtimeout_fuzzy.total_times))
+      self.fuzzy_streak_count += 1
+      if (self.strict_streak_count >= self.total_times*STREAK_RATIO):
+        plog("NOTICE",
+             "Strict termination condition reached at "
+             +str(self.total_times-self.strict_streak_count)
+             +" with streak of "+str(self.strict_streak_count))
+        # XXX: Signal termination condition
+
+
+
+def cleanup():
+  s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+  s.connect((TorUtil.control_host,TorUtil.control_port))
+  c = PathSupport.Connection(s)
+  c.authenticate_cookie(file("./tor-data/control_auth_cookie", "r"))
+  global FUDValue
+  from TorCtl.TorUtil import plog
+  plog("INFO", "Resetting FetchUselessDescriptors="+FUDValue)
+  c.set_option("FetchUselessDescriptors", FUDValue)
+
+def open_controller(filename):
+  """ starts stat gathering thread """
+
+  s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+  s.connect((TorUtil.control_host,TorUtil.control_port))
+  c = TorCtl.Connection(s)
+  t = c.launch_thread()
+  c.authenticate_cookie(file("./tor-data/control_auth_cookie", "r"))
+  c.debug(file(filename+".log", "w", buffering=0))
+  h = CircHandler(c)
+  c.set_event_handler(h)
+  c.add_event_listener(BuildTimeoutTracker())
+
+  global FUDValue
+  if not FUDValue:
+    FUDValue = c.get_option("FetchUselessDescriptors")[0][1]
+  c.set_option("FetchUselessDescriptors", "1")
+
+  c.set_events([TorCtl.EVENT_TYPE.BUILDTIMEOUT_SET,
+                TorCtl.EVENT_TYPE.BW,
+                TorCtl.EVENT_TYPE.CIRC], True)
+
+  # Close all the already open circuits to start fresh
+  h.close_all_circs()
+  return (c,t)
+
+def getargs():
+  if len(sys.argv[1:]) < 3:
+    usage()
+    sys.exit(2)
+  try:
+    opts,args = getopt.getopt(sys.argv[1:],"p:o:fmr")
+  except getopt.GetoptError,err:
+    print str(err)
+    usage()
+  for o,a in opts:
+    if o == '-n': pass
+    elif o == '-d': pass
+    else:
+      assert False, "Bad option"
+  return 0
+
+def usage():
+    print 'usage: FOAD'
+    sys.exit(1)
+
+def main():
+  #guard_slices,ncircuits,max_circuits,begin,end,pct,dirname,use_sql = getargs()
+  TorUtil.read_config('cbt.cfg')
+
+  try:
+    # XXX: Setconf guards for percentile range
+    atexit.register(cleanup)
+    (c,t) = open_controller("cbtest")
+    t.join()
+  except PathSupport.NoNodesRemain:
+    print 'No nodes remain at this percentile range.'
+    return
+
+  return (c,t)
+  #print "Using max_circuits: "+str(TorUtil.max_circuits)
+
+if __name__ == '__main__':
+  main()
+  #profile.run("main()", "prof.out")


Property changes on: torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/cbttest.py
___________________________________________________________________
Added: svn:executable
   + *

Added: torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/run_test.sh
===================================================================
--- torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/run_test.sh	                        (rev 0)
+++ torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/run_test.sh	2009-12-30 16:19:40 UTC (rev 21363)
@@ -0,0 +1,84 @@
+#!/bin/sh
+# TODO:
+# 1. Fire up a Tor
+# 2. For every 5% percentile, loop N times:
+# 3.   Remove state file + hup tor.
+# 4.   Run test with 3 guards from a percentile for c>10 circuits:
+# 5.     Record MIN_CIRCS=c/2 when past c/2 circuits did not change
+#        timeout more than +/-1.
+# 6.       Copy state file to saved location w/ guards and c/2
+# 7.     Stop test when past NCIRCS=c/2 circuits did not change timeout
+# 8.       Copy state file to new location w/ guards and c/2
+# 9. For each state file:
+# 10.   Insert state file + hup tor.
+# 11.   Loop M times for chosen guards:
+# 12.     Build NCIRCS circuits
+# 13.     Record circuit complete/(complete+timeout)
+# 14. XXX: Determine what % +/- 1, 2, 3 seconds gives us
+# 15. XXX: Graph timeout learned vs circuits over time.
+#
+# 4-8 in python
+# 11-13 in python
+#
+# Pick N = 10
+# Pick M = 3
+#
+# Final outputs:
+#  Percentile, MIN_CIRCS+timeout, NCIRCS+timeout, guards
+#
+# To do this need:
+# A. Event to export when circuitbuildtimeout is set
+#    - Check.
+# B. SIGNAL to close all circuits/build more?
+#    -> Or just close them via metatroller.. Make sure it will keep building
+#       though..
+# C. SETCONF EntryNodes/StrictEntryNodes
+
+TOR_DIR=../../tor.git/src/or
+TOR_DATA=./tor-data/
+
+kill `cat $TOR_DATA/tor.pid`
+if [ $? -eq 0 ]
+then
+ sleep 10
+fi
+
+$TOR_DIR/tor -f $TOR_DATA/torrc
+
+# XXX: Handle no guards left case
+for p in 65 0 5 10 15 20 25 30 35 40 45 50 55 60
+do
+  rm $TOR_DATA/state
+  kill -HUP `cat $TOR_DATA/tor.pid`
+  N=0
+  while [ $N -lt 10 ]
+  do
+    mkdir -p results/$p/$N/min
+    mkdir -p results/$p/$N/full
+    echo ./cbt-test.py -m -P 5 -p $p -o results/$p/$N/min/result -b results/$p/$N/min/buildtimes
+    # XXX: check retval
+    cp $TOR_DATA/state results/$p/$N/min/state
+    echo ./cbt-test.py -f -P 5 -p $p -o results/$p/$N/full/result -b results/$p/$N/full/buildtimes 
+    cp $TOR_DATA/state results/$p/$N/full/state
+    N=`expr $N + 1`
+  done
+done
+
+for p in `ls -1 results`
+do
+  for n in `ls -1 results/$p`
+  do
+    for t in `ls -1 results/$p/$n`
+    do
+      M=0
+      while [ $M -lt 3 ]
+      do
+        cp results/$p/$n/$t $TOR_DATA/state
+        kill -HUP `cat $TOR_DATA/tor.pid`
+        echo ./cbt-test.py -r -o results/$p/$n/$t/result -b results/$p/$N/buildtimes.redo.$M
+        M=`expr $N + 1`
+      done
+    done
+  done
+done
+


Property changes on: torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/run_test.sh
___________________________________________________________________
Added: svn:executable
   + *

Added: torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/tor-data/torrc
===================================================================
--- torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/tor-data/torrc	                        (rev 0)
+++ torflow/trunk/CircuitAnalysis/BuildTimes/CBT-Test/tor-data/torrc	2009-12-30 16:19:40 UTC (rev 21363)
@@ -0,0 +1,8 @@
+ControlPort 9551
+SocksPort 9550
+
+FetchUselessDescriptors 1
+DataDirectory ./tor-data/
+CookieAuthentication 1
+NewCircuitPeriod 1
+Log info file ./tor-data/tor.log



More information about the tor-commits mailing list