[tor-commits] [stegotorus/master] Version of scripts actually used for paper.

zwol at torproject.org zwol at torproject.org
Fri Jul 20 23:17:07 UTC 2012


commit 33984e92c72c799751845b8279822ab513a9df52
Author: Zack Weinberg <zackw at panix.com>
Date:   Tue Feb 28 08:37:12 2012 -0800

    Version of scripts actually used for paper.
---
 scripts/benchmark-plot.R     |   63 +++++++++++-
 scripts/benchmark.py         |  233 +++++++++++++++++++++++++-----------------
 scripts/bm-tor-controller.py |  118 ++++++++++++----------
 3 files changed, 263 insertions(+), 151 deletions(-)

diff --git a/scripts/benchmark-plot.R b/scripts/benchmark-plot.R
index a58ae0a..1ae178d 100644
--- a/scripts/benchmark-plot.R
+++ b/scripts/benchmark-plot.R
@@ -1,7 +1,68 @@
 #! /usr/bin/Rscript
 
 suppressPackageStartupMessages({
+  library(plyr)
   library(ggplot2)
+  library(tikzDevice)
 })
 
-lf.direct <- read.csv("bench-lf-direct.tab", header=TRUE)
+peval.raw <- read.csv("perf-eval.csv", header=TRUE)
+
+peval.u <- rename(ddply(peval.raw, .(benchmark,relay,cap),
+                        function(x) fivenum(x$up)),
+                  c(V1='min', V2='lhinge', V3='med', V4='uhinge', V5='max'))
+peval.d <- rename(ddply(peval.raw, .(benchmark,relay,cap),
+                        function(x) fivenum(x$down)),
+                  c(V1='min', V2='lhinge', V3='med', V4='uhinge', V5='max'))
+
+# pareto became unstable at 50 connections per second
+peval.u <- subset(peval.u, benchmark!='files.pareto'|cap<=50)
+peval.d <- subset(peval.d, benchmark!='files.pareto'|cap<=50)
+
+peval.u$direction <- factor("KBps upstream")
+peval.d$direction <- factor("KBps downstream")
+
+peval <- rbind(peval.u, peval.d)
+
+# force x=0 to appear on all the subplots
+zeroes <- ddply(peval, .(benchmark, relay, direction),
+                function(x) data.frame(cap=0,min=0,lhinge=0,med=0,
+                                       uhinge=0,max=0))
+peval <- rbind(peval, zeroes)
+
+peval$benchmark <- ordered(peval$benchmark,
+                           levels=c("fixedrate", "files.fixed", "files.pareto"),
+                           labels=c("Fixed rate stream", "Fixed-size files",
+                             "Pareto-distributed files"))
+
+peval$Relay <- ordered(peval$relay,
+                       levels=c("direct", "tor", "st.http"),
+                       labels=c("Direct", "Tor", "StegoTorus (HTTP)"))
+
+RelayFill=c("Direct"="#666666", "Tor"="#72B8E7",
+              "StegoTorus (HTTP)"="#E31A1C")
+
+RelayColors=c("Direct"="#666666", "Tor"="#1F78B4",
+            "StegoTorus (HTTP)"="#E31A1C")
+
+graf <- ggplot(peval, aes(x=cap, ymin=lhinge, ymax=uhinge, y=med)) +
+  geom_ribbon(aes(fill=Relay), alpha=0.3) +
+  geom_line(aes(colour=Relay)) +
+  facet_grid(direction~benchmark, scales='free') +
+  scale_x_continuous(expand=c(.01,0)) +
+  scale_y_continuous(expand=c(0,0)) +
+  scale_colour_manual(values=RelayColors) +
+  scale_fill_manual(values=RelayFill) +
+  theme_bw(base_size=8) +
+  opts(panel.border=theme_blank(),
+       legend.key=theme_blank(),
+       legend.title=theme_blank(),
+       legend.background=theme_rect(fill="white",colour=NA),
+       legend.position=c(0.1,0.8),
+       strip.background=theme_blank(),
+       axis.ticks.margin=unit(0.25, "lines")
+       )
+
+tikz(file="perf-eval.tex", width=6.5, height=3, standAlone=TRUE)
+print(graf)
+invisible(dev.off())
diff --git a/scripts/benchmark.py b/scripts/benchmark.py
index be45467..8029f11 100755
--- a/scripts/benchmark.py
+++ b/scripts/benchmark.py
@@ -27,8 +27,8 @@
 #
 # nylon: http://monkey.org/~marius/pages/?page=nylon
 # tor, stegotorus
