[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