2020-06-24 15:37:15 +00:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
2020-06-26 06:52:56 +00:00
|
|
|
from core.experiment import Experiment, ExperimentParameter, ExperimentParameter
|
2020-06-24 08:36:26 +00:00
|
|
|
from core.topo import Topo, TopoParameter
|
|
|
|
|
2020-06-24 09:26:56 +00:00
|
|
|
from mininet_builder import MininetBuilder
|
2020-07-03 13:19:35 +00:00
|
|
|
from mininet.clean import cleanup
|
2020-06-24 09:26:56 +00:00
|
|
|
|
2020-06-26 06:52:56 +00:00
|
|
|
from experiments import EXPERIMENTS
|
2020-06-24 15:18:40 +00:00
|
|
|
from topos import TOPO_CONFIGS, TOPOS
|
2020-06-24 14:11:54 +00:00
|
|
|
|
2020-06-25 08:53:56 +00:00
|
|
|
import logging
|
2021-10-26 07:16:08 +00:00
|
|
|
import os
|
2021-03-05 09:36:24 +00:00
|
|
|
import subprocess
|
2020-07-03 13:19:35 +00:00
|
|
|
import traceback
|
2020-06-25 08:53:56 +00:00
|
|
|
|
2022-02-16 04:26:18 +00:00
|
|
|
|
2021-03-05 09:36:24 +00:00
|
|
|
def get_git_revision_short_hash():
|
2021-10-26 07:16:08 +00:00
|
|
|
# Because we might run Minitopo from elsewhere.
|
|
|
|
curr_dir = os.getcwd()
|
|
|
|
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
os.chdir(ROOT_DIR)
|
2022-02-16 04:26:18 +00:00
|
|
|
ret = subprocess.check_output(
|
|
|
|
['git', 'rev-parse', '--short', 'HEAD']).decode("unicode_escape").strip()
|
2021-10-26 07:16:08 +00:00
|
|
|
os.chdir(curr_dir)
|
|
|
|
return ret
|
2015-01-08 11:04:42 +00:00
|
|
|
|
2022-02-16 04:26:18 +00:00
|
|
|
|
2020-06-24 15:37:15 +00:00
|
|
|
class Runner(object):
|
2020-06-25 08:53:56 +00:00
|
|
|
"""
|
2020-06-26 06:52:56 +00:00
|
|
|
Run an experiment described by `experiment_parameter_file` in the topology
|
2020-06-25 08:53:56 +00:00
|
|
|
described by `topo_parameter_file` in the network environment built by
|
|
|
|
`builder_type`.
|
|
|
|
|
|
|
|
All the operations are done when calling the constructor.
|
|
|
|
"""
|
2022-02-16 04:26:18 +00:00
|
|
|
|
2020-06-26 06:52:56 +00:00
|
|
|
def __init__(self, builder_type, topo_parameter_file, experiment_parameter_file):
|
2022-02-16 04:26:18 +00:00
|
|
|
logging.info("Minitopo version {}".format(
|
|
|
|
get_git_revision_short_hash()))
|
2020-06-25 08:53:56 +00:00
|
|
|
self.topo_parameter = TopoParameter(topo_parameter_file)
|
|
|
|
self.set_builder(builder_type)
|
2020-06-29 14:02:17 +00:00
|
|
|
self.apply_topo()
|
|
|
|
self.apply_topo_config()
|
2020-06-25 08:53:56 +00:00
|
|
|
self.start_topo()
|
2020-06-26 06:52:56 +00:00
|
|
|
self.run_experiment(experiment_parameter_file)
|
2020-06-25 08:53:56 +00:00
|
|
|
self.stop_topo()
|
|
|
|
|
|
|
|
def set_builder(self, builder_type):
|
|
|
|
"""
|
|
|
|
Currently the only builder type supported is Mininet...
|
|
|
|
"""
|
|
|
|
if builder_type == Topo.MININET_BUILDER:
|
|
|
|
self.topo_builder = MininetBuilder()
|
2020-06-24 15:18:40 +00:00
|
|
|
else:
|
2022-02-16 04:26:18 +00:00
|
|
|
raise Exception(
|
|
|
|
"I can not find the builder {}".format(builder_type))
|
2020-06-25 08:53:56 +00:00
|
|
|
|
2020-06-29 14:02:17 +00:00
|
|
|
def apply_topo(self):
|
2020-06-25 08:53:56 +00:00
|
|
|
"""
|
|
|
|
Matches the name of the topo and find the corresponding Topo class.
|
|
|
|
"""
|
|
|
|
t = self.topo_parameter.get(Topo.TOPO_ATTR)
|
2020-06-24 15:18:40 +00:00
|
|
|
if t in TOPOS:
|
2020-06-25 08:53:56 +00:00
|
|
|
self.topo = TOPOS[t](self.topo_builder, self.topo_parameter)
|
2020-06-24 15:18:40 +00:00
|
|
|
else:
|
|
|
|
raise Exception("Unknown topo: {}".format(t))
|
|
|
|
|
2020-06-25 08:53:56 +00:00
|
|
|
logging.info("Using topo {}".format(self.topo))
|
|
|
|
|
2020-06-29 14:02:17 +00:00
|
|
|
def apply_topo_config(self):
|
2020-06-25 08:53:56 +00:00
|
|
|
"""
|
|
|
|
Match the name of the topo and find the corresponding TopoConfig class.
|
|
|
|
"""
|
|
|
|
t = self.topo_parameter.get(Topo.TOPO_ATTR)
|
2020-06-24 15:18:40 +00:00
|
|
|
if t in TOPO_CONFIGS:
|
2020-06-25 08:53:56 +00:00
|
|
|
self.topo_config = TOPO_CONFIGS[t](self.topo, self.topo_parameter)
|
2020-06-24 15:18:40 +00:00
|
|
|
else:
|
|
|
|
raise Exception("Unknown topo config: {}".format(t))
|
|
|
|
|
2020-06-25 08:53:56 +00:00
|
|
|
logging.info("Using topo config {}".format(self.topo_config))
|
2020-06-24 15:18:40 +00:00
|
|
|
|
2020-06-25 08:53:56 +00:00
|
|
|
def start_topo(self):
|
|
|
|
"""
|
|
|
|
Initialize the topology with its configuration
|
|
|
|
"""
|
|
|
|
self.topo.start_network()
|
|
|
|
self.topo_config.configure_network()
|
|
|
|
|
2020-06-26 06:52:56 +00:00
|
|
|
def run_experiment(self, experiment_parameter_file):
|
2020-06-25 08:53:56 +00:00
|
|
|
"""
|
|
|
|
Match the name of the experiement and launch it
|
|
|
|
"""
|
2020-06-26 06:52:56 +00:00
|
|
|
# Well, we need to load twice the experiment parameters, is it really annoying?
|
2022-02-16 04:26:18 +00:00
|
|
|
xp = ExperimentParameter(experiment_parameter_file).get(
|
|
|
|
ExperimentParameter.XP_TYPE)
|
2020-06-26 06:52:56 +00:00
|
|
|
if xp in EXPERIMENTS:
|
2022-02-16 04:26:18 +00:00
|
|
|
exp = EXPERIMENTS[xp](experiment_parameter_file,
|
|
|
|
self.topo, self.topo_config)
|
2020-06-25 13:56:14 +00:00
|
|
|
exp.classic_run()
|
2020-06-24 15:18:40 +00:00
|
|
|
else:
|
2020-06-26 06:52:56 +00:00
|
|
|
raise Exception("Unknown experiment {}".format(xp))
|
2020-06-24 15:18:40 +00:00
|
|
|
|
2020-06-25 08:53:56 +00:00
|
|
|
def stop_topo(self):
|
|
|
|
"""
|
|
|
|
Stop the topology
|
|
|
|
"""
|
|
|
|
self.topo.stop_network()
|
2020-06-24 15:37:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description="Minitopo, a wrapper of Mininet to run multipath experiments")
|
|
|
|
|
|
|
|
parser.add_argument("--topo_param_file", "-t", required=True,
|
2022-02-16 04:26:18 +00:00
|
|
|
help="path to the topo parameter file")
|
2020-06-26 06:52:56 +00:00
|
|
|
parser.add_argument("--experiment_param_file", "-x",
|
2022-02-16 04:26:18 +00:00
|
|
|
help="path to the experiment parameter file")
|
2020-06-24 15:37:15 +00:00
|
|
|
|
|
|
|
args = parser.parse_args()
|
2020-06-25 08:53:56 +00:00
|
|
|
|
2022-02-16 04:26:18 +00:00
|
|
|
logging.basicConfig(
|
|
|
|
format="%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s", level=logging.INFO)
|
2020-06-25 08:53:56 +00:00
|
|
|
|
2020-06-24 15:37:15 +00:00
|
|
|
# XXX Currently, there is no alternate topo builder...
|
2020-07-03 13:19:35 +00:00
|
|
|
try:
|
2022-02-16 04:26:18 +00:00
|
|
|
Runner(Topo.MININET_BUILDER, args.topo_param_file,
|
|
|
|
args.experiment_param_file)
|
2020-07-03 13:19:35 +00:00
|
|
|
except Exception as e:
|
|
|
|
logging.fatal("A fatal error occurred: {}".format(e))
|
|
|
|
traceback.print_exc()
|
|
|
|
finally:
|
|
|
|
# Always cleanup Mininet
|
|
|
|
logging.info("cleanup mininet")
|
2022-02-16 04:26:18 +00:00
|
|
|
cleanup()
|