├── .github └── workflows │ └── build.yaml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── benchmark.py ├── contrib ├── go_ctrl │ ├── go.mod │ ├── go.sum │ └── go_ctrl.go ├── install_go_ctrl.sh └── install_goben.sh ├── control_test.py ├── dc_gym ├── __init__.py ├── control │ ├── Makefile │ ├── __init__.py │ ├── bw_control.c │ ├── ctrl_common.h │ ├── fq.c │ ├── go_ctrl │ ├── htb.c │ ├── iroko_bw_control.py │ ├── node_controller.c │ ├── raw_udp_socket.c │ ├── raw_udp_socket.h │ └── tbf.c ├── env_iroko.py ├── goben ├── inputs │ ├── dumbbell │ │ ├── incast_1024 │ │ ├── incast_128 │ │ ├── incast_16 │ │ ├── incast_2 │ │ ├── incast_256 │ │ ├── incast_32 │ │ ├── incast_4 │ │ ├── incast_512 │ │ ├── incast_64 │ │ └── incast_8 │ ├── fattree │ │ ├── all_to_all_data │ │ ├── all_to_all_data_exact │ │ ├── hotspot_one_to_one_data │ │ ├── random0_bij_data │ │ ├── random0_data │ │ ├── random1_bij_data │ │ ├── random1_data │ │ ├── random2_bij_data │ │ ├── random2_data │ │ ├── random3_bij_data │ │ ├── random3_data │ │ ├── random4_bij_data │ │ ├── random4_data │ │ ├── random_2_flows_data │ │ ├── random_3_flows_data │ │ ├── random_4_flows_data │ │ ├── random_5_flows_data │ │ ├── seed_interpod_test │ │ ├── stag_prob_0_1_0_data │ │ ├── stag_prob_0_2_3_data │ │ ├── stag_prob_0_5_3_data │ │ ├── stag_prob_1_2_3_data │ │ ├── stag_prob_1_5_3_data │ │ ├── stag_prob_2_2_3_data │ │ ├── stag_prob_2_5_3_data │ │ ├── stag_prob_3_2_3_data │ │ ├── stag_prob_3_5_3_data │ │ ├── stag_prob_4_2_3_data │ │ ├── stag_prob_4_5_3_data │ │ ├── stride1_data │ │ ├── stride2_data │ │ ├── stride4_data │ │ ├── stride8_data │ │ └── test │ └── nonblock ├── iroko_reward.py ├── iroko_sampler.py ├── iroko_state.py ├── iroko_traffic.py ├── monitor │ ├── .gitignore │ ├── Makefile │ ├── __init__.py │ ├── iroko_monitor.py │ ├── qdisc_stats.c │ └── test_qdisc_stats.py ├── topos │ ├── __init__.py │ ├── network_manager.py │ ├── topo_base.py │ ├── topo_dumbbell.py │ ├── topo_fattree.py │ └── topo_nonblock.py └── utils.py ├── do_install.sh ├── plot.py ├── pyproject.toml ├── ray_configs ├── appo.json ├── ddpg.json ├── ppo.json └── td3.json ├── run_basic.py ├── run_ray.py └── test_scalability.py /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: "build" 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | schedule: 8 | - cron: "0 13 * * 1" 9 | jobs: 10 | test-run-ray: 11 | runs-on: ubuntu-20.04 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Install 15 | run: | 16 | ./do_install.sh 17 | - name: Simple Test Run 18 | run: | 19 | sudo -E python3 run_ray.py --episodes 1 20 | test-benchmark: 21 | runs-on: ubuntu-20.04 22 | steps: 23 | - uses: actions/checkout@v1 24 | - name: Install 25 | run: | 26 | ./do_install.sh 27 | - name: Benchmark Run 28 | run: | 29 | sudo -E python3 benchmark.py --episodes 1 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################### Latex 2 | 3 | *.aux 4 | *.glo 5 | *.idx 6 | *.log 7 | *.toc 8 | *.ist 9 | *.acn 10 | *.acr 11 | *.alg 12 | *.bbl 13 | *.blg 14 | *.dvi 15 | *.glg 16 | *.gls 17 | *.ilg 18 | *.ind 19 | *.lof 20 | *.lot 21 | *.maf 22 | *.mtc 23 | *.mtc1 24 | *.out 25 | *.synctex.gz 26 | *.npy 27 | *.swp 28 | 29 | ################################################### Python 30 | 31 | # Byte-compiled / optimized / DLL files 32 | __pycache__/ 33 | *.py[cod] 34 | *$py.class 35 | 36 | # C extensions 37 | *.so 38 | 39 | **/*.o 40 | 41 | # Distribution / packaging 42 | .Python 43 | build/ 44 | develop-eggs/ 45 | dist/ 46 | downloads/ 47 | eggs/ 48 | .eggs/ 49 | # lib/ 50 | lib64/ 51 | parts/ 52 | sdist/ 53 | var/ 54 | wheels/ 55 | *.egg-info/ 56 | .installed.cfg 57 | *.egg 58 | MANIFEST 59 | 60 | # PyInstaller 61 | # Usually these files are written by a python script from a template 62 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 63 | *.manifest 64 | *.spec 65 | 66 | # Installer logs 67 | pip-log.txt 68 | pip-delete-this-directory.txt 69 | 70 | # Unit test / coverage reports 71 | htmlcov/ 72 | .tox/ 73 | .coverage 74 | .coverage.* 75 | .cache 76 | nosetests.xml 77 | coverage.xml 78 | *.cover 79 | .hypothesis/ 80 | 81 | # Translations 82 | *.mo 83 | *.pot 84 | 85 | # Django stuff: 86 | *.log 87 | .static_storage/ 88 | .media/ 89 | local_settings.py 90 | 91 | # Flask stuff: 92 | instance/ 93 | .webassets-cache 94 | 95 | # Scrapy stuff: 96 | .scrapy 97 | 98 | # Sphinx documentation 99 | docs/_build/ 100 | 101 | # PyBuilder 102 | target/ 103 | 104 | # Jupyter Notebook 105 | .ipynb_checkpoints 106 | 107 | # pyenv 108 | .python-version 109 | 110 | # celery beat schedule file 111 | celerybeat-schedule 112 | 113 | # SageMath parsed files 114 | *.sage.py 115 | 116 | # Environments 117 | .env 118 | .venv 119 | env/ 120 | venv/ 121 | ENV/ 122 | env.bak/ 123 | venv.bak/ 124 | 125 | # Spyder project settings 126 | .spyderproject 127 | .spyproject 128 | 129 | # Rope project settings 130 | .ropeproject 131 | 132 | # mkdocs documentation 133 | /site 134 | 135 | # mypy 136 | .mypy_cache/ 137 | 138 | ################################################### Misc 139 | .DS_Store 140 | *.sublime-workspace 141 | *.sublime-project 142 | sftp-config*.json 143 | results/ 144 | scalability_test/ 145 | *.lock 146 | data/ 147 | candidates/ 148 | plots/ 149 | dc_gym/control/node_control 150 | dc_gym/monitor/qdisc_stats 151 | *.ko 152 | contrib/go/ 153 | contrib/gopath/ 154 | control_test/ 155 | go/ 156 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mininet"] 2 | url = https://github.com/dcgym/mininet 3 | path = contrib/mininet 4 | ignore = dirty 5 | 6 | [submodule "goben"] 7 | url = https://github.com/dcgym/goben 8 | path = contrib/goben 9 | ignore = dirty 10 | 11 | [submodule "pcc"] 12 | url = https://github.com/PCCproject/PCC-Kernel 13 | path = contrib/pcc 14 | ignore = dirty 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Iroko: The Data Center RL Gym 2 | DISCLAIMER: This project is still very early stage research. It is not stable, well tested, and changes quickly. If you want to use this project, be warned. 3 | 4 | Iroko is an open source project that is focused on providing openAI compliant gyms. The aim is to develop machine learning algorithms that address data center problems and to fairly evaluate solutions again traditional techniques. 5 | 6 | A concrete description is available in our [Arxiv paper](https://arxiv.org/abs/1812.09975). A more elaborate version is presented in [this](https://open.library.ubc.ca/cIRcle/collections/ubctheses/24/items/1.0378362) master's thesis. There is also a published workshop paper on the topic: 7 | 8 | [*Iroko: A Framework to Prototype Reinforcement Learning for Data Center Traffic Control*](https://www.cs.ubc.ca/~bestchai/papers/iroko-nips18-workshop.pdf). Fabian Ruffy, Michael Przystupa, Ivan Beschastnikh. Workshop on ML for Systems at NIPS 2018. 9 | 10 | 11 | # Requirements 12 | The data center emulator makes heavy uses of Linux tooling and its networking features. It operates most reliably on a recent Linux kernel (`4.15+`) and is written in Python 3.6+. The supported platform is Ubuntu (at least `16.04` is required). Using the emulator requires full sudo access. 13 | 14 | # Package Dependencies 15 | - `GCC` or `Clang` and the `build-essentials` are required. 16 | - `git` for version control 17 | - `libnl-route-3-dev` to compile the traffic managers 18 | - `ifstat` and `tcpdump` to monitor traffic 19 | - `python3` and `python3-setuptools` to build Python packages and run the emulator 20 | 21 | ## Python Dependencies 22 | The generator supports only Python3. `pip3` can be used to install the packages. 23 | 24 | - `numpy` for matrix operations 25 | - `gym` to install openAI gym 26 | - `seaborn`, `pandas` and `matplotlib` to generate plots 27 | - `gevent` for lightweight threading 28 | 29 | ## Mininet Dependencies 30 | The datacenter networks are emulated using [Mininet](https://github.com/mininet/mininet). At minimum Mininet requires the installation of 31 | - `openvswitch-switch`, `cgroup-bin`, `help2man` 32 | 33 | ## Ray Dependencies 34 | The emulator uses [Ray](https://github.com/ray-project/ray) to implement and evaluate reinforcement learning algorithms. Ray's dependencies include: 35 | - Pip: `tensorflow`, `setproctitle`, `psutil`, `opencv-python`, `lz4` 36 | - Apt: `libsm6`, `libxext6`, `libxrender-dev` 37 | 38 | ## Goben Dependencies 39 | The emulator generates and measures traffic using [Goben](https://github.com/udhos/goben). While an amd64 binary is already provided in the repository, the generator submodule can also be compiled using `Go 1.11`. The `contrib/` folder contains a script to install Goben locally. 40 | 41 | # Installation 42 | A convenient, self-contained way to install the emulator is to run the `./install.sh`. It will install most dependencies locally via [Poetry](https://github.com/sdispater/poetry). 43 | 44 | # Run 45 | To test the emulator you can run `sudo -E python3 run_basic.py`. This is the most basic usage example of the Iroko environment. 46 | 47 | `run_ray.py` contains examples on how to use `Ray` with this project. 48 | 49 | `benchmark.py` is a test suite, which runs multiple tests in sequence and produces a comparison plot at the end of all runs. 50 | -------------------------------------------------------------------------------- /benchmark.py: -------------------------------------------------------------------------------- 1 | import os 2 | import datetime 3 | import time 4 | import socket 5 | import argparse 6 | 7 | import run_ray 8 | from plot import plot 9 | 10 | import dc_gym.utils as dc_utils 11 | 12 | import logging 13 | # Fix a bug introduced by an annoying Google extension 14 | import absl.logging 15 | try: 16 | logging.root.removeHandler(absl.logging._absl_handler) 17 | absl.logging._warn_preinit_stderr = False 18 | except Exception as e: 19 | print("Failed to fix absl logging bug", e) 20 | # configure logging 21 | logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.INFO) 22 | log = logging.getLogger(__name__) 23 | 24 | # set up paths 25 | exec_dir = os.getcwd() 26 | file_dir = os.path.dirname(__file__) 27 | OUTPUT_DIR = exec_dir + '/results' 28 | PLOT_DIR = exec_dir + '/plots' 29 | 30 | # RL Algorithms: PPO, APPO, DDPG, TD3, PG, A2C, RND 31 | # TCP Algorithms: TCP, DCTCP, TCP_NV, PCC 32 | RL_ALGOS = ["APPO", "TD3", "A2C"] 33 | TCP_ALGOS = ["DCTCP", "TCP_NV"] 34 | ALGOS = RL_ALGOS + TCP_ALGOS 35 | # Transport Protocols: tcp, udp 36 | TRANSPORT = ["udp", "tcp"] 37 | TF_PATTERNS = [0] 38 | RUNS = 1 39 | EPISODES = 60 40 | TOPO = "dumbbell" 41 | NETWORK_RATES = [10, 1000] 42 | TUNE = False 43 | 44 | 45 | def generate_testname(output_dir): 46 | n_folders = 0 47 | if os.path.isdir(output_dir): 48 | f_list = os.listdir(output_dir) 49 | n_folders = len(f_list) 50 | # Host name and a time stamp 51 | testname = "%s_%s" % (socket.gethostname(), n_folders) 52 | return testname 53 | 54 | 55 | def dump_config(args, path, pattern): 56 | test_config = {} 57 | test_config["transport"] = args.transports 58 | test_config["episodes"] = args.episodes 59 | test_config["runs"] = args.runs 60 | test_config["topology"] = args.topo 61 | test_config["tcp_algorithms"] = args.tcp_algos 62 | test_config["rl_algorithms"] = args.rl_algos 63 | test_config["rates"] = args.network_rates 64 | test_config["pattern"] = pattern 65 | # Get a string formatted time stamp 66 | ts = time.time() 67 | st = datetime.datetime.fromtimestamp(ts).strftime('%Y_%m_%d_%H_%M_%S') 68 | test_config["timestamp"] = st 69 | dc_utils.dump_json(path=path, name="bench_config", data=test_config) 70 | 71 | 72 | def launch_test(algo, results_subdir, transport, rate, topo, pattern, episodes): 73 | cmd = "-a %s " % algo 74 | cmd += "-e %d " % episodes 75 | cmd += "--output %s " % results_subdir 76 | cmd += "--topo %s " % topo 77 | if TUNE: 78 | cmd += "--tune " 79 | cmd += "--rate %d " % rate 80 | # always use TCP if we are dealing with a TCP algorithm 81 | cmd += "--transport %s " % transport 82 | cmd += "--pattern %d " % pattern 83 | log.info("Calling Ray command:") 84 | log.info("%s", cmd) 85 | run_ray.main(cmd.split()) 86 | 87 | 88 | def run_tests(args, results_dir, pattern, rate): 89 | for index in range(args.runs): 90 | for transport in args.transports: 91 | results_subdir = "%s/%s_run%d" % (results_dir, transport, index) 92 | for algo in args.rl_algos: 93 | launch_test(algo, results_subdir, transport, rate, 94 | args.topo, pattern, args.episodes) 95 | for algo in args.tcp_algos: 96 | results_subdir = "%s/%s_run%d" % (results_dir, "tcp", index) 97 | launch_test(algo, results_subdir, "tcp", rate, 98 | args.topo, pattern, args.episodes) 99 | 100 | 101 | def get_args(): 102 | p = argparse.ArgumentParser() 103 | p.add_argument('--rl_algos', 104 | dest='rl_algos', 105 | type=list, 106 | nargs='+', 107 | default=RL_ALGOS, 108 | help='The reinforcement learning algorithms to test.') 109 | p.add_argument('--tcp_algos', 110 | dest='tcp_algos', 111 | type=list, 112 | nargs='+', 113 | default=TCP_ALGOS, 114 | help='The TCP algorithms to test.') 115 | p.add_argument('--transports', 116 | dest='transports', 117 | type=list, 118 | nargs='+', 119 | default=TRANSPORT, 120 | help='The transport protocol choices to test.') 121 | p.add_argument('--traffic_patterns', 122 | dest='tf_patterns', 123 | type=list, 124 | nargs='+', 125 | default=TF_PATTERNS, 126 | help='The list of traffic patterns to use') 127 | p.add_argument('--network_rates', 128 | dest='network_rates', 129 | type=list, 130 | nargs='+', 131 | default=NETWORK_RATES, 132 | help='The link bandwidths of the network (Mbps) to test.') 133 | p.add_argument('--topo', 134 | '-t', 135 | dest='topo', 136 | type=str.lower, 137 | default=TOPO, 138 | help='The topology to operate on.') 139 | p.add_argument('--episodes', 140 | '-e', 141 | dest='episodes', 142 | type=int, 143 | default=EPISODES, 144 | help='Total number of episodes to train the RL agent.') 145 | p.add_argument('--runs', 146 | '-r', 147 | dest='runs', 148 | type=int, 149 | default=RUNS, 150 | help='Total number of repeated runs of this configuration.') 151 | p.add_argument('--output_dir', 152 | dest='output_dir', 153 | default=OUTPUT_DIR, 154 | help='Folder which contains all the collected metrics.') 155 | p.add_argument('--plot_dir', 156 | dest='plot_dir', 157 | default=PLOT_DIR, 158 | help='Folder where the plots will be saved.') 159 | p.add_argument('--tune', 160 | action="store_true", 161 | default=False, 162 | help='Specify whether to run the tune framework') 163 | return p.parse_args() 164 | 165 | 166 | def init(args): 167 | for pattern in args.tf_patterns: 168 | for rate in args.network_rates: 169 | testname = generate_testname(args.output_dir) 170 | results_dir = "%s/%s" % (args.output_dir, testname) 171 | log.info("Saving results to %s", results_dir) 172 | dc_utils.check_dir(results_dir) 173 | log.info("Dumping configuration in %s", results_dir) 174 | dump_config(args, results_dir, pattern) 175 | run_tests(args, results_dir, pattern, rate) 176 | # Plot the results and save the graphs under the given test name 177 | plot(results_dir, args.plot_dir, testname) 178 | 179 | 180 | if __name__ == '__main__': 181 | args = get_args() 182 | # Start pre-defined tests 183 | init(args) 184 | -------------------------------------------------------------------------------- /contrib/go_ctrl/go.mod: -------------------------------------------------------------------------------- 1 | module go_ctrl 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/DamnWidget/godef v0.0.0-20160905114020-c8917eb96a3d // indirect 7 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect 8 | github.com/fatih/motion v0.0.0-20190527122956-41470362fad4 // indirect 9 | github.com/google/gopacket v1.1.17 10 | github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf // indirect 11 | github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4 // indirect 12 | github.com/nicksnyder/go-i18n v1.10.0 // indirect 13 | github.com/nsf/gocode v0.0.0-20190302080247-5bee97b48836 // indirect 14 | github.com/pelletier/go-toml v1.4.0 // indirect 15 | github.com/rogpeppe/godef v1.1.1 // indirect 16 | github.com/vishvananda/netlink v1.0.0 17 | github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect 18 | github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a // indirect 19 | golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 // indirect 20 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65 // indirect 21 | golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed // indirect 22 | golang.org/x/text v0.3.2 // indirect 23 | golang.org/x/tools v0.0.0-20190603231351-8aaa1484dc10 // indirect 24 | gopkg.in/alecthomas/gometalinter.v1 v1.2.1 // indirect 25 | gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect 26 | ) 27 | -------------------------------------------------------------------------------- /contrib/go_ctrl/go.sum: -------------------------------------------------------------------------------- 1 | 9fans.net/go v0.0.0-20181112161441-237454027057 h1:OcHlKWkAMJEF1ndWLGxp5dnJQkYM/YImUOvsBoz6h5E= 2 | 9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/DamnWidget/godef v0.0.0-20160905114020-c8917eb96a3d h1:gaMApdPZseZG2G51ZdlfXNTZpcZoAPyJCMaTb40gDdQ= 5 | github.com/DamnWidget/godef v0.0.0-20160905114020-c8917eb96a3d/go.mod h1:p2sX0sa9Ck/6LErtXBaxzzInBhUheqcXXt2XYeZh3cw= 6 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= 7 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/fatih/motion v0.0.0-20190527122956-41470362fad4 h1:g4GA9iRiXHcBKOAjgZi2HsLP5zD2bSXZE5VL/+3yNN8= 10 | github.com/fatih/motion v0.0.0-20190527122956-41470362fad4/go.mod h1:pseIrV+t9A4+po+KJ1LheSnYH8m1qs6WhKx2zFiGi9I= 11 | github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= 12 | github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= 13 | github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= 14 | github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= 15 | github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4 h1:gmIVMdGlVf5e6Yo6+ZklxdOrvtOvyrAjJyXAbmOznyo= 16 | github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4/go.mod h1:t4Tr0tn92eq5ISef4cS5plFAMYAqZlAXtgUcKE6y8nw= 17 | github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q= 18 | github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= 19 | github.com/nsf/gocode v0.0.0-20190302080247-5bee97b48836 h1:oc3CL18CoGhyOQJ7HDa9gJAde33bwI8Vi28zLdIzJVc= 20 | github.com/nsf/gocode v0.0.0-20190302080247-5bee97b48836/go.mod h1:6Q8/OMaaKAgTX7/jt2bOXVDrm1eJhoNd+iwzghR7jvs= 21 | github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg= 22 | github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= 23 | github.com/rogpeppe/godef v1.1.1 h1:NujOtt9q9vIClRTB3sCZpavac+NMRaIayzrcz1h4fSE= 24 | github.com/rogpeppe/godef v1.1.1/go.mod h1:oEo1eMy1VUEHUzUIX4F7IqvMJRiz9UId44mvnR8oPlQ= 25 | github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM= 26 | github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= 27 | github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= 28 | github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= 29 | github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a h1:00UFliGZl2UciXe8o/2iuEsRQ9u7z0rzDTVzuj6EYY0= 30 | github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a/go.mod h1:ofmGw6LrMypycsiWcyug6516EXpIxSbZ+uI9ppGypfY= 31 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 32 | golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 33 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 34 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 35 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ= 36 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 37 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 38 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 39 | golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998= 40 | golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 41 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 42 | golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed h1:uPxWBzB3+mlnjy9W58qY1j/cjyFjutgw/Vhan2zLy/A= 43 | golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 44 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 45 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 46 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 47 | golang.org/x/tools v0.0.0-20181130195746-895048a75ecf/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 48 | golang.org/x/tools v0.0.0-20181207195948-8634b1ecd393/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 49 | golang.org/x/tools v0.0.0-20190603231351-8aaa1484dc10 h1:9LyHDLeGJwq8p/x0xbF8aG63cLC6EDjlNbGYc7dacDc= 50 | golang.org/x/tools v0.0.0-20190603231351-8aaa1484dc10/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 51 | gopkg.in/alecthomas/gometalinter.v1 v1.2.1 h1:au0U+I/O2t6EU8xSLYAjrFFdy5k9rEO/+YxeJRKGrAo= 52 | gopkg.in/alecthomas/gometalinter.v1 v1.2.1/go.mod h1:+HtZA9mve14tiBC2TPwjuAOssDAQ0kakuZthnpT+plw= 53 | gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c h1:vTxShRUnK60yd8DZU+f95p1zSLj814+5CuEh7NjF2/Y= 54 | gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= 55 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 56 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 57 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 58 | -------------------------------------------------------------------------------- /contrib/go_ctrl/go_ctrl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/binary" 5 | "flag" 6 | "log" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | "github.com/google/gopacket" 11 | "github.com/google/gopacket/layers" 12 | "github.com/google/gopacket/pcap" 13 | "github.com/vishvananda/netlink" 14 | ) 15 | 16 | var max_rate int 17 | 18 | 19 | func ctrl_loop(qdisc *netlink.Fq, packetSource *gopacket.PacketSource, handle *pcap.Handle) error { 20 | for packet := range packetSource.Packets() { 21 | app := packet.ApplicationLayer() 22 | rate := binary.LittleEndian.Uint32(app.Payload()) 23 | if err := change_qdisc(qdisc, rate); err != nil { 24 | return err 25 | } 26 | if err := send_response(handle, packet); err != nil { 27 | return err 28 | } 29 | } 30 | return nil 31 | } 32 | 33 | func send_response(handle *pcap.Handle, packet gopacket.Packet) error { 34 | if udplayer := packet.Layer(layers.LayerTypeUDP); udplayer != nil { 35 | udp := udplayer.(*layers.UDP) 36 | src_port := udp.SrcPort 37 | udp.SrcPort = udp.DstPort 38 | udp.DstPort = src_port 39 | if err := handle.WritePacketData(packet.Data()); err != nil { 40 | return err 41 | } 42 | } 43 | return nil 44 | } 45 | 46 | func change_qdisc(qdisc *netlink.Fq, rate uint32) error { 47 | qdisc.FlowMaxRate = rate / 8 48 | qdisc.Pacing = 1 49 | qdisc.InitialQuantum = (uint32(max_rate) / (8 * 10e6)) * 1500 50 | 51 | if err := netlink.QdiscChange(qdisc); err != nil { 52 | return err 53 | } 54 | return nil 55 | } 56 | 57 | func clean_all_qdiscs(ctrl_dev string) { 58 | link, err := netlink.LinkByName(ctrl_dev) 59 | if err != nil { 60 | log.Println(err) 61 | } 62 | qdiscs, err := netlink.QdiscList(link) 63 | if err != nil { 64 | log.Println(err) 65 | } 66 | if len(qdiscs) > 0 { 67 | for _, qdisc := range qdiscs { 68 | if err := netlink.QdiscDel(qdisc); err != nil { 69 | log.Println(err) 70 | } 71 | } 72 | } 73 | } 74 | 75 | func setup_qdisc(ctrl_dev string, rate uint32) (*netlink.Fq, error) { 76 | link, err := netlink.LinkByName(ctrl_dev) 77 | if err != nil { 78 | log.Println(err) 79 | return nil, err 80 | } 81 | qdisc := &netlink.Fq{ 82 | QdiscAttrs: netlink.QdiscAttrs{ 83 | LinkIndex: link.Attrs().Index, 84 | Handle: netlink.MakeHandle(1, 0), 85 | Parent: netlink.HANDLE_ROOT, 86 | }, 87 | FlowMaxRate: uint32(max_rate) / 8, 88 | Pacing: 1, 89 | InitialQuantum: (uint32(max_rate) / (8 * 10e6)) * 1500, 90 | } 91 | if err := netlink.QdiscAdd(qdisc); err != nil { 92 | return nil, err 93 | } 94 | return qdisc, nil 95 | } 96 | 97 | func set_exit_handler(qdisc *netlink.Fq) { 98 | c := make(chan os.Signal, 2) 99 | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) 100 | go func() { 101 | <-c 102 | log.Println("Handling interrupt...") 103 | exit_handler(qdisc) 104 | os.Exit(0) 105 | }() 106 | } 107 | 108 | func exit_handler(qdisc *netlink.Fq) { 109 | if err := netlink.QdiscDel(qdisc); err != nil { 110 | log.Println(err) 111 | } 112 | } 113 | 114 | func main() { 115 | var net_dev string 116 | var ctrl_dev string 117 | flag.StringVar(&net_dev, "n", "", 118 | "the interface attached to the main network") 119 | flag.StringVar(&ctrl_dev, "c", "", 120 | "the interface attached to the control network") 121 | flag.IntVar(&max_rate, "r", 0, 122 | "the maximum allowed sending rate in bps") 123 | flag.Parse() 124 | if net_dev == "" || ctrl_dev == "" { 125 | flag.Usage() 126 | os.Exit(1) 127 | } 128 | 129 | clean_all_qdiscs(net_dev) 130 | qdisc, err := setup_qdisc(net_dev, uint32(max_rate)); 131 | if err != nil { 132 | log.Println(err) 133 | os.Exit(1) 134 | } 135 | set_exit_handler(qdisc) 136 | 137 | handle, err := pcap.OpenLive(ctrl_dev, 1600, true, pcap.BlockForever) 138 | if err != nil { 139 | log.Println(err) 140 | os.Exit(1) 141 | } 142 | 143 | err = handle.SetBPFFilter("udp and port 20130") 144 | if err != nil { 145 | log.Println(err) 146 | os.Exit(1) 147 | } 148 | log.Println("Starting control loop...") 149 | packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) 150 | if err := ctrl_loop(qdisc, packetSource, handle); err != nil { 151 | log.Println(err) 152 | os.Exit(1) 153 | } 154 | if err := netlink.QdiscDel(qdisc); err != nil { 155 | log.Println(err) 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /contrib/install_go_ctrl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | GOARCH="$(dpkg --print-architecture)" 7 | GO_SRC="go1.12.linux-${GOARCH}.tar.gz" 8 | export GOPATH="$(pwd)/gopath" 9 | export GOROOT="$(pwd)/go" 10 | export PATH=${GOPATH}/bin:${GOROOT}/bin:${PATH} 11 | BIN="$(pwd)/go_ctrl/go_ctrl" 12 | 13 | wget https://dl.google.com/go/${GO_SRC} 14 | tar -xvf ${GO_SRC} 15 | cd go_ctrl 16 | go build 17 | cd .. 18 | chmod 775 ${BIN} 19 | mv ${BIN} $(pwd)/../dc_gym/control 20 | chmod -R 775 ${GOPATH} 21 | rm -rf ${GO_SRC} 22 | rm -rf ${GOPATH} 23 | rm -rf ${GOROOT} -------------------------------------------------------------------------------- /contrib/install_goben.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | GOARCH="$(dpkg --print-architecture)" 7 | GO_SRC="go1.12.linux-${GOARCH}.tar.gz" 8 | export GOPATH="$(pwd)/gopath" 9 | export GOROOT="$(pwd)/go" 10 | export PATH=${GOPATH}/bin:${GOROOT}/bin:${PATH} 11 | BIN="$(pwd)/goben/goben/goben" 12 | 13 | wget https://dl.google.com/go/${GO_SRC} 14 | tar -xvf ${GO_SRC} 15 | cd goben/goben 16 | go build 17 | cd ../.. 18 | chmod 775 ${BIN} 19 | mv ${BIN} $(pwd)/../dc_gym 20 | chmod -R 775 ${GOPATH} 21 | rm -rf ${GO_SRC} 22 | rm -rf ${GOPATH} 23 | rm -rf ${GOROOT} -------------------------------------------------------------------------------- /control_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | import ctypes 3 | import os 4 | import glob 5 | import numpy as np 6 | from mininet.topo import Topo 7 | from mininet.net import Mininet 8 | from mininet.log import setLogLevel 9 | from mininet.node import RemoteController 10 | from multiprocessing import RawArray 11 | 12 | from dc_gym.control.iroko_bw_control import BandwidthController 13 | import dc_gym.utils as dc_utils 14 | 15 | # configure logging 16 | import logging 17 | logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.INFO) 18 | log = logging.getLogger(__name__) 19 | 20 | 21 | class Ring(ctypes.Structure): 22 | pass 23 | 24 | 25 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 26 | SRC_PORT = 20130 27 | DST_PORT = 20130 28 | PACKET_RX_RING = 5 29 | PACKET_TX_RING = 13 30 | 31 | 32 | class TestTopo(Topo): 33 | def __init__(self, num_hosts=2): 34 | "The custom BlueBridge topo we use for testing." 35 | 36 | # Initialize topology 37 | Topo.__init__(self) 38 | 39 | switch = self.addSwitch('s1', failMode="standalone") 40 | for h in range(num_hosts): 41 | host = self.addHost('h%d' % (h), 42 | ip="10.0.0.%d/24" % (h + 1), 43 | mac='00:04:00:00:00:%02x' % h) 44 | self.addLink(host, switch) 45 | 46 | 47 | def connect_controller(net, host): 48 | controller = RemoteController("c") 49 | net.addController(controller) 50 | # Configure host 51 | net.addLink(controller, host) 52 | # Configure controller 53 | ctrl_iface = "c-eth0" 54 | return ctrl_iface 55 | 56 | 57 | def launch_ctrl_client(host, capacity): 58 | capacity = capacity 59 | ctrl_cmd = f"{FILE_DIR}/dc_gym/control/go_ctrl " 60 | ctrl_cmd += "-n %s " % host.intfList()[0] 61 | ctrl_cmd += "-c %s " % host.intfList()[1] 62 | ctrl_cmd += "-r %d " % capacity 63 | return dc_utils.start_process(ctrl_cmd, host) 64 | 65 | 66 | def launch_goben_server(host): 67 | traffic_cmd = f"{FILE_DIR}/dc_gym/goben " 68 | return dc_utils.start_process(traffic_cmd, host) 69 | 70 | 71 | def launch_goben_client(src_host, dst_host, in_rate): 72 | in_rate = in_rate / 1e6 # Goben operates on mbps 73 | # start the actual client 74 | traffic_cmd = f"{FILE_DIR}/dc_gym/goben --silent " 75 | traffic_cmd += "-totalDuration %s " % "inf" # infinite 76 | traffic_cmd += "-hosts %s " % dst_host.IP() 77 | traffic_cmd += "-maxSpeed %d " % in_rate # mbit 78 | traffic_cmd += "-passiveServer " 79 | traffic_cmd += "-udp " 80 | return dc_utils.start_process(traffic_cmd, src_host) 81 | 82 | 83 | def init_rate_control(ctrl_iface, rate): 84 | # Initialize the action array shared with the control manager 85 | tx_rate = RawArray(ctypes.c_uint32, 1) 86 | tx_rate = dc_utils.shmem_to_nparray(tx_rate, np.float32) 87 | tx_rate.fill(rate) 88 | bw_proc = BandwidthController({"test": ctrl_iface}, tx_rate, tx_rate, rate) 89 | bw_proc.start() 90 | return tx_rate, bw_proc 91 | 92 | 93 | def adjust_rate(ctrl_iface, rate=1e6): 94 | log.info(f"Setting rate to {rate}") 95 | bw_lib = ctypes.CDLL(f"{FILE_DIR}/dc_gym/control/libbw_control.so") 96 | bw_lib.init_ring.argtypes = [ 97 | ctypes.c_char_p, ctypes.c_ushort, ctypes.c_uint 98 | ] 99 | bw_lib.init_ring.restype = ctypes.POINTER(Ring) 100 | bw_lib.send_bw.argtypes = [ 101 | ctypes.c_uint32, 102 | ctypes.POINTER(Ring), ctypes.c_ushort 103 | ] 104 | bw_lib.send_bw.restype = ctypes.c_int 105 | bw_lib.wait_for_reply.argtypes = [ctypes.POINTER(Ring)] 106 | rx_ring = bw_lib.init_ring(ctrl_iface.encode("ascii"), SRC_PORT, 107 | PACKET_RX_RING) 108 | tx_ring = bw_lib.init_ring(ctrl_iface.encode("ascii"), SRC_PORT, 109 | PACKET_TX_RING) 110 | bw_lib.send_bw(int(rate), tx_ring, DST_PORT) 111 | bw_lib.wait_for_reply(rx_ring) 112 | 113 | 114 | def record_rate(in_rate, ctrl_rate, sleep, out_dir): 115 | # Convert to human readable format 116 | ctrl_rate = ctrl_rate * (in_rate / 1e3) 117 | in_rate = in_rate / 1e6 118 | log.info(f"Input: {in_rate} Mbps Expected: {ctrl_rate} kbps") 119 | log.info(f"Waiting for {sleep} seconds...") 120 | out_dir = "control_test" 121 | out_file = f"{out_dir}/{in_rate}mbps_in_{ctrl_rate}kbps_expected" 122 | dc_utils.check_dir(out_dir) 123 | ifstat_cmd = "ifstat -b " 124 | ifstat_cmd += "-i s1-eth1 " # interface to listen on 125 | ifstat_cmd += "-q 1 " # measurement interval 126 | ifstat_cmd += "%d " % sleep # measure how long 127 | return dc_utils.exec_process(ifstat_cmd, out_file=out_file) 128 | 129 | 130 | def generate_ctrl_rates(base_rate): 131 | ctrl_rates = [] 132 | ctrl_rates.extend([0.0001, 0.0005, 0.001, 0.005]) 133 | ctrl_rates.extend([0.01, 0.05, 0.1, 0.5, 1.0]) 134 | return np.array(ctrl_rates) 135 | 136 | 137 | def summarize(input_dir): 138 | with open(f"{input_dir}/summary.txt", 'w+') as summary_f: 139 | for out_file in glob.glob(f"{input_dir}/*.out"): 140 | file_name = os.path.splitext(out_file)[0] 141 | with open(out_file, 'r') as ifstat_file: 142 | summary_f.write(f"\n########## {file_name} ##########\n") 143 | items = ifstat_file.readlines() 144 | for item in items: 145 | summary_f.write(f"{item}") 146 | 147 | 148 | def main(): 149 | in_rates = [10e6, 100e6, 1000e6] 150 | ctrl_rates = [] 151 | out_dir = "control_test" 152 | sleep_per_test = 10 # seconds 153 | setLogLevel("info") 154 | topo = TestTopo(2) 155 | net = Mininet(topo=topo, controller=None) 156 | net.start() 157 | net.ping() 158 | hosts = net.hosts 159 | src_host = hosts[0] 160 | dst_host = hosts[1] 161 | ctrl_iface = connect_controller(net, src_host) 162 | server_proc = launch_goben_server(dst_host) 163 | time.sleep(2) 164 | for in_rate in in_rates: 165 | ctrl_proc = launch_ctrl_client(src_host, in_rate) 166 | tx_rate, bw_proc = init_rate_control(ctrl_iface, in_rate) 167 | time.sleep(0.5) 168 | ctrl_rates = generate_ctrl_rates(in_rate) 169 | client_proc = launch_goben_client(src_host, dst_host, in_rate) 170 | for ctrl_rate in ctrl_rates: 171 | log.info("#############################") 172 | tx_rate[0] = ctrl_rate 173 | dc_utils.start_process("tc qdisc show dev h0-eth0", src_host) 174 | record_rate(in_rate, ctrl_rate, sleep_per_test, out_dir) 175 | log.info("#############################") 176 | dc_utils.kill_processes([ctrl_proc, client_proc, bw_proc]) 177 | dc_utils.kill_processes([server_proc]) 178 | summarize(out_dir) 179 | net.stop() 180 | 181 | 182 | if __name__ == '__main__': 183 | main() 184 | -------------------------------------------------------------------------------- /dc_gym/__init__.py: -------------------------------------------------------------------------------- 1 | # from gym.envs.registration import register 2 | 3 | # register(id="dc-iroko-v0", entry_point="dc_gym.env_iroko:DCEnv") 4 | -------------------------------------------------------------------------------- /dc_gym/control/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS= -Wall -O3 -g 3 | LFLAGS= -lnl-3 -lnl-route-3 4 | QDISC=FQ 5 | QDISC_LOWER = $(shell echo $(QDISC) | tr A-Z a-z) 6 | DEPS = $(QDISC_LOWER).c raw_udp_socket.c raw_udp_socket.h 7 | LIBNAME=libbw_control.so 8 | 9 | all: bw_control node_control 10 | 11 | node_control: node_controller.c ${DEPS} 12 | $(CC) $(CFLAGS) $< ${DEPS} -o node_control -I /usr/include/libnl3/ $(LFLAGS) -DQDISC_$(QDISC) 13 | 14 | bw_control: bw_control.c ${DEPS} 15 | $(CC) $(CFLAGS) -fPIC -c raw_udp_socket.c -o raw_udp_socket.o $(LFLAGS) 16 | $(CC) $(CFLAGS) -fPIC -c $< -o bw_control.o $(LFLAGS) 17 | $(CC) $(CFLAGS) -shared bw_control.o raw_udp_socket.o -o $(LIBNAME) 18 | 19 | clean: 20 | rm -rf loadgen *.o node_control 21 | rm -rf loadgen *.o bw_control 22 | 23 | .PHONY: node_control bw_control 24 | -------------------------------------------------------------------------------- /dc_gym/control/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcgym/iroko/7941dd2a2d32d74cba11c1ea9118e9b23b8e1aa2/dc_gym/control/__init__.py -------------------------------------------------------------------------------- /dc_gym/control/bw_control.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "raw_udp_socket.h" 7 | 8 | static sig_atomic_t sigint = 0; 9 | static struct sigaction prev_handler; 10 | static uint16_t src_port; 11 | typedef void (*sighandler_t)(int); 12 | 13 | void fill_frame(uint8_t *ether_frame) { 14 | 15 | struct ethhdr *eth_hdr = (struct ethhdr *)((uint8_t *)ether_frame); 16 | struct iphdr *ip_hdr = (struct iphdr *)((uint8_t *)eth_hdr + ETH_HLEN); 17 | struct udphdr *udp_hdr = (struct udphdr *)((uint8_t *) ip_hdr + IP_HDRLEN); 18 | 19 | uint8_t src_mac[ETH_ALEN] = { 0xa0, 0x36, 0x9f, 0x45, 0xd8, 0x74 }; 20 | uint8_t dst_mac[ETH_ALEN] = { 0xa0, 0x36, 0x9f, 0x45, 0xd8, 0x75 }; 21 | 22 | // Destination and Source MAC addresses 23 | memcpy (eth_hdr->h_source, &src_mac, ETH_ALEN); 24 | memcpy (eth_hdr->h_dest, &dst_mac, ETH_ALEN); 25 | // Next is ethernet type code (ETH_P_IPV6 for IPv6). 26 | // http://www.iana.org/assignments/ethernet-numbers 27 | eth_hdr->h_proto = htons(ETH_P_IP); 28 | 29 | //Fill in the IP Header 30 | ip_hdr->ihl = 5; 31 | ip_hdr->version = 4; 32 | ip_hdr->tos = 0; 33 | ip_hdr->tot_len = IP_HDRLEN + UDP_HDRLEN; 34 | ip_hdr->id = htonl (54321); //Id of this packet 35 | ip_hdr->frag_off = 0; 36 | ip_hdr->ttl = 255; 37 | ip_hdr->protocol = IPPROTO_UDP; 38 | ip_hdr->check = 0; //Set to 0 before calculating checksum 39 | ip_hdr->saddr = htonl(INADDR_LOOPBACK); 40 | ip_hdr->daddr = htonl(INADDR_LOOPBACK); 41 | udp_hdr->source = htons(src_port); 42 | } 43 | 44 | int send_bw(uint32_t allocation, struct ring *ring_tx, uint16_t dst_port) { 45 | uint8_t ether_frame[100]; 46 | fill_frame(ether_frame); 47 | struct ethhdr *eth_hdr = (struct ethhdr *)ether_frame; 48 | struct iphdr *ip_hdr = (struct iphdr *)((uint8_t *)eth_hdr + ETH_HLEN); 49 | struct udphdr *udp_hdr = (struct udphdr *)((uint8_t *) ip_hdr + IP_HDRLEN); 50 | // Length of UDP datagram (16 bits): UDP header + UDP data 51 | udp_hdr->len = htons (UDP_HDRLEN + sizeof(uint32_t)); 52 | // Static UDP checksum 53 | udp_hdr->check = 0xFFAA; 54 | udp_hdr->dest = htons(dst_port); 55 | memcpy (ether_frame + HDRS_LEN, &allocation, sizeof(uint32_t)); 56 | int pkt_len = HDRS_LEN + sizeof(uint32_t); 57 | return send_pkt(ring_tx, ether_frame, pkt_len); 58 | } 59 | 60 | #ifdef PACKET_MMAPV2 61 | int walk_ring(struct ring *ring_rx) { 62 | char ifbuffer[IF_NAMESIZE]; 63 | char *ifname; 64 | while (likely(!sigint)) { 65 | struct tpacket2_hdr *hdr = ring_rx->rd[ring_rx->p_offset].iov_base; 66 | if (((hdr->tp_status & TP_STATUS_USER) == TP_STATUS_USER) == 0) { 67 | poll(&ring_rx->pfd, 1, -1); 68 | ifname = if_indextoname(ring_rx->ll.sll_ifindex, ifbuffer); 69 | if (!ifname) 70 | RETURN_ERROR(EXIT_FAILURE, "receive_packet"); 71 | continue; 72 | } 73 | hdr->tp_status = TP_STATUS_KERNEL; 74 | ring_rx->p_offset = (ring_rx->p_offset + 1) % ring_rx->rd_num; 75 | break; 76 | } 77 | return EXIT_SUCCESS; 78 | } 79 | #else 80 | void walk_block(struct block_desc *pbd, const int ring_offset) { 81 | int num_pkts = pbd->h1.num_pkts, i; 82 | struct tpacket3_hdr *ppd; 83 | 84 | ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + 85 | pbd->h1.offset_to_first_pkt); 86 | for (i = 0; i < num_pkts; ++i) { 87 | ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + 88 | ppd->tp_next_offset); 89 | } 90 | } 91 | 92 | void flush_block(struct block_desc *pbd) { 93 | pbd->h1.block_status = TP_STATUS_KERNEL; 94 | } 95 | 96 | void walk_ring(struct ring *ring_rx) { 97 | struct block_desc *pbd; 98 | while (likely(!sigint)) { 99 | pbd = (struct block_desc *) ring_rx->rd[ring_rx->p_offset].iov_base; 100 | 101 | if ((pbd->h1.block_status & TP_STATUS_USER) == 0) { 102 | poll(&ring_rx->pfd, 1, -1); 103 | continue; 104 | } 105 | walk_block(pbd, ring_rx->p_offset); 106 | flush_block(pbd); 107 | ring_rx->p_offset = (ring_rx->p_offset + 1) % 256; 108 | break; 109 | } 110 | } 111 | #endif 112 | 113 | 114 | void sighandler(int num) { 115 | sigint = 1; 116 | } 117 | 118 | void wait_for_reply(struct ring *ring_rx) { 119 | // Replace the signal handler with the internal C signal handler. 120 | signal(SIGINT, sighandler); 121 | // Wait for a packet. 122 | walk_ring(ring_rx); 123 | // We are done, restore the original handler. 124 | sigaction(SIGINT, &prev_handler, NULL ); 125 | // If we stopped because of an interrupt raise another one for Python. 126 | if (sigint) 127 | raise(SIGINT); 128 | } 129 | 130 | 131 | struct ring *init_ring(const char *iface, uint16_t filter_port, int ring_type) { 132 | // We save the current active signal handler 133 | sigaction(SIGINT, NULL, &prev_handler); 134 | 135 | struct ring *ring = init_raw_backend(iface, filter_port, ring_type); 136 | if (ring_type == PACKET_RX_RING) { 137 | memset(&ring->pfd, 0, sizeof(ring->pfd)); 138 | ring->pfd.fd = ring->socket; 139 | ring->pfd.events = POLLIN | POLLERR; 140 | ring->pfd.revents = 0; 141 | } 142 | if (ring_type == PACKET_TX_RING) { 143 | src_port = filter_port; 144 | } 145 | return ring; 146 | } 147 | 148 | void teardown_ring(struct ring *ring) { 149 | // Set up the rx and tx rings 150 | teardown_raw_backend(ring); 151 | } 152 | 153 | // int test() { 154 | // struct ring *ring_rx = init_ring("h1-eth0", 20135, PACKET_RX_RING); 155 | // struct ring *ring_tx = init_ring("h1-eth0", 20135, PACKET_TX_RING); 156 | // printf("SENDING PACKET\n"); 157 | // send_bw(100, ring_tx, 12321); 158 | // printf("WAITING...\n"); 159 | // wait_for_reply(ring_rx); 160 | // printf("WAITING DONE\n"); 161 | // teardown_ring(ring_rx); 162 | // teardown_ring(ring_tx); 163 | // return 0; 164 | // } -------------------------------------------------------------------------------- /dc_gym/control/ctrl_common.h: -------------------------------------------------------------------------------- 1 | #ifndef CTRL_COMMON_H 2 | #define CTRL_COMMON_H 3 | 4 | #include "raw_udp_socket.h" 5 | #include 6 | #include 7 | #include 8 | 9 | typedef struct ctrl_pckt { 10 | uint64_t tx_rate; 11 | } ctrl_pckt; 12 | 13 | 14 | #ifdef QDISC_FQ 15 | #define HANDLE_TYPE char 16 | #elif QDISC_TBF 17 | struct rtnl_qdisc; 18 | #define HANDLE_TYPE struct rtnl_qdisc 19 | #elif QDISC_HTB 20 | struct rtnl_qdisc; 21 | #define HANDLE_TYPE struct rtnl_qdisc 22 | #else 23 | #define HANDLE_TYPE void 24 | #endif 25 | 26 | int ctrl_set_bw(void *data, HANDLE_TYPE *ctrl_handle); 27 | HANDLE_TYPE *setup_qdisc(char *netdev, long rate); 28 | int clean_qdisc(HANDLE_TYPE *ctrl_handle); 29 | 30 | #endif // CTRL_COMMON_H -------------------------------------------------------------------------------- /dc_gym/control/fq.c: -------------------------------------------------------------------------------- 1 | #include "ctrl_common.h" 2 | 3 | #define HANDLE_TYPE char 4 | 5 | int ctrl_set_bw(void *data, HANDLE_TYPE *ctrl_handle) { 6 | char tc_cmd[200]; 7 | int err = 0; 8 | float tx_rate; 9 | ctrl_pckt *pkt; 10 | pkt = (ctrl_pckt *) data; 11 | tx_rate = pkt->tx_rate; 12 | // fprintf(stderr,"Host %s: tx_rate: %.3fmbit\n", iface, tx_rate / 10e5); 13 | snprintf(tc_cmd, 200,"tc qdisc change dev %s root fq maxrate %.3fmbit &", ctrl_handle, tx_rate / 10e5); 14 | // fprintf(stderr, "Host %s: tc_cmd: %s\n", iface, tc_cmd); 15 | err = system(tc_cmd); 16 | if (err) 17 | RETURN_ERROR(EXIT_FAILURE, "Problem with tc qdisc change"); 18 | return EXIT_SUCCESS; 19 | } 20 | 21 | HANDLE_TYPE *setup_qdisc(char *netdev, long rate){ 22 | int err = 0; 23 | char tc_cmd[200]; 24 | snprintf(tc_cmd, 200,"tc qdisc add dev %s root fq maxrate %lubit", netdev, rate); 25 | err = system(tc_cmd); 26 | if (err) 27 | RETURN_ERROR(NULL, "Problem with tc add"); 28 | return netdev; 29 | } 30 | 31 | 32 | int clean_qdisc(HANDLE_TYPE *ctrl_handle){ 33 | return EXIT_SUCCESS; 34 | } -------------------------------------------------------------------------------- /dc_gym/control/go_ctrl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcgym/iroko/7941dd2a2d32d74cba11c1ea9118e9b23b8e1aa2/dc_gym/control/go_ctrl -------------------------------------------------------------------------------- /dc_gym/control/htb.c: -------------------------------------------------------------------------------- 1 | struct rtnl_class *setup_class(struct nl_sock *qdisc_sock, const char *netdev, long rate){ 2 | struct rtnl_class *fq_class; 3 | int if_index; 4 | int err = 0; 5 | 6 | if_index = if_nametoindex(netdev); 7 | fq_class = rtnl_class_alloc(); 8 | rtnl_tc_set_ifindex(TC_CAST(fq_class), if_index); 9 | rtnl_tc_set_parent(TC_CAST(fq_class), TC_HANDLE(1,0)); 10 | rtnl_tc_set_handle(TC_CAST(fq_class), TC_HANDLE(1,1)); 11 | if ((err = rtnl_tc_set_kind(TC_CAST(fq_class), "htb"))) { 12 | printf("Can not allocate HTB\n"); 13 | exit (-1); 14 | } 15 | rtnl_htb_set_rate(fq_class, rate/8); 16 | // rtnl_htb_set_ceil(fq_class, 10e6); 17 | /* Submit request to kernel and wait for response */ 18 | if ((err = rtnl_class_add(qdisc_sock, fq_class, NLM_F_CREATE))) { 19 | printf("Can not allocate HTB Class\n"); 20 | return fq_class; 21 | } 22 | // rtnl_class_put(fq_class); 23 | return fq_class; 24 | } 25 | -------------------------------------------------------------------------------- /dc_gym/control/iroko_bw_control.py: -------------------------------------------------------------------------------- 1 | import os 2 | import ctypes 3 | import multiprocessing 4 | import logging 5 | log = logging.getLogger(__name__) 6 | 7 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 8 | 9 | SRC_PORT = 20130 10 | DST_PORT = 20130 11 | PACKET_RX_RING = 5 12 | PACKET_TX_RING = 13 13 | 14 | 15 | class Ring(ctypes.Structure): 16 | pass 17 | 18 | 19 | class BandwidthController(multiprocessing.Process): 20 | __slots__ = ["tx_rate", "active_rate", "max_rate", "name", "host_ctrl_map", 21 | "ring_list", "bw_lib", "kill"] 22 | 23 | def __init__(self, host_ctrl_map, tx_rate, active_rate, max_rate): 24 | self.name = "PolicyEnforcer" 25 | multiprocessing.Process.__init__(self) 26 | self.host_ctrl_map = host_ctrl_map 27 | self.tx_rate = tx_rate 28 | self.active_rate = active_rate 29 | self.max_rate = max_rate 30 | # self.sock_map = self.bind_sockets(host_ctrl_map) 31 | self.bw_lib = self.init_backend() 32 | self.ring_list = self.init_transmissions_rings(host_ctrl_map) 33 | self.kill = multiprocessing.Event() 34 | 35 | def run(self): 36 | while not self.kill.is_set(): 37 | try: 38 | self.broadcast_bw() 39 | except KeyboardInterrupt: 40 | log.error("%s: Caught Interrupt! Exiting..." % self.name) 41 | self.kill.set() 42 | self._clean() 43 | 44 | def stop(self): 45 | log.info("%s: Received termination signal! Exiting.." % self.name) 46 | self.kill.set() 47 | 48 | def close(self): 49 | self.stop() 50 | 51 | def _clean(self): 52 | pass 53 | 54 | def init_backend(self): 55 | bw_lib = ctypes.CDLL(FILE_DIR + "/libbw_control.so") 56 | bw_lib.init_ring.argtypes = [ 57 | ctypes.c_char_p, ctypes.c_ushort, ctypes.c_uint] 58 | bw_lib.init_ring.restype = ctypes.POINTER(Ring) 59 | bw_lib.send_bw.argtypes = [ 60 | ctypes.c_uint32, ctypes.POINTER(Ring), ctypes.c_ushort] 61 | bw_lib.send_bw.restype = ctypes.c_int 62 | bw_lib.wait_for_reply.argtypes = [ctypes.POINTER(Ring)] 63 | return bw_lib 64 | 65 | def init_transmissions_rings(self, host_ctrl_map): 66 | ring_list = {} 67 | for sw_iface, ctrl_iface in host_ctrl_map.items(): 68 | ring_list[sw_iface] = {} 69 | rx_ring = self.bw_lib.init_ring( 70 | ctrl_iface.encode("ascii"), SRC_PORT, PACKET_RX_RING) 71 | tx_ring = self.bw_lib.init_ring( 72 | ctrl_iface.encode("ascii"), SRC_PORT, PACKET_TX_RING) 73 | ring_list[sw_iface]["rx"] = rx_ring 74 | ring_list[sw_iface]["tx"] = tx_ring 75 | return ring_list 76 | 77 | def destroy_transmissions_rings(self): 78 | for ring_pair in self.ring_list.values(): 79 | self.bw_lib.teardown_ring(ring_pair["rx"]) 80 | self.bw_lib.teardown_ring(ring_pair["tx"]) 81 | 82 | def send_cntrl_pckt(self, iface, tx_rate): 83 | # Get the tx ring to transmit a packet 84 | tx_ring = self.ring_list[iface]["tx"] 85 | full_rate = tx_rate * self.max_rate 86 | ret = self.bw_lib.send_bw(int(full_rate), tx_ring, DST_PORT) 87 | return ret 88 | 89 | def await_response(self, iface): 90 | rx_ring = self.ring_list[iface]["rx"] 91 | # we do not care about payload 92 | # we only care about packets that pass the bpf filter 93 | self.bw_lib.wait_for_reply(rx_ring) 94 | 95 | def broadcast_bw(self): 96 | for index, ctrl_iface in enumerate(self.host_ctrl_map): 97 | if self.send_cntrl_pckt(ctrl_iface, self.active_rate[index]) != 0: 98 | log.error("Could not send packet!") 99 | self.kill.set() 100 | return 101 | for ctrl_iface in self.host_ctrl_map.keys(): 102 | self.await_response(ctrl_iface) 103 | # update the active rate 104 | self.active_rate[:] = self.tx_rate 105 | -------------------------------------------------------------------------------- /dc_gym/control/node_controller.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ctrl_common.h" 5 | 6 | #define CTRL_PORT 20130 7 | #define MTU 1500 8 | 9 | static sig_atomic_t sigint = 0; 10 | double MAX_RATE = 1e9; 11 | 12 | 13 | 14 | void handle_pkt(void *ppd_head, struct ring *ring_tx, HANDLE_TYPE *ctrl_handle) { 15 | 16 | #ifdef PACKET_MMAPV2 17 | struct tpacket2_hdr *ppd = (struct tpacket2_hdr *) ppd_head; 18 | #else 19 | struct tpacket3_hdr *ppd = (struct tpacket3_hdr *) ppd_head; 20 | #endif 21 | // Interpret rx packet headers 22 | struct ethhdr *eth_hdr = (struct ethhdr *)((uint8_t *) ppd + ppd->tp_mac); 23 | struct iphdr *ip_hdr = (struct iphdr *)((uint8_t *)eth_hdr + ETH_HLEN); 24 | struct udphdr *udp_hdr = (struct udphdr *)((uint8_t *) ip_hdr + IP_HDRLEN); 25 | uint8_t *data_rx = ((uint8_t *)eth_hdr + HDRS_LEN); 26 | uint16_t pkt_len = ppd->tp_snaplen; 27 | 28 | // set the bandwidth of the interface 29 | ctrl_set_bw(data_rx, ctrl_handle); 30 | 31 | // flip source and destination port 32 | uint16_t tmp_port = udp_hdr->dest; 33 | udp_hdr->dest = udp_hdr->source; 34 | udp_hdr->source = tmp_port; 35 | // bounce the flipped packet back 36 | send_pkt(ring_tx, (uint8_t *) eth_hdr, pkt_len); 37 | } 38 | 39 | #ifdef PACKET_MMAPV2 40 | static void walk_ring(struct ring *ring_rx, struct ring *ring_tx, HANDLE_TYPE *ctrl_handle) { 41 | memset(&ring_rx->pfd, 0, sizeof(ring_rx->pfd)); 42 | ring_rx->pfd.fd = ring_rx->socket; 43 | ring_rx->pfd.events = POLLIN | POLLERR; 44 | ring_rx->pfd.revents = 0; 45 | while (likely(!sigint)) { 46 | struct tpacket2_hdr *hdr = ring_rx->rd[ring_rx->p_offset].iov_base; 47 | if (((hdr->tp_status & TP_STATUS_USER) == TP_STATUS_USER) == 0) { 48 | poll(&ring_rx->pfd, 1, -1); 49 | if (ring_rx->pfd.revents & POLLERR) { 50 | perror("Error while polling"); 51 | exit(1); 52 | } 53 | continue; 54 | } 55 | handle_pkt(hdr, ring_tx, ctrl_handle); 56 | hdr->tp_status = TP_STATUS_KERNEL; 57 | ring_rx->p_offset = (ring_rx->p_offset + 1) % ring_rx->rd_num; 58 | } 59 | } 60 | #else 61 | static void walk_block(struct block_desc *pbd, const int block_num, struct ring *ring_tx, HANDLE_TYPE *ctrl_handle) { 62 | int num_pkts = pbd->h1.num_pkts, i; 63 | struct tpacket3_hdr *ppd; 64 | 65 | ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + 66 | pbd->h1.offset_to_first_pkt); 67 | for (i = 0; i < num_pkts; ++i) { 68 | handle_pkt(ppd, ring_tx, ctrl_handle); 69 | ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + 70 | ppd->tp_next_offset); 71 | } 72 | } 73 | 74 | static void flush_block(struct block_desc *pbd) { 75 | pbd->h1.block_status = TP_STATUS_KERNEL; 76 | } 77 | 78 | static void walk_ring(struct ring *ring_rx, struct ring *ring_tx, HANDLE_TYPE *ctrl_handle) { 79 | struct block_desc *pbd; 80 | memset(&ring_rx->pfd, 0, sizeof(ring_rx->pfd)); 81 | ring_rx->pfd.fd = ring_rx->socket; 82 | ring_rx->pfd.events = POLLIN | POLLERR; 83 | ring_rx->pfd.revents = 0; 84 | 85 | while (likely(!sigint)) { 86 | pbd = (struct block_desc *) ring_rx->rd[ring_rx->p_offset].iov_base; 87 | 88 | if ((pbd->h1.block_status & TP_STATUS_USER) == 0) { 89 | printf("waiting for packet\n"); 90 | poll(&ring_rx->pfd, 1, -1); 91 | if (ring_rx->pfd.revents & POLLERR) { 92 | perror("poll"); 93 | exit(1); 94 | } 95 | continue; 96 | } 97 | walk_block(pbd, ring_rx->p_offset, ring_tx, ctrl_handle); 98 | flush_block(pbd); 99 | ring_rx->p_offset = (ring_rx->p_offset + 1) % 256; 100 | } 101 | } 102 | #endif 103 | 104 | static void sighandler(int num) { 105 | sigint = 1; 106 | } 107 | 108 | int delete_qdisc(char *netdev) { 109 | char tc_cmd[200]; 110 | int err = 0; 111 | // delete the old qdisc on the device 112 | snprintf(tc_cmd, 200, "tc qdisc del dev %s root", netdev); 113 | err = system(tc_cmd); 114 | if (err) 115 | RETURN_ERROR(EXIT_FAILURE, "Problem with tc qdisc del"); 116 | return EXIT_SUCCESS; 117 | } 118 | 119 | void usage(char *prog_name){ 120 | printf("usage: %s [args]\n", prog_name); 121 | printf("-n - the interface attached to the main network\n"); 122 | printf("-c - the interface attached to the control network\n"); 123 | printf("-r - the initial rate of the controlling qdisc in bits\n"); 124 | exit(1); 125 | } 126 | 127 | int main(int argc, char **argv) { 128 | // process args 129 | char c; 130 | char *ctrldev = NULL; 131 | char *netdev = NULL; 132 | HANDLE_TYPE *ctrl_handle = NULL; 133 | char *prog_name = argv[0]; 134 | opterr = 0; 135 | while ((c = getopt(argc, argv, "n:c:r:")) != -1) { 136 | switch(c) 137 | { 138 | case 'n': 139 | netdev = optarg; 140 | break; 141 | case 'c': 142 | ctrldev = optarg; 143 | break; 144 | case 'r': 145 | MAX_RATE = atoll(optarg); 146 | break; 147 | case '?': 148 | printf("unknown option: %c\n", optopt); 149 | usage(prog_name); 150 | } 151 | } 152 | // Control and transmission devices are necessary 153 | if (!(netdev && ctrldev)) 154 | usage(prog_name); 155 | 156 | signal(SIGINT, sighandler); 157 | 158 | ctrl_handle = setup_qdisc(netdev, MAX_RATE); 159 | 160 | // Set up the rx and tx rings 161 | struct ring *ring_rx = init_raw_backend(ctrldev, CTRL_PORT, PACKET_RX_RING); 162 | struct ring *ring_tx = init_raw_backend(ctrldev, CTRL_PORT, PACKET_TX_RING); 163 | // Start main loop 164 | walk_ring(ring_rx, ring_tx, ctrl_handle); 165 | 166 | // Done with the loop, clean up 167 | teardown_raw_backend(ring_rx); 168 | teardown_raw_backend(ring_tx); 169 | 170 | // Clean up 171 | clean_qdisc(ctrl_handle); 172 | delete_qdisc(netdev); 173 | 174 | return EXIT_SUCCESS; 175 | } 176 | -------------------------------------------------------------------------------- /dc_gym/control/raw_udp_socket.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "raw_udp_socket.h" 10 | 11 | 12 | // Super shitty hack. Do not try this at home kids. 13 | int set_packet_filter(int sd, const char *iface, int port) { 14 | struct sock_fprog filter; 15 | int i, lineCount = 0; 16 | char cmd[512]; 17 | FILE* tcpdump_output; 18 | sprintf(cmd, "tcpdump -i %s dst port %d and udp -ddd", iface, port); 19 | // printf("Active Filter: %s\n",cmd ); 20 | if ( (tcpdump_output = popen(cmd, "r")) == NULL ) 21 | RETURN_ERROR(EXIT_FAILURE, "Cannot compile filter using tcpdump."); 22 | if (fscanf(tcpdump_output, "%d\n", &lineCount) < 1 ) 23 | RETURN_ERROR(EXIT_FAILURE, "cannot read lineCount."); 24 | filter.filter = (struct sock_filter *)calloc(1, sizeof(struct sock_filter)*lineCount); 25 | filter.len = lineCount; 26 | for (i = 0; i < lineCount; i++) { 27 | if (fscanf(tcpdump_output, "%u %u %u %u\n", (unsigned int *)&(filter.filter[i].code),(unsigned int *) &(filter.filter[i].jt),(unsigned int *) &(filter.filter[i].jf), &(filter.filter[i].k)) < 4 ) { 28 | free(filter.filter); 29 | RETURN_ERROR(EXIT_FAILURE, "fscanf: error in reading"); 30 | } 31 | setsockopt(sd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); 32 | } 33 | pclose(tcpdump_output); 34 | free(filter.filter); 35 | return EXIT_SUCCESS; 36 | } 37 | 38 | static int init_socket(int ver, const char *netdev) { 39 | int ret, sock = socket(AF_PACKET, SOCK_RAW, 0); 40 | if (sock == -1) { 41 | perror("socket"); 42 | exit(1); 43 | } 44 | 45 | ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver)); 46 | if (ret == -1) { 47 | perror("setsockopt"); 48 | exit(1); 49 | } 50 | return sock; 51 | } 52 | 53 | static void __v2_fill(struct ring *ring, unsigned int blocks) { 54 | ring->req.tp_block_size = getpagesize() << 2; 55 | ring->req.tp_frame_size = TPACKET_ALIGNMENT << 7; 56 | ring->req.tp_block_nr = blocks; 57 | 58 | ring->req.tp_frame_nr = ring->req.tp_block_size / 59 | ring->req.tp_frame_size * 60 | ring->req.tp_block_nr; 61 | 62 | ring->mm_len = ring->req.tp_block_size * ring->req.tp_block_nr; 63 | ring->rd_num = ring->req.tp_frame_nr; 64 | ring->flen = ring->req.tp_frame_size; 65 | } 66 | 67 | static void __v3_fill(struct ring *ring, unsigned int blocks, int type) { 68 | if (type == PACKET_RX_RING) { 69 | ring->req3.tp_retire_blk_tov = 64; 70 | ring->req3.tp_sizeof_priv = 0; 71 | ring->req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; 72 | } 73 | ring->req3.tp_block_size = getpagesize() << 2; 74 | ring->req3.tp_frame_size = TPACKET_ALIGNMENT << 7; 75 | ring->req3.tp_block_nr = blocks; 76 | 77 | ring->req3.tp_frame_nr = ring->req3.tp_block_size / 78 | ring->req3.tp_frame_size * 79 | ring->req3.tp_block_nr; 80 | 81 | ring->mm_len = ring->req3.tp_block_size * ring->req3.tp_block_nr; 82 | ring->rd_num = ring->req3.tp_block_nr; 83 | ring->flen = ring->req3.tp_block_size; 84 | } 85 | 86 | static void setup_ring(int sock, struct ring *ring, int version, int type) { 87 | int ret = 0; 88 | unsigned int blocks = 256; 89 | 90 | ring->type = type; 91 | 92 | switch (version) { 93 | case TPACKET_V2: 94 | __v2_fill(ring, blocks); 95 | ret = setsockopt(sock, SOL_PACKET, type, &ring->req, 96 | sizeof(ring->req)); 97 | break; 98 | 99 | case TPACKET_V3: 100 | __v3_fill(ring, blocks, type); 101 | ret = setsockopt(sock, SOL_PACKET, type, &ring->req3, 102 | sizeof(ring->req3)); 103 | break; 104 | } 105 | 106 | if (ret == -1) { 107 | perror("setsockopt"); 108 | exit(1); 109 | } 110 | ring->rd_len = ring->rd_num * sizeof(*ring->rd); 111 | ring->rd = malloc(ring->rd_len); 112 | if (ring->rd == NULL) { 113 | perror("malloc"); 114 | exit(1); 115 | } 116 | } 117 | 118 | static void mmap_ring(int sock, struct ring *ring) { 119 | 120 | ring->mm_space = mmap(0, ring->mm_len, PROT_READ | PROT_WRITE, 121 | MAP_SHARED | MAP_LOCKED | MAP_POPULATE, sock, 0); 122 | if (ring->mm_space == MAP_FAILED) { 123 | perror("mmap"); 124 | exit(1); 125 | } 126 | 127 | memset(ring->rd, 0, ring->rd_len); 128 | for (int i = 0; i < ring->rd_num; ++i) { 129 | ring->rd[i].iov_base = ring->mm_space + (i * ring->flen); 130 | ring->rd[i].iov_len = ring->flen; 131 | } 132 | } 133 | 134 | static void bind_ring(int sock, struct ring *ring, const char *iface, int port) { 135 | int ret; 136 | 137 | ring->ll.sll_family = AF_PACKET; 138 | ring->ll.sll_protocol = htons(ETH_P_ALL); 139 | ring->ll.sll_ifindex = if_nametoindex(iface); 140 | ring->ll.sll_hatype = 0; 141 | ring->ll.sll_pkttype = 0; 142 | ring->ll.sll_halen = 0; 143 | 144 | // if (ring->type == PACKET_RX_RING) { 145 | // int ret = set_packet_filter(ring->socket, iface, port); 146 | // if (ret == -1) { 147 | // perror("filter"); 148 | // exit(1); 149 | // } 150 | // } 151 | 152 | ret = bind(sock, (struct sockaddr *) &ring->ll, sizeof(ring->ll)); 153 | if (ret == -1) { 154 | perror("bind"); 155 | exit(1); 156 | } 157 | } 158 | 159 | static void unmap_ring(int sock, struct ring *ring) { 160 | munmap(ring->mm_space, ring->mm_len); 161 | free(ring->rd); 162 | } 163 | 164 | static inline int tx_kernel_ready(void *base) { 165 | #ifdef PACKET_MMAPV2 166 | struct tpacket2_hdr *hdr = (struct tpacket2_hdr *) base; 167 | #else 168 | struct tpacket3_hdr *hdr = (struct tpacket3_hdr *) base; 169 | #endif 170 | return !(hdr->tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING)); 171 | } 172 | 173 | static inline void *get_next_frame(struct ring *ring, int n) { 174 | #ifdef PACKET_MMAPV2 175 | return ring->rd[n].iov_base; 176 | #else 177 | uint8_t *f0 = ring->rd[0].iov_base; 178 | return f0 + (n * ring->req3.tp_frame_size); 179 | #endif 180 | } 181 | 182 | struct ring *init_raw_backend(const char *iface, int port, int type) { 183 | #ifdef PACKET_MMAPV2 184 | // fprintf(stderr, "Using tpacket_v2.\n"); 185 | int version = TPACKET_V2; 186 | #else 187 | int version = TPACKET_V3; 188 | #endif 189 | struct ring *ring = malloc(sizeof(struct ring)); 190 | memset(ring, 0, sizeof(struct ring)); 191 | ring->socket = init_socket(version, iface); 192 | if (type == PACKET_RX_RING) { 193 | int ret = set_packet_filter(ring->socket, iface, port); 194 | if (ret == -1) { 195 | perror("filter"); 196 | exit(1); 197 | } 198 | } 199 | setup_ring(ring->socket, ring, version, type); 200 | mmap_ring(ring->socket, ring); 201 | bind_ring(ring->socket, ring, iface, port); 202 | return ring; 203 | } 204 | 205 | void teardown_raw_backend(struct ring *ring) { 206 | unmap_ring(ring->socket, ring); 207 | close(ring->socket); 208 | free(ring); 209 | } 210 | 211 | int send_pkt(struct ring *ring, uint8_t *packet, size_t packet_len) { 212 | #ifdef PACKET_MMAPV2 213 | int nframes = ring->rd_num; 214 | struct tpacket2_hdr *next = get_next_frame(ring, ring->p_offset); 215 | #else 216 | struct tpacket3_hdr *next = get_next_frame(ring, ring->p_offset); 217 | int nframes = ring->req3.tp_frame_nr; 218 | #endif 219 | while (tx_kernel_ready(next) == 0) { 220 | ring->p_offset = (ring->p_offset + 1) % nframes; 221 | next = get_next_frame(ring, ring->p_offset); 222 | } 223 | // tx->tp_snaplen = packet_len; 224 | next->tp_len = packet_len; 225 | #ifdef PACKET_MMAPV2 226 | memcpy((uint8_t *)next + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll), packet, packet_len); 227 | #else 228 | next->tp_next_offset = 0; 229 | memcpy((uint8_t *)next + TPACKET3_HDRLEN - sizeof(struct sockaddr_ll), packet, packet_len); 230 | #endif 231 | 232 | next->tp_status = TP_STATUS_SEND_REQUEST; 233 | ring->p_offset = (ring->p_offset + 1) % nframes; 234 | int ret = sendto(ring->socket, NULL, 0, 0, NULL, 0); 235 | if (ret == -1) 236 | RETURN_ERROR(EXIT_FAILURE, "sendto:"); 237 | return EXIT_SUCCESS; 238 | } 239 | -------------------------------------------------------------------------------- /dc_gym/control/raw_udp_socket.h: -------------------------------------------------------------------------------- 1 | #ifndef RAW_UDP_SOCKET_H 2 | #define RAW_UDP_SOCKET_H 3 | #include // packet_mmap 4 | #include // Ethernet header declarations 5 | #include // IP header declarations 6 | #include // UDP header declarations 7 | #include // Linux version check 8 | #include // polling descriptors 9 | #include 10 | 11 | // Older kernel versions do not support TPACKET_V3. 12 | // Something is wrong with TPACKET_V3, so let's always use TPACKET_V2 for now. 13 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(4,15,0) 14 | #endif 15 | #define PACKET_MMAPV2 16 | 17 | // (unimportant) macro for loud failure 18 | // needs some love in the code 19 | #define RETURN_ERROR(lvl, msg) \ 20 | do { \ 21 | perror(msg); \ 22 | return lvl; \ 23 | } while(0); 24 | 25 | #ifndef likely 26 | # define likely(x) __builtin_expect(!!(x), 1) 27 | #endif 28 | #ifndef unlikely 29 | # define unlikely(x) __builtin_expect(!!(x), 0) 30 | #endif 31 | 32 | #define IP_HDRLEN sizeof(struct iphdr) // IP header length 33 | #define UDP_HDRLEN sizeof(struct udphdr) // UDP header length, excludes data 34 | #define HDRS_LEN ETH_HLEN + IP_HDRLEN + UDP_HDRLEN 35 | 36 | struct ring { 37 | struct iovec *rd; 38 | uint8_t *mm_space; 39 | size_t mm_len, rd_len; 40 | struct sockaddr_ll ll; 41 | void (*walk)(int sock, struct ring *ring); 42 | int type, rd_num, flen; 43 | int socket; // socket associated with ring 44 | struct pollfd pfd; // poll descriptor for associated socket 45 | int p_offset; // current offset in the ring 46 | union { 47 | struct tpacket_req req; 48 | struct tpacket_req3 req3; 49 | }; 50 | }; 51 | 52 | struct block_desc { 53 | uint32_t version; 54 | uint32_t offset_to_priv; 55 | struct tpacket_hdr_v1 h1; 56 | }; 57 | 58 | struct ring *init_raw_backend(const char *iface, int port, int type); 59 | void teardown_raw_backend(struct ring *ring); 60 | int send_pkt(struct ring *ring, uint8_t *packet, size_t packet_len); 61 | 62 | #endif // RAW_UDP_SOCKET_H -------------------------------------------------------------------------------- /dc_gym/control/tbf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ctrl_common.h" 9 | 10 | static struct nl_sock *qdisc_sock; 11 | 12 | int ctrl_set_bw(void *data, HANDLE_TYPE *ctrl_handle) { 13 | int err = 0; 14 | float tx_rate; 15 | ctrl_pckt *pkt; 16 | uint32_t burst; 17 | uint32_t limit; 18 | 19 | limit = 1530; 20 | burst = 5000; 21 | pkt = (ctrl_pckt *) data; 22 | tx_rate = pkt->tx_rate / 8.0; 23 | // used for debugging purposes 24 | // int old_rate = rtnl_qdisc_tbf_get_rate (fq_qdisc); 25 | // fprintf(stderr,"tx_rate: %.3fmbit old %.3fmbit\n", tx_rate* 8 / 1e6, 26 | // old_rate*8 / 1e6); 27 | // fprintf(stderr, "Burst %lu Limit %lu\n", burst, limit); 28 | rtnl_qdisc_tbf_set_rate(ctrl_handle, (uint32_t) tx_rate, burst , 0); 29 | rtnl_qdisc_tbf_set_peakrate(ctrl_handle, (uint32_t) tx_rate, burst, 0); 30 | // rtnl_qdisc_tbf_set_limit(ctrl_handle, limit); 31 | rtnl_qdisc_tbf_set_limit_by_latency(ctrl_handle, 0); 32 | err = rtnl_qdisc_add(qdisc_sock, ctrl_handle, NLM_F_REPLACE); 33 | if(err) { 34 | fprintf(stderr,"Rate %lu qdisc_add: %s\n", pkt->tx_rate, nl_geterror(err)); 35 | return EXIT_FAILURE; 36 | } 37 | return EXIT_SUCCESS; 38 | } 39 | 40 | HANDLE_TYPE *setup_qdisc(char *netdev, long rate){ 41 | struct rtnl_qdisc *fq_qdisc; 42 | int if_index; 43 | int err = 0; 44 | uint32_t burst = 12000; 45 | uint32_t limit = 1550; 46 | 47 | fprintf(stderr, "Kernel Clock Rate: %d\n", nl_get_user_hz()); 48 | qdisc_sock = nl_socket_alloc(); 49 | nl_connect(qdisc_sock, NETLINK_ROUTE); 50 | if_index = if_nametoindex(netdev); 51 | fq_qdisc = rtnl_qdisc_alloc(); 52 | rtnl_tc_set_ifindex(TC_CAST(fq_qdisc), if_index); 53 | rtnl_tc_set_parent(TC_CAST(fq_qdisc), TC_H_ROOT); 54 | rtnl_tc_set_handle(TC_CAST(fq_qdisc), TC_HANDLE(1,0)); 55 | rtnl_tc_set_mpu(TC_CAST(fq_qdisc), 0); 56 | rtnl_tc_set_mtu(TC_CAST(fq_qdisc), 1500); 57 | 58 | err = rtnl_tc_set_kind(TC_CAST(fq_qdisc), "tbf"); 59 | if (err) { 60 | fprintf(stderr,"Can not allocate TBF: %s\n", nl_geterror(err)); 61 | return NULL; 62 | } 63 | // fprintf(stderr, "Calculated limit: %lu \n", limit); 64 | rtnl_qdisc_tbf_set_rate(fq_qdisc, (uint32_t) rate, burst , 0); 65 | rtnl_qdisc_tbf_set_limit(fq_qdisc, limit); 66 | rtnl_qdisc_tbf_set_peakrate(fq_qdisc, (uint32_t) rate, burst, 0); 67 | err = rtnl_qdisc_add(qdisc_sock, fq_qdisc, NLM_F_CREATE); 68 | if (err) { 69 | fprintf(stderr,"Can not set TBF: %s\n", nl_geterror(err)); 70 | return NULL; 71 | } 72 | return fq_qdisc; 73 | } 74 | 75 | int clean_qdisc(HANDLE_TYPE *ctrl_handle) { 76 | nl_socket_free(qdisc_sock); 77 | nl_object_free((struct nl_object *) ctrl_handle); 78 | return EXIT_SUCCESS; 79 | } 80 | -------------------------------------------------------------------------------- /dc_gym/goben: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcgym/iroko/7941dd2a2d32d74cba11c1ea9118e9b23b8e1aa2/dc_gym/goben -------------------------------------------------------------------------------- /dc_gym/inputs/dumbbell/incast_128: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0,600,2147483647,exact,-1,0,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0,600,2147483647,exact,-1,0,exact 4 | 10.1.0.3,10.2.0.3,12345,2,0,600,2147483647,exact,-1,0,exact 5 | 10.1.0.4,10.2.0.4,12345,2,0,600,2147483647,exact,-1,0,exact 6 | 10.1.0.5,10.2.0.5,12345,2,0,600,2147483647,exact,-1,0,exact 7 | 10.1.0.6,10.2.0.6,12345,2,0,600,2147483647,exact,-1,0,exact 8 | 10.1.0.7,10.2.0.7,12345,2,0,600,2147483647,exact,-1,0,exact 9 | 10.1.0.8,10.2.0.8,12345,2,0,600,2147483647,exact,-1,0,exact 10 | 10.1.0.9,10.2.0.9,12345,2,0,600,2147483647,exact,-1,0,exact 11 | 10.1.0.10,10.2.0.10,12345,2,0,600,2147483647,exact,-1,0,exact 12 | 10.1.0.11,10.2.0.11,12345,1,0,600,2147483647,exact,-1,0,exact 13 | 10.1.0.12,10.2.0.12,12345,2,0,600,2147483647,exact,-1,0,exact 14 | 10.1.0.13,10.2.0.13,12345,2,0,600,2147483647,exact,-1,0,exact 15 | 10.1.0.14,10.2.0.14,12345,2,0,600,2147483647,exact,-1,0,exact 16 | 10.1.0.15,10.2.0.15,12345,2,0,600,2147483647,exact,-1,0,exact 17 | 10.1.0.16,10.2.0.16,12345,2,0,600,2147483647,exact,-1,0,exact 18 | 10.1.0.17,10.2.0.17,12345,2,0,600,2147483647,exact,-1,0,exact 19 | 10.1.0.18,10.2.0.18,12345,2,0,600,2147483647,exact,-1,0,exact 20 | 10.1.0.19,10.2.0.19,12345,2,0,600,2147483647,exact,-1,0,exact 21 | 10.1.0.20,10.2.0.20,12345,2,0,600,2147483647,exact,-1,0,exact 22 | 10.1.0.21,10.2.0.21,12345,1,0,600,2147483647,exact,-1,0,exact 23 | 10.1.0.22,10.2.0.22,12345,2,0,600,2147483647,exact,-1,0,exact 24 | 10.1.0.23,10.2.0.23,12345,2,0,600,2147483647,exact,-1,0,exact 25 | 10.1.0.24,10.2.0.24,12345,2,0,600,2147483647,exact,-1,0,exact 26 | 10.1.0.25,10.2.0.25,12345,2,0,600,2147483647,exact,-1,0,exact 27 | 10.1.0.26,10.2.0.26,12345,2,0,600,2147483647,exact,-1,0,exact 28 | 10.1.0.27,10.2.0.27,12345,2,0,600,2147483647,exact,-1,0,exact 29 | 10.1.0.28,10.2.0.28,12345,2,0,600,2147483647,exact,-1,0,exact 30 | 10.1.0.29,10.2.0.29,12345,2,0,600,2147483647,exact,-1,0,exact 31 | 10.1.0.30,10.2.0.30,12345,2,0,600,2147483647,exact,-1,0,exact 32 | 10.1.0.31,10.2.0.31,12345,1,0,600,2147483647,exact,-1,0,exact 33 | 10.1.0.32,10.2.0.32,12345,2,0,600,2147483647,exact,-1,0,exact 34 | 10.1.0.33,10.2.0.33,12345,2,0,600,2147483647,exact,-1,0,exact 35 | 10.1.0.34,10.2.0.34,12345,2,0,600,2147483647,exact,-1,0,exact 36 | 10.1.0.35,10.2.0.35,12345,2,0,600,2147483647,exact,-1,0,exact 37 | 10.1.0.36,10.2.0.36,12345,2,0,600,2147483647,exact,-1,0,exact 38 | 10.1.0.37,10.2.0.37,12345,2,0,600,2147483647,exact,-1,0,exact 39 | 10.1.0.38,10.2.0.38,12345,2,0,600,2147483647,exact,-1,0,exact 40 | 10.1.0.39,10.2.0.39,12345,2,0,600,2147483647,exact,-1,0,exact 41 | 10.1.0.40,10.2.0.40,12345,2,0,600,2147483647,exact,-1,0,exact 42 | 10.1.0.41,10.2.0.41,12345,1,0,600,2147483647,exact,-1,0,exact 43 | 10.1.0.42,10.2.0.42,12345,2,0,600,2147483647,exact,-1,0,exact 44 | 10.1.0.43,10.2.0.43,12345,2,0,600,2147483647,exact,-1,0,exact 45 | 10.1.0.44,10.2.0.44,12345,2,0,600,2147483647,exact,-1,0,exact 46 | 10.1.0.45,10.2.0.45,12345,2,0,600,2147483647,exact,-1,0,exact 47 | 10.1.0.46,10.2.0.46,12345,2,0,600,2147483647,exact,-1,0,exact 48 | 10.1.0.47,10.2.0.47,12345,2,0,600,2147483647,exact,-1,0,exact 49 | 10.1.0.48,10.2.0.48,12345,2,0,600,2147483647,exact,-1,0,exact 50 | 10.1.0.49,10.2.0.49,12345,2,0,600,2147483647,exact,-1,0,exact 51 | 10.1.0.50,10.2.0.50,12345,2,0,600,2147483647,exact,-1,0,exact 52 | 10.1.0.51,10.2.0.51,12345,1,0,600,2147483647,exact,-1,0,exact 53 | 10.1.0.52,10.2.0.52,12345,2,0,600,2147483647,exact,-1,0,exact 54 | 10.1.0.53,10.2.0.53,12345,2,0,600,2147483647,exact,-1,0,exact 55 | 10.1.0.54,10.2.0.54,12345,2,0,600,2147483647,exact,-1,0,exact 56 | 10.1.0.55,10.2.0.55,12345,2,0,600,2147483647,exact,-1,0,exact 57 | 10.1.0.56,10.2.0.56,12345,2,0,600,2147483647,exact,-1,0,exact 58 | 10.1.0.57,10.2.0.57,12345,2,0,600,2147483647,exact,-1,0,exact 59 | 10.1.0.58,10.2.0.58,12345,2,0,600,2147483647,exact,-1,0,exact 60 | 10.1.0.59,10.2.0.59,12345,2,0,600,2147483647,exact,-1,0,exact 61 | 10.1.0.60,10.2.0.60,12345,2,0,600,2147483647,exact,-1,0,exact 62 | 10.1.0.61,10.2.0.61,12345,1,0,600,2147483647,exact,-1,0,exact 63 | 10.1.0.62,10.2.0.62,12345,2,0,600,2147483647,exact,-1,0,exact 64 | 10.1.0.63,10.2.0.63,12345,2,0,600,2147483647,exact,-1,0,exact 65 | 10.1.0.64,10.2.0.64,12345,2,0,600,2147483647,exact,-1,0,exact 66 | 10.1.0.65,10.2.0.65,12345,2,0,600,2147483647,exact,-1,0,exact 67 | 10.1.0.66,10.2.0.66,12345,2,0,600,2147483647,exact,-1,0,exact 68 | 10.1.0.67,10.2.0.67,12345,2,0,600,2147483647,exact,-1,0,exact 69 | 10.1.0.68,10.2.0.68,12345,2,0,600,2147483647,exact,-1,0,exact 70 | 10.1.0.69,10.2.0.69,12345,2,0,600,2147483647,exact,-1,0,exact 71 | 10.1.0.70,10.2.0.70,12345,2,0,600,2147483647,exact,-1,0,exact 72 | 10.1.0.71,10.2.0.71,12345,1,0,600,2147483647,exact,-1,0,exact 73 | 10.1.0.72,10.2.0.72,12345,2,0,600,2147483647,exact,-1,0,exact 74 | 10.1.0.73,10.2.0.73,12345,2,0,600,2147483647,exact,-1,0,exact 75 | 10.1.0.74,10.2.0.74,12345,2,0,600,2147483647,exact,-1,0,exact 76 | 10.1.0.75,10.2.0.75,12345,2,0,600,2147483647,exact,-1,0,exact 77 | 10.1.0.76,10.2.0.76,12345,2,0,600,2147483647,exact,-1,0,exact 78 | 10.1.0.77,10.2.0.77,12345,2,0,600,2147483647,exact,-1,0,exact 79 | 10.1.0.78,10.2.0.78,12345,2,0,600,2147483647,exact,-1,0,exact 80 | 10.1.0.79,10.2.0.79,12345,2,0,600,2147483647,exact,-1,0,exact 81 | 10.1.0.80,10.2.0.80,12345,2,0,600,2147483647,exact,-1,0,exact 82 | 10.1.0.81,10.2.0.81,12345,1,0,600,2147483647,exact,-1,0,exact 83 | 10.1.0.82,10.2.0.82,12345,2,0,600,2147483647,exact,-1,0,exact 84 | 10.1.0.83,10.2.0.83,12345,2,0,600,2147483647,exact,-1,0,exact 85 | 10.1.0.84,10.2.0.84,12345,2,0,600,2147483647,exact,-1,0,exact 86 | 10.1.0.85,10.2.0.85,12345,2,0,600,2147483647,exact,-1,0,exact 87 | 10.1.0.86,10.2.0.86,12345,2,0,600,2147483647,exact,-1,0,exact 88 | 10.1.0.87,10.2.0.87,12345,2,0,600,2147483647,exact,-1,0,exact 89 | 10.1.0.88,10.2.0.88,12345,2,0,600,2147483647,exact,-1,0,exact 90 | 10.1.0.89,10.2.0.89,12345,2,0,600,2147483647,exact,-1,0,exact 91 | 10.1.0.90,10.2.0.90,12345,2,0,600,2147483647,exact,-1,0,exact 92 | 10.1.0.91,10.2.0.91,12345,1,0,600,2147483647,exact,-1,0,exact 93 | 10.1.0.92,10.2.0.92,12345,2,0,600,2147483647,exact,-1,0,exact 94 | 10.1.0.93,10.2.0.93,12345,2,0,600,2147483647,exact,-1,0,exact 95 | 10.1.0.94,10.2.0.94,12345,2,0,600,2147483647,exact,-1,0,exact 96 | 10.1.0.95,10.2.0.95,12345,2,0,600,2147483647,exact,-1,0,exact 97 | 10.1.0.96,10.2.0.96,12345,2,0,600,2147483647,exact,-1,0,exact 98 | 10.1.0.97,10.2.0.97,12345,2,0,600,2147483647,exact,-1,0,exact 99 | 10.1.0.98,10.2.0.98,12345,2,0,600,2147483647,exact,-1,0,exact 100 | 10.1.0.99,10.2.0.99,12345,2,0,600,2147483647,exact,-1,0,exact 101 | 10.1.0.100,10.2.0.100,12345,2,0,600,2147483647,exact,-1,0,exact 102 | 10.1.0.101,10.2.0.101,12345,2,0,600,2147483647,exact,-1,0,exact 103 | 10.1.0.102,10.2.0.102,12345,2,0,600,2147483647,exact,-1,0,exact 104 | 10.1.0.103,10.2.0.103,12345,2,0,600,2147483647,exact,-1,0,exact 105 | 10.1.0.104,10.2.0.104,12345,2,0,600,2147483647,exact,-1,0,exact 106 | 10.1.0.105,10.2.0.105,12345,2,0,600,2147483647,exact,-1,0,exact 107 | 10.1.0.106,10.2.0.106,12345,2,0,600,2147483647,exact,-1,0,exact 108 | 10.1.0.107,10.2.0.107,12345,2,0,600,2147483647,exact,-1,0,exact 109 | 10.1.0.108,10.2.0.108,12345,2,0,600,2147483647,exact,-1,0,exact 110 | 10.1.0.109,10.2.0.109,12345,2,0,600,2147483647,exact,-1,0,exact 111 | 10.1.0.110,10.2.0.110,12345,2,0,600,2147483647,exact,-1,0,exact 112 | 10.1.0.111,10.2.0.111,12345,2,0,600,2147483647,exact,-1,0,exact 113 | 10.1.0.112,10.2.0.112,12345,2,0,600,2147483647,exact,-1,0,exact 114 | 10.1.0.113,10.2.0.113,12345,2,0,600,2147483647,exact,-1,0,exact 115 | 10.1.0.114,10.2.0.114,12345,2,0,600,2147483647,exact,-1,0,exact 116 | 10.1.0.115,10.2.0.115,12345,2,0,600,2147483647,exact,-1,0,exact 117 | 10.1.0.116,10.2.0.116,12345,2,0,600,2147483647,exact,-1,0,exact 118 | 10.1.0.117,10.2.0.117,12345,2,0,600,2147483647,exact,-1,0,exact 119 | 10.1.0.118,10.2.0.118,12345,2,0,600,2147483647,exact,-1,0,exact 120 | 10.1.0.119,10.2.0.119,12345,2,0,600,2147483647,exact,-1,0,exact 121 | 10.1.0.120,10.2.0.120,12345,2,0,600,2147483647,exact,-1,0,exact 122 | 10.1.0.121,10.2.0.121,12345,2,0,600,2147483647,exact,-1,0,exact 123 | 10.1.0.122,10.2.0.122,12345,2,0,600,2147483647,exact,-1,0,exact 124 | 10.1.0.123,10.2.0.123,12345,2,0,600,2147483647,exact,-1,0,exact 125 | 10.1.0.124,10.2.0.124,12345,2,0,600,2147483647,exact,-1,0,exact 126 | 10.1.0.125,10.2.0.125,12345,2,0,600,2147483647,exact,-1,0,exact 127 | 10.1.0.126,10.2.0.126,12345,2,0,600,2147483647,exact,-1,0,exact 128 | 10.1.0.127,10.2.0.127,12345,2,0,600,2147483647,exact,-1,0,exact 129 | 10.1.0.128,10.2.0.128,12345,2,0,600,2147483647,exact,-1,0,exact -------------------------------------------------------------------------------- /dc_gym/inputs/dumbbell/incast_16: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0,600,2147483647,exact,-1,0,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0,600,2147483647,exact,-1,0,exact 4 | 10.1.0.3,10.2.0.3,12345,2,0,600,2147483647,exact,-1,0,exact 5 | 10.1.0.4,10.2.0.4,12345,2,0,600,2147483647,exact,-1,0,exact 6 | 10.1.0.5,10.2.0.5,12345,2,0,600,2147483647,exact,-1,0,exact 7 | 10.1.0.6,10.2.0.6,12345,2,0,600,2147483647,exact,-1,0,exact 8 | 10.1.0.7,10.2.0.7,12345,2,0,600,2147483647,exact,-1,0,exact 9 | 10.1.0.8,10.2.0.8,12345,2,0,600,2147483647,exact,-1,0,exact 10 | 10.1.0.9,10.2.0.9,12345,2,0,600,2147483647,exact,-1,0,exact 11 | 10.1.0.10,10.2.0.10,12345,2,0,600,2147483647,exact,-1,0,exact 12 | 10.1.0.11,10.2.0.11,12345,1,0,600,2147483647,exact,-1,0,exact 13 | 10.1.0.12,10.2.0.12,12345,2,0,600,2147483647,exact,-1,0,exact 14 | 10.1.0.13,10.2.0.13,12345,2,0,600,2147483647,exact,-1,0,exact 15 | 10.1.0.14,10.2.0.14,12345,2,0,600,2147483647,exact,-1,0,exact 16 | 10.1.0.15,10.2.0.15,12345,2,0,600,2147483647,exact,-1,0,exact 17 | 10.1.0.16,10.2.0.16,12345,2,0,600,2147483647,exact,-1,0,exact -------------------------------------------------------------------------------- /dc_gym/inputs/dumbbell/incast_2: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.0,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.0,exact 4 | -------------------------------------------------------------------------------- /dc_gym/inputs/dumbbell/incast_32: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0,600,2147483647,exact,-1,0,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0,600,2147483647,exact,-1,0,exact 4 | 10.1.0.3,10.2.0.3,12345,2,0,600,2147483647,exact,-1,0,exact 5 | 10.1.0.4,10.2.0.4,12345,2,0,600,2147483647,exact,-1,0,exact 6 | 10.1.0.5,10.2.0.5,12345,2,0,600,2147483647,exact,-1,0,exact 7 | 10.1.0.6,10.2.0.6,12345,2,0,600,2147483647,exact,-1,0,exact 8 | 10.1.0.7,10.2.0.7,12345,2,0,600,2147483647,exact,-1,0,exact 9 | 10.1.0.8,10.2.0.8,12345,2,0,600,2147483647,exact,-1,0,exact 10 | 10.1.0.9,10.2.0.9,12345,2,0,600,2147483647,exact,-1,0,exact 11 | 10.1.0.10,10.2.0.10,12345,2,0,600,2147483647,exact,-1,0,exact 12 | 10.1.0.11,10.2.0.11,12345,1,0,600,2147483647,exact,-1,0,exact 13 | 10.1.0.12,10.2.0.12,12345,2,0,600,2147483647,exact,-1,0,exact 14 | 10.1.0.13,10.2.0.13,12345,2,0,600,2147483647,exact,-1,0,exact 15 | 10.1.0.14,10.2.0.14,12345,2,0,600,2147483647,exact,-1,0,exact 16 | 10.1.0.15,10.2.0.15,12345,2,0,600,2147483647,exact,-1,0,exact 17 | 10.1.0.16,10.2.0.16,12345,2,0,600,2147483647,exact,-1,0,exact 18 | 10.1.0.17,10.2.0.17,12345,2,0,600,2147483647,exact,-1,0,exact 19 | 10.1.0.18,10.2.0.18,12345,2,0,600,2147483647,exact,-1,0,exact 20 | 10.1.0.19,10.2.0.19,12345,2,0,600,2147483647,exact,-1,0,exact 21 | 10.1.0.20,10.2.0.20,12345,2,0,600,2147483647,exact,-1,0,exact 22 | 10.1.0.21,10.2.0.21,12345,1,0,600,2147483647,exact,-1,0,exact 23 | 10.1.0.22,10.2.0.22,12345,2,0,600,2147483647,exact,-1,0,exact 24 | 10.1.0.23,10.2.0.23,12345,2,0,600,2147483647,exact,-1,0,exact 25 | 10.1.0.24,10.2.0.24,12345,2,0,600,2147483647,exact,-1,0,exact 26 | 10.1.0.25,10.2.0.25,12345,2,0,600,2147483647,exact,-1,0,exact 27 | 10.1.0.26,10.2.0.26,12345,2,0,600,2147483647,exact,-1,0,exact 28 | 10.1.0.27,10.2.0.27,12345,2,0,600,2147483647,exact,-1,0,exact 29 | 10.1.0.28,10.2.0.28,12345,2,0,600,2147483647,exact,-1,0,exact 30 | 10.1.0.29,10.2.0.29,12345,2,0,600,2147483647,exact,-1,0,exact 31 | 10.1.0.30,10.2.0.30,12345,2,0,600,2147483647,exact,-1,0,exact 32 | 10.1.0.31,10.2.0.31,12345,1,0,600,2147483647,exact,-1,0,exact 33 | 10.1.0.32,10.2.0.32,12345,1,0,600,2147483647,exact,-1,0,exact 34 | -------------------------------------------------------------------------------- /dc_gym/inputs/dumbbell/incast_4: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0.0,600.0,2147483647,exact,-1,0.0,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 4 | 10.1.0.3,10.2.0.3,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 5 | 10.1.0.4,10.2.0.4,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 6 | 7 | -------------------------------------------------------------------------------- /dc_gym/inputs/dumbbell/incast_64: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0,600,2147483647,exact,-1,0,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0,600,2147483647,exact,-1,0,exact 4 | 10.1.0.3,10.2.0.3,12345,2,0,600,2147483647,exact,-1,0,exact 5 | 10.1.0.4,10.2.0.4,12345,2,0,600,2147483647,exact,-1,0,exact 6 | 10.1.0.5,10.2.0.5,12345,2,0,600,2147483647,exact,-1,0,exact 7 | 10.1.0.6,10.2.0.6,12345,2,0,600,2147483647,exact,-1,0,exact 8 | 10.1.0.7,10.2.0.7,12345,2,0,600,2147483647,exact,-1,0,exact 9 | 10.1.0.8,10.2.0.8,12345,2,0,600,2147483647,exact,-1,0,exact 10 | 10.1.0.9,10.2.0.9,12345,2,0,600,2147483647,exact,-1,0,exact 11 | 10.1.0.10,10.2.0.10,12345,2,0,600,2147483647,exact,-1,0,exact 12 | 10.1.0.11,10.2.0.11,12345,1,0,600,2147483647,exact,-1,0,exact 13 | 10.1.0.12,10.2.0.12,12345,2,0,600,2147483647,exact,-1,0,exact 14 | 10.1.0.13,10.2.0.13,12345,2,0,600,2147483647,exact,-1,0,exact 15 | 10.1.0.14,10.2.0.14,12345,2,0,600,2147483647,exact,-1,0,exact 16 | 10.1.0.15,10.2.0.15,12345,2,0,600,2147483647,exact,-1,0,exact 17 | 10.1.0.16,10.2.0.16,12345,2,0,600,2147483647,exact,-1,0,exact 18 | 10.1.0.17,10.2.0.17,12345,2,0,600,2147483647,exact,-1,0,exact 19 | 10.1.0.18,10.2.0.18,12345,2,0,600,2147483647,exact,-1,0,exact 20 | 10.1.0.19,10.2.0.19,12345,2,0,600,2147483647,exact,-1,0,exact 21 | 10.1.0.20,10.2.0.20,12345,2,0,600,2147483647,exact,-1,0,exact 22 | 10.1.0.21,10.2.0.21,12345,1,0,600,2147483647,exact,-1,0,exact 23 | 10.1.0.22,10.2.0.22,12345,2,0,600,2147483647,exact,-1,0,exact 24 | 10.1.0.23,10.2.0.23,12345,2,0,600,2147483647,exact,-1,0,exact 25 | 10.1.0.24,10.2.0.24,12345,2,0,600,2147483647,exact,-1,0,exact 26 | 10.1.0.25,10.2.0.25,12345,2,0,600,2147483647,exact,-1,0,exact 27 | 10.1.0.26,10.2.0.26,12345,2,0,600,2147483647,exact,-1,0,exact 28 | 10.1.0.27,10.2.0.27,12345,2,0,600,2147483647,exact,-1,0,exact 29 | 10.1.0.28,10.2.0.28,12345,2,0,600,2147483647,exact,-1,0,exact 30 | 10.1.0.29,10.2.0.29,12345,2,0,600,2147483647,exact,-1,0,exact 31 | 10.1.0.30,10.2.0.30,12345,2,0,600,2147483647,exact,-1,0,exact 32 | 10.1.0.31,10.2.0.31,12345,1,0,600,2147483647,exact,-1,0,exact 33 | 10.1.0.32,10.2.0.32,12345,2,0,600,2147483647,exact,-1,0,exact 34 | 10.1.0.33,10.2.0.33,12345,2,0,600,2147483647,exact,-1,0,exact 35 | 10.1.0.34,10.2.0.34,12345,2,0,600,2147483647,exact,-1,0,exact 36 | 10.1.0.35,10.2.0.35,12345,2,0,600,2147483647,exact,-1,0,exact 37 | 10.1.0.36,10.2.0.36,12345,2,0,600,2147483647,exact,-1,0,exact 38 | 10.1.0.37,10.2.0.37,12345,2,0,600,2147483647,exact,-1,0,exact 39 | 10.1.0.38,10.2.0.38,12345,2,0,600,2147483647,exact,-1,0,exact 40 | 10.1.0.39,10.2.0.39,12345,2,0,600,2147483647,exact,-1,0,exact 41 | 10.1.0.40,10.2.0.40,12345,2,0,600,2147483647,exact,-1,0,exact 42 | 10.1.0.41,10.2.0.41,12345,1,0,600,2147483647,exact,-1,0,exact 43 | 10.1.0.42,10.2.0.42,12345,2,0,600,2147483647,exact,-1,0,exact 44 | 10.1.0.43,10.2.0.43,12345,2,0,600,2147483647,exact,-1,0,exact 45 | 10.1.0.44,10.2.0.44,12345,2,0,600,2147483647,exact,-1,0,exact 46 | 10.1.0.45,10.2.0.45,12345,2,0,600,2147483647,exact,-1,0,exact 47 | 10.1.0.46,10.2.0.46,12345,2,0,600,2147483647,exact,-1,0,exact 48 | 10.1.0.47,10.2.0.47,12345,2,0,600,2147483647,exact,-1,0,exact 49 | 10.1.0.48,10.2.0.48,12345,2,0,600,2147483647,exact,-1,0,exact 50 | 10.1.0.49,10.2.0.49,12345,2,0,600,2147483647,exact,-1,0,exact 51 | 10.1.0.50,10.2.0.50,12345,2,0,600,2147483647,exact,-1,0,exact 52 | 10.1.0.51,10.2.0.51,12345,1,0,600,2147483647,exact,-1,0,exact 53 | 10.1.0.52,10.2.0.52,12345,2,0,600,2147483647,exact,-1,0,exact 54 | 10.1.0.53,10.2.0.53,12345,2,0,600,2147483647,exact,-1,0,exact 55 | 10.1.0.54,10.2.0.54,12345,2,0,600,2147483647,exact,-1,0,exact 56 | 10.1.0.55,10.2.0.55,12345,2,0,600,2147483647,exact,-1,0,exact 57 | 10.1.0.56,10.2.0.56,12345,2,0,600,2147483647,exact,-1,0,exact 58 | 10.1.0.57,10.2.0.57,12345,2,0,600,2147483647,exact,-1,0,exact 59 | 10.1.0.58,10.2.0.58,12345,2,0,600,2147483647,exact,-1,0,exact 60 | 10.1.0.59,10.2.0.59,12345,2,0,600,2147483647,exact,-1,0,exact 61 | 10.1.0.60,10.2.0.60,12345,2,0,600,2147483647,exact,-1,0,exact 62 | 10.1.0.61,10.2.0.61,12345,1,0,600,2147483647,exact,-1,0,exact 63 | 10.1.0.62,10.2.0.62,12345,2,0,600,2147483647,exact,-1,0,exact 64 | 10.1.0.63,10.2.0.63,12345,2,0,600,2147483647,exact,-1,0,exact 65 | 10.1.0.64,10.2.0.64,12345,2,0,600,2147483647,exact,-1,0,exact 66 | -------------------------------------------------------------------------------- /dc_gym/inputs/dumbbell/incast_8: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0.0,600.0,2147483647,exact,-1,0.0,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 4 | 10.1.0.3,10.2.0.3,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 5 | 10.1.0.4,10.2.0.4,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 6 | 10.1.0.5,10.2.0.5,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 7 | 10.1.0.6,10.2.0.6,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 8 | 10.1.0.7,10.2.0.7,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 9 | 10.1.0.8,10.2.0.8,12345,2,0.0,600.0,2147483647,exact,-1,0.0,exact 10 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/hotspot_one_to_one_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.7.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.0,exact 3 | 10.1.0.2,10.3.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.0,exact 4 | 10.2.0.1,10.4.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.0,exact 5 | 10.2.0.2,10.5.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.0,exact 6 | 10.3.0.1,10.8.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.0,exact 7 | 10.3.0.2,10.5.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.0,exact 8 | 10.4.0.1,10.6.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.0,exact 9 | 10.4.0.2,10.7.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.0,exact 10 | 10.5.0.1,10.2.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.0,exact 11 | 10.5.0.2,10.7.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.0,exact 12 | 10.6.0.1,10.6.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.0,exact 13 | 10.6.0.2,10.8.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.0,exact 14 | 10.7.0.1,10.1.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.0,exact 15 | 10.7.0.2,10.5.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.0,exact 16 | 10.8.0.1,10.2.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.0,exact 17 | 10.8.0.2,10.3.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.0,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random0_bij_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.4.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.7.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.4.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.8.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.7.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.1.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.1.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.8.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.3.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.3.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.6.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.5.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.2.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.2.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.6.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random0_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.8.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.7.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.6.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.5.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.4.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.4.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.6.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.2.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.6.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.4.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.7.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.8.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.5.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.2.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.5.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.5.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random1_bij_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.7.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.5.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.7.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.4.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.1.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.2.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.5.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.2.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.8.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.4.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.6.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.1.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.8.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.3.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.3.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.6.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random1_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.6.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.4.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.4.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.7.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.2.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.8.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.5.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.1.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.8.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.6.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.3.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.2.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.6.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.6.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.3.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.1.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random2_bij_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.8.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.5.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.7.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.5.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.2.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.7.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.1.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.2.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.6.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.1.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.3.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.4.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.6.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.8.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.3.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random2_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.7.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.4.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.8.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.1.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.6.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.2.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.3.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.3.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.7.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.6.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.5.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.1.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.1.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.2.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.1.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.6.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random3_bij_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.3.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.3.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.7.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.6.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.1.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.1.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.8.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.2.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.4.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.8.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.6.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.5.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.4.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.7.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.2.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.3.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.4.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.7.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.4.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.1.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.8.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.7.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.6.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.4.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.2.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.1.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.3.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.6.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.8.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random4_bij_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.4.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.5.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.3.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.3.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.5.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.6.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.6.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.1.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.8.0.1,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.2.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.2.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.8.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.4.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.1.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.7.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.7.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random4_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.8.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.1.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.2.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.5.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.2.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.4.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.6.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.3.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.7.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.1.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.8.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.5.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.7.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.6.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.8.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.4.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random_2_flows_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.4.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.1,10.5.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.1.0.2,10.7.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.1.0.2,10.8.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.2.0.1,10.5.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.2.0.1,10.6.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.2.0.2,10.8.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.2.0.2,10.1.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.3.0.1,10.2.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.3.0.1,10.4.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.3.0.2,10.5.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.3.0.2,10.7.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.4.0.1,10.8.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.4.0.1,10.2.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.4.0.2,10.3.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.4.0.2,10.5.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | 10.5.0.1,10.6.0.2,12345,17,0.0,60.0,2147483647,exact,-1,0.001,exact 19 | 10.5.0.1,10.8.0.1,12345,18,0.0,60.0,2147483647,exact,-1,0.001,exact 20 | 10.5.0.2,10.1.0.2,12345,19,0.0,60.0,2147483647,exact,-1,0.001,exact 21 | 10.5.0.2,10.3.0.1,12345,20,0.0,60.0,2147483647,exact,-1,0.001,exact 22 | 10.6.0.1,10.4.0.2,12345,21,0.0,60.0,2147483647,exact,-1,0.001,exact 23 | 10.6.0.1,10.5.0.2,12345,22,0.0,60.0,2147483647,exact,-1,0.001,exact 24 | 10.6.0.2,10.7.0.1,12345,23,0.0,60.0,2147483647,exact,-1,0.001,exact 25 | 10.6.0.2,10.8.0.2,12345,24,0.0,60.0,2147483647,exact,-1,0.001,exact 26 | 10.7.0.1,10.2.0.1,12345,25,0.0,60.0,2147483647,exact,-1,0.001,exact 27 | 10.7.0.1,10.3.0.2,12345,26,0.0,60.0,2147483647,exact,-1,0.001,exact 28 | 10.7.0.2,10.5.0.1,12345,27,0.0,60.0,2147483647,exact,-1,0.001,exact 29 | 10.7.0.2,10.6.0.2,12345,28,0.0,60.0,2147483647,exact,-1,0.001,exact 30 | 10.8.0.1,10.3.0.1,12345,29,0.0,60.0,2147483647,exact,-1,0.001,exact 31 | 10.8.0.1,10.4.0.2,12345,30,0.0,60.0,2147483647,exact,-1,0.001,exact 32 | 10.8.0.2,10.6.0.1,12345,31,0.0,60.0,2147483647,exact,-1,0.001,exact 33 | 10.8.0.2,10.7.0.2,12345,32,0.0,60.0,2147483647,exact,-1,0.001,exact 34 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random_3_flows_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.4.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.1,10.6.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.1.0.1,10.7.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.1.0.2,10.1.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.1.0.2,10.2.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.1.0.2,10.7.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.2.0.1,10.8.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.2.0.1,10.5.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.2.0.1,10.6.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.2.0.2,10.8.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.2.0.2,10.1.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.2.0.2,10.3.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.3.0.1,10.4.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.3.0.1,10.6.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.3.0.1,10.7.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.3.0.2,10.1.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | 10.3.0.2,10.2.0.2,12345,17,0.0,60.0,2147483647,exact,-1,0.001,exact 19 | 10.3.0.2,10.4.0.1,12345,18,0.0,60.0,2147483647,exact,-1,0.001,exact 20 | 10.4.0.1,10.5.0.1,12345,19,0.0,60.0,2147483647,exact,-1,0.001,exact 21 | 10.4.0.1,10.6.0.2,12345,20,0.0,60.0,2147483647,exact,-1,0.001,exact 22 | 10.4.0.1,10.8.0.1,12345,21,0.0,60.0,2147483647,exact,-1,0.001,exact 23 | 10.4.0.2,10.1.0.2,12345,22,0.0,60.0,2147483647,exact,-1,0.001,exact 24 | 10.4.0.2,10.3.0.1,12345,23,0.0,60.0,2147483647,exact,-1,0.001,exact 25 | 10.4.0.2,10.7.0.2,12345,24,0.0,60.0,2147483647,exact,-1,0.001,exact 26 | 10.5.0.1,10.1.0.1,12345,25,0.0,60.0,2147483647,exact,-1,0.001,exact 27 | 10.5.0.1,10.2.0.2,12345,26,0.0,60.0,2147483647,exact,-1,0.001,exact 28 | 10.5.0.1,10.4.0.1,12345,27,0.0,60.0,2147483647,exact,-1,0.001,exact 29 | 10.5.0.2,10.8.0.2,12345,28,0.0,60.0,2147483647,exact,-1,0.001,exact 30 | 10.5.0.2,10.2.0.1,12345,29,0.0,60.0,2147483647,exact,-1,0.001,exact 31 | 10.5.0.2,10.3.0.2,12345,30,0.0,60.0,2147483647,exact,-1,0.001,exact 32 | 10.6.0.1,10.5.0.1,12345,31,0.0,60.0,2147483647,exact,-1,0.001,exact 33 | 10.6.0.1,10.6.0.2,12345,32,0.0,60.0,2147483647,exact,-1,0.001,exact 34 | 10.6.0.1,10.8.0.1,12345,33,0.0,60.0,2147483647,exact,-1,0.001,exact 35 | 10.6.0.2,10.1.0.2,12345,34,0.0,60.0,2147483647,exact,-1,0.001,exact 36 | 10.6.0.2,10.3.0.1,12345,35,0.0,60.0,2147483647,exact,-1,0.001,exact 37 | 10.6.0.2,10.4.0.2,12345,36,0.0,60.0,2147483647,exact,-1,0.001,exact 38 | 10.7.0.1,10.6.0.1,12345,37,0.0,60.0,2147483647,exact,-1,0.001,exact 39 | 10.7.0.1,10.7.0.2,12345,38,0.0,60.0,2147483647,exact,-1,0.001,exact 40 | 10.7.0.1,10.8.0.2,12345,39,0.0,60.0,2147483647,exact,-1,0.001,exact 41 | 10.7.0.2,10.2.0.1,12345,40,0.0,60.0,2147483647,exact,-1,0.001,exact 42 | 10.7.0.2,10.3.0.2,12345,41,0.0,60.0,2147483647,exact,-1,0.001,exact 43 | 10.7.0.2,10.5.0.1,12345,42,0.0,60.0,2147483647,exact,-1,0.001,exact 44 | 10.8.0.1,10.6.0.2,12345,43,0.0,60.0,2147483647,exact,-1,0.001,exact 45 | 10.8.0.1,10.3.0.1,12345,44,0.0,60.0,2147483647,exact,-1,0.001,exact 46 | 10.8.0.1,10.4.0.2,12345,45,0.0,60.0,2147483647,exact,-1,0.001,exact 47 | 10.8.0.2,10.6.0.1,12345,46,0.0,60.0,2147483647,exact,-1,0.001,exact 48 | 10.8.0.2,10.7.0.2,12345,47,0.0,60.0,2147483647,exact,-1,0.001,exact 49 | 10.8.0.2,10.1.0.1,12345,48,0.0,60.0,2147483647,exact,-1,0.001,exact 50 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random_4_flows_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.1,10.4.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.1.0.1,10.5.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.1.0.1,10.7.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.1.0.2,10.8.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.1.0.2,10.2.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.1.0.2,10.3.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.1.0.2,10.4.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.2.0.1,10.6.0.1,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.2.0.1,10.7.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.2.0.1,10.1.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.2.0.1,10.2.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.2.0.2,10.4.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.2.0.2,10.5.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.2.0.2,10.7.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.2.0.2,10.8.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | 10.3.0.1,10.2.0.1,12345,17,0.0,60.0,2147483647,exact,-1,0.001,exact 19 | 10.3.0.1,10.3.0.2,12345,18,0.0,60.0,2147483647,exact,-1,0.001,exact 20 | 10.3.0.1,10.4.0.2,12345,19,0.0,60.0,2147483647,exact,-1,0.001,exact 21 | 10.3.0.1,10.6.0.1,12345,20,0.0,60.0,2147483647,exact,-1,0.001,exact 22 | 10.3.0.2,10.7.0.2,12345,21,0.0,60.0,2147483647,exact,-1,0.001,exact 23 | 10.3.0.2,10.1.0.1,12345,22,0.0,60.0,2147483647,exact,-1,0.001,exact 24 | 10.3.0.2,10.2.0.2,12345,23,0.0,60.0,2147483647,exact,-1,0.001,exact 25 | 10.3.0.2,10.4.0.1,12345,24,0.0,60.0,2147483647,exact,-1,0.001,exact 26 | 10.4.0.1,10.5.0.2,12345,25,0.0,60.0,2147483647,exact,-1,0.001,exact 27 | 10.4.0.1,10.7.0.1,12345,26,0.0,60.0,2147483647,exact,-1,0.001,exact 28 | 10.4.0.1,10.8.0.2,12345,27,0.0,60.0,2147483647,exact,-1,0.001,exact 29 | 10.4.0.1,10.2.0.1,12345,28,0.0,60.0,2147483647,exact,-1,0.001,exact 30 | 10.4.0.2,10.3.0.2,12345,29,0.0,60.0,2147483647,exact,-1,0.001,exact 31 | 10.4.0.2,10.5.0.1,12345,30,0.0,60.0,2147483647,exact,-1,0.001,exact 32 | 10.4.0.2,10.6.0.2,12345,31,0.0,60.0,2147483647,exact,-1,0.001,exact 33 | 10.4.0.2,10.7.0.2,12345,32,0.0,60.0,2147483647,exact,-1,0.001,exact 34 | 10.5.0.1,10.1.0.1,12345,33,0.0,60.0,2147483647,exact,-1,0.001,exact 35 | 10.5.0.1,10.2.0.2,12345,34,0.0,60.0,2147483647,exact,-1,0.001,exact 36 | 10.5.0.1,10.4.0.1,12345,35,0.0,60.0,2147483647,exact,-1,0.001,exact 37 | 10.5.0.1,10.5.0.2,12345,36,0.0,60.0,2147483647,exact,-1,0.001,exact 38 | 10.5.0.2,10.7.0.1,12345,37,0.0,60.0,2147483647,exact,-1,0.001,exact 39 | 10.5.0.2,10.8.0.2,12345,38,0.0,60.0,2147483647,exact,-1,0.001,exact 40 | 10.5.0.2,10.2.0.1,12345,39,0.0,60.0,2147483647,exact,-1,0.001,exact 41 | 10.5.0.2,10.3.0.2,12345,40,0.0,60.0,2147483647,exact,-1,0.001,exact 42 | 10.6.0.1,10.5.0.1,12345,41,0.0,60.0,2147483647,exact,-1,0.001,exact 43 | 10.6.0.1,10.6.0.2,12345,42,0.0,60.0,2147483647,exact,-1,0.001,exact 44 | 10.6.0.1,10.8.0.1,12345,43,0.0,60.0,2147483647,exact,-1,0.001,exact 45 | 10.6.0.1,10.1.0.1,12345,44,0.0,60.0,2147483647,exact,-1,0.001,exact 46 | 10.6.0.2,10.2.0.2,12345,45,0.0,60.0,2147483647,exact,-1,0.001,exact 47 | 10.6.0.2,10.4.0.1,12345,46,0.0,60.0,2147483647,exact,-1,0.001,exact 48 | 10.6.0.2,10.5.0.2,12345,47,0.0,60.0,2147483647,exact,-1,0.001,exact 49 | 10.6.0.2,10.7.0.1,12345,48,0.0,60.0,2147483647,exact,-1,0.001,exact 50 | 10.7.0.1,10.8.0.2,12345,49,0.0,60.0,2147483647,exact,-1,0.001,exact 51 | 10.7.0.1,10.2.0.1,12345,50,0.0,60.0,2147483647,exact,-1,0.001,exact 52 | 10.7.0.1,10.3.0.2,12345,51,0.0,60.0,2147483647,exact,-1,0.001,exact 53 | 10.7.0.1,10.5.0.1,12345,52,0.0,60.0,2147483647,exact,-1,0.001,exact 54 | 10.7.0.2,10.6.0.2,12345,53,0.0,60.0,2147483647,exact,-1,0.001,exact 55 | 10.7.0.2,10.8.0.1,12345,54,0.0,60.0,2147483647,exact,-1,0.001,exact 56 | 10.7.0.2,10.1.0.2,12345,55,0.0,60.0,2147483647,exact,-1,0.001,exact 57 | 10.7.0.2,10.2.0.2,12345,56,0.0,60.0,2147483647,exact,-1,0.001,exact 58 | 10.8.0.1,10.4.0.1,12345,57,0.0,60.0,2147483647,exact,-1,0.001,exact 59 | 10.8.0.1,10.5.0.2,12345,58,0.0,60.0,2147483647,exact,-1,0.001,exact 60 | 10.8.0.1,10.7.0.1,12345,59,0.0,60.0,2147483647,exact,-1,0.001,exact 61 | 10.8.0.1,10.8.0.2,12345,60,0.0,60.0,2147483647,exact,-1,0.001,exact 62 | 10.8.0.2,10.2.0.1,12345,61,0.0,60.0,2147483647,exact,-1,0.001,exact 63 | 10.8.0.2,10.3.0.2,12345,62,0.0,60.0,2147483647,exact,-1,0.001,exact 64 | 10.8.0.2,10.5.0.1,12345,63,0.0,60.0,2147483647,exact,-1,0.001,exact 65 | 10.8.0.2,10.6.0.2,12345,64,0.0,60.0,2147483647,exact,-1,0.001,exact 66 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/random_5_flows_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.1.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.1,10.3.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.1.0.1,10.4.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.1.0.1,10.6.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.1.0.1,10.7.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.1.0.2,10.1.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.1.0.2,10.2.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.1.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.1.0.2,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.1.0.2,10.7.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.2.0.1,10.8.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.2.0.1,10.5.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.2.0.1,10.6.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.2.0.1,10.8.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.2.0.1,10.1.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.2.0.2,10.3.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | 10.2.0.2,10.4.0.1,12345,17,0.0,60.0,2147483647,exact,-1,0.001,exact 19 | 10.2.0.2,10.5.0.2,12345,18,0.0,60.0,2147483647,exact,-1,0.001,exact 20 | 10.2.0.2,10.7.0.1,12345,19,0.0,60.0,2147483647,exact,-1,0.001,exact 21 | 10.2.0.2,10.8.0.2,12345,20,0.0,60.0,2147483647,exact,-1,0.001,exact 22 | 10.3.0.1,10.2.0.1,12345,21,0.0,60.0,2147483647,exact,-1,0.001,exact 23 | 10.3.0.1,10.3.0.2,12345,22,0.0,60.0,2147483647,exact,-1,0.001,exact 24 | 10.3.0.1,10.5.0.1,12345,23,0.0,60.0,2147483647,exact,-1,0.001,exact 25 | 10.3.0.1,10.6.0.2,12345,24,0.0,60.0,2147483647,exact,-1,0.001,exact 26 | 10.3.0.1,10.8.0.1,12345,25,0.0,60.0,2147483647,exact,-1,0.001,exact 27 | 10.3.0.2,10.1.0.2,12345,26,0.0,60.0,2147483647,exact,-1,0.001,exact 28 | 10.3.0.2,10.3.0.1,12345,27,0.0,60.0,2147483647,exact,-1,0.001,exact 29 | 10.3.0.2,10.4.0.2,12345,28,0.0,60.0,2147483647,exact,-1,0.001,exact 30 | 10.3.0.2,10.5.0.2,12345,29,0.0,60.0,2147483647,exact,-1,0.001,exact 31 | 10.3.0.2,10.7.0.1,12345,30,0.0,60.0,2147483647,exact,-1,0.001,exact 32 | 10.4.0.1,10.8.0.2,12345,31,0.0,60.0,2147483647,exact,-1,0.001,exact 33 | 10.4.0.1,10.2.0.1,12345,32,0.0,60.0,2147483647,exact,-1,0.001,exact 34 | 10.4.0.1,10.3.0.2,12345,33,0.0,60.0,2147483647,exact,-1,0.001,exact 35 | 10.4.0.1,10.5.0.1,12345,34,0.0,60.0,2147483647,exact,-1,0.001,exact 36 | 10.4.0.1,10.6.0.2,12345,35,0.0,60.0,2147483647,exact,-1,0.001,exact 37 | 10.4.0.2,10.8.0.1,12345,36,0.0,60.0,2147483647,exact,-1,0.001,exact 38 | 10.4.0.2,10.1.0.2,12345,37,0.0,60.0,2147483647,exact,-1,0.001,exact 39 | 10.4.0.2,10.3.0.1,12345,38,0.0,60.0,2147483647,exact,-1,0.001,exact 40 | 10.4.0.2,10.7.0.2,12345,39,0.0,60.0,2147483647,exact,-1,0.001,exact 41 | 10.4.0.2,10.1.0.1,12345,40,0.0,60.0,2147483647,exact,-1,0.001,exact 42 | 10.5.0.1,10.2.0.2,12345,41,0.0,60.0,2147483647,exact,-1,0.001,exact 43 | 10.5.0.1,10.4.0.1,12345,42,0.0,60.0,2147483647,exact,-1,0.001,exact 44 | 10.5.0.1,10.5.0.2,12345,43,0.0,60.0,2147483647,exact,-1,0.001,exact 45 | 10.5.0.1,10.7.0.1,12345,44,0.0,60.0,2147483647,exact,-1,0.001,exact 46 | 10.5.0.1,10.8.0.1,12345,45,0.0,60.0,2147483647,exact,-1,0.001,exact 47 | 10.5.0.2,10.1.0.2,12345,46,0.0,60.0,2147483647,exact,-1,0.001,exact 48 | 10.5.0.2,10.3.0.1,12345,47,0.0,60.0,2147483647,exact,-1,0.001,exact 49 | 10.5.0.2,10.4.0.2,12345,48,0.0,60.0,2147483647,exact,-1,0.001,exact 50 | 10.5.0.2,10.6.0.1,12345,49,0.0,60.0,2147483647,exact,-1,0.001,exact 51 | 10.5.0.2,10.7.0.2,12345,50,0.0,60.0,2147483647,exact,-1,0.001,exact 52 | 10.6.0.1,10.1.0.1,12345,51,0.0,60.0,2147483647,exact,-1,0.001,exact 53 | 10.6.0.1,10.2.0.2,12345,52,0.0,60.0,2147483647,exact,-1,0.001,exact 54 | 10.6.0.1,10.4.0.1,12345,53,0.0,60.0,2147483647,exact,-1,0.001,exact 55 | 10.6.0.1,10.5.0.2,12345,54,0.0,60.0,2147483647,exact,-1,0.001,exact 56 | 10.6.0.1,10.7.0.1,12345,55,0.0,60.0,2147483647,exact,-1,0.001,exact 57 | 10.6.0.2,10.8.0.2,12345,56,0.0,60.0,2147483647,exact,-1,0.001,exact 58 | 10.6.0.2,10.2.0.1,12345,57,0.0,60.0,2147483647,exact,-1,0.001,exact 59 | 10.6.0.2,10.3.0.1,12345,58,0.0,60.0,2147483647,exact,-1,0.001,exact 60 | 10.6.0.2,10.4.0.2,12345,59,0.0,60.0,2147483647,exact,-1,0.001,exact 61 | 10.6.0.2,10.6.0.1,12345,60,0.0,60.0,2147483647,exact,-1,0.001,exact 62 | 10.7.0.1,10.7.0.2,12345,61,0.0,60.0,2147483647,exact,-1,0.001,exact 63 | 10.7.0.1,10.1.0.1,12345,62,0.0,60.0,2147483647,exact,-1,0.001,exact 64 | 10.7.0.1,10.2.0.2,12345,63,0.0,60.0,2147483647,exact,-1,0.001,exact 65 | 10.7.0.1,10.4.0.1,12345,64,0.0,60.0,2147483647,exact,-1,0.001,exact 66 | 10.7.0.1,10.5.0.2,12345,65,0.0,60.0,2147483647,exact,-1,0.001,exact 67 | 10.7.0.2,10.7.0.1,12345,66,0.0,60.0,2147483647,exact,-1,0.001,exact 68 | 10.7.0.2,10.8.0.2,12345,67,0.0,60.0,2147483647,exact,-1,0.001,exact 69 | 10.7.0.2,10.2.0.1,12345,68,0.0,60.0,2147483647,exact,-1,0.001,exact 70 | 10.7.0.2,10.3.0.2,12345,69,0.0,60.0,2147483647,exact,-1,0.001,exact 71 | 10.7.0.2,10.4.0.2,12345,70,0.0,60.0,2147483647,exact,-1,0.001,exact 72 | 10.8.0.1,10.6.0.1,12345,71,0.0,60.0,2147483647,exact,-1,0.001,exact 73 | 10.8.0.1,10.7.0.2,12345,72,0.0,60.0,2147483647,exact,-1,0.001,exact 74 | 10.8.0.1,10.1.0.1,12345,73,0.0,60.0,2147483647,exact,-1,0.001,exact 75 | 10.8.0.1,10.2.0.2,12345,74,0.0,60.0,2147483647,exact,-1,0.001,exact 76 | 10.8.0.1,10.4.0.1,12345,75,0.0,60.0,2147483647,exact,-1,0.001,exact 77 | 10.8.0.2,10.4.0.1,12345,76,0.0,60.0,2147483647,exact,-1,0.001,exact 78 | 10.8.0.2,10.5.0.2,12345,77,0.0,60.0,2147483647,exact,-1,0.001,exact 79 | 10.8.0.2,10.6.0.2,12345,78,0.0,60.0,2147483647,exact,-1,0.001,exact 80 | 10.8.0.2,10.8.0.1,12345,79,0.0,60.0,2147483647,exact,-1,0.001,exact 81 | 10.8.0.2,10.5.0.1,12345,80,0.0,60.0,2147483647,exact,-1,0.001,exact 82 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/seed_interpod_test: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 192.168.4.61,192.168.4.71,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 3 | 192.168.4.62,192.168.4.72,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 4 | 192.168.4.63,192.168.4.73,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 5 | 192.168.4.64,192.168.4.74,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 6 | 192.168.4.65,192.168.4.75,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 7 | 192.168.4.66,192.168.4.76,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 8 | 192.168.4.67,192.168.4.77,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 9 | 192.168.4.68,192.168.4.78,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 10 | 192.168.4.69,192.168.4.79,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 11 | 192.168.4.70,192.168.4.80,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 12 | 192.168.4.71,192.168.4.61,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 13 | #192.168.4.72,192.168.4.62,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 14 | 192.168.4.73,192.168.4.63,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 15 | 192.168.4.74,192.168.4.64,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 16 | 192.168.4.75,192.168.4.65,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 17 | 192.168.4.76,192.168.4.66,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 18 | 192.168.4.77,192.168.4.67,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 19 | 192.168.4.78,192.168.4.68,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 20 | 192.168.4.79,192.168.4.69,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 21 | 192.168.4.80,192.168.4.70,12345,1,0.0,180.0,2147483647000,exact,-1,0.001,exact 22 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_0_1_0_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.1.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.1.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.2.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.2.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.4.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.6.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.6.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.7.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.7.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.8.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.8.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_0_2_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.1.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.1.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.3.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.8.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.4.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.2.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.6.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.3.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.6.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.5.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.8.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.7.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.7.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.2.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.4.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_0_5_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.1.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.1.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.6.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.4.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.8.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.7.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.7.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.8.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.6.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.2.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_1_2_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.4.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.4.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.2.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.8.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.1.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.5.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.3.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.6.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.7.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.1.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.8.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.7.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.3.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.6.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_1_5_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.2.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.4.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.2.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.6.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.5.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.7.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.6.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.1.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.8.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.7.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.8.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.1.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_2_2_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.8.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.1.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.5.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.1.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.4.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.7.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.6.0.1,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.6.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.4.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.8.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.2.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.5.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.2.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.7.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_2_5_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.1.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.2.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.6.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.2.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.4.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.8.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.8.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.6.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.4.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.7.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.7.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.1.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.3.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_3_2_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.8.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.5.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.3.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.1.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.4.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.6.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.8.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.2.0.1,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.4.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.7.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.5.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.6.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.7.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.2.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.1.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_3_5_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.1.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.5.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.2.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.7.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.4.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.6.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.8.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.6.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.7.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.1.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.2.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.8.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_4_2_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.7.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.2.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.2.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.8.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.4.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.6.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.6.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.5.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.1.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.8.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.7.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.4.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.1.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stag_prob_4_5_3_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.1.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.2.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.1.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.4.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.5.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.3.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.7.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.4.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.6.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.5.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.3.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.6.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.8.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.8.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.7.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.2,10.2.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stride1_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 3 | 10.1.0.1,10.1.0.2,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.1.0.2,10.2.0.1,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.1,10.2.0.2,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.2.0.2,10.3.0.1,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.1,10.3.0.2,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.3.0.2,10.4.0.1,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.1,10.4.0.2,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.4.0.2,10.5.0.1,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.1,10.5.0.2,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.5.0.2,10.6.0.1,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.1,10.6.0.2,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.6.0.2,10.7.0.1,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.1,10.7.0.2,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.7.0.2,10.8.0.1,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.1,10.8.0.2,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | 10.8.0.2,10.1.0.1,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 19 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stride2_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 3 | 10.1.0.1,10.2.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.1.0.2,10.2.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.1,10.3.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.2.0.2,10.3.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.1,10.4.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.3.0.2,10.4.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.1,10.5.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.4.0.2,10.5.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.1,10.6.0.1,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.5.0.2,10.6.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.1,10.7.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.6.0.2,10.7.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.1,10.8.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.7.0.2,10.8.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.8.0.1,10.1.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | 10.8.0.2,10.1.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 19 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stride4_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.3.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.0,exact 3 | 10.1.0.2,10.3.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.0,exact 4 | 10.2.0.1,10.4.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.0,exact 5 | 10.2.0.2,10.4.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.0,exact 6 | 10.3.0.1,10.5.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.0,exact 7 | 10.3.0.2,10.5.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.0,exact 8 | 10.4.0.1,10.6.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.0,exact 9 | 10.4.0.2,10.6.0.2,12345,8,0.0,60.0,2147483647,exact,-1,0.0,exact 10 | 10.5.0.1,10.7.0.1,12345,9,0.0,60.0,2147483647,exact,-1,0.0,exact 11 | 10.5.0.2,10.7.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.0,exact 12 | 10.6.0.1,10.8.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.0,exact 13 | 10.6.0.2,10.8.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.0,exact 14 | 10.7.0.1,10.1.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.0,exact 15 | 10.7.0.2,10.1.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.0,exact 16 | 10.8.0.1,10.2.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.0,exact 17 | 10.8.0.2,10.2.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.0,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/stride8_data: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 10.1.0.1,10.5.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | 10.1.0.2,10.5.0.2,12345,2,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | 10.2.0.1,10.6.0.1,12345,3,0.0,60.0,2147483647,exact,-1,0.001,exact 5 | 10.2.0.2,10.6.0.2,12345,4,0.0,60.0,2147483647,exact,-1,0.001,exact 6 | 10.3.0.1,10.7.0.1,12345,5,0.0,60.0,2147483647,exact,-1,0.001,exact 7 | 10.3.0.2,10.7.0.2,12345,6,0.0,60.0,2147483647,exact,-1,0.001,exact 8 | 10.4.0.1,10.8.0.1,12345,7,0.0,60.0,2147483647,exact,-1,0.001,exact 9 | 10.4.0.2,10.3.1.3,12345,8,0.0,60.0,2147483647,exact,-1,0.001,exact 10 | 10.5.0.1,10.1.0.1,12345,9,0.0,60.0,2147483647,exact,-1,0.001,exact 11 | 10.5.0.2,10.1.0.2,12345,10,0.0,60.0,2147483647,exact,-1,0.001,exact 12 | 10.6.0.1,10.2.0.1,12345,11,0.0,60.0,2147483647,exact,-1,0.001,exact 13 | 10.6.0.2,10.2.0.2,12345,12,0.0,60.0,2147483647,exact,-1,0.001,exact 14 | 10.7.0.1,10.3.0.1,12345,13,0.0,60.0,2147483647,exact,-1,0.001,exact 15 | 10.7.0.2,10.3.0.2,12345,14,0.0,60.0,2147483647,exact,-1,0.001,exact 16 | 10.8.0.1,10.4.0.1,12345,15,0.0,60.0,2147483647,exact,-1,0.001,exact 17 | 10.3.1.3,10.4.0.2,12345,16,0.0,60.0,2147483647,exact,-1,0.001,exact 18 | -------------------------------------------------------------------------------- /dc_gym/inputs/fattree/test: -------------------------------------------------------------------------------- 1 | src,dst,port,seed,start_time,stop_time,flow_size,flow_size_pattern,reps,flow_gap,random_gap 2 | 127.0.0.1,127.0.0.1,12345,1,0.0,60.0,2147483647,exact,-1,0.001,exact 3 | #206.12.64.149,127.0.0.1,22345,UDP,1,0.0,60.0,2147483647,exact,-1,0.001,exact 4 | -------------------------------------------------------------------------------- /dc_gym/inputs/nonblock: -------------------------------------------------------------------------------- 1 | fattree -------------------------------------------------------------------------------- /dc_gym/iroko_reward.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | import logging 4 | log = logging.getLogger(__name__) 5 | 6 | 7 | def fairness_reward(actions, queues=None): 8 | """Compute Jain"s fairness index for a list of values. 9 | See http://en.wikipedia.org/wiki/Fairness_measure for fairness equations. 10 | @param values: list of values 11 | @return fairness: JFI 12 | """ 13 | if len(actions) == 0: 14 | return 1.0 15 | num = sum(actions) ** 2 16 | denom = len(actions) * sum([i ** 2 for i in actions]) 17 | return num / float(denom) 18 | 19 | 20 | def gini_reward(actions, queues=None): 21 | """Calculate the Gini coefficient of a numpy array.""" 22 | # based on bottom eq: 23 | # http://www.statsdirect.com/help/generatedimages/equations/equation154.svg 24 | # from: 25 | # http://www.statsdirect.com/help/default.htm#nonparametric_methods/gini.htm 26 | # All values are treated equally, arrays must be 1d: 27 | # Values must be sorted: 28 | actions = np.sort(actions) 29 | # Number of array elements: 30 | n = actions.shape[0] 31 | # Index per array element: 32 | index = np.arange(1, n + 1) 33 | # Gini coefficient: 34 | return ((np.sum((2 * index - n - 1) * actions)) / (n * np.sum(actions))) 35 | 36 | 37 | def action_reward(actions, queues=None): 38 | return np.mean(actions) 39 | 40 | 41 | def fair_queue_reward(actions, queues): 42 | queue = np.max(queues) 43 | action = np.mean(actions) 44 | fairness = fairness_reward(actions[actions < 1.0]) 45 | reward = action - queue * action + (fairness * (1 - queue)) 46 | return reward 47 | 48 | 49 | def joint_queue_reward(actions, queues): 50 | queue = np.max(queues) 51 | action = np.mean(actions) 52 | reward = action - 2 * (queue * action) 53 | return reward 54 | 55 | 56 | def step_reward(actions, queues): 57 | queue = np.max(queues) 58 | action = np.mean(actions) 59 | if queue > 0.30: 60 | return -action - queue 61 | else: 62 | return action * (1 + (1 - gini_reward(actions))) - queue 63 | 64 | 65 | def std_dev_reward(actions, queues=None): 66 | return -np.std(actions) 67 | 68 | 69 | def queue_reward(actions, queues): 70 | queue_reward = -np.sum(queues)**2 71 | return queue_reward 72 | 73 | 74 | def selu_reward(reward): 75 | alpha = 1.6732632423543772848170429916717 76 | scale = 1.0507009873554804934193349852946 77 | return scale * (max(0, reward) + min(0, alpha * (math.exp(reward) - 1))) 78 | 79 | 80 | class RewardFunction: 81 | __slots__ = ["stats_dict", "reward_funs"] 82 | 83 | def __init__(self, reward_models, stats_dict): 84 | self.stats_dict = stats_dict 85 | self.reward_funs = self._set_reward(reward_models) 86 | 87 | def _set_reward(self, reward_models): 88 | reward_funs = [] 89 | for model in reward_models: 90 | reward_funs.append(globals()["%s_reward" % model]) 91 | return reward_funs 92 | 93 | def get_reward(self, stats, actions): 94 | queues = stats[self.stats_dict["backlog"]] 95 | reward = 0.0 96 | for reward_fun in self.reward_funs: 97 | reward += reward_fun(actions, queues) 98 | return reward 99 | 100 | 101 | # small script to visualize the reward output 102 | if __name__ == "__main__": 103 | import matplotlib.pyplot as plt 104 | queues = [i * 0.1 for i in range(0, 11)] 105 | actions = [i * .001 for i in range(0, 1000)] 106 | for queue in queues: 107 | rewards = [] 108 | queue_input = np.array([queue]) 109 | for action in actions: 110 | action_input = np.array([action]) 111 | rewards.append((joint_queue_reward(action_input, queue_input))) 112 | plt.plot(actions, rewards, label="Queue Size %f" % queue) 113 | plt.xlabel("Action Input") 114 | plt.ylabel("Reward") 115 | plt.legend() 116 | plt.show() 117 | -------------------------------------------------------------------------------- /dc_gym/iroko_sampler.py: -------------------------------------------------------------------------------- 1 | import os 2 | import multiprocessing 3 | import time 4 | import logging 5 | import shelve 6 | log = logging.getLogger(__name__) 7 | 8 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 9 | 10 | 11 | class StatsSampler(multiprocessing.Process): 12 | def __init__(self, stats, actions, reward, output_dir): 13 | multiprocessing.Process.__init__(self) 14 | self.name = "SampleCollector" 15 | self.stat_file = f"{output_dir}/statistics.npy" 16 | self.stats = stats 17 | self.actions = actions 18 | self.reward = reward 19 | self.stat_shelve = None 20 | self._set_data_checkpoints() 21 | self.kill = multiprocessing.Event() 22 | 23 | def run(self): 24 | while not self.kill.is_set(): 25 | try: 26 | self._checkpoint() 27 | except KeyboardInterrupt: 28 | log.error("%s: Caught Interrupt! Exiting...", self.name) 29 | self.kill.set() 30 | time.sleep(0.1) 31 | self._clean() 32 | 33 | def _set_data_checkpoints(self): 34 | if self.stat_shelve: 35 | return 36 | # define file name 37 | self.stat_shelve = {} 38 | self.stat_shelve = shelve.open(self.stat_file, 'c', writeback=True) 39 | self.stat_shelve["reward"] = [] 40 | self.stat_shelve["actions"] = [] 41 | self.stat_shelve["stats"] = [] 42 | self.stat_shelve["num_samples"] = 0 43 | 44 | def stop(self): 45 | log.info("%s: Received termination signal! Exiting..", self.name) 46 | self.kill.set() 47 | 48 | def close(self): 49 | self.stop() 50 | self.stat_shelve.close() 51 | 52 | def _clean(self): 53 | if self.stat_shelve: 54 | try: 55 | self._flush() 56 | except Exception as e: 57 | log.error("Error flushing file %s:\n%s", self.stat_file, e) 58 | self.stat_shelve = None 59 | 60 | def _checkpoint(self): 61 | # Save collected data 62 | self.stat_shelve["stats"].append(self.stats.copy()) 63 | self.stat_shelve["reward"].append(self.reward.value) 64 | self.stat_shelve["actions"].append(self.actions.copy()) 65 | self.stat_shelve["num_samples"] += 1 66 | 67 | def _flush(self): 68 | if self.stat_shelve: 69 | log.info("Writing collected data to disk") 70 | self.stat_shelve.sync() 71 | log.info("Done saving statistics...") 72 | -------------------------------------------------------------------------------- /dc_gym/iroko_state.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import RawArray 2 | from ctypes import c_ulong, c_ubyte 3 | import numpy as np 4 | 5 | from dc_gym.monitor.iroko_monitor import BandwidthCollector 6 | from dc_gym.monitor.iroko_monitor import QueueCollector 7 | from dc_gym.monitor.iroko_monitor import FlowCollector 8 | from dc_gym.iroko_reward import RewardFunction 9 | import dc_gym.utils as dc_utils 10 | import logging 11 | log = logging.getLogger(__name__) 12 | 13 | 14 | class StateManager: 15 | __slots__ = ["num_ports", "deltas", "prev_stats", "stats_keys", 16 | "stats_dict", "dopamin", "stats", "flow_stats", "procs", 17 | "collect_flows", "reward_model"] 18 | 19 | def __init__(self, conf, net_man, stats_dict): 20 | self.stats = None 21 | self.prev_stats = None 22 | self.flow_stats = None 23 | self.deltas = None 24 | self.procs = [] 25 | self.stats_dict = stats_dict 26 | 27 | self.stats_keys = conf["state_model"] 28 | self.collect_flows = conf["collect_flows"] 29 | self.reward_model = conf["reward_model"] 30 | 31 | self.num_ports = net_man.get_num_sw_ports() 32 | num_hosts = net_man.get_num_hosts() 33 | self.dopamin = RewardFunction(self.reward_model, self.stats_dict) 34 | self._init_stats_matrices(self.num_ports, num_hosts) 35 | self._spawn_collectors(net_man) 36 | 37 | def stop(self): 38 | self.stats.fill(0) 39 | self.prev_stats.fill(0) 40 | 41 | def close(self): 42 | self.stop() 43 | self._terminate_collectors() 44 | 45 | def _init_stats_matrices(self, num_ports, num_hosts): 46 | # Set up the shared stats matrix 47 | stats_arr_len = num_ports * len(self.stats_dict) 48 | mp_stats = RawArray(c_ulong, stats_arr_len) 49 | np_stats = dc_utils.shmem_to_nparray(mp_stats, np.float64) 50 | self.stats = np_stats.reshape((len(self.stats_dict), num_ports)) 51 | # Set up the shared flow matrix 52 | if (self.collect_flows): 53 | flow_arr_len = num_ports * num_hosts * 2 54 | mp_flows = RawArray(c_ubyte, flow_arr_len) 55 | np_flows = dc_utils.shmem_to_nparray(mp_flows, np.uint8) 56 | self.flow_stats = np_flows.reshape((num_ports, 2, num_hosts)) 57 | # Save the initialized stats matrix to compute deltas 58 | self.prev_stats = self.stats.copy() 59 | self.deltas = np.zeros(shape=(len(self.stats_dict), num_ports)) 60 | 61 | def _spawn_collectors(self, net_man): 62 | sw_ports = net_man.get_sw_ports() 63 | host_ports = net_man.get_host_ports() 64 | # Launch an asynchronous queue collector 65 | proc = QueueCollector( 66 | sw_ports, self.stats, self.stats_dict, net_man.topo.max_queue) 67 | proc.start() 68 | self.procs.append(proc) 69 | # Launch an asynchronous bandwidth collector 70 | proc = BandwidthCollector( 71 | host_ports, self.stats, self.stats_dict, net_man.topo.max_bps) 72 | proc.start() 73 | self.procs.append(proc) 74 | # Launch an asynchronous flow collector 75 | if (self.collect_flows): 76 | host_ips = net_man.topo.host_ips.values() 77 | proc = FlowCollector(sw_ports, host_ips, self.flow_stats) 78 | proc.start() 79 | self.procs.append(proc) 80 | 81 | def _terminate_collectors(self): 82 | for proc in self.procs: 83 | if proc is not None: 84 | proc.terminate() 85 | 86 | def _compute_deltas(self, stats_prev, stats_now): 87 | self.deltas = stats_now - stats_prev 88 | self.deltas[self.deltas < 0] = -1 89 | self.deltas[self.deltas > 0] = 1 90 | 91 | def get_stats(self): 92 | return self.stats 93 | 94 | def observe(self): 95 | obs = [] 96 | # retrieve the current deltas before updating total values 97 | self._compute_deltas(self.prev_stats, self.stats) 98 | self.prev_stats = self.stats.copy() 99 | # Create the data matrix for the agent based on the collected stats 100 | for index in range(self.num_ports): 101 | for key in self.stats_keys: 102 | if (key.startswith("d_")): 103 | # remove the first two chars and get the actual key 104 | obs.append(self.deltas[self.stats_dict[key[2:]]][index]) 105 | else: 106 | obs.append(self.stats[self.stats_dict[key]][index]) 107 | if self.collect_flows: 108 | obs.extend(self.flow_stats[index]) 109 | return obs 110 | 111 | def get_reward(self, curr_action): 112 | # Compute the reward 113 | return self.dopamin.get_reward(self.stats, curr_action) 114 | -------------------------------------------------------------------------------- /dc_gym/iroko_traffic.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import csv 4 | import time 5 | 6 | import dc_gym.utils as dc_utils 7 | import logging 8 | log = logging.getLogger(__name__) 9 | 10 | # The binaries are located in the control subfolder 11 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 12 | 13 | 14 | def parse_traffic_file(traffic_file): 15 | if not os.path.isfile(traffic_file): 16 | log.info("The input traffic pattern does not exist.") 17 | return None 18 | traffic_pattern = [] 19 | with open(traffic_file, 'r') as tf: 20 | traffic_reader = csv.DictReader(tf) 21 | for row in traffic_reader: 22 | traffic_pattern.append(row) 23 | return traffic_pattern 24 | 25 | 26 | class TrafficGen(): 27 | name = "TrafficGen" 28 | SUPPORTED_TRANSPORT = ["tcp", "udp"] 29 | 30 | def __init__(self, net_man, transport, out_dir): 31 | self.net_man = net_man 32 | self.service_procs = [] 33 | self.traffic_procs = [] 34 | self._set_t_type(transport) 35 | self.out_dir = out_dir 36 | dc_utils.check_dir(out_dir) 37 | self._init_services() 38 | 39 | def start(self, input_file): 40 | self._start_traffic(input_file) 41 | 42 | def stop(self): 43 | self._stop_traffic() 44 | 45 | def close(self): 46 | self._stop_traffic() 47 | self._stop_services() 48 | 49 | def _set_t_type(self, transport): 50 | if transport.lower() in self.SUPPORTED_TRANSPORT: 51 | self.transport = transport.lower() 52 | else: 53 | log.info("Fatal: Unknown transport protocol %s!" % 54 | transport.lower()) 55 | log.info("Supported protocols are: ") 56 | for transport in self.SUPPORTED_TRANSPORT: 57 | log.info(transport) 58 | exit(1) 59 | 60 | def check_if_traffic_alive(self): 61 | """ Return false if any of the processes has terminated """ 62 | for proc in self.traffic_procs: 63 | poll = proc.poll() 64 | if poll is None: 65 | return True 66 | return False 67 | 68 | def _start_servers(self, hosts, traffic_gen, out_dir): 69 | log.info("Starting servers") 70 | for host in hosts: 71 | out_file = "%s/%s_server" % (out_dir, host.name) 72 | server_cmd = traffic_gen 73 | s_proc = dc_utils.start_process(server_cmd, host, out_file) 74 | self.service_procs.append(s_proc) 75 | 76 | def _start_controllers(self, hosts, out_dir): 77 | # The binary of the host rate limiter 78 | traffic_ctrl = FILE_DIR + "/control/go_ctrl" 79 | if not os.path.isfile(traffic_ctrl): 80 | log.info("The traffic controller does not exist.\n" 81 | "Run the install.sh script to compile it.") 82 | dc_utils.kill_processes(self.service_procs) 83 | exit(1) 84 | log.info("Starting controllers") 85 | for host in hosts: 86 | iface_net = host.intfList()[0] 87 | ifaces_ctrl = host.intfList()[1] 88 | out_file = "%s/%s_ctrl" % (out_dir, host.name) 89 | ctrl_cmd = "%s " % traffic_ctrl 90 | ctrl_cmd += "-n %s " % iface_net 91 | ctrl_cmd += "-c %s " % ifaces_ctrl 92 | ctrl_cmd += "-r %d " % self.net_man.topo.conf["max_capacity"] 93 | c_proc = dc_utils.start_process(ctrl_cmd, host, out_file) 94 | self.service_procs.append(c_proc) 95 | 96 | def _start_client(self, traffic_gen, host, out_dir, dst_hosts): 97 | if not dst_hosts: 98 | return 99 | dst_string = "" 100 | for dst in dst_hosts: 101 | dst_string += "%s," % dst 102 | dst_string = dst_string[:len(dst_string) - 1] 103 | out_file = "%s/%s_client" % (out_dir, host.name) 104 | max_rate = self.net_man.topo.conf["max_capacity"] / 1e6 105 | # start the actual client 106 | traffic_cmd = "%s " % traffic_gen 107 | # FIXME: Duration is hardcoded 108 | traffic_cmd += "--totalDuration %d " % 60 109 | traffic_cmd += "--totalFlow %d " % (max_rate * 100000) 110 | traffic_cmd += "--hosts %s " % dst_string 111 | traffic_cmd += "--maxSpeed %d " % max_rate 112 | traffic_cmd += "--passiveServer " 113 | traffic_cmd += "--csv %s/%%d-%%s.csv " % out_dir 114 | if self.transport == "udp": 115 | traffic_cmd += "-udp " 116 | t_proc = dc_utils.start_process(traffic_cmd, host, out_file) 117 | self.traffic_procs.append(t_proc) 118 | 119 | def _start_pkt_capture_tshark(self, out_dir): 120 | # start a tshark capture process 121 | dmp_file = "%s/pkt_snapshot.pcap" % (out_dir) 122 | dmp_cmd = "tshark " 123 | for host_iface in self.net_man.host_ctrl_map: 124 | dmp_cmd += "-i %s " % host_iface 125 | dmp_cmd += "-w %s " % dmp_file 126 | dmp_cmd += "-f %s " % self.transport # filter transport protocol 127 | dmp_cmd += "-b duration:300 " # reset pcap file after 300s 128 | dmp_cmd += "-b filesize:%d " % 10e5 # reset pcap file after 1GB 129 | dmp_cmd += "-b files:1 " # only write one capture file 130 | dmp_cmd += "-B 500 " # mb size of the packet buffer 131 | dmp_cmd += "-q " # do not log.info to stdout 132 | dmp_cmd += "-n " # do not resolve hosts 133 | dmp_cmd += "-F pcapng " # format of the capture file 134 | dmp_proc = dc_utils.exec_process(dmp_cmd, out_file=dmp_file) 135 | self.service_procs.append(dmp_proc) 136 | 137 | def _start_pkt_capture_tcpdump(self, host, out_dir): 138 | # start a tcpdump capture process 139 | iface_net = host.intfList()[0] 140 | dmp_file = "%s/%s.pcap" % (out_dir, host.name) 141 | dmp_cmd = "tcpdump " 142 | dmp_cmd += "-i %s " % iface_net 143 | dmp_cmd += "-C 50 " # roll over every 100 MB 144 | dmp_cmd += "-w %s " % dmp_file 145 | dmp_cmd += "-W 2 " # rotate two files 146 | dmp_cmd += "%s " % self.transport # filter for transport protocol 147 | dmp_cmd += "-Z root " 148 | dmp_cmd += "-s96 " # Capture only headers 149 | dmp_proc = dc_utils.start_process(dmp_cmd, host, dmp_file) 150 | self.service_procs.append(dmp_proc) 151 | 152 | def _start_generators(self, hosts, input_file, traffic_gen, out_dir): 153 | log.info("Loading file: %s" % input_file) 154 | if not os.path.basename(input_file) == "all": 155 | traffic_pattern = parse_traffic_file(input_file) 156 | if traffic_pattern is None: 157 | log.error("No traffic pattern provided!") 158 | dc_utils.kill_processes(self.service_procs, use_sigkill=True) 159 | exit(1) 160 | log.info("Starting load-generators") 161 | if os.path.basename(input_file) == "all": 162 | # generate an all-to-all pattern 163 | for src_host in hosts: 164 | dst_hosts = [] 165 | for dst_host in hosts: 166 | if src_host != dst_host: 167 | dst_hosts.append(dst_host.intfList()[0].IP()) 168 | self._start_client(traffic_gen, src_host, out_dir, dst_hosts) 169 | else: 170 | for src_host in hosts: 171 | host_ip = src_host.intfList()[0].IP() 172 | dst_hosts = [] 173 | # generate a pattern according to the traffic matrix 174 | for config_row in traffic_pattern: 175 | if host_ip == config_row["src"]: 176 | dst_hosts.append(config_row["dst"]) 177 | self._start_client(traffic_gen, src_host, out_dir, dst_hosts) 178 | # self._start_pkt_capture_tcpdump(src_host, out_dir) 179 | 180 | def _init_services(self): 181 | """ Run the servers and monitors on all the host interfaces """ 182 | hosts = self.net_man.get_net().hosts 183 | # The binary of the traffic generator 184 | traffic_gen = FILE_DIR + "/goben" 185 | if not os.path.isfile(traffic_gen): 186 | log.info("The traffic generator does not exist.\n" 187 | "Run the install.sh script with the --goben" 188 | " option to compile it.") 189 | exit(1) 190 | # Suppress output of the traffic generators 191 | traffic_gen += " --silent " 192 | self._start_servers(hosts, traffic_gen, self.out_dir) 193 | self._start_controllers(hosts, self.out_dir) 194 | # self._start_pkt_capture(self.out_dir) 195 | # wait for load controllers to initialize 196 | time.sleep(0.5) 197 | 198 | def _stop_services(self): 199 | log.info("") 200 | log.info("Stopping services") 201 | dc_utils.kill_processes(self.service_procs, use_sigkill=True) 202 | del self.service_procs[:] 203 | sys.stdout.flush() 204 | 205 | def _start_traffic(self, input_file): 206 | """ Run the traffic generators""" 207 | if not input_file: 208 | log.error("No traffic file provided!") 209 | exit(1) 210 | hosts = self.net_man.get_net().hosts 211 | # The binary of the traffic generator 212 | traffic_gen = FILE_DIR + "/goben" 213 | # Suppress output of the traffic generators 214 | traffic_gen += " --silent " 215 | 216 | log.info("Starting traffic") 217 | self._start_generators(hosts, input_file, traffic_gen, self.out_dir) 218 | 219 | def _stop_traffic(self): 220 | log.info("") 221 | log.info("Stopping traffic processes") 222 | dc_utils.kill_processes(self.traffic_procs) 223 | del self.traffic_procs[:] 224 | sys.stdout.flush() 225 | -------------------------------------------------------------------------------- /dc_gym/monitor/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /dc_gym/monitor/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -O3 -g 3 | LFLAGS= -Wl,--as-needed -lnl-3 -lnl-route-3 4 | LIBNAME=libqdisc_stats.so 5 | 6 | all: qdisc_stats.c 7 | $(CC) $(CFLAGS) -fPIC -c $< -o qdisc_stats -I /usr/include/libnl3/ $(LFLAGS) 8 | $(CC) $(CFLAGS) -shared -o $(LIBNAME) qdisc_stats -lnl-3 -lnl-route-3 9 | 10 | clean: 11 | rm -rf *.o .so qdisc_stats 12 | 13 | -------------------------------------------------------------------------------- /dc_gym/monitor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcgym/iroko/7941dd2a2d32d74cba11c1ea9118e9b23b8e1aa2/dc_gym/monitor/__init__.py -------------------------------------------------------------------------------- /dc_gym/monitor/iroko_monitor.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import multiprocessing 3 | import ctypes 4 | import os 5 | import time 6 | import logging 7 | log = logging.getLogger(__name__) 8 | 9 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 10 | 11 | 12 | class Collector(multiprocessing.Process): 13 | 14 | def __init__(self, iface_list): 15 | multiprocessing.Process.__init__(self) 16 | self.name = "Collector" 17 | self.iface_list = iface_list 18 | self.kill = multiprocessing.Event() 19 | 20 | def set_interfaces(self): 21 | cmd = "sudo ovs-vsctl list-br | xargs -L1 sudo ovs-vsctl list-ports" 22 | output = subprocess.check_output(cmd, shell=True).decode() 23 | iface_list_temp = [] 24 | for row in output.split("\n"): 25 | if row != "": 26 | iface_list_temp.append(row) 27 | self.iface_list = iface_list_temp 28 | 29 | def run(self): 30 | while not self.kill.is_set(): 31 | try: 32 | self._collect() 33 | except KeyboardInterrupt: 34 | log.error("%s: Caught Interrupt! Exiting..." % self.name) 35 | self.kill.set() 36 | self._clean() 37 | 38 | def _collect(self): 39 | raise NotImplementedError("Method _collect not implemented!") 40 | 41 | def terminate(self): 42 | log.info("%s: Received termination signal! Exiting.." % self.name) 43 | self.kill.set() 44 | 45 | def _clean(self): 46 | pass 47 | 48 | 49 | class BandwidthCollector(Collector): 50 | 51 | def __init__(self, iface_list, shared_stats, stats_dict, max_bps): 52 | Collector.__init__(self, iface_list) 53 | self.name = "StatsCollector" 54 | self.stats = shared_stats 55 | self.max_bps = max_bps 56 | self.stats_dict = stats_dict 57 | self.stats_offset = len(stats_dict) 58 | 59 | def _get_bandwidths(self, iface_list): 60 | 61 | processes = [] 62 | for iface in iface_list: 63 | cmd = (" ifstat -i %s -b -q 0.5 1 | awk \'{if (NR==3) print $0}\' | \ 64 | awk \'{$1=$1}1\' OFS=\", \"" % (iface)) 65 | proc = subprocess.Popen([cmd], stdout=subprocess.PIPE, 66 | shell=True) 67 | processes.append((proc, iface)) 68 | 69 | for index, (proc, iface) in enumerate(processes): 70 | proc.wait() 71 | output, _ = proc.communicate() 72 | output = output.decode() 73 | bw = output.split(',') 74 | if bw[0] != 'n/a' and bw[1] != ' n/a\n': 75 | bps_rx = float(bw[0]) * 1000.0 / float(self.max_bps) 76 | bps_tx = float(bw[1]) * 1000.0 / float(self.max_bps) 77 | self.stats[self.stats_dict["bw_rx"]][index] = bps_rx 78 | self.stats[self.stats_dict["bw_tx"]][index] = bps_tx 79 | 80 | def _collect(self): 81 | self._get_bandwidths(self.iface_list) 82 | 83 | 84 | class Qdisc(ctypes.Structure): 85 | pass 86 | 87 | 88 | class QueueCollector(Collector): 89 | 90 | def __init__(self, iface_list, shared_stats, stats_dict, max_queue): 91 | Collector.__init__(self, iface_list) 92 | self.name = "QueueCollector" 93 | self.stats = shared_stats 94 | self.stats_dict = stats_dict 95 | self.max_queue = max_queue 96 | self.stats_offset = len(stats_dict) 97 | self.q_lib = self._init_stats() 98 | 99 | def _init_stats(self): 100 | # init qdisc C library 101 | q_lib = ctypes.CDLL(FILE_DIR + "/libqdisc_stats.so") 102 | q_lib.init_qdisc_monitor.argtypes = [ctypes.c_char_p] 103 | q_lib.init_qdisc_monitor.restype = ctypes.POINTER(Qdisc) 104 | return q_lib 105 | 106 | # def _init_qdiscs(self, iface_list, q_lib): 107 | # self.qdisc_map = {} 108 | # for iface in iface_list: 109 | # qdisc = q_lib.init_qdisc_monitor(iface) 110 | # self.qdisc_map[iface] = qdisc 111 | 112 | # def _clean(self): 113 | # for iface in self.iface_list: 114 | # qdisc = self.qdisc_map[iface] 115 | # self.q_lib.delete_qdisc_monitor(qdisc) 116 | 117 | def _get_qdisc_stats(self, iface_list): 118 | for index, iface in enumerate(iface_list): 119 | qdisc = self.q_lib.init_qdisc_monitor(iface.encode("ascii")) 120 | if not qdisc: 121 | log.error("Fatal Error when trying to set up a qdisc") 122 | self.kill.set() 123 | return 124 | queue_backlog = float(self.q_lib.get_qdisc_backlog(qdisc)) 125 | queue_backlog /= float(self.max_queue) 126 | queue_drops = self.q_lib.get_qdisc_drops(qdisc) 127 | queue_overlimits = self.q_lib.get_qdisc_overlimits(qdisc) 128 | # queue_rate_bps = self.q_lib.get_qdisc_rate_bps(qdisc) 129 | # queue_rate_pps = self.q_lib.get_qdisc_rate_pps(qdisc) 130 | self.stats[self.stats_dict["backlog"]][index] = queue_backlog 131 | self.stats[self.stats_dict["olimit"]][index] = queue_overlimits 132 | self.stats[self.stats_dict["drops"]][index] = queue_drops 133 | # # tx rate 134 | # self.stats[index][self.stats_dict["rate_bps"]] = queue_rate_bps 135 | # # packet rate 136 | # self.stats[index][self.stats_dict["rate_pps"]] = queue_rate_pps 137 | self.q_lib.delete_qdisc_monitor(qdisc) 138 | 139 | def _collect(self): 140 | self._get_qdisc_stats(self.iface_list) 141 | # We are too fast, let it rest for a bit... 142 | time.sleep(0.001) 143 | 144 | 145 | class FlowCollector(Collector): 146 | 147 | def __init__(self, iface_list, host_ips, shared_flows): 148 | Collector.__init__(self, iface_list) 149 | self.name = "FlowCollector" 150 | self.host_ips = host_ips 151 | self.shared_flows = shared_flows 152 | 153 | def _get_flow_stats(self, iface_list): 154 | processes = [] 155 | for iface in iface_list: 156 | cmd = "sudo timeout 1 tcpdump -l -i %s " % iface 157 | cmd += "-n -c 50 ip 2>/dev/null | " 158 | cmd += "grep -P -o \'([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+).*? > " 159 | cmd += "([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)\' | " 160 | cmd += "grep -P -o \'[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\' | " 161 | cmd += "xargs -n 2 echo | awk \'!a[$0]++\'" 162 | # output = subprocess.check_output(cmd, shell=True) 163 | proc = subprocess.Popen( 164 | [cmd], stdout=subprocess.PIPE, shell=True) 165 | processes.append((proc, iface)) 166 | for index, (proc, iface) in enumerate(processes): 167 | proc.wait() 168 | output, _ = proc.communicate() 169 | output = output.decode() 170 | for row in output.split("\n"): 171 | if row != "": 172 | src, dst = row.split(" ") 173 | for i, ip in enumerate(self.host_ips): 174 | i_src = 0 175 | i_dst = 1 176 | self.shared_flows[index][i_src][i] = 0 177 | self.shared_flows[index][i_dst][i] = 0 178 | if src == ip: 179 | self.shared_flows[index][i_src][i] = 1 180 | if dst == ip: 181 | self.shared_flows[index][i_dst][i] = 1 182 | 183 | def _collect(self): 184 | self._get_flow_stats(self.iface_list) 185 | -------------------------------------------------------------------------------- /dc_gym/monitor/qdisc_stats.c: -------------------------------------------------------------------------------- 1 | #include // if_nametoindex 2 | #include 3 | #include // nl_object_free() 4 | 5 | 6 | struct rtnl_qdisc *init_qdisc_monitor(char *interface) { 7 | struct nl_sock *sock; 8 | struct nl_cache *qdisc_cache; 9 | struct rtnl_qdisc *qdisc; 10 | int ifindex, err; 11 | ifindex = if_nametoindex(interface); 12 | /* Allocate a netlink socket and connect it with the netlink route module */ 13 | sock = nl_socket_alloc(); 14 | if(!sock) 15 | fprintf(stderr,"Could not allocated socket!\n"); 16 | err = nl_connect(sock, NETLINK_ROUTE); 17 | if (err) 18 | fprintf(stderr,"nl_connect: %s\n", nl_geterror(err)); 19 | /* Get all active qdiscs and find the main qdisc of the target interface*/ 20 | err =rtnl_qdisc_alloc_cache(sock, &qdisc_cache); 21 | if (err) 22 | fprintf(stderr,"qdisc_alloc_cache: %s\n", nl_geterror(err)); 23 | qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); 24 | if(!qdisc) { 25 | fprintf(stderr,"Qdisc for interface %s not found!\n", interface); 26 | return NULL; 27 | } 28 | /* Free all allocated data structures */ 29 | nl_cache_free(qdisc_cache); 30 | nl_socket_free(sock); 31 | return qdisc; 32 | } 33 | 34 | int get_qdisc_packets(struct rtnl_qdisc *qdisc) { 35 | /* Query current queue length on the interface */ 36 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_PACKETS); 37 | return get_qdisc_backlog; 38 | } 39 | 40 | int get_qdisc_bytes(struct rtnl_qdisc *qdisc) { 41 | /* Query current queue length on the interface */ 42 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_BYTES); 43 | return get_qdisc_backlog; 44 | } 45 | 46 | int get_qdisc_rate_bps(struct rtnl_qdisc *qdisc) { 47 | /* Query current queue length on the interface */ 48 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_RATE_BPS); 49 | return get_qdisc_backlog; 50 | } 51 | 52 | int get_qdisc_rate_pps(struct rtnl_qdisc *qdisc) { 53 | /* Query current queue length on the interface */ 54 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_RATE_PPS); 55 | return get_qdisc_backlog; 56 | } 57 | 58 | int get_qdisc_qlen(struct rtnl_qdisc *qdisc) { 59 | /* Query current queue length on the interface */ 60 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_QLEN); 61 | return get_qdisc_backlog; 62 | } 63 | 64 | int get_qdisc_backlog(struct rtnl_qdisc *qdisc) { 65 | /* Query current queue length on the interface */ 66 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_BACKLOG); 67 | return get_qdisc_backlog; 68 | } 69 | 70 | int get_qdisc_drops(struct rtnl_qdisc *qdisc) { 71 | /* Query current queue length on the interface */ 72 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS); 73 | return get_qdisc_backlog; 74 | } 75 | 76 | int get_qdisc_requeues(struct rtnl_qdisc *qdisc) { 77 | /* Query current queue length on the interface */ 78 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_REQUEUES); 79 | return get_qdisc_backlog; 80 | } 81 | 82 | int get_qdisc_overlimits(struct rtnl_qdisc *qdisc) { 83 | /* Query current queue length on the interface */ 84 | int get_qdisc_backlog = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_OVERLIMITS); 85 | return get_qdisc_backlog; 86 | } 87 | 88 | void delete_qdisc_monitor(struct rtnl_qdisc *qdisc) { 89 | nl_object_free((struct nl_object *) qdisc); 90 | 91 | } 92 | // Minimal test to verify functionality 93 | // int main(int argc, char ** argv) { 94 | // int num_ifaces = 1; 95 | // char *ifaces[] = {"enp0s31f6"}; 96 | 97 | // for (int i = 0; i < num_ifaces; i++) { 98 | // int queue_len = get_iface_queue(ifaces[i]); 99 | // printf("%d ", queue_len); 100 | // } 101 | // printf("\n"); 102 | // return 0; 103 | // } -------------------------------------------------------------------------------- /dc_gym/monitor/test_qdisc_stats.py: -------------------------------------------------------------------------------- 1 | """ Simple test suite to verify the functionality of the bandwidth 2 | control library. Hardcoded. """ 3 | 4 | import ctypes 5 | import os 6 | 7 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 8 | 9 | 10 | class Qdisc(ctypes.Structure): 11 | pass 12 | 13 | 14 | q_lib = ctypes.CDLL(FILE_DIR + "/libqdisc_stats.so") 15 | q_lib.init_qdisc_monitor.argtypes = [ctypes.c_char_p] 16 | q_lib.init_qdisc_monitor.restype = ctypes.POINTER(Qdisc) 17 | qdisc = q_lib.init_qdisc_monitor("sw1-eth1") 18 | qdisc2 = q_lib.init_qdisc_monitor("sw1-eth3") 19 | print(q_lib.get_qdisc_backlog(qdisc)) 20 | print(q_lib.get_qdisc_drops(qdisc)) 21 | print(q_lib.get_qdisc_overlimits(qdisc)) 22 | print(q_lib.get_qdisc_packets(qdisc)) 23 | print(q_lib.get_qdisc_backlog(qdisc2)) 24 | print(q_lib.get_qdisc_drops(qdisc2)) 25 | print(q_lib.get_qdisc_overlimits(qdisc2)) 26 | print(q_lib.get_qdisc_packets(qdisc2)) 27 | q_lib.delete_qdisc_monitor(qdisc) 28 | q_lib.delete_qdisc_monitor(qdisc2) 29 | -------------------------------------------------------------------------------- /dc_gym/topos/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcgym/iroko/7941dd2a2d32d74cba11c1ea9118e9b23b8e1aa2/dc_gym/topos/__init__.py -------------------------------------------------------------------------------- /dc_gym/topos/topo_base.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from mininet.log import setLogLevel 4 | from mininet.topo import Topo 5 | 6 | import logging 7 | log = logging.getLogger(__name__) 8 | 9 | cwd = os.getcwd() 10 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 11 | sys.path.insert(0, FILE_DIR) 12 | 13 | DEFAULT_CONF = { 14 | "max_capacity": 10e6, # max bw capacity of link in bytes 15 | "min_capacity": 0.1e6, # min possible bw of an interface in bytes 16 | "num_hosts": "0", # the initial number of hosts is zero 17 | "id": "" # ids support multiple topologies 18 | } 19 | 20 | 21 | def calculate_max_queue(max_bps): 22 | queue = 4e6 23 | if max_bps < 1e9: 24 | queue = 4e6 / (1e9 / max_bps) 25 | # keep a sensible minimum size 26 | if queue < 4e5: 27 | queue = 4e5 28 | return queue 29 | 30 | 31 | def get_log_level(log_level): 32 | if log_level == 50: 33 | return "critical" 34 | elif log_level == 40: 35 | return "error" 36 | elif log_level == 30: 37 | return "warning" 38 | elif log_level == 20: 39 | return "info" 40 | elif log_level == 10: 41 | return "debug" 42 | else: 43 | return "output" 44 | 45 | 46 | class BaseTopo(Topo): 47 | 48 | def __init__(self, conf={}): 49 | Topo.__init__(self) 50 | self.conf = DEFAULT_CONF 51 | self.conf.update(conf) 52 | self.name = "base" 53 | self.host_list = [] 54 | self.host_ips = {} 55 | self.max_bps = self.conf["max_capacity"] 56 | self.switch_id = self.conf["id"] 57 | self.max_queue = calculate_max_queue(self.max_bps) 58 | setLogLevel(get_log_level(log.level)) 59 | 60 | def _config_topo(self, ovs_v, is_ecmp): 61 | raise NotImplementedError("Method _config_topo not implemented!") 62 | 63 | def get_traffic_pattern(self, index): 64 | # start an all-to-all pattern if the list index is -1 65 | if index == -1: 66 | return "all" 67 | return self.conf["traffic_files"][index] 68 | 69 | def create_topo(self): 70 | self.create_nodes() 71 | self.create_links() 72 | 73 | def get_num_sw_ports(self): 74 | sw_ports = 0 75 | for node, links in self.ports.items(): 76 | if self.isSwitch(node): 77 | sw_ports += len(links) 78 | return sw_ports 79 | 80 | def get_num_hosts(self): 81 | return self.conf["num_hosts"] 82 | 83 | def get_name(self): 84 | return self.name 85 | -------------------------------------------------------------------------------- /dc_gym/topos/topo_dumbbell.py: -------------------------------------------------------------------------------- 1 | from topos.topo_base import BaseTopo 2 | import dc_gym.utils as dc_utils 3 | import logging 4 | log = logging.getLogger(__name__) 5 | 6 | DEFAULT_CONF = { 7 | "num_hosts": 4, # number of hosts in the topology 8 | "traffic_files": ["incast_2", "incast_4", "incast_8", "incast_16", 9 | "incast_32", "incast_64", "incast_128", "incast_256", 10 | "incast_512", "incast_1024"], 11 | } 12 | 13 | 14 | class IrokoTopo(BaseTopo): 15 | """ 16 | A Dumbbell Topology Class. 17 | """ 18 | 19 | def __init__(self, conf={}): 20 | self.conf = DEFAULT_CONF 21 | self.conf.update(conf) 22 | BaseTopo.__init__(self, self.conf) 23 | self.name = "dumbbell" 24 | 25 | # Topo initiation 26 | self.switch_w = None 27 | self.switch_e = None 28 | self.hosts_w = [] 29 | self.hosts_e = [] 30 | 31 | def create_nodes(self): 32 | self._create_switches() 33 | self._create_hosts(self.conf["num_hosts"]) 34 | 35 | def _create_switches(self): 36 | sw_w_name = self.switch_id + "s1" 37 | sw_e_name = self.switch_id + "s2" 38 | self.switch_w = self.addSwitch(name=sw_w_name) 39 | self.switch_e = self.addSwitch(name=sw_e_name) 40 | 41 | def _create_hosts(self, num): 42 | """ 43 | Create hosts. 44 | """ 45 | for i in range(num): 46 | name = "h" + str(i) 47 | c_class = i / 510 48 | d_class = i % 510 49 | if (i % 2) == 1: 50 | ip = "10.1.%d.%d" % (c_class, (d_class + 1) / 2) 51 | host = self.addHost(name=name, cpu=1.0 / num, ip=ip) 52 | self.hosts_w.append(host) 53 | else: 54 | ip = "10.2.%d.%d" % (c_class, (d_class + 2) / 2) 55 | host = self.addHost(name=name, cpu=1.0 / num, ip=ip) 56 | self.hosts_e.append(host) 57 | log.info("Host %s IP %s" % (host, ip)) 58 | self.host_ips[host] = ip 59 | 60 | self.host_list = self.hosts_w + self.hosts_e 61 | 62 | def create_links(self): 63 | """ 64 | Add links between switch and hosts. 65 | """ 66 | self.addLink(self.switch_w, self.switch_e) 67 | for host in self.hosts_w: 68 | self.addLink(self.switch_w, host) 69 | for host in self.hosts_e: 70 | self.addLink(self.switch_e, host) 71 | 72 | def _install_proactive(self): 73 | """ 74 | Install proactive flow entries for the switch. 75 | """ 76 | protocols = ["ip", "arp"] 77 | for prot in protocols: 78 | # West Switch 79 | ovs_flow_cmd = "ovs-ofctl add-flow %s " % self.switch_w 80 | ovs_flow_cmd += "-O OpenFlow13 " 81 | for index, host in enumerate(self.hosts_w): 82 | port = index + 2 83 | host_ip = self.host_ips[host] 84 | cmd = ovs_flow_cmd 85 | cmd += "table=0,idle_timeout=0," 86 | cmd += "hard_timeout=0,priority=10," 87 | cmd += "%s," % prot 88 | cmd += "nw_dst=%s," % host_ip 89 | cmd += "actions=output:%d" % port 90 | dc_utils.exec_process(cmd) 91 | cmd = ovs_flow_cmd 92 | cmd += "table=0,idle_timeout=0,hard_timeout=0,priority=10," 93 | cmd += "%s," % prot 94 | cmd += "nw_dst=10.2.0.0/16,actions=output:1" 95 | dc_utils.exec_process(cmd) 96 | 97 | # East Switch 98 | ovs_flow_cmd = "ovs-ofctl add-flow %s " % self.switch_e 99 | ovs_flow_cmd += "-O OpenFlow13 " 100 | for index, host in enumerate(self.hosts_e): 101 | port = index + 2 102 | host_ip = self.host_ips[host] 103 | cmd = ovs_flow_cmd 104 | cmd += "table=0,idle_timeout=0," 105 | cmd += "hard_timeout=0,priority=10," 106 | cmd += "%s," % prot 107 | cmd += "nw_dst=%s," % host_ip 108 | cmd += "actions=output:%d" % port 109 | dc_utils.exec_process(cmd) 110 | cmd = ovs_flow_cmd 111 | cmd += "table=0,idle_timeout=0,hard_timeout=0,priority=10," 112 | cmd += "%s," % prot 113 | cmd += "nw_dst=10.1.0.0/16,actions=output:1" 114 | dc_utils.exec_process(cmd) 115 | 116 | def _config_topo(self): 117 | # Set hosts IP addresses. 118 | self._install_proactive() 119 | -------------------------------------------------------------------------------- /dc_gym/topos/topo_fattree.py: -------------------------------------------------------------------------------- 1 | from topos.topo_base import BaseTopo 2 | import dc_gym.utils as dc_utils 3 | import logging 4 | log = logging.getLogger(__name__) 5 | 6 | DEFAULT_CONF = { 7 | # number of hosts in the topology 8 | "num_hosts": 16, 9 | "traffic_files": ["stag_prob_0_2_3_data", "stag_prob_1_2_3_data", 10 | "stag_prob_2_2_3_data", "stag_prob_0_5_3_data", 11 | "stag_prob_1_5_3_data", "stag_prob_2_5_3_data", 12 | "stride1_data", "stride2_data", "stride4_data", 13 | "stride8_data", "random0_data", "random1_data", 14 | "random2_data", "random0_bij_data", "random1_bij_data", 15 | "random2_bij_data", "random_2_flows_data", 16 | "random_3_flows_data", "random_4_flows_data", 17 | "hotspot_one_to_one_data"], 18 | "fanout": 4, 19 | "ecmp": True, 20 | } 21 | 22 | 23 | class IrokoTopo(BaseTopo): 24 | """ Class of Fattree Topology. """ 25 | 26 | def __init__(self, conf={}): 27 | self.conf = DEFAULT_CONF 28 | self.conf.update(conf) 29 | BaseTopo.__init__(self, self.conf) 30 | self.name = "fattree" 31 | 32 | # Init Topo 33 | self.fanout = self.conf["fanout"] 34 | # check if fanout is valid 35 | if self.fanout not in [4, 8]: 36 | log.error("Invalid fanout!") 37 | return -1 38 | self.density = int(self.conf["num_hosts"] / (self.fanout**2 / 2)) 39 | self.core_switch_num = int((self.fanout / 2)**2) 40 | self.agg_switch_num = int(self.fanout**2 / 2) 41 | self.edge_switch_num = int(self.fanout**2 / 2) 42 | self.core_switches = [] 43 | self.agg_switches = [] 44 | self.edge_switches = [] 45 | 46 | def create_nodes(self): 47 | self._add_switches(self.core_switch_num, 1, self.core_switches) 48 | self._add_switches(self.agg_switch_num, 2, self.agg_switches) 49 | self._add_switches(self.edge_switch_num, 3, self.edge_switches) 50 | self.create_hosts(self.conf["num_hosts"]) 51 | 52 | def _add_switches(self, number, level, switch_list): 53 | """ Create switches. """ 54 | for index in range(1, number + 1): 55 | sw_name = "%ss%d%d" % (self.switch_id, level, index) 56 | switch_list.append(self.addSwitch(sw_name)) 57 | 58 | def create_hosts(self, num): 59 | i = 1 60 | j = 1 61 | """ Create hosts. """ 62 | for host_num in range(1, num + 1): 63 | host_name = "h%d" % host_num 64 | ip = "10.%d.0.%d" % (i, j) 65 | host = self.addHost(host_name, cpu=1.0 / num, ip=ip) 66 | self.host_ips[host] = ip 67 | self.host_list.append(host) 68 | j += 1 69 | if j == self.density + 1: 70 | j = 1 71 | i += 1 72 | 73 | def create_links(self): 74 | """ Add network links. """ 75 | # Core to Agg 76 | end = int(self.fanout / 2) 77 | for switch in range(0, self.agg_switch_num, end): 78 | for i in range(0, end): 79 | for j in range(0, end): 80 | self.addLink( 81 | self.core_switches[i * end + j], 82 | self.agg_switches[switch + i]) 83 | # Agg to Edge 84 | for switch in range(0, self.agg_switch_num, end): 85 | for i in range(0, end): 86 | for j in range(0, end): 87 | self.addLink( 88 | self.agg_switches[switch + 89 | i], self.edge_switches[switch + j]) 90 | # Edge to Host 91 | for switch in range(0, self.edge_switch_num): 92 | for i in range(0, self.density): 93 | self.addLink( 94 | self.edge_switches[switch], 95 | self.host_list[self.density * switch + i]) 96 | 97 | def create_subnet_list(self, num): 98 | """ 99 | Create the subnet list of the certain Pod. 100 | """ 101 | subnetlist = [] 102 | remainder = num % (self.fanout / 2) 103 | if self.fanout == 4: 104 | if remainder == 0: 105 | subnetlist = [num - 1, num] 106 | elif remainder == 1: 107 | subnetlist = [num, num + 1] 108 | else: 109 | pass 110 | elif self.fanout == 8: 111 | if remainder == 0: 112 | subnetlist = [num - 3, num - 2, num - 1, num] 113 | elif remainder == 1: 114 | subnetlist = [num, num + 1, num + 2, num + 3] 115 | elif remainder == 2: 116 | subnetlist = [num - 1, num, num + 1, num + 2] 117 | elif remainder == 3: 118 | subnetlist = [num - 2, num - 1, num, num + 1] 119 | else: 120 | pass 121 | else: 122 | pass 123 | return subnetlist 124 | 125 | def _install_proactive(self): 126 | """ 127 | Install proactive flow entries for switches. 128 | """ 129 | protocols = ["ip", "arp"] 130 | switches = self.edge_switches + self.agg_switches + self.core_switches 131 | for sw in switches: 132 | num = int(sw[-1:]) 133 | ovs_flow_cmd = "ovs-ofctl add-flow %s -O OpenFlow13 " % sw 134 | ovs_grp_cmd = "ovs-ofctl add-group %s -O OpenFlow13 " % sw 135 | 136 | # Set upstream links of lower level switches 137 | if sw in self.edge_switches or sw in self.agg_switches: 138 | 139 | cmd = ovs_grp_cmd 140 | cmd += "group_id=1,type=select," 141 | cmd += "bucket=output:1,bucket=output:2" 142 | if self.fanout == 8: 143 | cmd += ",bucket=output:3,bucket=output:4" 144 | dc_utils.exec_process(cmd) 145 | 146 | # Configure entries per protocol 147 | for prot in protocols: 148 | cmd = ovs_flow_cmd 149 | cmd += "table=0,priority=10,%s,actions=group:1" % prot 150 | dc_utils.exec_process(cmd) 151 | 152 | # Configure entries per protocol 153 | for prot in protocols: 154 | # Edge Switches 155 | if sw in self.edge_switches: 156 | # Set downstream links 157 | for i in range(1, self.density + 1): 158 | cmd = ovs_flow_cmd 159 | cmd += "table=0,idle_timeout=0," 160 | cmd += "hard_timeout=0,priority=40," 161 | cmd += "%s," % prot 162 | cmd += "nw_dst=10.%d.0.%d," % (num, i) 163 | cmd += "actions=output:%d" % (self.fanout / 2 + i) 164 | dc_utils.exec_process(cmd) 165 | 166 | # Aggregation Switches 167 | if sw in self.agg_switches: 168 | # Set downstream links 169 | subnetList = self.create_subnet_list(num) 170 | k = 1 171 | for i in subnetList: 172 | cmd = ovs_flow_cmd 173 | cmd += "table=0,idle_timeout=0," 174 | cmd += "hard_timeout=0,priority=40," 175 | cmd += "%s," % prot 176 | cmd += "nw_dst=10.%d.0.0/16," % i 177 | cmd += "actions=output:%d" % (self.fanout / 2 + k) 178 | dc_utils.exec_process(cmd) 179 | k += 1 180 | 181 | # Core Switches 182 | if sw in self.core_switches: 183 | # Set downstream links 184 | j = 1 185 | k = 1 186 | for i in range(1, len(self.edge_switches) + 1): 187 | cmd = ovs_flow_cmd 188 | cmd += "table=0,idle_timeout=0," 189 | cmd += "hard_timeout=0,priority=10," 190 | cmd += "%s," % prot 191 | cmd += "nw_dst=10.%d.0.0/16," % i 192 | cmd += "actions=output:%d" % j 193 | dc_utils.exec_process(cmd) 194 | k += 1 195 | if k == self.fanout / 2 + 1: 196 | j += 1 197 | k = 1 198 | 199 | def _config_topo(self): 200 | # Install proactive flow entries 201 | if self.conf["ecmp"]: 202 | self._install_proactive() 203 | -------------------------------------------------------------------------------- /dc_gym/topos/topo_nonblock.py: -------------------------------------------------------------------------------- 1 | from topos.topo_base import BaseTopo 2 | import dc_gym.utils as dc_utils 3 | import logging 4 | log = logging.getLogger(__name__) 5 | 6 | DEFAULT_CONF = { 7 | "num_hosts": 16, # number of hosts in the topology 8 | "traffic_files": ["stag_prob_0_2_3_data", "stag_prob_1_2_3_data", 9 | "stag_prob_2_2_3_data", "stag_prob_0_5_3_data", 10 | "stag_prob_1_5_3_data", "stag_prob_2_5_3_data", 11 | "stride1_data", "stride2_data", "stride4_data", 12 | "stride8_data", "random0_data", "random1_data", 13 | "random2_data", "random0_bij_data", "random1_bij_data", 14 | "random2_bij_data", "random_2_flows_data", 15 | "random_3_flows_data", "random_4_flows_data", 16 | "hotspot_one_to_one_data"], 17 | } 18 | 19 | 20 | class IrokoTopo(BaseTopo): 21 | 22 | def __init__(self, conf={}): 23 | self.conf = DEFAULT_CONF 24 | self.conf.update(conf) 25 | BaseTopo.__init__(self, self.conf) 26 | self.name = "dumbbell" 27 | self.core_switch = None 28 | 29 | def create_nodes(self): 30 | self.create_core_switch() 31 | self.create_hosts(self.conf["num_hosts"]) 32 | 33 | def create_core_switch(self): 34 | sw_name = "%ss1" % self.switch_id 35 | self.core_switch = self.addSwitch(sw_name) 36 | 37 | def create_hosts(self, num): 38 | i = 1 39 | j = 1 40 | """ Create hosts. """ 41 | for host_num in range(1, num + 1): 42 | host_name = "h%d" % host_num 43 | ip = "10.%d.0.%d" % (i, j) 44 | host = self.addHost(host_name, cpu=1.0 / num, ip=ip) 45 | self.host_ips[host] = ip 46 | self.host_list.append(host) 47 | j += 1 48 | if j == 3: 49 | j = 1 50 | i += 1 51 | 52 | def create_links(self): 53 | """ 54 | Add links between switch and hosts. 55 | """ 56 | for host in self.host_list: 57 | self.addLink(self.core_switch, host) 58 | 59 | def _install_proactive(self): 60 | """ 61 | Install proactive flow entries for the switch. 62 | """ 63 | protocols = ["ip", "arp"] 64 | # West Switch 65 | ovs_flow_cmd = "ovs-ofctl add-flow %s " % self.core_switch 66 | ovs_flow_cmd += "-O OpenFlow13 " 67 | for prot in protocols: 68 | i = 1 69 | j = 1 70 | for k in range(1, self.conf["num_hosts"] + 1): 71 | cmd = ovs_flow_cmd 72 | cmd += "table=0,idle_timeout=0," 73 | cmd += "hard_timeout=0,priority=10," 74 | cmd += "nw_dst=10.%d.0.%d," % (i, j) 75 | cmd += "%s," % prot 76 | cmd += "actions=output:%d" % k 77 | dc_utils.exec_process(cmd) 78 | j += 1 79 | if j == 3: 80 | j = 1 81 | i += 1 82 | 83 | def _config_topo(self): 84 | # Set hosts IP addresses. 85 | self._install_proactive() 86 | -------------------------------------------------------------------------------- /dc_gym/utils.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import Array 2 | import subprocess 3 | import os 4 | import sys 5 | import random 6 | import string 7 | import json 8 | import logging 9 | import pwd 10 | import grp 11 | import psutil 12 | import numpy as np 13 | 14 | log = logging.getLogger(__name__) 15 | 16 | cwd = os.getcwd() 17 | FILE_DIR = os.path.dirname(os.path.abspath(__file__)) 18 | sys.path.insert(0, FILE_DIR) 19 | 20 | 21 | def shmem_to_nparray(shmem_array, dtype): 22 | if isinstance(shmem_array, type(Array)): 23 | return np.frombuffer(shmem_array.get_obj(), dtype=dtype) 24 | else: 25 | return np.frombuffer(shmem_array, dtype=dtype) 26 | 27 | 28 | def exec_process(cmd, host=None, out_file=subprocess.STDOUT): 29 | if host is not None: 30 | host_pid = host.pid 31 | mn_cmd = "mnexec -a %d %s" % (host_pid, cmd) 32 | return exec_process(mn_cmd, out_file=out_file) 33 | log.debug("Executing %s ", cmd) 34 | if out_file is subprocess.STDOUT: 35 | result = subprocess.run( 36 | cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) 37 | if result.stdout: 38 | log.debug("Process output: %s", result.stdout) 39 | if result.stderr and result.returncode != 0: 40 | log.error(result.stderr) 41 | return 42 | err = out_file + ".err" 43 | out = out_file + ".out" 44 | with open(out, "w+") as f_out, open(err, "w+") as f_err: 45 | return subprocess.run(cmd.split(), stdout=f_out, stderr=f_err) 46 | 47 | 48 | def start_process(cmd, host=None, out_file=subprocess.STDOUT): 49 | if host is not None: 50 | host_pid = host.pid 51 | mn_cmd = "mnexec -a %d %s" % (host_pid, cmd) 52 | return start_process(mn_cmd, out_file=out_file) 53 | log.debug("Starting %s ", cmd) 54 | if out_file is subprocess.STDOUT: 55 | return subprocess.Popen(cmd.split()) 56 | err = out_file + ".err" 57 | out = out_file + ".out" 58 | with open(out, "w+") as f_out, open(err, "w+") as f_err: 59 | return subprocess.Popen(cmd.split(), stdout=f_out, stderr=f_err) 60 | 61 | 62 | def list_processes(pattern): 63 | procs = [] 64 | for proc in psutil.process_iter(): 65 | if pattern in proc.name(): 66 | log.debug("Found %s", proc) 67 | procs.append(proc) 68 | return procs 69 | 70 | 71 | def kill_processes(procs, use_sigkill=False): 72 | if not isinstance(procs, list): 73 | procs = [procs] 74 | for proc in procs: 75 | # kill process, 15 is SIGTERM, 9 is SIGKILL 76 | try: 77 | os.kill(proc.pid, 15) 78 | if use_sigkill: 79 | os.kill(proc.pid, 9) 80 | except OSError as e: 81 | log.warning("Could not kill process %d: %s", proc.pid, e) 82 | 83 | 84 | def kill_processes_with_name(pattern, use_sigkill=False): 85 | procs = list_processes(pattern) 86 | kill_processes(procs, use_sigkill) 87 | 88 | 89 | def dump_json(path, name, data): 90 | check_dir(path) 91 | with open(f"{path}/{name}.json", 'w') as fp: 92 | json.dump(data, fp) 93 | 94 | 95 | def change_owner(directory): 96 | if "SUDO_USER" in os.environ: 97 | user = os.environ["SUDO_USER"] 98 | else: 99 | user = os.environ["USER"] 100 | 101 | uid = pwd.getpwnam(user).pw_uid 102 | gid = grp.getgrnam(user).gr_gid 103 | for root, folders, files in os.walk(directory): 104 | for folder in folders: 105 | os.chown(os.path.join(root, folder), uid, gid) 106 | for file in files: 107 | os.chown(os.path.join(root, file), uid, gid) 108 | 109 | 110 | def generate_id(): 111 | """ Mininet needs unique ids if we want to launch 112 | multiple topologies at once """ 113 | # Best collision-free technique for the limited amount of characters 114 | sw_id = "".join(random.choice("".join([random.choice( 115 | string.ascii_letters + string.digits) 116 | for ch in range(4)])) for _ in range(4)) 117 | return sw_id 118 | 119 | 120 | def check_dir(directory): 121 | # create the folder if it does not exit 122 | if not directory == "" and not os.path.exists(directory): 123 | log.info("Folder %s does not exist! Creating...", directory) 124 | os.makedirs(directory) 125 | # preserve the original owner 126 | 127 | 128 | def import_from(module, name): 129 | """ Try to import a module and class directly instead of the typical 130 | Python method. Allows for dynamic imports. """ 131 | module = __import__(module, fromlist=[name]) 132 | return getattr(module, name) 133 | 134 | 135 | class EnvFactory(): 136 | """ Generator class. 137 | Returns a target subclass based on the provided target option.""" 138 | @staticmethod 139 | def create(config): 140 | 141 | env_name = "dc_gym.env_" + config["env"] 142 | env_class = "DCEnv" 143 | log.info("Loading environment %s ", env_name) 144 | try: 145 | BaseEnv = import_from(env_name, env_class) 146 | except ImportError as e: 147 | log.info("Could not import requested environment: %s", e) 148 | sys.exit(1) 149 | return BaseEnv(config) 150 | 151 | 152 | class TopoFactory(): 153 | """ Generator class. 154 | Returns a target subclass based on the provided target option.""" 155 | @staticmethod 156 | def create(topo_name, options): 157 | env_name = "dc_gym.topos.topo_" + topo_name 158 | env_class = "IrokoTopo" 159 | log.info("Loading topology %s ", env_name) 160 | try: 161 | IrokoTopo = import_from(env_name, env_class) 162 | except ImportError as e: 163 | log.info("Could not import requested topology: %s", e) 164 | sys.exit(1) 165 | topo = IrokoTopo(options) 166 | topo.create_topo() 167 | return topo 168 | -------------------------------------------------------------------------------- /do_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit when any command fails 4 | set -e 5 | # Make verbose 6 | set -x 7 | 8 | # fetch submodules at their latest version 9 | git submodule update --init --recursive 10 | 11 | # Install essential dependencies 12 | sudo apt install -y build-essential 13 | sudo apt install -y curl 14 | sudo apt-get install --reinstall python3-pkg-resources 15 | 16 | # Install Python dependencies 17 | sudo apt install -y python3 # default ubuntu python3.x 18 | sudo apt install -y python3-venv # support Python virtual environments 19 | sudo apt install -y python3-dev # for python3.x installs 20 | sudo apt install -y python3-setuptools # unfortunately required for poetry 21 | # Get the correct Python version 22 | PYTHON3_VERSION=`python3 -c 'import sys; version=sys.version_info[:3]; print("{0}{1}".format(*version))'` 23 | 24 | if [ "$PYTHON3_VERSION" -lt "36" ]; then 25 | echo "\nPython version lower than 3.6! Installing 3.6...\n" 26 | sudo apt install -y python3.6; 27 | sudo apt install -y python3.6-venv; 28 | sudo apt install -y python3.6-dev; 29 | PYTHON3_CMD="python3.6"; 30 | PYTHON3_VERSION="36"; 31 | PIP_VERSION="pip3.6" 32 | else 33 | PYTHON3_CMD="python3"; 34 | PIP_VERSION="pip3" 35 | fi 36 | 37 | # install Mininet dependencies 38 | sudo apt install -y openvswitch-switch cgroup-tools help2man 39 | # install Mininet 40 | cd contrib/mininet 41 | sudo make install PYTHON=$PYTHON3_CMD # install the Python3 version 42 | cd ../.. 43 | 44 | # install traffic monitors 45 | sudo apt install -y tcpdump ifstat 46 | 47 | # install the traffic generator using Go 48 | if [[ $1 = "--goben" ]]; then 49 | echo "Building goben traffic generator..." 50 | cd contrib 51 | ./install_goben.sh 52 | cd .. 53 | fi 54 | 55 | # install the PCC kernel module 56 | if [[ $1 = "--pcc" ]]; then 57 | make -C contrib/pcc/src/ 58 | cp contrib/pcc/src/tcp_pcc.ko dc_gym/topos 59 | fi 60 | 61 | # required for traffic adjustment 62 | sudo apt install -y libnl-route-3-dev 63 | 64 | # Install pip locally 65 | export PATH+=$PATH:~/.local/bin 66 | wget https://bootstrap.pypa.io/get-pip.py 67 | $PYTHON3_CMD get-pip.py --user 68 | rm get-pip.py 69 | 70 | # Build the dc_gym 71 | curl -sSL https://install.python-poetry.org | $PYTHON3_CMD - 72 | yes | poetry cache clear --all . # Clear Poetry cache, this is sometimes needed 73 | rm -rf poetry.lock # # Bugfix for repeated install 74 | rm -rf dist # Bugfix for repeated install 75 | poetry update # Update Poetry lock dependencies 76 | poetry install # Package the dc_gym 77 | poetry build # Build distribution package 78 | 79 | # Install the dc_gym locally 80 | $PIP_VERSION install --upgrade --user dist/*.whl 81 | 82 | # compile the traffic control 83 | make -C dc_gym/monitor 84 | make -C dc_gym/control 85 | 86 | # Install the latest ray build for $PYTHON3_CMD and 3 87 | # $PIP_VERSION install --user -U https://s3-us-west-2.amazonaws.com/ray-wheels/latest/ray-0.9.0.dev0-cp${PYTHON3_VERSION}-cp${PYTHON3_VERSION}m-manylinux1_x86_64.whl 88 | 89 | # Install unresolved Ray runtime dependencies... 90 | sudo apt install -y libsm6 libxext6 libxrender-dev 91 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "dc_gym" 3 | version = "0.0.1" 4 | description = "Iroko is an open source project that is focused on providing openAI compliant gyms. The aim is to develop machine learning algorithms that address data center problems and to fairly evaluate solutions again traditional techniques." 5 | 6 | license = "Apache-2.0" 7 | 8 | authors = [ 9 | "Fabian Ruffy", 10 | "Michael Przystupa", 11 | "Ivan Beschastnikh" 12 | ] 13 | 14 | readme = 'README.md' 15 | 16 | repository = "https://github.com/dc_gym/iroko" 17 | homepage = "https://github.com/dc_gym/iroko" 18 | 19 | keywords = ['tcp', 'congestion control', 'reinforcement learning', 'rl', 'data center'] 20 | 21 | [tool.poetry.dependencies] 22 | python = ">=3.6.1" # Compatible python versions 23 | toml = "^0.9" 24 | numpy = "1.19.*" 25 | pandas = "1.1.*" 26 | gym = "0.18.*" 27 | seaborn = "0.11.*" 28 | matplotlib = "3.3.*" 29 | gevent = "21.1.*" 30 | ray = "1.7.*" 31 | opencv-python = "4.5.*" 32 | tabulate = "0.8.*" 33 | dm-tree = "0.1.6" 34 | cloudpickle = "1.6.*" 35 | tensorflow-probability = "0.10.*" 36 | tensorboardX = "2.1" 37 | tensorflow = "2.6.*" 38 | absl-py = "0.12" 39 | lz4 = "3.1" 40 | psutil = "5.7.*" 41 | setproctitle = "1.1.*" 42 | -------------------------------------------------------------------------------- /ray_configs/appo.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": { 3 | "fcnet_hiddens":[ 4 | 400, 5 | 300, 6 | 200, 7 | 200 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /ray_configs/ddpg.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /ray_configs/ppo.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": { 3 | "fcnet_hiddens":[ 4 | 400, 5 | 300, 6 | 200, 7 | 200 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /ray_configs/td3.json: -------------------------------------------------------------------------------- 1 | { 2 | "twin_q" : true, 3 | "smooth_target_policy": true, 4 | "exploration_config": { 5 | "type": "OrnsteinUhlenbeckNoise", 6 | "random_timesteps": 1000, 7 | "ou_base_scale": 0.1, 8 | "ou_theta": 0.15, 9 | "ou_sigma": 0.2, 10 | "initial_scale": 1.0, 11 | "final_scale": 1.0, 12 | "scale_timesteps": 10000 13 | }, 14 | "actor_hiddens":[ 15 | 400, 16 | 300, 17 | 200, 18 | 200 19 | ], 20 | "critic_hiddens":[ 21 | 400, 22 | 300, 23 | 200, 24 | 200 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /run_basic.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import argparse 3 | import logging 4 | import os 5 | 6 | # Iroko imports 7 | import dc_gym 8 | import dc_gym.utils as dc_utils 9 | 10 | # configure logging 11 | log = logging.getLogger(__name__) 12 | 13 | 14 | # set up paths 15 | cwd = os.getcwd() 16 | lib_dir = os.path.dirname(dc_gym.__file__) 17 | INPUT_DIR = lib_dir + '/inputs' 18 | OUTPUT_DIR = cwd + '/results' 19 | 20 | PARSER = argparse.ArgumentParser() 21 | PARSER.add_argument('--env', '-e', dest='env', 22 | default='iroko', help='The platform to run.') 23 | PARSER.add_argument('--topo', '-to', dest='topo', 24 | default='dumbbell', help='The topology to operate on.') 25 | PARSER.add_argument('--episodes', '-t', dest='episodes', 26 | type=int, default=2, 27 | help='total number of episodes to train rl agent') 28 | PARSER.add_argument('--output', dest='output_dir', default=OUTPUT_DIR, 29 | help='Folder which contains all the collected metrics.') 30 | PARSER.add_argument('--transport', dest='transport', default="udp", 31 | help='Choose the transport protocol of the hosts.') 32 | PARSER.add_argument('--agent', '-a', dest='agent', default="PG", 33 | help='must be string of either: PPO, DDPG, PG,' 34 | ' DCTCP, TCP_NV, PCC, or TCP', type=str.lower) 35 | ARGS = PARSER.parse_args() 36 | 37 | 38 | def test_run(input_dir, output_dir, env, topo): 39 | # Assemble a configuration dictionary for the environment 40 | env_config = { 41 | "input_dir": input_dir, 42 | "output_dir": output_dir, 43 | "env": env, 44 | "topo": topo, 45 | "agent": ARGS.agent, 46 | "transport": ARGS.transport, 47 | "episodes": ARGS.episodes, 48 | "tf_index": 0 49 | } 50 | dc_env = dc_utils.EnvFactory.create(env_config) 51 | for episodes in range(ARGS.episodes): 52 | dc_env.reset() 53 | done = False 54 | while not done: 55 | action = dc_env.action_space.sample() 56 | obs, reward, done, info = dc_env.step(action) 57 | 58 | log.info("Generator Finished. Simulation over. Clearing dc_env...") 59 | dc_env.close() 60 | 61 | 62 | def clean(): 63 | log.info("Removing all traces of Mininet") 64 | os.system('sudo mn -c') 65 | os.system("sudo killall -9 goben") 66 | os.system("sudo killall -9 node_control") 67 | 68 | 69 | def init(): 70 | output_dir = ARGS.output_dir + "/" + ARGS.agent 71 | dc_utils.check_dir(output_dir) 72 | test_run(INPUT_DIR, output_dir, ARGS.env, ARGS.topo) 73 | 74 | 75 | if __name__ == '__main__': 76 | logging.basicConfig(format="%(levelname)s:%(message)s", 77 | level=logging.INFO) 78 | init() 79 | -------------------------------------------------------------------------------- /test_scalability.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division # For Python 2 3 | import numpy as np 4 | import pandas as pd 5 | from filelock import FileLock 6 | import os 7 | import logging 8 | import time 9 | import argparse 10 | # Ray imports 11 | import ray 12 | from ray.rllib.agents.registry import get_agent_class 13 | from ray.rllib.agents.agent import Agent, with_common_config 14 | from ray.tune.registry import register_env 15 | import ray.tune as tune 16 | # Iroko imports 17 | import dc_gym 18 | import dc_gym.utils as dc_utils 19 | log = dc_utils.IrokoLogger.__call__().get_logger() 20 | 21 | # Fixed matplotlib import 22 | import matplotlib 23 | matplotlib.use('Agg') 24 | import matplotlib.pyplot as plt 25 | import seaborn as sns 26 | from matplotlib.ticker import FormatStrFormatter 27 | 28 | PARSER = argparse.ArgumentParser() 29 | PARSER.add_argument('--plot', '-p', action="store_true", 30 | default=False, help='Only plot results.') 31 | PARSER.add_argument('--input', '-i', dest='input_dir', 32 | default="scalability_test") 33 | ARGS = PARSER.parse_args() 34 | 35 | PLOT_DIR = os.path.dirname(os.path.abspath(__file__)) + "/plots" 36 | 37 | # These commands might help with scaling out the machine. After inserting 38 | # reboot the machine. 39 | 40 | # echo "* soft nofile 1048576" >> /etc/security/limits.conf 41 | # echo "* hard nofile 1048576" >> /etc/security/limits.conf 42 | # echo "* soft nproc unlimited" >> /etc/security/limits.conf 43 | # echo "* hard nproc unlimited" >> /etc/security/limits.conf 44 | # echo "* soft stack unlimited" >> /etc/security/limits.conf 45 | # echo "* hard stack unlimited" >> /etc/security/limits.conf 46 | # echo "kernel.threads-max = 2091845" >> /etc/sysctl.conf 47 | # echo "kernel.pty.max = 210000" >> /etc/sysctl.conf 48 | # echo "DefaultTasksMax=infinity" >> /etc/systemd/system.conf 49 | # echo "UserTasksMax=infinity" >> /etc/systemd/logind.conf 50 | # sysctl -p 51 | # systemctl daemon-reload 52 | # systemctl daemon-reexec 53 | 54 | # set up paths 55 | TESTNAME = ARGS.input_dir 56 | cwd = os.getcwd() 57 | lib_dir = os.path.dirname(dc_gym.__file__) 58 | INPUT_DIR = lib_dir + '/inputs' 59 | OUTPUT_DIR = cwd + '/' + TESTNAME 60 | 61 | 62 | class MaxAgent(Agent): 63 | """Agent that always takes the maximum available action.""" 64 | _agent_name = "MaxAgent" 65 | _default_config = with_common_config({}) 66 | 67 | def _init(self): 68 | self.env = self.env_creator(self.config["env_config"]) 69 | self.env.reset() 70 | 71 | def _train(self): 72 | steps = 0 73 | done = False 74 | reward = 0.0 75 | max_iterations = self.config["env_config"]["iterations"] 76 | while steps < max_iterations: 77 | action = self.env.action_space.high 78 | obs, r, done, info = self.env.step(action) 79 | reward += r 80 | steps = steps + 1 81 | return { 82 | "episode_reward_mean": reward, 83 | "timesteps_this_iter": steps, 84 | } 85 | 86 | 87 | def get_env(env_config): 88 | return dc_utils.EnvFactory.create(env_config) 89 | 90 | 91 | def get_agent(agent_name): 92 | try: 93 | agent_class = get_agent_class(agent_name.upper()) 94 | except Exception as e: 95 | log.info("%s Loading basic algorithm" % e) 96 | # We use PG as the base class for experiments 97 | agent_class = type(agent_name.upper(), (MaxAgent,), {}) 98 | return agent_class 99 | 100 | 101 | def get_tune_experiment(config, agent): 102 | scheduler = None 103 | name = "%s_tune" % agent 104 | agent_class = get_agent(agent) 105 | 106 | experiment = { 107 | name: { 108 | 'run': agent_class, 109 | 'local_dir': config['env_config']["output_dir"], 110 | "stop": {"timesteps_total": config['env_config']["iterations"]}, 111 | "env": "dc_env", 112 | } 113 | } 114 | experiment[name]["config"] = config 115 | return experiment, scheduler 116 | 117 | 118 | def configure_ray(num_hosts, tf_index): 119 | config = {} 120 | config['num_workers'] = 0 121 | config['num_gpus'] = 0 122 | config["batch_mode"] = "truncate_episodes" 123 | config["log_level"] = "ERROR" 124 | config['env_config'] = { 125 | "input_dir": INPUT_DIR, 126 | "output_dir": OUTPUT_DIR + "/%d_hosts" % num_hosts, 127 | "env": "iroko", 128 | "topo": "dumbbell", 129 | "agent": "TCP", 130 | "transport": "udp", 131 | "iterations": 1000, 132 | "tf_index": tf_index, 133 | "topo_conf": {"num_hosts": num_hosts, "parallel_envs": True, 134 | "max_capacity": 1000e9}, 135 | } 136 | return config 137 | 138 | 139 | def tune_run(config): 140 | agent = config['env_config']['agent'] 141 | experiment, scheduler = get_tune_experiment(config, agent) 142 | tune.run_experiments(experiment, scheduler=scheduler) 143 | 144 | 145 | STATS_DICT = {"backlog": 0, "olimit": 1, 146 | "drops": 2, "bw_rx": 3, "bw_tx": 4} 147 | 148 | 149 | def check_plt_dir(plt_name): 150 | plt_dir = os.path.dirname(plt_name) 151 | if not plt_dir == '' and not os.path.exists(plt_dir): 152 | log.info("Folder %s does not exist! Creating..." % plt_name) 153 | os.makedirs(plt_dir) 154 | 155 | 156 | def plot_scalability_graph(increments, data_dirs, plot_dir, name): 157 | # Set seaborn style for plotting 158 | sns.set(style="whitegrid", rc={"lines.linewidth": 2.5}) 159 | sns.set_context("paper") 160 | files = increments 161 | increments = [0] + increments 162 | agg_df = pd.DataFrame({'Number of Hosts': increments}) 163 | for data_dir in data_dirs.keys(): 164 | bw_list = {} 165 | bw_list["rx"] = [] 166 | bw_list["tx"] = [] 167 | for increment in files: 168 | stats_file = '%s/%s_hosts/runtime_statistics.npy' % ( 169 | data_dir, increment) 170 | log.info("Loading %s..." % stats_file) 171 | try: 172 | with FileLock(stats_file + ".lock"): 173 | statistics = np.load(stats_file).item() 174 | except Exception: 175 | log.info("Error loading file %s" % stats_file) 176 | continue 177 | port_stats = np.moveaxis(statistics["stats"], 0, -1) 178 | port_rx_bws = np.array( 179 | port_stats[STATS_DICT["bw_rx"]].mean(axis=1)) 180 | port_tx_bws = np.array( 181 | port_stats[STATS_DICT["bw_tx"]].mean(axis=1)) 182 | # bandwidths 183 | log.info("Computing mean of interface bandwidth per step.") 184 | bw_list["rx"].append(port_rx_bws.sum()) 185 | bw_list["tx"].append(port_tx_bws.sum()) 186 | bw_list["rx"] = [0] + bw_list["rx"] 187 | bw_list["tx"] = [0] + bw_list["tx"] 188 | agg_bw = np.add(bw_list["rx"], bw_list["tx"]) 189 | t_df = pd.DataFrame({data_dirs[data_dir]: agg_bw}) 190 | agg_df = pd.concat((agg_df, t_df), axis=1) 191 | agg_df.set_index('Number of Hosts', inplace=True) 192 | fig = sns.lineplot(data=agg_df, markers=True, markersize=8) 193 | fig.set_xscale('symlog', basex=2, linthreshx=4) 194 | fig.set_yscale('symlog', basey=2, linthreshy=4 * 10e6) 195 | fig.set(xlabel='Hosts', ylabel='Mbps (Avg)') 196 | y_increments = np.array(increments) * 10e6 197 | fig.set_yticks(y_increments) 198 | fig.set_yticklabels(increments) 199 | fig.set_xticks(increments) 200 | fig.set_xticklabels(increments) 201 | fig.set_ylim(ymin=0, ymax=y_increments[len(y_increments) - 1] + 100) 202 | fig.set_xlim(xmin=0, xmax=increments[len(increments) - 1] + 100) 203 | 204 | log.info("Test Summary:") 205 | log.info(agg_df) 206 | 207 | plt_name = "%s/" % (plot_dir) 208 | plt_name += "%s" % name 209 | log.info("Saving plot %s" % plt_name) 210 | check_plt_dir(plt_name) 211 | plt.savefig(plt_name + ".pdf", bbox_inches='tight', pad_inches=0.05) 212 | plt.savefig(plt_name + ".png", bbox_inches='tight', pad_inches=0.05) 213 | plt.gcf().clear() 214 | 215 | 216 | def run(config): 217 | agent_class = get_agent(config["env_config"]["agent"]) 218 | agent = agent_class(config=config, env="dc_env") 219 | agent.train() 220 | log.info('Generator Finished. Simulation over. Clearing dc_env...') 221 | 222 | 223 | data_dirs = { 224 | "candidates/scalability_test_10mbit_60core": "60 Core Rate Limited", 225 | "candidates/scalability_test_gbit_60core": "60 Core Full", 226 | "candidates/scalability_test_10mbit_8core": "8 Core Rate Limited", 227 | "candidates/scalability_test_gbit_8core": "8 Core Full"} 228 | 229 | 230 | def init(): 231 | increments = [4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] 232 | if not ARGS.plot: 233 | dc_utils.check_dir(OUTPUT_DIR) 234 | log.info("Registering the DC environment...") 235 | register_env("dc_env", get_env) 236 | 237 | log.info("Starting Ray...") 238 | ray.init(num_cpus=1, logging_level=logging.WARN) 239 | 240 | for tf_index, num_hosts in enumerate(increments): 241 | config = configure_ray(num_hosts, tf_index) 242 | log.info("Starting experiment.") 243 | tune_run(config) 244 | time.sleep(10) 245 | log.info("Experiment has completed.") 246 | time.sleep(10) 247 | plot_scalability_graph(increments, data_dirs, 248 | PLOT_DIR, os.path.basename(TESTNAME.strip("/"))) 249 | 250 | 251 | if __name__ == '__main__': 252 | init() 253 | --------------------------------------------------------------------------------