-#
-# You configure this script by setting variables below.
+
+# CONFIGURATION - ADJUST VARIABLES BELOW AS NECESSARY
 
 # Client host
 
@@ -39,18 +39,13 @@ CLIENT_IFACE  = "eth0"
 
 PROXY         = "sandbox03.sv.cmu.edu"
 PROXY_IP      = "209.129.244.30" # some things won't do DNS for this
-PROXY_PORT    = "1080"
+PROXY_PORT    = 1080
 PROXY_SSH_CMD = ("ssh", PROXY)
 
 # Target
 
 TARGET    = "storustest.nfshost.com"
 
-# For some reason, bm-fixedrate generates data a linear factor slower
-# than it was meant to; this is the quick fix.
-
-FUDGE_FIXEDRATE = 1.939
-
 # Programs we need to run.  Change these if any binary is not in the
 # default path or hasn't got the default name.
 # C_ - for the client.  P_ - for the proxy.
@@ -59,15 +54,23 @@ FUDGE_FIXEDRATE = 1.939
 
 C_bwm     = "bwm-ng"
 C_mcurl   = "bm-mcurl"
-C_storus  = "stegotorus-wrapper"
+C_storus  = "stegotorus"
 C_tor     = "/usr/sbin/tor"
 
 P_nylon   = "nylon"
-P_storus  = "stegotorus-wrapper"
+P_storus  = "./stegotorus/build/stegotorus"
 P_tor     = "tor"
 P_python  = "/usr/local/bin/python" # this must be an absolute path,
                                     # it goes on a shebang line
 
+# For some reason, bm-fixedrate generates data a linear factor slower
+# than it was meant to; this is the quick fix.  To calibrate this
+# number, set it to 1 and run the direct fixedrate test, do a linear
+# regression on 'down' as a function of 'cap', and the number you want
+# is 1 over the slope of the line.
+
+FUDGE_FIXEDRATE = 1.939
+
 # ACTUAL PROGRAM STARTS HERE
 
 from types import MethodType
@@ -220,28 +223,38 @@ Verbose=0
 PIDfile=nylon.pid
 
 [Server]
-Port=%s
+Port=%d
 Allow-IP=%s/32
 """ % (PROXY_PORT, CLIENT_IP))
 
-def p_tor_direct():
-    return ProxyProcess((P_tor, "--quiet", "-f", "tor-direct.conf"),
-                        "tor-direct.conf",
+def p_tor():
+    return ProxyProcess((P_tor, "--quiet", "-f", "tor.conf"),
+                        "tor.conf",
                         """\
-ORPort %s
+ORPort %d
 SocksPort 0
 BridgeRelay 1
 AssumeReachable 1
 PublishServerDescriptor 0
-ExitPolicy reject *:*
+ExitPolicy accept *:80
 DataDirectory .
 Log err stderr
 ContactInfo zackw at cmu dot edu
 Nickname storustest
+AllowSingleHopExits 1
 # unfortunately there doesn't seem to be any way to tell Tor to accept
 # OR connections from specific IP addresses only.
 """ % PROXY_PORT)
 
+def p_storus(smode):
+    return ProxyProcess((P_storus, "--log-min-severity=warn",
+                         "chop", "server", "127.0.0.1:%d" % PROXY_PORT,
+                         "%s:%d" % (PROXY_IP, PROXY_PORT+1), smode,
+                         "%s:%d" % (PROXY_IP, PROXY_PORT+2), smode,
+                         "%s:%d" % (PROXY_IP, PROXY_PORT+3), smode,
+                         "%s:%d" % (PROXY_IP, PROXY_PORT+4), smode))
+
+
 class ClientProcess(subprocess.Popen):
     """A process running on the local machine.  This is probably doing
     the meat of the work of some benchmark.  Basically a shim around
