Controller target

This commit is contained in:
Pascal Engélibert 2026-06-16 10:07:58 +02:00
commit 563d6a4e07
3 changed files with 112 additions and 113 deletions

217
exp.py
View file

@ -2,6 +2,83 @@
import os, sys, subprocess, socket, signal
CONFIGS = {
# This first config is a placeholder for documenting the available options.
# A config defines settings and values that will be tested in all possible combinations.
"choose_a_config_name": {
# List of the experiments to perform, in order. (they are defined in EXPERIMENTS below)
"experiments": [
"impl-cipher-ver",
"impl-cert-ver",
"impl-kex-ver",
],
# Run client and server on the target (what is being measured).
"sides": [
"client",
"server",
],
# Run without and with TLS
# Within an experiment, settings combinations that have no impact when TLS is not used (e.g. different ciphers) run only once.
"tls": [
False,
True,
],
# Traffic records to replay
# * filename: in the ./records folder
# * repeat: maximum number of times to replay the records (mostly useful to stop early in case of misconfiguration, best not to hit it)
# * time: number of seconds to run the experiment
# * reproduce: number of times to run the experiment
"records": [
{ "filename": "wp2", "repeat": 10000, "time": 120, "reproduce": 10 },
],
# Path to the repository on the controller machine
"repo_dir": "/home/pengelib/tlsbench",
# Path to temporary data on both machines (will be created automatically)
"exp_dir": "/dev/shm/exp",
# Directory where experiment logs (raw results) are stored
"log_backup_dir": "/home/pengelib",
# LAN address of the controller
"local_addr": "172.16.101.x",
# LAN address of the target
"remote_addr": "172.16.101.x",
# SSH user@host of the target (remove if target is in the same machine/user)
"remote_ssh": "pengelib@paradoxe-x",
# SSH password for the target (may be None)
"remote_psw": None,
# Path to this repository on the target
"remote_repo_dir": "/home/pengelib/tlsbench",
# Whether a YoctoWatt wattmeter is used (measuring target, USB plugged to controller)
"wattmeter": False,
# Whether perf is used to monitor target
# If using perf, reduce experiment time to a few seconds and 1 repeat, and ensure good storage bandwidth and large RAM.
"perf": False,
# Whether RAPL is used to estimate target power consumption
"rapl": False,
# Whether sa is used to count CPU time on the target
"sa": False,
# Server listen port (avoid <1024 because it may require permissions)
"listen_port": 8080,
# Log line obtained by running with --idle option.
# Will be added to every log file without re-running the idle experiment.
"idle": "target_name idle - - - - - - - - - 1779276600 1779277200 600 0 222346 1105446 2.935994312264558 0 -",
# This script will listen to this address to monitor the number of repetitions of the experiment.
# The netreplay client will send UDP packets to this port.
"notify_listen": ("0.0.0.0", 8090),
# The notify address from LAN
"notify_addr": "172.16.101.x:8090",
# LD_PRELOAD for netreplay, to override shared libraries like OpenSSL
# Must contain absolute paths to shared objects, separated by colons.
# Key is the implementation identifier.
"ld_preload": {
"openssl": "/home/pengelib/openssl-openssl-3.6.1/libssl.so.3:/home/pengelib/openssl-openssl-3.6.1/libcrypto.so.3",
},
# Whether to create a log line for both target and controller
# Because this script's overhead may be negligible, and it enables to get twice more data.
"measure_both": False,
# Target name for the log file
"target": "my_target_computer",
# Controller target name for the log file (only used with measure_both, can be removed else)
"controller_target": "my_controller_computer",
},
"debug": {
"experiments": [
"impl-cipher-ver",
@ -34,42 +111,9 @@ CONFIGS = {
"listen_port": 8080,
"notify_listen": ("127.0.0.1", 8090),
"notify_addr": "127.0.0.1:8090",
"measure_both": False,
"target": "debug",
},
# i7-4790 local
"local": {
"experiments": [
"impl-cipher-ver",
"impl-cert-ver",
"impl-kex-ver",
"zrtt",
],
"sides": [
"client",
"server",
],
"tls": [
#False,
True,
],
"records": [
{ "filename": "wikipedia", "repeat": 5 },
],
"repo_dir": "/home/tuxmain/reps/tlsbench",
"exp_dir": "/dev/shm/exp",
"log_backup_dir": "/home/tuxmain",
"local_addr": "127.0.0.1",
"remote_addr": "127.0.0.1",
"remote_repo_dir": "/home/tuxmain/reps/tlsbench",
"wattmeter": False,
"perf": True,
"rapl": False,
"sa": True,
"perf_dir": "/home/tuxmain/.cache/exp",
"listen_port": 8080,
"notify_listen": ("127.0.0.1", 8090),
"notify_addr": "127.0.0.1:8090",
},
# i7-4790 -> pi3
"pi3": {
"experiments": [
#"impl-cipher-ver",
@ -105,12 +149,13 @@ CONFIGS = {
"rapl": False,
"sa": True,
"listen_port": 8080,
"idle": "idle - - - - - - - - - - - 600.000081539154 0.0 896 4792 0.5399999999999991 0 -",
"idle": "pi3 idle - - - - - - - - - - - 600.000081539154 0.0 896 4792 0.5399999999999991 0 -",
"notify_listen": ("0.0.0.0", 8090),
"notify_addr": "192.168.3.1:8090",
"concurrency": "1",
"concurrency": "2",
"measure_both": False,
"target": "pi3",
},
# i7-4790 -> core2
"core2": {
"experiments": [
#"impl-cipher-ver",
@ -148,42 +193,13 @@ CONFIGS = {
"rapl": False,
"sa": True,
"listen_port": 8080,
"idle": "idle - - - - - - - - - 1777360401.7482355 1777361601.7482355 1200.0000903606415 0 589 4764 3.478999999999999 0 -",
"idle": "core2 idle - - - - - - - - - 1777360401.7482355 1777361601.7482355 1200.0000903606415 0 589 4764 3.478999999999999 0 -",
"notify_listen": ("0.0.0.0", 8090),
"notify_addr": "192.168.3.1:8090",
"concurrency": "1",
"measure_both": False,
"target": "core2",
},
"core2-local": {
"experiments": [
"impl-cipher-ver",
"impl-cert-ver",
"impl-kex-ver",
],
"sides": [
"client",
"server",
],
"tls": [
False,
True,
],
"records": [
{ "filename": "wikipedia", "repeat": 10 },
],
"repo_dir": "/home/exp/exp",
"exp_dir": "/dev/shm/exp",
"log_backup_dir": "/home/exp",
"local_addr": "127.0.0.1",
"remote_addr": "127.0.0.1",
"remote_repo_dir": "/home/exp/exp",
"wattmeter": False,
"perf": True,
"rapl": False,
"sa": True,
"perf_dir": "/home/exp/.cache/exp",
"listen_port": 8080,
},
# i7-4790 -> i5-7300HQ
"i5": {
"experiments": [
#"impl-cipher-ver",
@ -219,43 +235,15 @@ CONFIGS = {
"rapl": True,
"sa": True,
"listen_port": 8080,
"idle": "idle - - - - - - - - - 1772446308.8950071 1772447508.8950853 1200.000078201294 0 1747 6555 2.4309999999999974 564883014 -",
"idle": "i5 idle - - - - - - - - - 1772446308.8950071 1772447508.8950853 1200.000078201294 0 1747 6555 2.4309999999999974 564883014 -",
"notify_listen": ("0.0.0.0", 8090),
"notify_addr": "192.168.3.1:8090",
"ld_preload": {
"openssl": "/home/tuxmain/reps/tlsbench/libssl.so:/home/tuxmain/reps/tlsbench/libcrypto.so",
},
"concurrency": "1",
},
"i5-local": {
"experiments": [
"impl-cipher-ver",
"impl-cert-ver",
"impl-kex-ver",
],
"sides": [
"client",
"server",
],
"tls": [
False,
True,
],
"records": [
{ "filename": "wikipedia", "repeat": 100 },
],
"repo_dir": "/home/exp/exp",
"exp_dir": "/dev/shm/exp",
"log_backup_dir": "/home/exp",
"local_addr": "127.0.0.1",
"remote_addr": "127.0.0.1",
"remote_repo_dir": "/home/exp/exp",
"wattmeter": False,
"perf": True,
"rapl": False,
"sa": True,
"perf_dir": "/home/exp/.cache/exp",
"listen_port": 8080,
"concurrency": "2",
"measure_both": False,
"target": "i5",
},
"g5k": {
"experiments": [
@ -294,12 +282,15 @@ CONFIGS = {
"rapl": False,
"sa": False,
"listen_port": 8080,
"idle": "idle - - - - - - - - - 1779276600 1779277200 600 0 222346 1105446 2.935994312264558 0 -",
"idle": "paradoxe-todo idle - - - - - - - - - 1779276600 1779277200 600 0 222346 1105446 2.935994312264558 0 -",
"notify_listen": ("0.0.0.0", 8090),
"notify_addr": "172.16.101.x:8090",
"ld_preload": {
"openssl": "/home/pengelib/openssl-openssl-3.6.1/libssl.so.3:/home/pengelib/openssl-openssl-3.6.1/libcrypto.so.3",
}
},
"measure_both": True,
"target": "paradoxe-x",
"controller_target": "paradoxe-x",
},
}
@ -756,6 +747,8 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False):
log_backup_dir = config["log_backup_dir"]
remote_path = config["remote_repo_dir"]
config_name = config["name"]
target = config["target"]
controller_target = config.get("controller_target")
wattmeter = None
if config["wattmeter"]:
errmsg = YRefParam()
@ -780,7 +773,7 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False):
logfile_name = "log-"+timestr
logfile_path = exp_dir+"/"+logfile_name
logfile = open(logfile_path, "w")
logfile.write("exp impl alg kex cipher ed side tls record n start stop time cpu bytes_in bytes_out Wh Wh_rapl prof\n")
logfile.write("target exp impl alg kex cipher ed side tls record n start stop time cpu bytes_in bytes_out Wh Wh_rapl prof\n")
logfile.close()
perf_dir = ""
@ -817,7 +810,7 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False):
while True:
try:
with open(logfile_path, "a") as logfile:
logfile.write(f"idle - - - - - - - - - {start} {end} {time_diff} 0 {remote_bytes_in_diff} {remote_bytes_out_diff} {energy_diff} {energy_rapl_diff} -\n")
logfile.write(f"{target} idle - - - - - - - - - {start} {end} {time_diff} 0 {remote_bytes_in_diff} {remote_bytes_out_diff} {energy_diff} {energy_rapl_diff} -\n")
logfile.close()
break
except Exception as e:
@ -951,8 +944,11 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False):
# Measure
cpu = 0
controller_cpu = 0
if config["sa"]:
cpu = get_cpu_stat(ssh, ["netreplay-"+impl, "tokio-runtime-w", "tokio-rt-worker"])
if config["measure_both"]:
controller_cpu = get_cpu_stat(None, ["netreplay-"+impl, "tokio-runtime-w", "tokio-rt-worker"])
remote_bytes_in, remote_bytes_out = get_net_stat(ssh)
energy = 0
energy_rapl = 0
@ -1004,11 +1000,15 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False):
# Measure CPU after (as it may update only after the process is killed)
new_cpu = 0
new_controller_cpu = 0
if config["sa"]:
new_cpu = get_cpu_stat(ssh, ["netreplay-"+impl, "tokio-runtime-w", "tokio-rt-worker"])
if config["measure_both"]:
new_controller_cpu = get_cpu_stat(None, ["netreplay-"+impl, "tokio-runtime-w", "tokio-rt-worker"])
record_filename = record["filename"]
cpu_diff = new_cpu - cpu
controller_cpu_diff = controller_new_cpu - controller_cpu
remote_bytes_in_diff = new_remote_bytes_in - remote_bytes_in
remote_bytes_out_diff = new_remote_bytes_out - remote_bytes_out
energy_diff = new_energy - energy
@ -1017,7 +1017,10 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False):
while True:
try:
with open(logfile_path, "a") as logfile:
logfile.write(f"{expname} {impl} {alg} {kex} {cipher} {earlydata} {side} {tls_int} {record_filename} {session_count} {start} {end} {time_diff} {cpu_diff} {remote_bytes_in_diff} {remote_bytes_out_diff} {energy_diff} {energy_rapl_diff} {prof_filename}\n")
logfile.write(f"{target} {expname} {impl} {alg} {kex} {cipher} {earlydata} {side} {tls_int} {record_filename} {session_count} {start} {end} {time_diff} {cpu_diff} {remote_bytes_in_diff} {remote_bytes_out_diff} {energy_diff} {energy_rapl_diff} {prof_filename}\n")
if config["measure_both"]:
other_side = "client" if side == "server" else "server"
logfile.write(f"{controller_target} {expname} {impl} {alg} {kex} {cipher} {earlydata} {other_side} {tls_int} {record_filename} {session_count} {start} {end} {time_diff} {controller_cpu_diff} {remote_bytes_out_diff} {remote_bytes_in_diff} 0 0 -\n")
logfile.close()
break
except Exception as e:

View file

@ -36,7 +36,7 @@ def fetch(site, node, start, stop, user, psw):
"w_avg": ws / (stop - start)
}
def insert_wh_into_logfile(path, site, node, user, psw):
def insert_wh_into_logfile(path, site, user, psw):
# Read
logfile = open(path, "r")
lines = logfile.readlines()
@ -44,9 +44,6 @@ def insert_wh_into_logfile(path, site, node, user, psw):
# Parse
colnames = lines[0].removesuffix("\n").split(" ")
col_start = colnames.index("start")
col_start = colnames.index("stop")
col_start = colnames.index("Wh")
logs = []
records = {}
@ -72,7 +69,7 @@ def insert_wh_into_logfile(path, site, node, user, psw):
# Modify
if col == "Wh" and (log[col] == "-" or log[col] == "0") and not abort:
try:
measure = fetch(site, node, float(log["start"]), float(log["stop"]), user, psw)
measure = fetch(site, log["target"], float(log["start"]), float(log["stop"]), user, psw)
log[col] = str(measure["Wh"])
except Exception as e:
print("Abort:", e)
@ -102,16 +99,15 @@ def get_psw():
def main():
if len(sys.argv) < 5:
print("Usage:")
print("python g5watt.py <user> <site> <node> <logfile_path>")
print("python g5watt.py <user> <site> <logfile_path>")
exit(0)
user = sys.argv[1]
site = sys.argv[2]
node = sys.argv[3]
path = sys.argv[4]
path = sys.argv[3]
psw = get_psw()
insert_wh_into_logfile(path, site, node, user, psw)
insert_wh_into_logfile(path, site, user, psw)
if __name__ == "__main__":
main()

View file

@ -67,13 +67,13 @@ CRITERION_TITLE = {
"ed": "0-RTT",
}
PRETTY_TABLE = {
"pi3": "$\\pi$3",
"pi3": "Pi",
"wp2": "WP",
"yt2-ads": "YT",
"yt2-ublock": "YT+µ",
}
PRETTY_TABLE_GNUPLOT = {
"pi3": "$\\\\pi$3",
"pi3": "Pi",
"wp2": "WP",
"yt2-ads": "YT",
"yt2-ublock": "YT+µ",
@ -1180,15 +1180,15 @@ def make_summary_plot(logs_by_target):
print(tabulate(lines))
print()
print("\
\\multicolumn{1}{|c|}{\\textbf{Target}}&\
\\multicolumn{1}{|c|}{\\textbf{Idle}}&\
\\multicolumn{1}{|c|}{\\textbf{Record}}&\
\\multicolumn{1}{|c|}{\\textbf{Side}}&\
\\multicolumn{1}{|c|}{\\textbf{Energy}}&\
\\multicolumn{1}{|c|}{\\multirow{2}*{\\textbf{Target}}}&\
\\multicolumn{1}{|c|}{\\multirow{2}*{\\textbf{Idle (W)}}}&\
\\multicolumn{1}{|c|}{\\multirow{2}*{\\textbf{Record}}}&\
\\multicolumn{1}{|c|}{\\multirow{2}*{\\textbf{Side}}}&\
\\multicolumn{1}{|c|}{\\multirow{2}*{\\textbf{Energy (J)}}}&\
\\multicolumn{2}{|c|}{\\textbf{Traffic}}\
\\\\")
print("\\cline{6-7}&&&&&\\multicolumn{1}{|c|}{(MB)}&\\multicolumn{1}{|c|}{(J)}\\\\")
latex_lines = {}
latex_keys = []
for log in results:
@ -1198,13 +1198,13 @@ def make_summary_plot(logs_by_target):
latex_keys.append(key)
latex_lines[key] = [
PRETTY_TABLE.get(log["target"], log["target"]),
"${}$W".format(roundz(log["idle_energy"], 2)),
"${}$".format(roundz(log["idle_energy"], 2)),
PRETTY_TABLE[log["record"]],
log["side"],
"${}$J".format(roundz(log["plain_energy"], 2)),
"${}$MB".format(roundz(log["plain_io"]/1024**2, 1)),
#"${}$J".format(roundz(log["plain_io"] * WS_PER_BYTE, 2))
"${}$J".format(int(log["plain_io"] * WS_PER_BYTE))
"${}$".format(roundz(log["plain_energy"], 2)),
"${}$".format(roundz(log["plain_io"]/1024**2, 1)),
#"${}$".format(roundz(log["plain_io"] * WS_PER_BYTE, 2))
"${}$".format(int(log["plain_io"] * WS_PER_BYTE))
]
latex_keys.sort()
last = None
@ -1237,7 +1237,7 @@ def make_summary_plot(logs_by_target):
if last[3] == latex_lines[key][3]:
cline = 5
print(f"\cline{{{cline}-7}} " + " & ".join(line) + "\\\\")
print(f"\\cline{{{cline}-7}} " + " & ".join(line) + "\\\\")
last = latex_lines[key]
key_i += 1