-
Notifications
You must be signed in to change notification settings - Fork 1
/
config.py
149 lines (135 loc) · 7.5 KB
/
config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from collections import namedtuple
import agenda
import itertools
import random
import toml
import os
import sys
from util import *
def read_config(args):
agenda.task("Reading config file: {}".format(args.config))
with open(args.config) as f:
try:
config = toml.loads(f.read())
config['experiment_name'] = args.name #args.config.split(".toml")[0]
except Exception as e:
print(e)
fatal_error("Failed to parse config")
raise e
check_config(config)
bundler_root = config['structure']['bundler_root']
config['box_root'] = os.path.join(bundler_root, "bundler")
config['experiment_root'] = os.path.join(bundler_root, "experiments")
config['distribution_dir'] = os.path.join(bundler_root, 'distributions')
config['etg_client_path'] = os.path.join(config['structure']['bundler_root'], "empirical-traffic-gen/bin/etgClient")
config['etg_server_path'] = os.path.join(config['structure']['bundler_root'], "empirical-traffic-gen/run-servers.py")
config['experiment_dir'] = os.path.join(config['experiment_root'], config['experiment_name'])
config['local_experiment_dir'] = os.path.join("experiments", config['experiment_name'])
config['ccp_dir'] = os.path.join(bundler_root, 'ccp')
return config
def check_config(config):
agenda.task("Checking config file")
topology = config['topology']
if 'cloudlab' not in topology:
nodes = ['sender', 'inbox', 'outbox', 'receiver']
for node in nodes:
assert node in topology, "Missing key topology.{}".format(node)
assert 'name' in topology[node], "topology.{} is missing 'name' key".format(node)
assert 'ifaces' in topology[node], "topology.{} is missing 'ifaces' key".format(node)
assert len(topology[node]['ifaces']) > 0, "topology.{} must have at least 1 interface".format(node)
for i,iface in enumerate(topology[node]['ifaces']):
assert 'dev' in iface, "topology.{} iface {} is missing 'dev' key".format(node, i)
assert 'addr' in iface, "topology.{} iface {} is missing 'addr' key".format(node, i)
assert len(topology['inbox']['ifaces']) > 1, "topology.inbox must have at least 2 interaces"
assert 'listen_port' in topology['inbox'], "topology.inbox must define listen_port"
num_self = 0
for node in topology:
if 'self' in topology[node] and topology[node]['self']:
num_self += 1
assert num_self > 0, "One node in topology section must be labeled with \"self = true\""
assert num_self == 1, "Only one node in topology section can be labeled self"
else:
assert 'listen_port' in topology['inbox'], "topology.inbox must define listen_port"
nodes = ['sender', 'outbox', 'receiver']
for node in nodes:
assert node not in topology, "Don't use key topology.{} with cloudlab; it will be auto-populated".format(node)
for k in config['sysctl']:
v = config['sysctl'][k]
assert type(v) == str, "key names with dots must be enclosed in quotes (sysctl)"
parameters = ['initial_sample_rate', 'bg_port_start', 'bg_port_end', 'qdisc_buf_size', 'fifo_uplink', 'fifo_downlink']
for param in parameters:
assert param in config['parameters'], "parameters must include {}".format(param)
structure_fields = [
('bundler_root', 'root directory for all experiments and code'),
]
for (field,detail) in structure_fields:
assert field in config['structure'], "[structure] missing key '{}': {}".format(field, detail)
assert len(config['experiment']['seed']) > 0, "must specify at least one seed"
assert len(config['experiment']['sch']) > 0, "must specify at least one scheduler (sch)"
assert len(config['experiment']['alg']) > 0, "must specify at least one algorithm (alg)"
assert all('name' in a for a in config['experiment']['alg']), "algs must have key name"
assert len(config['experiment']['rate']) > 0, "must specify at least one rate"
assert len(config['experiment']['rtt']) > 0, "must specify at least one rtt"
assert len(config['experiment']['bdp']) > 0, "must specify at least one bdp"
assert 'bundle_traffic' in config['experiment'], "must specify at least one type of bundle traffic"
assert len(config['experiment']['bundle_traffic']) > 0, "must specify at least one type of bundle traffic"
assert 'cross_traffic' in config['experiment'], "must specify at least one type of cross traffic"
assert len(config['experiment']['cross_traffic']) > 0, "must specify at least one type of cross traffic"
sources = ['iperf', 'poisson', 'cbr']
for traffic_type in ['bundle_traffic', 'cross_traffic']:
for traffic in config['experiment'][traffic_type]:
for t in traffic:
print('traffic:', t)
assert t['source'] in sources, "{} traffic source must be one of ({})".format(traffic_type, "|".join(sources))
assert 'start_delay' in t, "{} missing start_delay (int)".format(traffic_type)
if t['source'] == 'iperf':
assert t['alg'], "{} missing 'alg' (str)".format(traffic_type)
assert t['flows'], "{} missing 'flows' (int)".format(traffic_type)
assert t['length'], "{} missing 'length' (int)".format(traffic_type)
if t['source'] == 'poisson':
assert t['conns'], "{} missing 'conns' (int)".format(traffic_type)
assert t['start_port'], "{} missing 'start_port' (int)".format(traffic_type)
assert t['reqs'], "{} missing 'reqs' (int)".format(traffic_type)
assert t['dist'], "{} missing 'dist' (str)".format(traffic_type)
assert t['load'], "{} missing 'load' (str)".format(traffic_type)
assert t['alg'], "{} missing 'alg' (str)".format(traffic_type)
assert 'backlogged' in t, "{} missing 'backlogged' (int)".format(traffic_type)
if t['source'] == 'cbr':
assert t['length'], "{} missing 'length (int)'".format(traffic_type)
assert t['port'], "{} missing 'port (int)'".format(traffic_type)
assert t['rate'], "{} missing 'rate (int)'".format(traffic_type)
def flatten(exps, dim):
def f(dct):
xs = [(k, dct[k]) for k in dct]
expl = [(a,b) for a,b in xs if type(b) == type([])]
done = [(a,b) for a,b in xs if type(b) != type([])]
if len(expl) > 0:
ks, bs = zip(*expl)
else:
ks, bs = ([], [])
bs = list(itertools.product(*bs))
expl = [dict(done + list(zip(ks, b))) for b in bs]
return expl
for e in exps:
es = f(e[dim])
for a in es:
n = e
n[dim] = a
yield n
def enumerate_experiments(config):
agenda.section("Starting experiments")
exp_args = config['experiment']
axes = list(exp_args.values())
ps = list(itertools.product(*axes))
exps = [dict(zip(exp_args.keys(), p)) for p in ps]
Experiment = namedtuple("Experiment", exp_args.keys())
exps = [Experiment(**x) for x in flatten(exps, 'alg')]
def skip_condition(_exp):
return \
(_exp.alg['name'] == 'nimbus' and _exp.sch == 'fifo') or\
(_exp.alg['name'] == 'nobundler' and _exp.sch != 'fifo')
#filtered_exps = [e for e in exps if not skip_condition(e)]
random.shuffle(exps)
return exps
#random.shuffle(filtered_exps)
#return filtered_exps