@@ -264,80 +277,91 @@ def c_tor_direct():
     fp = open("tor-direct-client.conf", "w")
     fp.write("""\
 ORPort 0
-SocksPort %s
+SocksPort %d
 DataDirectory .
 Log err stderr
-Bridge %s:%s
+Bridge %s:%d
 UseBridges 1
 SafeSocks 0
 ControlPort 9051
+AllowSingleHopCircuits 1
+ExcludeSingleHopRelays 0
 __DisablePredictedCircuits 1
 __LeaveStreamsUnattached 1
 """ % (PROXY_PORT, PROXY_IP, PROXY_PORT))
     fp.close()
     return ClientProcess((C_tor, "--quiet", "-f", "tor-direct-client.conf"))
 
+def c_tor_storus():
+    fp = open("tor-storus-client.conf", "w")
+    fp.write("""\
+ORPort 0
+SocksPort %d
+Socks5Proxy 127.0.0.1:%s
+DataDirectory .
+Log err stderr
+Bridge %s:%d
+UseBridges 1
+SafeSocks 0
+ControlPort 9051
+AllowSingleHopCircuits 1
+ExcludeSingleHopRelays 0
+__DisablePredictedCircuits 1
+__LeaveStreamsUnattached 1
+""" % (PROXY_PORT, PROXY_PORT+1, PROXY_IP, PROXY_PORT))
+    fp.close()
+    return ClientProcess((C_tor, "--quiet", "-f", "tor-storus-client.conf"))
+
+def c_storus(smode):
+    return ClientProcess((C_storus, "--log-min-severity=warn",
+                          "chop", "socks", "127.0.0.1:%d" % (PROXY_PORT+1),
+                          "%s:%d" % (PROXY_IP, PROXY_PORT+1), smode,
+                          "%s:%d" % (PROXY_IP, PROXY_PORT+2), smode,
+                          "%s:%d" % (PROXY_IP, PROXY_PORT+3), smode,
+                          "%s:%d" % (PROXY_IP, PROXY_PORT+4), smode))
+
 def c_torctl():
-    return ClientProcess((os.path.dirname(__file__) + '/bm-tor-controller.py'))
+    return ClientProcess((os.path.dirname(__file__) + '/bm-tor-controller.py'
+                          ))
 
 def c_curl(url, proxyhost):
     return ClientProcess((C_mcurl, '1', '1',
-                          proxyhost + ":" + PROXY_PORT,
+                          proxyhost + ":" + str(PROXY_PORT),
                           url))
 
 def c_mcurl(prefix, cps, proxyhost):
     return ClientProcess((C_mcurl, str(cps), '200',
-                          proxyhost + ':' + PROXY_PORT,
+                          proxyhost + ':' + str(PROXY_PORT),
                           'http://' + TARGET + '/' + prefix +
                           '/[0-9]/[0-9]/[0-9]/[0-9].html'))
 
 # Benchmarks.
 
-def bench_fixedrate_direct(report):
-    client = None
+def t_direct(report, bench, *args):
     proxy = None
     try:
         proxy = p_nylon()
 
-        for cap in range(10,810,10):
-            sys.stderr.write("fixedrate,direct,%d\n" % (cap * 1000))
-            try:
-                client = c_curl('http://' + TARGET + '/bm-fixedrate.cgi/' +
-                                str(int(cap * 1000 * FUDGE_FIXEDRATE)),
-                                PROXY)
-                monitor(report, "fixedrate,direct,%d" % cap, 10)
-            finally:
-                if client is not None:
-                    client.terminate()
-                    client.wait()
-                    client = None
+        bench(report, PROXY_IP, "direct", *args)
+
     finally:
         if proxy is not None:
             proxy.terminate()
             proxy.wait()
 
-def bench_fixedrate_tor(report):
-    client = None
+def t_tor(report, bench, *args):
     proxy = None
     proxyl = None
+    proxyc = None
     try:
