#!/bin/bash # Reproduce the Duoram experiments from our paper: # Adithya Vadapalli, Ryan Henry, Ian Goldberg. Duoram: A # Bandwidth-Efficient Distributed ORAM for 2- and 3-Party Computation. # USENIX Security Symposium 2023. # cd into the directory containing this script (from the bash faq 028) if [[ $BASH_SOURCE = */* ]]; then cd -- "${BASH_SOURCE%/*}/" || exit fi # If the master NUMA commands are set, use them for Duoram if [ "$NUMA_P0" != "" ]; then export DUORAM_NUMA_P0="$NUMA_P0" fi if [ "$NUMA_P1" != "" ]; then export DUORAM_NUMA_P1="$NUMA_P1" fi # Allow running only subsets of the experiment suite. Valid values are # "test", "small", "large", "scaling", "all", "none". ("none" is useful # if you just want to re-parse the output of existing logs. "scaling" # is the subset of "small" that generates the data points for Figure 10; # see the README for that one, since you need a machine with at least 64 # cores to generate it.) You can also say "single" followed by all the # arguments to "run" (below) to run a single experiment; for example: # ./repro single readwrite 20 1us 100gbit 128 if [ "$1" = "" ]; then whichexps="test" else whichexps="$1" fi # The number of operations per run; the graphs in the paper use 128 if [ "$whichexps" = "single" -o "$2" = "" ]; then # If there's an explicit experiment on the command line, don't read # the next argument as the number of operations. $numops will be # ignored, anyway, since it will be specified as part of the # command. numops=128 else numops="$2" fi # Run one experiment # Arguments: # $1: mode (read, write, readwrite) # $2: depth (the ORAM has 2^depth elements) # $3: latency (e.g., 30ms) # $4: bandwidth (e.g., 100mbit) # $5: number of operations (e.g., 128) run() { now=`date` echo "$now: Running $1 $2 $3 $4 $5 ..." logfile="${1}_${3}_${4}_${5}.out${LOGSUFFIX}" sh set-networking.sh $3 $4 echo "Network setup: $3 $4" >> $logfile sh run-experiment.sh $1 $2 $5 >> $logfile } # Parse the output logs. We run this in the docker in case you don't # have perl installed on the host. # Arguments: a list of logfiles parse() { cat $* | docker exec -w /root -i floram_p0 ./parse_logs } # A very small kick-the-tires test to ensure everything compiled and # built properly if [ "$whichexps" = "test" ]; then echo "Running test experiment..." run read 16 1us 100gbit 2 parse read_1us_100gbit_2.out${LOGSUFFIX} exit fi # Be able to run a single experiment specified on the command line if [ "$whichexps" = "single" ]; then echo "Running single experiment..." shift run $* exit fi now=`date` echo "$now: Starting experiments" # if [ "$whichexps" = "small" -o "$whichexps" = "all" ]; then # echo "Running small experiments..." # # Figure 7(a), 8(c) # run readwrite 16 30ms 100mbit ${numops} # run readwrite 18 30ms 100mbit ${numops} # run readwrite 20 30ms 100mbit ${numops} # run readwrite 22 30ms 100mbit ${numops} # run readwrite 24 30ms 100mbit ${numops} # run readwrite 26 30ms 100mbit ${numops} # # Figure 7(b) # run readwrite 20 30ms 10mbit ${numops} # run readwrite 20 30ms 30mbit ${numops} # run readwrite 20 30ms 50mbit ${numops} # run readwrite 20 30ms 70mbit ${numops} # run readwrite 20 30ms 90mbit ${numops} # run readwrite 20 30ms 110mbit ${numops} # # Figure 7(c) # run readwrite 20 10ms 100mbit ${numops} # run readwrite 20 50ms 100mbit ${numops} # run readwrite 20 70ms 100mbit ${numops} # # Figures 8(a), 9(b), and 9(c) # # Note that we set the latency to 1us, which really means "don't add # # artificial latency", but we measure the one-way latency to # # actually be 30us, which is what we report in the paper. (pings # # from one docker to the other take about 60us round trip.) # run read 16 1us 100gbit ${numops} # run read 18 1us 100gbit ${numops} # run read 20 1us 100gbit ${numops} # run read 22 1us 100gbit ${numops} # run read 24 1us 100gbit ${numops} # run read 26 1us 100gbit ${numops} # # Figure 8(b) # run write 16 1us 100gbit ${numops} # run write 18 1us 100gbit ${numops} # run write 20 1us 100gbit ${numops} # run write 22 1us 100gbit ${numops} # run write 24 1us 100gbit ${numops} # run write 26 1us 100gbit ${numops} # # Figure 9(a) # run read 18 30ms 100mbit ${numops} # run read 22 30ms 100mbit ${numops} # run read 24 30ms 100mbit ${numops} # fi # if [ "$whichexps" = "small" -o "$whichexps" = "scaling" -o "$whichexps" = "all" ]; then # # Figures 9(a), 10 # run read 16 30ms 100mbit ${numops} # run read 20 30ms 100mbit ${numops} # run read 26 30ms 100mbit ${numops} # fi # if [ "$whichexps" = "large" -o "$whichexps" = "all" ]; then # echo "Running large experiments..." # # Figure 9(a) # run read 28 30ms 100mbit ${numops} # run read 30 30ms 100mbit ${numops} # run read 32 30ms 100mbit ${numops} # # Figures 9(b) and 9(c) # run read 28 1us 100gbit ${numops} # run read 30 1us 100gbit ${numops} # run read 32 1us 100gbit ${numops} # fi # now=`date` # echo "$now: Experiments complete" # # If you specified a custom log suffix, you're going to be parsing the # # outputs differently. # if [ "$LOGSUFFIX" = "" ]; then # parse *_${numops}.out > floram_${numops}.dat # echo # echo "# Figure 7(a)" # egrep 'Duoram readwrite .* 30ms 100mbit .* s$' floram_${numops}.dat | sort -k3 -n # echo # echo "# Figure 7(b)" # egrep 'Duoram readwrite 20 30ms .* s$' floram_${numops}.dat | sort -k5 -n # echo # echo "# Figure 7(c)" # egrep 'Duoram readwrite 20 .* 100mbit .* s$' floram_${numops}.dat | sort -k4 -n # echo # echo "# Figure 8(a)" # egrep 'Duoram read .* 1us 100gbit .* KiB$' floram_${numops}.dat | sort -k3 -n # echo # echo "# Figure 8(b)" # egrep 'Duoram write .* 1us 100gbit .* KiB$' floram_${numops}.dat | sort -k3 -n # echo # echo "# Figure 8(c)" # egrep 'Duoram readwrite .* 30ms 100mbit .* KiB$' floram_${numops}.dat | sort -k3 -n # echo # echo "# Figure 9(a)" # egrep 'Duoram read .* 30ms 100mbit .* s$' floram_${numops}.dat | sort -k3 -n # echo # echo "# Figure 9(b)" # egrep 'Duoram read .* 1us 100gbit .* s$' floram_${numops}.dat | sort -k3 -n # echo # echo "# Figure 9(c)" # egrep 'Duoram read .* 1us 100gbit .* KiB$' floram_${numops}.dat | sort -k3 -n # fi