-        proxy = p_tor_direct()
+        proxy = p_tor()
         proxyl = c_tor_direct()
+        time.sleep(1)
         proxyc = c_torctl()
-        time.sleep(5) # tor startup is slow
-
-        for cap in range(10,810,10):
-            sys.stderr.write("fixedrate,tor,%d\n" % cap)
-            try:
-                client = c_curl('http://' + TARGET + '/bm-fixedrate.cgi/' +
-                                str(int(cap * 1000 * FUDGE_FIXEDRATE)),
-                                '127.0.0.1')
-                monitor(report, "fixedrate,tor,%d" % cap, 60)
-            finally:
-                if client is not None:
-                    client.terminate()
-                    client.wait()
-                    client = None
+        time.sleep(4)
+
+        bench(report, '127.0.0.1', "tor", *args)
+
     finally:
         if proxy is not None:
             proxy.terminate()
@@ -349,47 +373,23 @@ def bench_fixedrate_tor(report):
             proxyl.terminate()
             proxyl.wait()
 
-def bench_files_direct(report, prefix, maxconn):
-    client = None
-    proxy = None
-    try:
-        proxy = p_nylon()
-
-        for cps in range(1,maxconn+1):
-            sys.stderr.write("files.%s,direct,%d\n" % (prefix, cps))
-            try:
-                client = c_mcurl(prefix, cps, PROXY_IP)
-                monitor(report, "files.%s,direct,%d" % (prefix, cps), 60)
-            finally:
-                if client is not None:
-                    client.terminate()
-                    client.wait()
-                    client = None
-    finally:
-        if proxy is not None:
-            proxy.terminate()
-            proxy.wait()
-
-def bench_files_tor(report, prefix, maxconn):
-    client = None
+def t_storus(report, bench, smode, *args):
     proxy = None
+    proxys = None
     proxyl = None
+    proxym = None
+    proxyc = None
     try:
-        proxy = p_tor_direct()
-        proxyl = c_tor_direct()
+        proxy = p_tor()
+        proxys = p_storus(smode)
+        proxyl = c_tor_storus()
+        proxym = c_storus(smode)
+        time.sleep(1)
         proxyc = c_torctl()
-        time.sleep(5) # tor startup is slow
-
-        for cps in range(1,maxconn+1):
-            sys.stderr.write("files.%s,tor,%d\n" % (prefix, cps))
-            try:
-                client = c_mcurl(prefix, cps, '127.0.0.1')
-                monitor(report, "files.%s,tor,%d" % (prefix, cps), 60)
-            finally:
-                if client is not None:
-                    client.terminate()
-                    client.wait()
-                    client = None
+        time.sleep(4)
+
+        bench(report, '127.0.0.1', "st.http", *args)
+
     finally:
         if proxy is not None:
             proxy.terminate()
@@ -400,12 +400,53 @@ def bench_files_tor(report, prefix, maxconn):
         if proxyl is not None:
             proxyl.terminate()
             proxyl.wait()
+        if proxys is not None:
+            proxys.terminate()
+            proxys.wait()
+        if proxym is not None:
+            proxym.terminate()
+            proxym.wait()
+
+def bench_fixedrate(report, proxyaddr, relay, bmax, bstep, mtime):
+    for cap in range(bstep, bmax+bstep, bstep):
+        tag = "fixedrate,%s,%d" % (relay, cap)
+        sys.stderr.write(tag + "\n")
+        try:
+            client = c_curl('http://' + TARGET + '/bm-fixedrate.cgi/' +
+                            str(int(cap * 1000 * FUDGE_FIXEDRATE)),
+                            proxyaddr)
+            monitor(report, tag, mtime)
+        finally:
+            if client is not None:
+                client.terminate()
+                client.wait()
+                client = None
+
+def bench_files(report, proxyaddr, relay, prefix, maxconn, mtime):
+    for cps in range(1,maxconn+1):
+        tag = "files.%s,%s,%d" % (prefix, relay, cps)
+        sys.stderr.write(tag + "\n")
+        try:
+            client = c_mcurl(prefix, cps, proxyaddr)
+            monitor(report, tag, mtime)
+        finally:
+            if client is not None:
+                client.terminate()
+                client.wait()
+                client = None
 
 if __name__ == '__main__':
-    sys.stdout.write("benchmark,relay,cap,obs,up,down\n")
-    bench_fixedrate_direct(sys.stdout)
-    bench_fixedrate_tor(sys.stdout)
-    bench_files_direct(sys.stdout, "fixed", 120)
-    bench_files_tor(sys.stdout, "fixed", 120)
-    bench_files_direct(sys.stdout, "pareto", 80)
-    bench_files_tor(sys.stdout, "pareto", 80)
+    r = sys.stdout
+    r.write("benchmark,relay,cap,obs,up,down\n")
+
+    t_direct(r, bench_fixedrate, 700, 10, 20)
+    t_direct(r, bench_files, "fixed", 120, 20)
+    t_direct(r, bench_files, "pareto", 120, 20)
+
+    t_tor(r, bench_fixedrate, 700, 10, 20)
+    t_tor(r, bench_files, "fixed", 120, 20)
+    t_tor(r, bench_files, "pareto", 120, 20)
+
+    t_storus(r, bench_fixedrate, "http", 700, 10, 30)
+    t_storus(r, bench_files, "http", "fixed", 120, 30)
+    t_storus(r, bench_files, "http", "pareto", 120, 30)
diff --git a/scripts/bm-tor-controller.py b/scripts/bm-tor-controller.py
index 1b147be..f10d8d2 100755
--- a/scripts/bm-tor-controller.py
+++ b/scripts/bm-tor-controller.py
@@ -1,76 +1,86 @@
 #! /usr/bin/python
 
 from torctl import TorCtl, TorUtil, PathSupport
-
+import sys
 import time
 
-i = PathSupport.IdHexRestriction
-
-# in San Francisco
-amunet = PathSupport.OrNodeRestriction([
-  i('$0CE3CFB1E9CC47B63EA8869813BF6FAB7D4540C1'), # amunet4
-  i('$E0BD57A11F00041A9789577C53A1B784473669E4'), # amunet3
-  i('$E5E3E9A472EAF7BE9682B86E92305DB4C71048EF') # amunet2
-])
-
-# probably in L.A.
-hazare = PathSupport.OrNodeRestriction([
-  i('$3D0FAFB36EB9FC9D1EFD68758E2B0025117D3D1B'), # hazare2
-  i('$6586CEE14353DD1E6FAF3F172A23B00119A67C57'), # saeed
-  i('$6F383C2629471E1AE7DA053D04625AAED69844CC')  # hazare
-])
-
-# very likely in L.A.
-noisebr = PathSupport.OrNodeRestriction([
-  i('$3A415473854F9F082F16EECDFE436218FE1169EA'), # noiseexit01c
-  i('$9C98B38FE270546C69205E16047B8D46BBBB0447'), # noiseexit01d
-  i('$F97F3B153FED6604230CD497A3D1E9815B007636')  # noiseexit01a
-])
-
-# I shouldn't have to do this
-class TheseUniformly(PathSupport.BaseSelectionManager):
-    def __init__(self, res_entry, res_mid, res_exit):
+#i = PathSupport.IdHexRestriction
+
+#nodes_entry = PathSupport.OrNodeRestriction([
+#   i('$580075B70F4CBA0C6819819CC3CB7F4D5D06F0FD') # torEFF
+#  i('$0CE3CFB1E9CC47B63EA8869813BF6FAB7D4540C1'), # amunet4
+#  i('$E0BD57A11F00041A9789577C53A1B784473669E4'), # amunet3
+#  i('$E5E3E9A472EAF7BE9682B86E92305DB4C71048EF') # amunet2
+#])
+
+#nodes_mid = PathSupport.OrNodeRestriction([
+#   i('$204C0D7C6E1D06D7645B07F9BEAC9971DBD7E5EC') # ITM
+#  i('$3D0FAFB36EB9FC9D1EFD68758E2B0025117D3D1B'), # hazare2
+#  i('$6586CEE14353DD1E6FAF3F172A23B00119A67C57'), # saeed
+#  i('$6F383C2629471E1AE7DA053D04625AAED69844CC')  # hazare
+#])
+
+#nodes_exit = PathSupport.OrNodeRestriction([
+#   i('$13A742728E5E0FC7FE363A07799F0FAD276DED43') # Goodnet01
+#  i('$3A415473854F9F082F16EECDFE436218FE1169EA'), # noiseexit01c
+#  i('$9C98B38FE270546C69205E16047B8D46BBBB0447'), # noiseexit01d
+#  i('$F97F3B153FED6604230CD497A3D1E9815B007636')  # noiseexit01a
+#])
+
+def ensure_nrl(x):
+    if not isinstance(x, PathSupport.NodeRestrictionList):
+        x = PathSupport.NodeRestrictionList([x])
+    return x
+
+class ThisSequenceUniformly(PathSupport.BaseSelectionManager):
+    def __init__(self, restrictions):
         PathSupport.BaseSelectionManager.__init__(self)
-        if not isinstance(res_entry, PathSupport.NodeRestrictionList):
-            res_entry = PathSupport.NodeRestrictionList([res_entry])
-        if not isinstance(res_mid, PathSupport.NodeRestrictionList):
-            res_mid = PathSupport.NodeRestrictionList([res_mid])
-        if not isinstance(res_exit, PathSupport.NodeRestrictionList):
-            res_exit = PathSupport.NodeRestrictionList([res_exit])
-        self.res_entry = res_entry
-        self.res_mid   = res_mid
-        self.res_exit  = res_exit
-        self.path_selector = None
+        self.restrictions = [ ensure_nrl(x) for x in restrictions ]
+        self.generators = None
 
     def reconfigure(self, consensus):
-        if self.path_selector is not None:
+        if self.generators is not None:
             try:
-                self.path_selector.rebuild_gens(consensus.sorted_r)
-            except NoNodesRemain:
-                pass
+                for g in self.generators:
+                    g.rebuild(consensus.sorted_r)
+            except PathSupport.NoNodesRemain:
+                pass # have to make new generators
 
-        self.path_selector = PathSupport.PathSelector(
-            PathSupport.ExactUniformGenerator(consensus.sorted_r, self.res_entry),
-            PathSupport.ExactUniformGenerator(consensus.sorted_r, self.res_mid),
-            PathSupport.ExactUniformGenerator(consensus.sorted_r, self.res_exit),
-            PathSupport.PathRestrictionList([PathSupport.UniqueRestriction()]))
+        self.generators = [
+            PathSupport.ExactUniformGenerator(consensus.sorted_r, restr)
+            for restr in self.restrictions
+        ]
 
     def new_consensus(self, consensus):
         self.reconfigure(consensus)
 
-    def set_exit(self, exit_name):
-        pass
-
-    def set_target(self, host, port):
-        pass
+    def select_path(self):
+        if self.generators is None: raise PathSupport.NoNodesRemain
+        path = []
+        for g in self.generators:
+            g.rewind()
+            r = g.generate().next()
+            r.refcount += 1
+            path.append(r)
+        return path
+
+class ThisBridgeAndNothingElse(PathSupport.BaseSelectionManager):
+    def __init__(self, bridge):
+        self.bridge = bridge
 
     def select_path(self):
-        return self.path_selector.select_path(3)
+        self.bridge.refcount += 1
+        return [self.bridge]
 
 TorUtil.loglevel = "WARN"
 
-s = TheseUniformly(amunet, hazare, noisebr)
-c = TorCtl.connect(ConnClass=PathSupport.Connection)
+c  = TorCtl.connect(ConnClass=PathSupport.Connection)
+bs = c.get_network_status("purpose/bridge")
+while len(bs) == 0:
+    bs = c.get_network_status("purpose/bridge")
+
+s  = ThisBridgeAndNothingElse(c.get_router(bs[0]))
+
 h = PathSupport.PathBuilder(c, s)
 c.set_event_handler(h)
 c.set_events([TorCtl.EVENT_TYPE.STREAM,





More information about the tor-commits mailing list