├── .gitignore ├── DINC.py ├── LICENSE ├── P4 ├── Node_0.p4 ├── Node_1.p4 ├── Node_2.p4 ├── Node_3.p4 ├── Node_4.p4 ├── Node_5.p4 └── Node_6.p4 ├── README.md └── src ├── architecture ├── tna │ └── p4_generator.py └── v1model │ └── p4_generator.py ├── code_generator ├── exact │ └── unified_generation_controller.py ├── readme.txt └── v1model │ └── unified_generation_controller.py ├── configs ├── DINC_config.json ├── Network_Topology.json └── requirements_Python3_10_8.txt ├── eval ├── BT-Topology │ ├── BT-UK-Topology_withoutUK.py │ └── load_BT.py ├── Baseline Comparison │ ├── Duplication.py │ ├── Hop.py │ └── Node.py ├── Coefficent-Res │ ├── BT-Coefficent-Res-Lat.py │ └── Clos-Coefficent-Res-Lat.py ├── Configurations │ ├── Table3_DINC_config_pegasus_sliced.json │ ├── Table3_DINC_config_pint_sliced.json │ ├── Table3_DT_DINC_config.json │ ├── Table3_NB_DINC_config.json │ ├── Table3_RF_DINC_config.json │ ├── Table3_SVM_DINC_config.json │ └── Table3_XGB_DINC_config.json ├── Hops-CDF │ ├── Setups_BT-Hops.py │ ├── Setups_Clos-Hops.py │ └── Setups_label.py ├── Split Overhead │ ├── Mem.py │ ├── Stage.py │ └── with_switchp4.py ├── Throughput-Latency │ ├── Model_name-Latency.py │ └── Model_name-Throughput.py ├── Time-Path_Segments │ ├── Time-Edge_Clos.py │ ├── Time-Segments_BT.py │ ├── Time-Segments_Clos.py │ └── Time-Tier1_BT.py ├── evaluation.md └── figures │ ├── BT-UK-topo-nouk_v2.png │ ├── Coefficent-hops_BT.pdf │ ├── Coefficent-hops_Clos.pdf │ ├── DINC_Flightplan_Dup.pdf │ ├── DINC_Flightplan_Hop.pdf │ ├── DINC_Flightplan_Node.pdf │ ├── Segment-Latency.pdf │ ├── Segment-Throughput.pdf │ ├── Setup-Hops_BT.pdf │ ├── Setup-Hops_Clos.pdf │ ├── Setups_label.pdf │ ├── Split_mem.pdf │ ├── Split_stage.pdf │ ├── Split_stage_with_switch_p4.pdf │ ├── Time-Edge_clos.pdf │ ├── Time-Segment_Fat-Tree.pdf │ ├── Time-Tier1_BT.pdf │ ├── Time_Segments_BT.pdf │ ├── Time_Segments_clos.pdf │ ├── ml_scaling.pdf │ └── rare_heatmap_v3.pdf ├── functions ├── add_license.py ├── cmd_related.py ├── config_modification.py ├── directory_management.py ├── figure_to_ASCII.py ├── input_CLI.py ├── json_encoder.py └── write_file.py ├── help ├── DINC_Supports │ ├── DINC_Supported_Architectures.md │ ├── DINC_Supported_Topologies.md │ └── DINC_Supported_Use_Cases.md ├── Sample_Tutorial │ └── DINC_Tutorial.md └── Zheng_et_al_2023_DINC_toward_distributed.pdf ├── images ├── BT-UK-topo.png ├── DINC_framework.png ├── logo.png ├── sample_marking.png └── topos.png ├── logs └── DT_performance_Iris_Fat-Tree_3depth_2branch.pdf ├── sample ├── PINT │ └── pint_sliced.p4 ├── Planter_Bayes │ ├── Bayes_performance_UNSW_5_tuple.p4 │ └── Bayes_performance_UNSW_5_tuple_2.p4 ├── Planter_DT │ ├── DT_performance_Iris.p4 │ └── DT_performance_Iris_2.p4 ├── Planter_RF │ ├── RF_performance_UNSW_5_tuple copy.p4 │ ├── RF_performance_UNSW_5_tuple.p4 │ ├── RF_performance_UNSW_5_tuple_2.p4 │ ├── RF_performance_UNSW_5_tuple_3.p4 │ ├── RF_performance_UNSW_5_tuple_4.p4 │ ├── RF_performance_UNSW_5_tuple_5.p4 │ └── RF_performance_UNSW_5_tuple_6.p4 ├── Planter_SVM │ ├── SVM_performance_UNSW_5_tuple.p4 │ ├── SVM_performance_UNSW_5_tuple_2.p4 │ └── SVM_performance_UNSW_5_tuple_3.p4 ├── Planter_XGB │ ├── XGB_performance_UNSW_5_tuple.p4 │ ├── XGB_performance_UNSW_5_tuple_3.p4 │ └── XGB_performance_UNSW_5_tuple_4.p4 ├── RF_hardware │ └── RF_performance_UNSW_5_tuple.p4 └── pegasus_tofino │ ├── pegasus_sliced.p4 │ ├── pred_load.p4 │ ├── qlen.p4 │ ├── rr.p4 │ └── server_load.p4 ├── slicing └── Manually │ └── p4_slicing.py ├── solver └── ILP │ └── Type_1 │ └── do_optimization.py ├── temp └── P4 │ ├── E0_control-apply.p4 │ ├── E0_control.p4 │ ├── E1_control-apply.p4 │ ├── E1_control.p4 │ ├── E2_control-apply.p4 │ └── E2_control.p4 ├── test └── BMv2 │ ├── run_test.py │ ├── test_environment │ ├── Makefile │ ├── P4 │ │ ├── s0.p4 │ │ ├── s1.p4 │ │ ├── s10.p4 │ │ ├── s11.p4 │ │ ├── s12.p4 │ │ ├── s13.p4 │ │ ├── s14.p4 │ │ ├── s2.p4 │ │ ├── s3.p4 │ │ ├── s4.p4 │ │ ├── s5.p4 │ │ ├── s6.p4 │ │ ├── s7.p4 │ │ ├── s8.p4 │ │ └── s9.p4 │ ├── commands │ │ ├── s0.txt │ │ ├── s1.txt │ │ ├── s10.txt │ │ ├── s11.txt │ │ ├── s12.txt │ │ ├── s13.txt │ │ ├── s14.txt │ │ ├── s2.txt │ │ ├── s3.txt │ │ ├── s4.txt │ │ ├── s5.txt │ │ ├── s6.txt │ │ ├── s7.txt │ │ ├── s8.txt │ │ └── s9.txt │ ├── insert_rules.sh │ ├── main.py │ ├── run_demo.sh │ └── temp │ │ └── BMv2_network_config.json │ └── utils │ ├── Makefile │ ├── architecture │ ├── psa │ │ └── Makefile │ └── v1model │ │ └── Makefile │ ├── cheat_sheet_src │ ├── main.tex │ └── src │ │ ├── actions.txt │ │ ├── adv_parsing.txt │ │ ├── architecture.txt │ │ ├── control_flow.txt │ │ ├── counters.txt │ │ ├── data_types.txt │ │ ├── deparsing.txt │ │ ├── expressions.txt │ │ ├── header_stack.txt │ │ ├── parsers.txt │ │ ├── tables.txt │ │ └── v1model_std_metadata.txt │ ├── mininet │ ├── appcontroller.py │ ├── apptopo.py │ ├── multi_switch_mininet.py │ ├── p4_mininet.py │ ├── shortest_path.py │ └── single_switch_mininet.py │ ├── netstat.py │ ├── p4_mininet.py │ ├── p4_program.py │ ├── p4app_util.py │ ├── p4apprunner.py │ ├── p4runtime_lib │ ├── __init__.py │ ├── bmv2.py │ ├── convert-modified.py │ ├── convert.py │ ├── error_utils.py │ ├── helper.py │ ├── simple_controller.py │ └── switch.py │ ├── p4runtime_switch.py │ └── run_exercise.py ├── topologies ├── BT-ASP │ └── network_topology.py ├── BT-All │ └── network_topology.py ├── BT │ └── network_topology.py ├── Fat-Tree │ └── network_topology.py ├── Folded-Clos-ASP │ └── network_topology.py ├── Folded-Clos-All │ └── network_topology.py └── Folded-Clos │ └── network_topology.py └── use_cases ├── standard_block └── common_p4.py └── standard_classification └── common_p4.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | # C extensions 7 | *.so 8 | # Distribution / packaging 9 | .Python 10 | build/ 11 | develop-eggs/ 12 | dist/ 13 | downloads/ 14 | eggs/ 15 | .eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | wheels/ 22 | share/python-wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .nox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *.cover 45 | *.py,cover 46 | .hypothesis/ 47 | .pytest_cache/ 48 | cover/ 49 | # Translations 50 | *.mo 51 | *.pot 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | db.sqlite3 56 | db.sqlite3-journal 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | # Scrapy stuff: 61 | .scrapy 62 | # Sphinx documentation 63 | docs/_build/ 64 | # PyBuilder 65 | .pybuilder/ 66 | target/ 67 | # Jupyter Notebook 68 | .ipynb_checkpoints 69 | # IPython 70 | profile_default/ 71 | ipython_config.py 72 | # pyenv 73 | # For a library or package, you might want to ignore these files since the code is 74 | # intended to run in multiple environments; otherwise, check them in: 75 | # .python-version 76 | # pipenv 77 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 78 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 79 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 80 | # install all needed dependencies. 81 | #Pipfile.lock 82 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 83 | __pypackages__/ 84 | # Celery stuff 85 | celerybeat-schedule 86 | celerybeat.pid 87 | # SageMath parsed files 88 | *.sage.py 89 | # Environments 90 | .env 91 | .venv 92 | env/ 93 | venv/ 94 | ENV/ 95 | env.bak/ 96 | venv.bak/ 97 | # Spyder project settings 98 | .spyderproject 99 | .spyproject 100 | # Rope project settings 101 | .ropeproject 102 | # mkdocs documentation 103 | /site 104 | # mypy 105 | .mypy_cache/ 106 | .dmypy.json 107 | dmypy.json 108 | # Pyre type checker 109 | .pyre/ 110 | # pytype static type analyzer 111 | .pytype/ 112 | # Cython debug symbols 113 | cython_debug/ 114 | # OSX 115 | .DS_Store 116 | .idea/ 117 | .ide 118 | 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Distributed In-Network Computing (DINC) 2 | ![DINC Logo](src/images/logo.png) 3 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 4 | ![GitHub release](https://img.shields.io/badge/pre--release%20tag-v0.0.0-orange) 5 | 6 | ## Introducing DINC 7 | DINC is a framework to provide automating distributed in-network computing services. This repo is the artifact for the paper "DINC: Toward Distributed In-Network Computing" [PDF](./src/help/Zheng_et_al_2023_DINC_toward_distributed.pdf) in ACM CoNEXT '23. 8 | 9 | ## Setting up the DINC environment 10 | 11 | DINC requires python 3.10 or above, with the packages listed in [requirements\_Python3\_10\_8.txt](./src/configs/requirements_Python3_10_8.txt). To install the aforementioned packages, start your working environment and execute the following command: 12 | 13 | ``` 14 | pip3 install -r ./src/configs/requirements_Python3_10_8.txt 15 | ``` 16 | 17 | ## Getting started with DINC 18 | 19 | First, prepare a working environment as described in the previous section [Link](#environment). 20 | 21 | Run the following command to start DINC in manual configuration mode ```-m``` with target in-network computing program directory after ```-d```. Use help model with ```-h``` command to see additional options. 22 | 23 | ``` 24 | python3 DINC.py -m -d 25 | ``` 26 | 27 | 💡 A detailed getting started tutorial [Link: "Please click me!"](./src/help/Sample_Tutorial/DINC_Tutorial.md) (**Strongly Recommended**). 28 | 29 | ## DINC Supports 30 | DINC supports a wide range of modules mainly including modular Topologies, Architectures, and Usecases: 31 | 32 | - DINC Supported Topologies [wiki](./src/help/DINC_Supports/DINC_Supported_Topologies.md) 33 | - DINC Supported Architectures [wiki](./src/help/DINC_Supports/DINC_Supported_Architectures.md) 34 | - DINC Supported Usecases [wiki](./src/help/DINC_Supports/DINC_Supported_Use_Cases.md) 35 | 36 | DINC also supports modular [Slicer](./src/slicing)s, [Solver](./src/solver)s, [Code Generator](./src/code_generator)s, [Test Controller](./src/test)s, etc. 37 | 38 | 39 | ## How to manually mark P4 grogram for DINC 40 | The following figure gives a general outlook of how P4 programs are sliced in the current P4 slicer module ([Manually](./src/slicing/Manually)). 41 | 42 | 43 | 44 | 45 | 46 | ## The DINC Framework 47 | ![DINC figure](src/images/DINC_framework.png) 48 | 49 | ## DINC's Availability 50 | 51 | If you're interested in this work and find anything unclear, please feel free to contact me at ```changgang.zheng@eng.ox.ac.uk```. **_We are welcoming collaborations._** It can be exciting to collaborate, if you think in-network machine learning is helpful to your research or use case. If there are any potential interests, please feel free to contact PI ```noa.zilberman@eng.ox.ac.uk``` and project lead ```changgang.zheng@eng.ox.ac.uk```. 52 | 53 | ## License 54 | 55 | The files are licensed under Apache License: [LICENSE](./LICENSE). The text of the license can also be found in the LICENSE file. 56 | 57 | ## Citation 58 | ``` 59 | @article{zheng2023dinc, 60 | title={DINC: Toward Distributed In-Network Computing}, 61 | author={Zheng, Changgang and Tang, Haoyue and Zang, Mingyuan and Hong, Xinpeng and Feng, Aosong and Tassiulas, Leandros and Zilberman, Noa}, 62 | journal={Proceedings of the ACM on Networking}, 63 | volume={1}, 64 | number={CoNEXT3}, 65 | pages={1--25}, 66 | year={2023}, 67 | publisher={ACM New York, NY, USA} 68 | } 69 | ``` 70 | 71 | We are also excited to introduce several DINC related papers ([Planter](https://arxiv.org/pdf/2205.08824.pdf), [Planter poster](https://dl.acm.org/doi/10.1145/3472716.3472846), [IIsy](https://arxiv.org/pdf/2205.08243.pdf), [Linnet](https://changgang-zheng.github.io/Home-Page/papers/Linnet%20Limit%20Order%20Books%20Within%20Switches.pdf), and [P4Pir](https://changgang-zheng.github.io/Home-Page/papers/P4Pir%20In-Network%20Analysis%20for%20Smart%20IoT%20Gateways.pdf)): 72 | 73 | ``` 74 | @article{zheng2022automating, 75 | title={Automating In-Network Machine Learning}, 76 | author={Zheng, Changgang and Zang, Mingyuan and Hong, Xinpeng and Bensoussane, Riyad and Vargaftik, Shay and Ben-Itzhak, Yaniv and Zilberman, Noa}, 77 | journal={arXiv preprint arXiv:2205.08824}, 78 | year={2022} 79 | } 80 | 81 | @incollection{zheng2021planter, 82 | title={Planter: seeding trees within switches}, 83 | author={Zheng, Changgang and Zilberman, Noa}, 84 | booktitle={Proceedings of the SIGCOMM'21 Poster and Demo Sessions}, 85 | pages={12--14}, 86 | year={2021} 87 | } 88 | 89 | @article{zheng2022iisy, 90 | title={IIsy: Practical In-Network Classification}, 91 | author={Zheng, Changgang and Xiong, Zhaoqi and Bui, Thanh T and Kaupmees, Siim and Bensoussane, Riyad and Bernabeu, Antoine and Vargaftik, Shay and Ben-Itzhak, Yaniv and Zilberman, Noa}, 92 | journal={arXiv preprint arXiv:2205.08243}, 93 | year={2022} 94 | } 95 | 96 | @incollection{hong2022linnet, 97 | title={Linnet: Limit Order Books Within Switches}, 98 | author={Hong, Xinpeng and Zheng, Changgang and Zohren, Stefan and Zilberman, Noa}, 99 | booktitle={Proceedings of the SIGCOMM'22 Poster and Demo Sessions}, 100 | year={2022} 101 | } 102 | 103 | @incollection{zang2022p4pir, 104 | title={P4Pir: In-Network Analysis for Smart IoT Gateways}, 105 | author={Zang, Mingyuan and Zheng, Changgang and Stoyanov, Radostin and Dittmann, Lars and Zilberman, Noa}, 106 | booktitle={Proceedings of the SIGCOMM'22 Poster and Demo Sessions}, 107 | year={2022} 108 | } 109 | ``` 110 | 111 | Planter builds upon [IIsy](https://github.com/cucl-srg/IIsy) and is further inspired by [SwitchTree](https://github.com/ksingh25/SwitchTree), [Qin](https://github.com/vxxx03/IFIPNetworking20), and [Clustreams](https://dl.acm.org/doi/pdf/10.1145/3482898.3483356). 112 | 113 | 114 | ## Acknowledgments 115 | This paper complies with all applicable ethical standards of the authors’ home institution. This 116 | work was partly funded by VMware, EU Horizon SMARTEDGE (101092908, UKRI 10056403), ARO 117 | W911NF-23-1-0088 and W911NF-23-1-0064. We acknowledge support from Intel. For the purpose 118 | of Open Access, the author has applied a CC-BY public copyright license to any Author Accepted 119 | Manuscript (AAM) version arising from this submission. -------------------------------------------------------------------------------- /src/code_generator/readme.txt: -------------------------------------------------------------------------------- 1 | This part decides how we do metadata supplement. -------------------------------------------------------------------------------- /src/configs/DINC_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/jesu3779/Documents/GitHub/DINC", 4 | "log plot file name": "Fat-Tree_3depth_2branch.pdf", 5 | "p4 file": "./src/sample/Planter_DT/DT_performance_Iris.p4", 6 | "BMv2": "/home/jesu3779/mysde/behavioral-model-1.15.0" 7 | }, 8 | "network config": { 9 | "topology": "Fat-Tree", 10 | "n_depth": 3, 11 | "n_branch": 2, 12 | "input device list": [ 13 | 2, 14 | 3, 15 | 5, 16 | 6 17 | ], 18 | "output device list": [ 19 | 0 20 | ], 21 | "resources list": [ 22 | "stage", 23 | "memory" 24 | ], 25 | "stage": [ 26 | 5, 27 | 5, 28 | 5, 29 | 5, 30 | 5, 31 | 5, 32 | 5 33 | ], 34 | "memory": [ 35 | 5, 36 | 5, 37 | 5, 38 | 5, 39 | 5, 40 | 5, 41 | 5 42 | ], 43 | "architectures": [ 44 | "v1model", 45 | "v1model", 46 | "v1model", 47 | "v1model", 48 | "v1model", 49 | "v1model", 50 | "v1model" 51 | ], 52 | "use cases": [ 53 | "standard_block", 54 | "standard_block", 55 | "standard_block", 56 | "standard_block", 57 | "standard_block", 58 | "standard_block", 59 | "standard_block" 60 | ], 61 | "targets": [ 62 | "bmv2", 63 | "bmv2", 64 | "bmv2", 65 | "bmv2", 66 | "bmv2", 67 | "bmv2", 68 | "bmv2" 69 | ] 70 | }, 71 | "operation config": { 72 | "display plot": false, 73 | "test ILP": false 74 | }, 75 | "p4 config": { 76 | "slicing method": "Manually", 77 | "start marker": "@!", 78 | "end marker": "!@", 79 | "key element info": [ 80 | "slice", 81 | "position" 82 | ], 83 | "existed sliced p4 file": [ 84 | "/home/jesu3779/Documents/GitHub/DINC/src/temp/P4/E0_control.p4", 85 | "/home/jesu3779/Documents/GitHub/DINC/src/temp/P4/E1_control.p4", 86 | "/home/jesu3779/Documents/GitHub/DINC/src/temp/P4/E2_control.p4", 87 | "/home/jesu3779/Documents/GitHub/DINC/src/temp/P4/E0_control-apply.p4", 88 | "/home/jesu3779/Documents/GitHub/DINC/src/temp/P4/E1_control-apply.p4", 89 | "/home/jesu3779/Documents/GitHub/DINC/src/temp/P4/E2_control-apply.p4" 90 | ], 91 | "stage": [ 92 | 5, 93 | 5, 94 | 5 95 | ], 96 | "memory": [ 97 | 5, 98 | 5, 99 | 5 100 | ], 101 | "generator": "exact", 102 | "begin test": "T" 103 | }, 104 | "solver config": { 105 | "solver type": "ILP", 106 | "solver variation": "Type_1" 107 | }, 108 | "test config": { 109 | "if test": "Y", 110 | "targets": "BMv2" 111 | } 112 | } -------------------------------------------------------------------------------- /src/configs/Network_Topology.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_list": { 3 | "0": [ 4 | 0, 5 | 0 6 | ], 7 | "1": [ 8 | 1, 9 | 0 10 | ], 11 | "2": [ 12 | 2, 13 | 0 14 | ], 15 | "3": [ 16 | 2, 17 | 1 18 | ], 19 | "4": [ 20 | 1, 21 | 1 22 | ], 23 | "5": [ 24 | 2, 25 | 2 26 | ], 27 | "6": [ 28 | 2, 29 | 3 30 | ] 31 | }, 32 | "adjacent_matrix": [ 33 | [ 34 | 0.0, 35 | 1.0, 36 | 0.0, 37 | 0.0, 38 | 1.0, 39 | 0.0, 40 | 0.0 41 | ], 42 | [ 43 | 1.0, 44 | 0.0, 45 | 1.0, 46 | 1.0, 47 | 0.0, 48 | 0.0, 49 | 0.0 50 | ], 51 | [ 52 | 0.0, 53 | 1.0, 54 | 0.0, 55 | 0.0, 56 | 0.0, 57 | 0.0, 58 | 0.0 59 | ], 60 | [ 61 | 0.0, 62 | 1.0, 63 | 0.0, 64 | 0.0, 65 | 0.0, 66 | 0.0, 67 | 0.0 68 | ], 69 | [ 70 | 1.0, 71 | 0.0, 72 | 0.0, 73 | 0.0, 74 | 0.0, 75 | 1.0, 76 | 1.0 77 | ], 78 | [ 79 | 0.0, 80 | 0.0, 81 | 0.0, 82 | 0.0, 83 | 1.0, 84 | 0.0, 85 | 0.0 86 | ], 87 | [ 88 | 0.0, 89 | 0.0, 90 | 0.0, 91 | 0.0, 92 | 1.0, 93 | 0.0, 94 | 0.0 95 | ] 96 | ], 97 | "input device list": [ 98 | 2, 99 | 3, 100 | 5, 101 | 6 102 | ], 103 | "output device list": [ 104 | 0 105 | ], 106 | "resources list": [ 107 | "stage", 108 | "memory" 109 | ], 110 | "stage": [ 111 | 5, 112 | 5, 113 | 5, 114 | 5, 115 | 5, 116 | 5, 117 | 5 118 | ], 119 | "memory": [ 120 | 5, 121 | 5, 122 | 5, 123 | 5, 124 | 5, 125 | 5, 126 | 5 127 | ], 128 | "Path": { 129 | "0": [ 130 | 2, 131 | 1, 132 | 0 133 | ], 134 | "1": [ 135 | 3, 136 | 1, 137 | 0 138 | ], 139 | "2": [ 140 | 5, 141 | 4, 142 | 0 143 | ], 144 | "3": [ 145 | 6, 146 | 4, 147 | 0 148 | ] 149 | } 150 | } -------------------------------------------------------------------------------- /src/configs/requirements_Python3_10_8.txt: -------------------------------------------------------------------------------- 1 | networkx==2.8.8 2 | numpy==1.23.5 3 | matplotlib==3.6.2 4 | pandas==1.5.2 5 | scipy==1.9.3 6 | -------------------------------------------------------------------------------- /src/eval/BT-Topology/BT-UK-Topology_withoutUK.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import cartopy.crs as ccrs 3 | import cartopy.io.img_tiles as cimgt 4 | import cartopy.feature as cfeature 5 | from matplotlib.offsetbox import AnchoredText 6 | from load_BT import * 7 | from convertbng.util import convert_bng, convert_lonlat 8 | import time 9 | 10 | rotated_pole = ccrs.RotatedPole(pole_latitude=45, pole_longitude=180) 11 | 12 | fig = plt.figure() 13 | ax = fig.add_subplot(1, 1, 1, projection=rotated_pole) 14 | ax.set_extent([-10.2, 2, 49.5, 59.5], crs=ccrs.PlateCarree()) 15 | # ax.add_feature(cfeature.LAND) 16 | # ax.add_feature(cfeature.OCEAN) 17 | # ax.add_feature(cfeature.COASTLINE) 18 | # ax.add_feature(cfeature.BORDERS, linestyle=':') 19 | # ax.add_feature(cfeature.LAKES, alpha=0.5) 20 | # ax.add_feature(cfeature.RIVERS) 21 | # stamen_terrain = cimgt.Stamen('terrain-background') 22 | # ax.add_image(stamen_terrain, 6) 23 | # stamen_terrain = cimgt.Stamen('toner-hybrid') 24 | # ax.add_image(stamen_terrain, 6) 25 | # stamen_terrain = cimgt.Stamen('toner-lite') 26 | # ax.add_image(stamen_terrain, 6) 27 | # stamen_terrain = cimgt.Stamen('toner-lines') 28 | # ax.add_image(stamen_terrain, 6) 29 | # stamen_terrain = cimgt.Stamen('toner-labels') 30 | # ax.add_image(stamen_terrain, 6) 31 | # ax.gridlines(draw_labels=False, dms=True, x_inline=False, y_inline=False) 32 | # Put a background image on for nice sea rendering. 33 | # ax.stock_img() 34 | 35 | 36 | 37 | D, adjacent_matrix, Level_dict = load_data(Reload=True) 38 | num_d = len(D.keys()) 39 | x_lon_list = [] 40 | x_lat_list = [] 41 | 42 | x_oc_lon_list = [] 43 | x_oc_lat_list = [] 44 | 45 | x_ic_lon_list = [] 46 | x_ic_lat_list = [] 47 | 48 | x_metro_lon_list = [] 49 | x_metro_lat_list = [] 50 | 51 | x_tier1_lon_list = [] 52 | x_tier1_lat_list = [] 53 | 54 | for x in range(num_d): 55 | print('\rProcessing BT raw data [' + str(int(100 * np.round(x / len(D), 2))) + '%], plotting connections...', 56 | end='') 57 | for y in range(x): 58 | if x == y or adjacent_matrix[x][y] != 1: 59 | continue 60 | # print(adjacent_matrix[x][y]) 61 | eastings = [D[str(x)]['E'],D[str(y)]['E']] 62 | northings = [D[str(x)]['N'],D[str(y)]['N']] 63 | res_list_en = convert_lonlat(eastings, northings) 64 | x_lon = res_list_en[0][0] 65 | x_lat = res_list_en[1][0] 66 | y_lon = res_list_en[0][1] 67 | y_lat = res_list_en[1][1] 68 | plt.plot([y_lon, x_lon], [y_lat, x_lat], color='gray', linewidth=0.08, transform=ccrs.PlateCarree(), alpha=0.8, 69 | zorder=2) 70 | 71 | 72 | eastings = [D[str(x)]['E']] 73 | northings = [D[str(x)]['N']] 74 | res_list_en = convert_lonlat(eastings, northings) 75 | x_lon = res_list_en[0][0] 76 | x_lat = res_list_en[1][0] 77 | x_lon_list += [res_list_en[0][0]] 78 | x_lat_list += [res_list_en[1][0]] 79 | if x in Level_dict['tier_1']: 80 | x_tier1_lon_list += [res_list_en[0][0]] 81 | x_tier1_lat_list += [res_list_en[1][0]] 82 | elif x in Level_dict['inner core']: 83 | x_ic_lon_list += [res_list_en[0][0]] 84 | x_ic_lat_list += [res_list_en[1][0]] 85 | elif x in Level_dict['metro']: 86 | x_metro_lon_list += [res_list_en[0][0]] 87 | x_metro_lat_list += [res_list_en[1][0]] 88 | elif x in Level_dict['outer core']: 89 | x_oc_lon_list += [res_list_en[0][0]] 90 | x_oc_lat_list += [res_list_en[1][0]] 91 | else: 92 | print('error') 93 | 94 | # time.sleep(0.00001) 95 | 96 | 97 | # plt.plot([y_lon,x_lon], [y_lat, x_lat], color='gray',linewidth =0.08, marker='.', markerfacecolor='lightskyblue', ms=3, markeredgecolor='black', markeredgewidth=0.2, transform=ccrs.PlateCarree(),alpha=0.8 ) 98 | # plt.scatter(x_lon_list, x_lat_list, color='palevioletred', marker='.', s = 6, linewidths=0.1, edgecolors='black', transform=ccrs.PlateCarree(), zorder=2 ) 99 | plt.scatter(x_tier1_lon_list, x_tier1_lat_list, color='palevioletred', marker='.', s = 6, linewidths=0.1, edgecolors='black', transform=ccrs.PlateCarree(), zorder=2, label='Tier 1') 100 | plt.scatter(x_metro_lon_list, x_metro_lat_list, color='lightskyblue', marker='.', s = 6, linewidths=0.1, edgecolors='black', transform=ccrs.PlateCarree(), zorder=3, label='Metro' ) 101 | plt.scatter(x_oc_lon_list, x_oc_lat_list, color='lightskyblue', marker='.', s = 6, linewidths=0.1, edgecolors='black', transform=ccrs.PlateCarree(), zorder=4 , label='Outer Core') 102 | plt.scatter(x_ic_lon_list, x_ic_lat_list, color='mediumseagreen', marker='.', s = 6, linewidths=0.1, edgecolors='black', transform=ccrs.PlateCarree(), zorder=5 , label='Inner Core') 103 | 104 | 105 | # Create a feature for States/Admin 1 regions at 1:50m from Natural Earth 106 | # states_provinces = cfeature.NaturalEarthFeature( 107 | # category='cultural', 108 | # name='admin_1_states_provinces_lines', 109 | # scale='50m', 110 | # facecolor='none') 111 | 112 | SOURCE = 'Natural Earth' 113 | LICENSE = 'public domain' 114 | 115 | states = cfeature.NaturalEarthFeature('cultural', 'admin_1_states_provinces', '10m', edgecolor='gray',facecolor='none') 116 | ax.add_feature(states, linewidth = 0.1, linestyle='-') 117 | ax.add_feature(cfeature.LAND) 118 | # ax.add_feature(cfeature.COASTLINE) 119 | # ax.add_feature(states_provinces, edgecolor='gray') 120 | 121 | # Add a text annotation for the license information to the 122 | # the bottom right corner. 123 | text = AnchoredText('\u00A9 {}; license: {}' 124 | ''.format(SOURCE, LICENSE), 125 | loc=4, prop={'size': 5}, frameon=True) 126 | ax.add_artist(text) 127 | plt.legend(loc = "upper right", ncol=1, fontsize=5) 128 | print(' Done') 129 | plt.savefig('../figures/BT-UK-topo-nouk.png',dpi=600,format='png', bbox_inches='tight') 130 | # plt.savefig('../figures/BT-UK-topo.pdf',dpi=600,format='pdf', bbox_inches='tight') 131 | 132 | plt.show() 133 | 134 | -------------------------------------------------------------------------------- /src/eval/Baseline Comparison/Duplication.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | # warnings.filterwarnings('ignore') 4 | import matplotlib 5 | import numpy as np 6 | import json 7 | from math import sqrt 8 | 9 | 10 | 11 | x = [2,3] 12 | DINC = [33, 405] 13 | flightplan = [ 51, 1901] 14 | 15 | fig, ax = plt.subplots(figsize=(3, 3)) 16 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 17 | matplotlib.rcParams['pdf.fonttype'] = 42 18 | matplotlib.rcParams['ps.fonttype'] = 42 19 | width = 0.3 20 | 21 | x_n = [i-0.65*width for i in x] 22 | plt.bar(x_n, flightplan,width=width, label='Flightplan', color="pink" ,linewidth = 1,edgecolor = 'black') 23 | 24 | x_n = [i+0.65*width for i in x] 25 | plt.bar(x_n, DINC, width= width, label='DINC', color="lightskyblue",linewidth = 1,edgecolor = 'black') 26 | 27 | fsize =25 28 | plt.ylabel('Duplications', fontsize=fsize) 29 | plt.yscale('log') 30 | plt.yticks([1,10,100,1000] ,fontsize=fsize-1) 31 | plt.xticks(x, labels=['Clos', 'BT'], fontsize=fsize-1) 32 | # plt.ylim(0.2,5000) 33 | plt.ylim(0.1,10000) 34 | plt.xlim(1.4,3.6) 35 | leg = plt.legend(loc='lower center', fontsize=fsize-8) 36 | plt.grid(which ='major',linestyle= ':', axis="y") #'major', 'minor', 'both' 37 | plt.savefig('../figures/DINC_Flightplan_Dup.pdf',dpi=600,format='pdf', bbox_inches='tight') 38 | 39 | -------------------------------------------------------------------------------- /src/eval/Baseline Comparison/Hop.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | # warnings.filterwarnings('ignore') 4 | import matplotlib 5 | import numpy as np 6 | import json 7 | from math import sqrt 8 | 9 | 10 | 11 | x = [2,3] 12 | DINC = [100*2/3, 100*3.11/3.81] 13 | flightplan = [100*2/3 , 100*3.11/3.81] 14 | fig, ax = plt.subplots(figsize=(3, 3)) 15 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 16 | matplotlib.rcParams['pdf.fonttype'] = 42 17 | matplotlib.rcParams['ps.fonttype'] = 42 18 | width = 0.3 19 | 20 | x_n = [i-0.65*width for i in x] 21 | plt.bar(x_n, flightplan,width=width, label='Flightplan', color="pink" ,linewidth = 1,edgecolor = 'black') 22 | 23 | x_n = [i+0.65*width for i in x] 24 | plt.bar(x_n, DINC, width= width, label='DINC', color="lightskyblue",linewidth = 1,edgecolor = 'black') 25 | 26 | fsize =25 27 | # plt.ylabel('Nodes', fontsize=fsize) 28 | plt.ylabel('Hops (%)', fontsize=fsize) 29 | # plt.yscale('log') 30 | # plt.yticks([0.2,0.4,0.6,0.8] ,fontsize=fsize-1) 31 | plt.yticks([20,40,60,80] ,fontsize=fsize-1) 32 | plt.xticks(x, labels=['Clos', 'BT'], fontsize=fsize-1) 33 | # plt.ylim(0,1) 34 | plt.ylim(0,100) 35 | plt.xlim(1.4,3.6) 36 | leg = plt.legend(loc='lower center', fontsize=fsize-8) 37 | plt.grid(which ='major',linestyle= ':', axis="y") #'major', 'minor', 'both' 38 | plt.savefig('../figures/DINC_Flightplan_Hop.pdf',dpi=600,format='pdf', bbox_inches='tight') 39 | 40 | -------------------------------------------------------------------------------- /src/eval/Baseline Comparison/Node.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | # warnings.filterwarnings('ignore') 4 | import matplotlib 5 | import numpy as np 6 | import json 7 | from math import sqrt 8 | 9 | 10 | 11 | x = [2,3] 12 | # DINC = [30/33, 400/1008] 13 | # flightplan = [30/33 , 971/1008] 14 | DINC = [100*30/33, 100*400/1008] 15 | flightplan = [100*30/33 , 100*971/1008] 16 | fig, ax = plt.subplots(figsize=(3, 3)) 17 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 18 | matplotlib.rcParams['pdf.fonttype'] = 42 19 | matplotlib.rcParams['ps.fonttype'] = 42 20 | width = 0.3 21 | 22 | x_n = [i-0.65*width for i in x] 23 | plt.bar(x_n, flightplan,width=width, label='Flightplan', color="pink" ,linewidth = 1,edgecolor = 'black') 24 | 25 | x_n = [i+0.65*width for i in x] 26 | plt.bar(x_n, DINC, width= width, label='DINC', color="lightskyblue",linewidth = 1,edgecolor = 'black') 27 | 28 | fsize =25 29 | # plt.ylabel('Nodes', fontsize=fsize) 30 | plt.ylabel('Nodes (%)', fontsize=fsize) 31 | # plt.yscale('log') 32 | # plt.yticks([0.2,0.4,0.6,0.8] ,fontsize=fsize-1) 33 | plt.yticks([20,40,60,80] ,fontsize=fsize-1) 34 | plt.xticks(x, labels=['Clos', 'BT'], fontsize=fsize-1) 35 | # plt.ylim(0,1) 36 | plt.ylim(0,100) 37 | plt.xlim(1.4,3.6) 38 | leg = plt.legend(loc='lower center', fontsize=fsize-8) 39 | plt.grid(which ='major',linestyle= ':', axis="y") #'major', 'minor', 'both' 40 | plt.savefig('../figures/DINC_Flightplan_Node.pdf',dpi=600,format='pdf', bbox_inches='tight') 41 | 42 | -------------------------------------------------------------------------------- /src/eval/Coefficent-Res/BT-Coefficent-Res-Lat.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | import matplotlib 4 | import numpy as np 5 | import json 6 | from math import sqrt 7 | 8 | fsize =25 9 | lw=2 10 | ms = 6 11 | mes = 1 12 | lw=2 13 | 14 | 15 | 16 | 17 | # model = ['-2', '-1', '0', '1', '2'] 18 | # x = [-2, -1, 0, 1, 2] 19 | # hops = [2, 3.11, 3.11, 3.11, 3.11] 20 | # var = [0, 0.575, 0.575, 0.575, 0.575 ] 21 | # segment = [1169,416,416,416,416] 22 | model = ['1', '2', '3', '4', '5'] 23 | x = [1, 2, 3, 4, 5] 24 | hops = [3.11, 2, 2, 2, 2] 25 | var = [0.575, 0, 0, 0, 0] 26 | segment = [416, 1169,1169,1169,1169] 27 | 28 | 29 | 30 | 31 | fig, ax1 = plt.subplots(figsize=(5, 3)) 32 | ax2 = ax1.twinx() 33 | matplotlib.rcParams['pdf.fonttype'] = 42 34 | matplotlib.rcParams['ps.fonttype'] = 42 35 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 36 | # plt.rcParams['mathtext.fontset']= 'custom' 37 | width = 0.26 38 | # cm stic stixsans custom 39 | x_n = [i-0*width for i in x] 40 | ax1.bar(x_n,hops ,width=width, label='Hops', color="lightskyblue" ,linewidth = 1,edgecolor = 'black' ,yerr=var, error_kw=dict(lw=1, capsize=2.5, capthick=1)) 41 | 42 | 43 | 44 | l1 = ax2.plot(x, segment, '--', label='Segments', marker = 's', ms=ms, markeredgecolor='black', markeredgewidth=mes, color="#ff7f0e",linewidth = lw) 45 | 46 | 47 | 48 | 49 | fsize+=2 50 | plt.xlabel('Model', fontsize=fsize+1) 51 | ax1.set_xticks(x) 52 | ax1.set_xticklabels(labels=model,rotation=-0, fontsize=fsize+1) 53 | ax1.set_xlabel('Relative Weight', fontsize=fsize+1) 54 | 55 | # ax1.set_yscale('log') 56 | ax1.set_ylabel('Hops (s)', fontsize=fsize+1) 57 | ax1.set_yticks([1,2,3,4]) 58 | ax1.set_yticklabels(labels=['1','2','3','4'], fontsize=fsize+1) 59 | ax1.set_ylim(0,5) 60 | 61 | 62 | ax2.set_ylabel('Segments', fontsize=fsize+1) 63 | ax2.set_yticks([450,700,950,1200]) 64 | ax2.set_yticklabels(labels=['450','700','950', '1.2k'], fontsize=fsize+1) 65 | ax2.set_ylim(200,1450) 66 | 67 | 68 | plt.xlim(0.3, 5.7) 69 | 70 | 71 | lines, labels = ax1.get_legend_handles_labels() 72 | lines2, labels2 = ax2.get_legend_handles_labels() 73 | f_line = lines + lines2 74 | # f_line[1] = lines[0] 75 | # f_line[0] = lines2[0] 76 | # f_line[3] = lines[1] 77 | # f_line[2] = lines2[1] 78 | f_lable = labels + labels2 79 | # f_lable[1] = labels[0] 80 | # f_lable[0] = labels2[0] 81 | # f_lable[3] = labels[1] 82 | # f_lable[2] = labels2[1] 83 | ax2.legend(f_line, f_lable, fancybox=True, fontsize=fsize-8,loc = "upper right", ncol=1) 84 | 85 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 86 | plt.savefig('../figures/Coefficent-hops_BT.pdf',dpi=600,format='pdf', bbox_inches='tight') 87 | # plt.show() 88 | -------------------------------------------------------------------------------- /src/eval/Coefficent-Res/Clos-Coefficent-Res-Lat.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | import matplotlib 4 | import numpy as np 5 | import json 6 | from math import sqrt 7 | 8 | fsize =25 9 | lw=2 10 | ms = 6 11 | mes = 1 12 | lw=2 13 | 14 | 15 | 16 | 17 | # model = ['-2', '-1', '0', '1', '2'] 18 | # x = [-2, -1, 0, 1, 2] 19 | # hops = [2, 3, 2, 2, 2] 20 | # var = [0, 0, 0, 0, 0 ] 21 | # segment = [45,15,42,42,42] 22 | model = ['1', '2', '3', '4', '5'] 23 | x = [1, 2, 3, 4, 5] 24 | hops = [3, 2, 2, 2, 2] 25 | var = [0, 0, 0, 0, 0 ] 26 | segment = [15, 45, 45, 45, 45] 27 | 28 | 29 | 30 | fig, ax1 = plt.subplots(figsize=(5, 3)) 31 | ax2 = ax1.twinx() 32 | matplotlib.rcParams['pdf.fonttype'] = 42 33 | matplotlib.rcParams['ps.fonttype'] = 42 34 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 35 | # plt.rcParams['mathtext.fontset']= 'custom' 36 | width = 0.26 37 | # cm stic stixsans custom 38 | x_n = [i-0*width for i in x] 39 | ax1.bar(x_n,hops ,width=width, label='Hops', color="lightskyblue" ,linewidth = 1,edgecolor = 'black' ,yerr=var, error_kw=dict(lw=1, capsize=2.5, capthick=1)) 40 | 41 | 42 | 43 | l1 = ax2.plot(x, segment, '--', label='Segments', marker = 's', ms=ms, markeredgecolor='black', markeredgewidth=mes, color="#ff7f0e",linewidth = lw) 44 | 45 | 46 | 47 | 48 | fsize+=2 49 | plt.xlabel('Model', fontsize=fsize+1) 50 | ax1.set_xticks(x) 51 | ax1.set_xticklabels(labels=model,rotation=-0, fontsize=fsize+1) 52 | ax1.set_xlabel('Relative Weight', fontsize=fsize+1) 53 | 54 | # ax1.set_yscale('log') 55 | ax1.set_ylabel('Hops (s)', fontsize=fsize+1) 56 | ax1.set_yticks([1,2,3,4]) 57 | ax1.set_yticklabels(labels=['1','2','3','4'], fontsize=fsize+1) 58 | ax1.set_ylim(0,5) 59 | 60 | 61 | ax2.set_ylabel('Segments', fontsize=fsize+1) 62 | ax2.set_yticks([25, 50, 75, 100]) 63 | ax2.set_yticklabels(labels=['25','50','75','100'], fontsize=fsize+1) 64 | ax2.set_ylim(0,125) 65 | 66 | 67 | plt.xlim(0.3,5.7) 68 | 69 | 70 | lines, labels = ax1.get_legend_handles_labels() 71 | lines2, labels2 = ax2.get_legend_handles_labels() 72 | f_line = lines + lines2 73 | # f_line[1] = lines[0] 74 | # f_line[0] = lines2[0] 75 | # f_line[3] = lines[1] 76 | # f_line[2] = lines2[1] 77 | f_lable = labels + labels2 78 | # f_lable[1] = labels[0] 79 | # f_lable[0] = labels2[0] 80 | # f_lable[3] = labels[1] 81 | # f_lable[2] = labels2[1] 82 | ax2.legend(f_line, f_lable, fancybox=True, fontsize=fsize-8,loc = "upper right", ncol=1) 83 | 84 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 85 | plt.savefig('../figures/Coefficent-hops_Clos.pdf',dpi=600,format='pdf', bbox_inches='tight') 86 | # plt.show() 87 | -------------------------------------------------------------------------------- /src/eval/Configurations/Table3_DINC_config_pegasus_sliced.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/p4/DINC_oct", 4 | "log plot file name": "Folded-Clos_3core_6aggregation_24access.pdf", 5 | "p4 file": "./src/sample/pegasus_tofino/pegasus_sliced.p4" 6 | }, 7 | "network config": { 8 | "topology": "Folded-Clos", 9 | "n_core": 3, 10 | "n_aggregation": 6, 11 | "n_access": 24, 12 | "input device list": [ 13 | 9, 14 | 10, 15 | 11, 16 | 12, 17 | 13, 18 | 14, 19 | 15, 20 | 16, 21 | 17, 22 | 18, 23 | 19, 24 | 20, 25 | 21, 26 | 22, 27 | 23, 28 | 24, 29 | 25, 30 | 26, 31 | 27, 32 | 28, 33 | 29, 34 | 30, 35 | 31, 36 | 32 37 | ], 38 | "output device list": [ 39 | 0, 40 | 1, 41 | 2 42 | ], 43 | "resources list": [ 44 | "stage", 45 | "memory" 46 | ], 47 | "stage": [ 48 | 5, 49 | 5, 50 | 5, 51 | 5, 52 | 5, 53 | 5, 54 | 5, 55 | 5, 56 | 5, 57 | 5, 58 | 5, 59 | 5, 60 | 5, 61 | 5, 62 | 5, 63 | 5, 64 | 5, 65 | 5, 66 | 5, 67 | 5, 68 | 5, 69 | 5, 70 | 5, 71 | 5, 72 | 5, 73 | 5, 74 | 5, 75 | 5, 76 | 5, 77 | 5, 78 | 5, 79 | 5, 80 | 5 81 | ], 82 | "memory": [ 83 | 5, 84 | 5, 85 | 5, 86 | 5, 87 | 5, 88 | 5, 89 | 5, 90 | 5, 91 | 5, 92 | 5, 93 | 5, 94 | 5, 95 | 5, 96 | 5, 97 | 5, 98 | 5, 99 | 5, 100 | 5, 101 | 5, 102 | 5, 103 | 5, 104 | 5, 105 | 5, 106 | 5, 107 | 5, 108 | 5, 109 | 5, 110 | 5, 111 | 5, 112 | 5, 113 | 5, 114 | 5, 115 | 5 116 | ] 117 | }, 118 | "operation config": { 119 | "display plot": false, 120 | "test ILP": "True", 121 | "test details": false 122 | }, 123 | "p4 config": { 124 | "slicing method": "Manually", 125 | "start marker": "@!", 126 | "end marker": "!@", 127 | "key element info": [ 128 | "slice", 129 | "position" 130 | ], 131 | "existed sliced p4 file": [ 132 | "/home/p4/DINC_oct/src/temp/P4/E3_control.p4", 133 | "/home/p4/DINC_oct/src/temp/P4/E0_control.p4", 134 | "/home/p4/DINC_oct/src/temp/P4/E1_control.p4", 135 | "/home/p4/DINC_oct/src/temp/P4/E0_control-apply.p4", 136 | "/home/p4/DINC_oct/src/temp/P4/E1_control-apply.p4", 137 | "/home/p4/DINC_oct/src/temp/P4/E2_control-apply.p4", 138 | "/home/p4/DINC_oct/src/temp/P4/E3_control-apply.p4" 139 | ], 140 | "stage": [ 141 | 1, 142 | 4, 143 | 2, 144 | 1 145 | ], 146 | "memory": [ 147 | 1, 148 | 4, 149 | 2, 150 | 1 151 | ] 152 | }, 153 | "solver config": { 154 | "solver type": "ILP", 155 | "solver variation": "Type_1" 156 | } 157 | } -------------------------------------------------------------------------------- /src/eval/Configurations/Table3_DINC_config_pint_sliced.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/p4/DINC_oct", 4 | "log plot file name": "Folded-Clos_3core_6aggregation_24access.pdf", 5 | "p4 file": "./src/sample/PINT/pint_sliced.p4" 6 | }, 7 | "network config": { 8 | "topology": "Folded-Clos", 9 | "n_core": 3, 10 | "n_aggregation": 6, 11 | "n_access": 24, 12 | "input device list": [ 13 | 0, 14 | 1, 15 | 2 16 | ], 17 | "output device list": [ 18 | 9 19 | ], 20 | "resources list": [ 21 | "stage", 22 | "memory" 23 | ], 24 | "stage": [ 25 | 5, 26 | 5, 27 | 5, 28 | 5, 29 | 5, 30 | 5, 31 | 5, 32 | 5, 33 | 5, 34 | 5, 35 | 5, 36 | 5, 37 | 5, 38 | 5, 39 | 5, 40 | 5, 41 | 5, 42 | 5, 43 | 5, 44 | 5, 45 | 5, 46 | 5, 47 | 5, 48 | 5, 49 | 5, 50 | 5, 51 | 5, 52 | 5, 53 | 5, 54 | 5, 55 | 5, 56 | 5, 57 | 5 58 | ], 59 | "memory": [ 60 | 5, 61 | 5, 62 | 5, 63 | 5, 64 | 5, 65 | 5, 66 | 5, 67 | 5, 68 | 5, 69 | 5, 70 | 5, 71 | 5, 72 | 5, 73 | 5, 74 | 5, 75 | 5, 76 | 5, 77 | 5, 78 | 5, 79 | 5, 80 | 5, 81 | 5, 82 | 5, 83 | 5, 84 | 5, 85 | 5, 86 | 5, 87 | 5, 88 | 5, 89 | 5, 90 | 5, 91 | 5, 92 | 5 93 | ] 94 | }, 95 | "operation config": { 96 | "display plot": false, 97 | "test ILP": "True", 98 | "test details": false 99 | }, 100 | "p4 config": { 101 | "slicing method": "Manually", 102 | "start marker": "@!", 103 | "end marker": "!@", 104 | "key element info": [ 105 | "slice", 106 | "position" 107 | ], 108 | "existed sliced p4 file": [ 109 | "/home/p4/DINC_oct/src/temp/P4/E0_control.p4", 110 | "/home/p4/DINC_oct/src/temp/P4/E1_control.p4", 111 | "/home/p4/DINC_oct/src/temp/P4/E2_control.p4", 112 | "/home/p4/DINC_oct/src/temp/P4/E3_control.p4", 113 | "/home/p4/DINC_oct/src/temp/P4/E0_control-apply.p4", 114 | "/home/p4/DINC_oct/src/temp/P4/E1_control-apply.p4", 115 | "/home/p4/DINC_oct/src/temp/P4/E2_control-apply.p4", 116 | "/home/p4/DINC_oct/src/temp/P4/E3_control-apply.p4", 117 | "/home/p4/DINC_oct/src/temp/P4/E4_control-apply.p4" 118 | ], 119 | "stage": [ 120 | 1, 121 | 1, 122 | 5, 123 | 3, 124 | 1 125 | ], 126 | "memory": [ 127 | 1, 128 | 1, 129 | 5, 130 | 3, 131 | 1 132 | ] 133 | }, 134 | "solver config": { 135 | "solver type": "ILP", 136 | "solver variation": "Type_1" 137 | } 138 | } -------------------------------------------------------------------------------- /src/eval/Configurations/Table3_DT_DINC_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/jesu3779/Documents/DINC/DINC_OSR_1.1", 4 | "log plot file name": "Folded-Clos-ASP_3core_6aggregation_24access.pdf", 5 | "p4 file": "./src/sample/Planter_DT/DT_performance_Iris_2.p4" 6 | }, 7 | "network config": { 8 | "topology": "Folded-Clos-ASP", 9 | "n_core": 3, 10 | "n_aggregation": 6, 11 | "n_access": 24, 12 | "input device list": [ 13 | 9 14 | ], 15 | "output device list": [ 16 | 0, 17 | 1, 18 | 2 19 | ], 20 | "resources list": [ 21 | "stage", 22 | "memory" 23 | ], 24 | "stage": [ 25 | 5, 26 | 5, 27 | 5, 28 | 5, 29 | 5, 30 | 5, 31 | 5, 32 | 5, 33 | 5, 34 | 5, 35 | 5, 36 | 5, 37 | 5, 38 | 5, 39 | 5, 40 | 5, 41 | 5, 42 | 5, 43 | 5, 44 | 5, 45 | 5, 46 | 5, 47 | 5, 48 | 5, 49 | 5, 50 | 5, 51 | 5, 52 | 5, 53 | 5, 54 | 5, 55 | 5, 56 | 5, 57 | 5 58 | ], 59 | "memory": [ 60 | 5, 61 | 5, 62 | 5, 63 | 5, 64 | 5, 65 | 5, 66 | 5, 67 | 5, 68 | 5, 69 | 5, 70 | 5, 71 | 5, 72 | 5, 73 | 5, 74 | 5, 75 | 5, 76 | 5, 77 | 5, 78 | 5, 79 | 5, 80 | 5, 81 | 5, 82 | 5, 83 | 5, 84 | 5, 85 | 5, 86 | 5, 87 | 5, 88 | 5, 89 | 5, 90 | 5, 91 | 5, 92 | 5 93 | ] 94 | }, 95 | "operation config": { 96 | "display plot": false, 97 | "test ILP": "True", 98 | "test details": "True" 99 | }, 100 | "p4 config": { 101 | "slicing method": "Manually", 102 | "start marker": "@!", 103 | "end marker": "!@", 104 | "key element info": [ 105 | "slice", 106 | "position" 107 | ], 108 | "existed sliced p4 file": [ 109 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control.p4", 110 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control.p4", 111 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control-apply.p4", 112 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control-apply.p4" 113 | ], 114 | "stage": [ 115 | 1, 116 | 1 117 | ], 118 | "memory": [ 119 | 1, 120 | 1 121 | ] 122 | }, 123 | "solver config": { 124 | "solver type": "ILP", 125 | "solver variation": "Type_1" 126 | } 127 | } -------------------------------------------------------------------------------- /src/eval/Configurations/Table3_NB_DINC_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/jesu3779/Documents/DINC/DINC_OSR_1.1", 4 | "log plot file name": "Folded-Clos-ASP_3core_6aggregation_24access.pdf", 5 | "p4 file": "./src/sample/Planter_Bayes/Bayes_performance_UNSW_5_tuple_2.p4" 6 | }, 7 | "network config": { 8 | "topology": "Folded-Clos-ASP", 9 | "n_core": 3, 10 | "n_aggregation": 6, 11 | "n_access": 24, 12 | "input device list": [ 13 | 0, 14 | 1, 15 | 2 16 | ], 17 | "output device list": [ 18 | 9, 19 | 10, 20 | 11, 21 | 12, 22 | 13, 23 | 14, 24 | 15, 25 | 16, 26 | 17, 27 | 18, 28 | 19, 29 | 20, 30 | 21, 31 | 22, 32 | 23, 33 | 24, 34 | 25, 35 | 26, 36 | 27, 37 | 28, 38 | 29, 39 | 30, 40 | 31, 41 | 32 42 | ], 43 | "resources list": [ 44 | "stage", 45 | "memory" 46 | ], 47 | "stage": [ 48 | 5, 49 | 5, 50 | 5, 51 | 5, 52 | 5, 53 | 5, 54 | 5, 55 | 5, 56 | 5, 57 | 5, 58 | 5, 59 | 5, 60 | 5, 61 | 5, 62 | 5, 63 | 5, 64 | 5, 65 | 5, 66 | 5, 67 | 5, 68 | 5, 69 | 5, 70 | 5, 71 | 5, 72 | 5, 73 | 5, 74 | 5, 75 | 5, 76 | 5, 77 | 5, 78 | 5, 79 | 5, 80 | 5 81 | ], 82 | "memory": [ 83 | 5, 84 | 5, 85 | 5, 86 | 5, 87 | 5, 88 | 5, 89 | 5, 90 | 5, 91 | 5, 92 | 5, 93 | 5, 94 | 5, 95 | 5, 96 | 5, 97 | 5, 98 | 5, 99 | 5, 100 | 5, 101 | 5, 102 | 5, 103 | 5, 104 | 5, 105 | 5, 106 | 5, 107 | 5, 108 | 5, 109 | 5, 110 | 5, 111 | 5, 112 | 5, 113 | 5, 114 | 5, 115 | 5 116 | ] 117 | }, 118 | "operation config": { 119 | "display plot": false, 120 | "test ILP": "True", 121 | "test details": "True" 122 | }, 123 | "p4 config": { 124 | "slicing method": "Manually", 125 | "start marker": "@!", 126 | "end marker": "!@", 127 | "key element info": [ 128 | "slice", 129 | "position" 130 | ], 131 | "existed sliced p4 file": [ 132 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control.p4", 133 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control.p4", 134 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control-apply.p4", 135 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control-apply.p4" 136 | ], 137 | "stage": [ 138 | 4, 139 | 4 140 | ], 141 | "memory": [ 142 | 1, 143 | 1 144 | ] 145 | }, 146 | "solver config": { 147 | "solver type": "ILP", 148 | "solver variation": "Type_1" 149 | } 150 | } -------------------------------------------------------------------------------- /src/eval/Configurations/Table3_RF_DINC_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/jesu3779/Documents/DINC/DINC_OSR_1.1", 4 | "log plot file name": "Folded-Clos-ASP_3core_6aggregation_24access.pdf", 5 | "p4 file": "./src/sample/Planter_RF/RF_performance_UNSW_5_tuple_3.p4" 6 | }, 7 | "network config": { 8 | "topology": "Folded-Clos-ASP", 9 | "n_core": 3, 10 | "n_aggregation": 6, 11 | "n_access": 24, 12 | "input device list": [ 13 | 9, 14 | 10, 15 | 11, 16 | 12, 17 | 13, 18 | 14, 19 | 15, 20 | 16, 21 | 17, 22 | 18, 23 | 19, 24 | 20, 25 | 21, 26 | 22, 27 | 23, 28 | 24, 29 | 25, 30 | 26, 31 | 27, 32 | 28, 33 | 29, 34 | 30, 35 | 31, 36 | 32 37 | ], 38 | "output device list": [ 39 | 0, 40 | 1, 41 | 2 42 | ], 43 | "resources list": [ 44 | "stage", 45 | "memory" 46 | ], 47 | "stage": [ 48 | 5, 49 | 5, 50 | 5, 51 | 5, 52 | 5, 53 | 5, 54 | 5, 55 | 5, 56 | 5, 57 | 5, 58 | 5, 59 | 5, 60 | 5, 61 | 5, 62 | 5, 63 | 5, 64 | 5, 65 | 5, 66 | 5, 67 | 5, 68 | 5, 69 | 5, 70 | 5, 71 | 5, 72 | 5, 73 | 5, 74 | 5, 75 | 5, 76 | 5, 77 | 5, 78 | 5, 79 | 5, 80 | 5 81 | ], 82 | "memory": [ 83 | 5, 84 | 5, 85 | 5, 86 | 5, 87 | 5, 88 | 5, 89 | 5, 90 | 5, 91 | 5, 92 | 5, 93 | 5, 94 | 5, 95 | 5, 96 | 5, 97 | 5, 98 | 5, 99 | 5, 100 | 5, 101 | 5, 102 | 5, 103 | 5, 104 | 5, 105 | 5, 106 | 5, 107 | 5, 108 | 5, 109 | 5, 110 | 5, 111 | 5, 112 | 5, 113 | 5, 114 | 5, 115 | 5 116 | ] 117 | }, 118 | "operation config": { 119 | "display plot": false, 120 | "test ILP": "True", 121 | "test details": "True" 122 | }, 123 | "p4 config": { 124 | "slicing method": "Manually", 125 | "start marker": "@!", 126 | "end marker": "!@", 127 | "key element info": [ 128 | "slice", 129 | "position" 130 | ], 131 | "existed sliced p4 file": [ 132 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control-apply.p4", 133 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control-apply.p4", 134 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E2_control-apply.p4" 135 | ], 136 | "stage": [ 137 | 3, 138 | 2, 139 | 1 140 | ], 141 | "memory": [ 142 | 3, 143 | 2, 144 | 1 145 | ] 146 | }, 147 | "solver config": { 148 | "solver type": "ILP", 149 | "solver variation": "Type_1" 150 | } 151 | } -------------------------------------------------------------------------------- /src/eval/Configurations/Table3_SVM_DINC_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/jesu3779/Documents/DINC/DINC_OSR_1.1", 4 | "log plot file name": "Folded-Clos-ASP_3core_6aggregation_24access.pdf", 5 | "p4 file": "./src/sample/Planter_SVM/SVM_performance_UNSW_5_tuple_3.p4" 6 | }, 7 | "network config": { 8 | "topology": "Folded-Clos-ASP", 9 | "n_core": 3, 10 | "n_aggregation": 6, 11 | "n_access": 24, 12 | "input device list": [ 13 | 9 14 | ], 15 | "output device list": [ 16 | 32 17 | ], 18 | "resources list": [ 19 | "stage", 20 | "memory" 21 | ], 22 | "stage": [ 23 | 5, 24 | 5, 25 | 5, 26 | 5, 27 | 5, 28 | 5, 29 | 5, 30 | 5, 31 | 5, 32 | 5, 33 | 5, 34 | 5, 35 | 5, 36 | 5, 37 | 5, 38 | 5, 39 | 5, 40 | 5, 41 | 5, 42 | 5, 43 | 5, 44 | 5, 45 | 5, 46 | 5, 47 | 5, 48 | 5, 49 | 5, 50 | 5, 51 | 5, 52 | 5, 53 | 5, 54 | 5, 55 | 5 56 | ], 57 | "memory": [ 58 | 5, 59 | 5, 60 | 5, 61 | 5, 62 | 5, 63 | 5, 64 | 5, 65 | 5, 66 | 5, 67 | 5, 68 | 5, 69 | 5, 70 | 5, 71 | 5, 72 | 5, 73 | 5, 74 | 5, 75 | 5, 76 | 5, 77 | 5, 78 | 5, 79 | 5, 80 | 5, 81 | 5, 82 | 5, 83 | 5, 84 | 5, 85 | 5, 86 | 5, 87 | 5, 88 | 5, 89 | 5, 90 | 5 91 | ] 92 | }, 93 | "operation config": { 94 | "display plot": false, 95 | "test ILP": "True", 96 | "test details": "True" 97 | }, 98 | "p4 config": { 99 | "slicing method": "Manually", 100 | "start marker": "@!", 101 | "end marker": "!@", 102 | "key element info": [ 103 | "slice", 104 | "position" 105 | ], 106 | "existed sliced p4 file": [ 107 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control.p4", 108 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control.p4", 109 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control-apply.p4", 110 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control-apply.p4", 111 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E2_control-apply.p4" 112 | ], 113 | "stage": [ 114 | 3, 115 | 3, 116 | 3 117 | ], 118 | "memory": [ 119 | 1, 120 | 1, 121 | 1 122 | ] 123 | }, 124 | "solver config": { 125 | "solver type": "ILP", 126 | "solver variation": "Type_1" 127 | } 128 | } -------------------------------------------------------------------------------- /src/eval/Configurations/Table3_XGB_DINC_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory config": { 3 | "work": "/home/jesu3779/Documents/DINC/DINC_OSR_1.1", 4 | "log plot file name": "Folded-Clos-ASP_3core_6aggregation_24access.pdf", 5 | "p4 file": "./src/sample/Planter_XGB/XGB_performance_UNSW_5_tuple_4.p4" 6 | }, 7 | "network config": { 8 | "topology": "Folded-Clos-ASP", 9 | "n_core": 3, 10 | "n_aggregation": 6, 11 | "n_access": 24, 12 | "input device list": [ 13 | 0, 14 | 1, 15 | 2 16 | ], 17 | "output device list": [ 18 | 9, 19 | 10, 20 | 11, 21 | 12, 22 | 13, 23 | 14, 24 | 15, 25 | 16, 26 | 17, 27 | 18, 28 | 19, 29 | 20, 30 | 21, 31 | 22, 32 | 23, 33 | 24, 34 | 25, 35 | 26, 36 | 27, 37 | 28, 38 | 29, 39 | 30, 40 | 31, 41 | 32 42 | ], 43 | "resources list": [ 44 | "stage", 45 | "memory" 46 | ], 47 | "stage": [ 48 | 5, 49 | 5, 50 | 5, 51 | 5, 52 | 5, 53 | 5, 54 | 5, 55 | 5, 56 | 5, 57 | 5, 58 | 5, 59 | 5, 60 | 5, 61 | 5, 62 | 5, 63 | 5, 64 | 5, 65 | 5, 66 | 5, 67 | 5, 68 | 5, 69 | 5, 70 | 5, 71 | 5, 72 | 5, 73 | 5, 74 | 5, 75 | 5, 76 | 5, 77 | 5, 78 | 5, 79 | 5, 80 | 5 81 | ], 82 | "memory": [ 83 | 5, 84 | 5, 85 | 5, 86 | 5, 87 | 5, 88 | 5, 89 | 5, 90 | 5, 91 | 5, 92 | 5, 93 | 5, 94 | 5, 95 | 5, 96 | 5, 97 | 5, 98 | 5, 99 | 5, 100 | 5, 101 | 5, 102 | 5, 103 | 5, 104 | 5, 105 | 5, 106 | 5, 107 | 5, 108 | 5, 109 | 5, 110 | 5, 111 | 5, 112 | 5, 113 | 5, 114 | 5, 115 | 5 116 | ] 117 | }, 118 | "operation config": { 119 | "display plot": false, 120 | "test ILP": "True", 121 | "test details": "True" 122 | }, 123 | "p4 config": { 124 | "slicing method": "Manually", 125 | "start marker": "@!", 126 | "end marker": "!@", 127 | "key element info": [ 128 | "slice", 129 | "position" 130 | ], 131 | "existed sliced p4 file": [ 132 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E0_control-apply.p4", 133 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E1_control-apply.p4", 134 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E2_control-apply.p4", 135 | "/home/jesu3779/Documents/DINC/DINC_OSR_1.1/src/temp/P4/E3_control-apply.p4" 136 | ], 137 | "stage": [ 138 | 1, 139 | 2, 140 | 2, 141 | 1 142 | ], 143 | "memory": [ 144 | 1, 145 | 1, 146 | 1, 147 | 1 148 | ] 149 | }, 150 | "solver config": { 151 | "solver type": "ILP", 152 | "solver variation": "Type_1" 153 | } 154 | } -------------------------------------------------------------------------------- /src/eval/Hops-CDF/Setups_BT-Hops.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | # import seaborn as sns 4 | 5 | 6 | x = [1,2,3,4,5] 7 | y1 = [0, 0.10538624, 0.7928108, 0.98947646, 1] 8 | y2 = [0, 0.24792547, 0.993965, 1, 1] 9 | y3 = [0, 1, 1, 1,1] 10 | y4 = [0, 0.08333333, 1, 1, 1] 11 | y5 = [0, 1, 1, 1, 1,] 12 | 13 | y1 = [i*100 for i in y1] 14 | y2 = [i*100 for i in y2] 15 | y3 = [i*100 for i in y3] 16 | y4 = [i*100 for i in y4] 17 | y5 = [i*100 for i in y5] 18 | distance = 0 19 | x1 = x 20 | x2 = [i-distance for i in x] 21 | x3 = [i-2*distance for i in x] 22 | x4 = [i+distance for i in x] 23 | x5 = [i+2*distance for i in x] 24 | 25 | 26 | fsize =25 27 | lw=2 28 | ms = 6 29 | mes = 1 30 | lw=2 31 | 32 | fig, ax1 = plt.subplots(figsize=(5.5, 3)) 33 | plt.rcParams['pdf.fonttype'] = 42 34 | plt.rcParams['ps.fonttype'] = 42 35 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 36 | # plt.rcParams['mathtext.fontset']= 'custom' 37 | plt.step(x5, y5, marker = '^',color="dodgerblue",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 38 | plt.step(x3, y3, marker = 'd',color="mediumslateblue",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 39 | plt.step(x2, y2, marker = 'p',color="mediumseagreen",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 40 | plt.step(x4, y4, marker = 'H',color="firebrick",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 41 | plt.step(x1, y1, marker = 's',color="palevioletred",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 42 | 43 | 44 | plt.xlabel('Number of Hops', fontsize=fsize) 45 | plt.ylabel('CDF', fontsize=fsize) 46 | 47 | 48 | 49 | plt.yticks([ 0,30,60,90],labels=['0.1','0.3','0.6','0.9'], fontsize=fsize-1) 50 | plt.xticks([1,2,3,4,5], fontsize=fsize-1) 51 | plt.ylim(-15,115) 52 | plt.xlim(0.5,5.5) 53 | # plt.legend(loc = "upper left", ncol=1, fontsize=fsize-8) 54 | 55 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 56 | plt.savefig('../figures/Setup-Hops_BT.pdf',dpi=600,format='pdf', bbox_inches='tight') 57 | -------------------------------------------------------------------------------- /src/eval/Hops-CDF/Setups_Clos-Hops.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | # import seaborn as sns 4 | 5 | 6 | x = [1,2,3,4,5] 7 | y1 = [0, 1, 1, 1, 1,] 8 | y2 = [0, 1, 1, 1, 1,] 9 | y3 = [0, 1, 1, 1, 1,] 10 | y4 = [0, 1, 1, 1, 1,] 11 | y5 = [0, 1, 1, 1, 1,] 12 | 13 | y1 = [i*100 for i in y1] 14 | y2 = [i*100 for i in y2] 15 | y3 = [i*100 for i in y3] 16 | y4 = [i*100 for i in y4] 17 | y5 = [i*100 for i in y5] 18 | distance = 0 19 | x1 = x 20 | x2 = [i-distance for i in x] 21 | x3 = [i-2*distance for i in x] 22 | x4 = [i+distance for i in x] 23 | x5 = [i+2*distance for i in x] 24 | 25 | 26 | fsize =25 27 | lw=2 28 | ms = 6 29 | mes = 1 30 | lw=2 31 | 32 | fig, ax1 = plt.subplots(figsize=(5.5, 3)) 33 | plt.rcParams['pdf.fonttype'] = 42 34 | plt.rcParams['ps.fonttype'] = 42 35 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 36 | # plt.rcParams['mathtext.fontset']= 'custom' 37 | 38 | plt.step(x3, y3, marker = 'd',color="mediumslateblue",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 39 | plt.step(x2, y2, marker = 'p',color="mediumseagreen",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 40 | plt.step(x1, y1, marker = 's',color="palevioletred",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 41 | plt.step(x5, y5, marker = '^',color="dodgerblue",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 42 | plt.step(x4, y4, marker = 'H',color="firebrick",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='post') 43 | 44 | 45 | plt.xlabel('Number of Hops', fontsize=fsize) 46 | plt.ylabel('CDF', fontsize=fsize) 47 | 48 | 49 | 50 | plt.yticks([ 0,30,60,90],labels=['0.1','0.3','0.6','0.9'], fontsize=fsize-1) 51 | plt.xticks([1,2,3,4,5], fontsize=fsize-1) 52 | plt.ylim(-15,115) 53 | plt.xlim(0.5,5.5) 54 | # plt.legend(loc = "upper left", ncol=1, fontsize=fsize-8) 55 | 56 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 57 | plt.savefig('../figures/Setup-Hops_Clos.pdf',dpi=600,format='pdf', bbox_inches='tight') 58 | -------------------------------------------------------------------------------- /src/eval/Hops-CDF/Setups_label.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | # import seaborn as sns 4 | 5 | 6 | x = [1,2,3,4,5] 7 | y1 = [0, 1, 1, 1, 1,] 8 | y2 = [0, 1, 1, 1, 1,] 9 | y3 = [0, 1, 1, 1, 1,] 10 | y4 = [0, 1, 1, 1, 1,] 11 | y5 = [0, 1, 1, 1, 1,] 12 | 13 | y1 = [i*100 for i in y1] 14 | y2 = [i*100 for i in y2] 15 | y3 = [i*100 for i in y3] 16 | y4 = [i*100 for i in y4] 17 | y5 = [i*100 for i in y5] 18 | distance = 0.03 19 | x1 = x 20 | x2 = [i-distance for i in x] 21 | x3 = [i-2*distance for i in x] 22 | x4 = [i+distance for i in x] 23 | x5 = [i+2*distance for i in x] 24 | 25 | 26 | fsize =25 27 | lw=2 28 | ms = 6 29 | mes = 1 30 | lw=2 31 | 32 | fig, ax1 = plt.subplots(figsize=(5, 3)) 33 | plt.rcParams['pdf.fonttype'] = 42 34 | plt.rcParams['ps.fonttype'] = 42 35 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 36 | # plt.rcParams['mathtext.fontset']= 'custom' 37 | 38 | plt.step(x1, y1, marker = 's',color="palevioletred",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='Setup 1') 39 | plt.step(x2, y2, marker = 'p',color="mediumseagreen",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='Setup 2') 40 | plt.step(x3, y3, marker = 'd',color="mediumslateblue",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='Setup 3') 41 | plt.step(x4, y4, marker = 'H',color="firebrick",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='Setup 4') 42 | plt.step(x5, y5, marker = '^',color="dodgerblue",linewidth = lw , ms=ms, markeredgecolor='black', markeredgewidth=mes, where='post', label='Setup 5') 43 | 44 | 45 | 46 | plt.xlabel('Number of Hops', fontsize=fsize) 47 | plt.ylabel('CDF Percent (%)', fontsize=fsize) 48 | 49 | 50 | 51 | plt.yticks([ 0,30,60,90], fontsize=fsize-1) 52 | plt.xticks([1,2,3,4,5], fontsize=fsize-1) 53 | plt.ylim(-15,115) 54 | plt.xlim(0.5,5.5) 55 | plt.legend(bbox_to_anchor=(1.05, 0), loc=3,ncol=5, labelspacing=0.4,columnspacing=0.4, borderaxespad=0, fontsize=fsize-8) 56 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 57 | plt.savefig('../figures/Setups_label.pdf',dpi=600,format='pdf', bbox_inches='tight') 58 | -------------------------------------------------------------------------------- /src/eval/Split Overhead/Mem.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | # warnings.filterwarnings('ignore') 4 | import matplotlib 5 | import numpy as np 6 | import json 7 | from math import sqrt 8 | 9 | 10 | 11 | x = [2,3] 12 | 13 | DINC = [1700 , 600000] 14 | standalone = [1700 , 600000] 15 | fig, ax = plt.subplots(figsize=(3, 3)) 16 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 17 | plt.rcParams['pdf.fonttype'] = 42 18 | plt.rcParams['ps.fonttype'] = 42 19 | width = 0.3 20 | 21 | x_n = [i-0.65*width for i in x] 22 | plt.bar(x_n, standalone,width=width, label='Seg. Ideal', color="pink" ,linewidth = 1,edgecolor = 'black') 23 | 24 | x_n = [i+0.65*width for i in x] 25 | plt.bar(x_n, DINC, width= width, label='Seg. DINC', color="lightskyblue",linewidth = 1,edgecolor = 'black') 26 | 27 | fsize =25 28 | # plt.ylabel('Nodes', fontsize=fsize) 29 | plt.ylabel('Entries', fontsize=fsize) 30 | plt.yscale('log') 31 | # plt.yticks([0.2,0.4,0.6,0.8] ,fontsize=fsize-1) 32 | plt.yticks([100,1000,10000,100000] ,fontsize=fsize-1) 33 | plt.xticks(x, labels=['Node 1', 'Node 2'], fontsize=fsize-1) 34 | 35 | plt.ylim(10,1000000) 36 | plt.xlim(1.4,3.6) 37 | #leg = plt.legend(loc='lower center', fontsize=fsize-8, handlelength=1) 38 | leg = plt.legend(loc='lower center', fontsize=fsize-8) 39 | plt.grid(which ='major',linestyle= ':', axis="y") #'major', 'minor', 'both' 40 | plt.savefig('../figures/Split_mem.pdf',dpi=600,format='pdf', bbox_inches='tight') 41 | 42 | -------------------------------------------------------------------------------- /src/eval/Split Overhead/Stage.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | # warnings.filterwarnings('ignore') 4 | import matplotlib 5 | import numpy as np 6 | import json 7 | from math import sqrt 8 | 9 | 10 | 11 | x = [2,3] 12 | 13 | DINC = [3 , 5] 14 | standalone = [2, 4] 15 | fig, ax = plt.subplots(figsize=(3, 3)) 16 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 17 | plt.rcParams['pdf.fonttype'] = 42 18 | plt.rcParams['ps.fonttype'] = 42 19 | width = 0.3 20 | 21 | x_n = [i-0.65*width for i in x] 22 | plt.bar(x_n, standalone,width=width, label='Seg. Ideal', color="pink" ,linewidth = 1,edgecolor = 'black') 23 | 24 | x_n = [i+0.65*width for i in x] 25 | plt.bar(x_n, DINC, width= width, label='Seg. DINC', color="lightskyblue",linewidth = 1,edgecolor = 'black') 26 | 27 | fsize =25 28 | # plt.ylabel('Nodes', fontsize=fsize) 29 | plt.ylabel('Stage', fontsize=fsize) 30 | # plt.yscale('log') 31 | # plt.yticks([0.2,0.4,0.6,0.8] ,fontsize=fsize-1) 32 | plt.yticks([1.5,2.5,3.5,4.5] ,fontsize=fsize-1) 33 | plt.xticks(x, labels=['Node 1', 'Node 2'], fontsize=fsize-1) 34 | # plt.ylim(0,1) 35 | plt.ylim(0.5,5.5) 36 | plt.xlim(1.4,3.6) 37 | # leg = plt.legend(loc='lower center', fontsize=fsize-8, handlelength=1) 38 | leg = plt.legend(loc='lower center', fontsize=fsize-8) 39 | plt.grid(which ='major',linestyle= ':', axis="y") #'major', 'minor', 'both' 40 | plt.savefig('../figures/Split_stage.pdf',dpi=600,format='pdf', bbox_inches='tight') 41 | 42 | -------------------------------------------------------------------------------- /src/eval/Split Overhead/with_switchp4.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | # warnings.filterwarnings('ignore') 4 | import matplotlib 5 | import numpy as np 6 | import json 7 | from math import sqrt 8 | 9 | 10 | 11 | x = [2,3] 12 | 13 | DINC = [11, 12] 14 | standalone = [11 , 11] 15 | fig, ax = plt.subplots(figsize=(3, 3)) 16 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 17 | plt.rcParams['pdf.fonttype'] = 42 18 | plt.rcParams['ps.fonttype'] = 42 19 | width = 0.3 20 | 21 | x_n = [i-0.65*width for i in x] 22 | plt.bar(x_n, standalone,width=width, label='Switch.p4', color="pink" ,linewidth = 1,edgecolor = 'black') 23 | 24 | x_n = [i+0.65*width for i in x] 25 | plt.bar(x_n, DINC, width= width, label='Seg.+Switch.p4', color="lightskyblue",linewidth = 1,edgecolor = 'black') 26 | 27 | fsize =25 28 | # plt.ylabel('Nodes', fontsize=fsize) 29 | plt.ylabel('Stage', fontsize=fsize) 30 | # plt.yscale('log') 31 | # plt.yticks([0.2,0.4,0.6,0.8] ,fontsize=fsize-1) 32 | plt.yticks([9,10,11,12] ,fontsize=fsize-1) 33 | plt.xticks(x, labels=['Node 1', 'Node 2'], fontsize=fsize-1) 34 | # plt.ylim(0,1) 35 | plt.ylim(8,13) 36 | plt.xlim(1.4,3.6) 37 | leg = plt.legend(loc='lower center', fontsize=fsize-8, handlelength=1) 38 | plt.grid(which ='major',linestyle= ':', axis="y") #'major', 'minor', 'both' 39 | plt.savefig('../figures/Split_stage_with_switch_p4.pdf',dpi=600,format='pdf', bbox_inches='tight') 40 | 41 | -------------------------------------------------------------------------------- /src/eval/Throughput-Latency/Model_name-Latency.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | 4 | # warnings.filterwarnings('ignore') 5 | import matplotlib 6 | import numpy as np 7 | import json 8 | from math import sqrt 9 | # warnings.filterwarnings('ignore') 10 | 11 | 12 | titles=[] 13 | latency=[] 14 | srams=[] 15 | tcams=[] 16 | memory=[] 17 | 18 | config = {} 19 | config['list of files'] = [] 20 | config['list of files'] += [['sample', './Logs/switch_p4_metrics.json']] 21 | config['list of files'] +=[['seg0', './Logs/metrics0.json']] 22 | config['list of files'] +=[['seg1', './Logs/metrics1.json']] 23 | config['list of files'] +=[['seg2', './Logs/metrics2.json']] 24 | config['list of files'] +=[['seg3', './Logs/metrics3.json']] 25 | config['list of files'] +=[['switch', './Logs/metrics_switch.json']] 26 | 27 | for i in range(0,len(config['list of files'])): 28 | titles.append(config['list of files'][i][0]) 29 | resources=json.load(open(config['list of files'][i][1],'r')) 30 | # print(resources['mau']['latency'][0]['cycles']) 31 | if (i==0): 32 | srams.append(1) 33 | tcams.append(1) 34 | sram_baseline=int(resources['mau']['srams']) 35 | tcam_baseline=int(resources['mau']['tcams']) 36 | memory.append(1) 37 | latency.append(1) 38 | latency_baseline=int(resources['mau']['latency'][0]['cycles']) 39 | else: 40 | sram=int(resources['mau']['srams'])/sram_baseline 41 | srams.append(sram) 42 | tcam=int(resources['mau']['tcams'])/tcam_baseline 43 | tcams.append(tcam) 44 | mems=(sram+tcam)/2 45 | memory.append(mems) 46 | lat=int(resources['mau']['latency'][0]['cycles'])/latency_baseline 47 | latency.append(lat) 48 | print("App: "+config['list of files'][i][0]+" Latency: "+str(lat)+" Memory: "+str(mems)+" SRAM: "+str(sram)+" TCAM: "+str(tcam)) 49 | 50 | 51 | 52 | model = ['Seg0', 'Seg1', 'Seg2', 'Seg3' , 'RARE' ] 53 | x = [1,2,3,4] 54 | 55 | seg0 = latency[1]*100 56 | seg1 = latency[2]*100 57 | seg2 = latency[3]*100 58 | seg3 = latency[4]*100 59 | 60 | switch = latency[5]*100 61 | 62 | ASIC = [seg0, seg1,seg2, seg3] 63 | 64 | fig, ax = plt.subplots(figsize=(6.2, 3)) 65 | plt.rcParams['pdf.fonttype'] = 42 66 | plt.rcParams['ps.fonttype'] = 42 67 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 68 | width = 0.26 69 | 70 | x_n = [i-0*width for i in x] 71 | plt.bar(x_n,ASIC , width= width, label='Coexist with RARE',color = 'lightskyblue', linewidth = 1,edgecolor = 'black') 72 | 73 | 74 | plt.bar([5],[switch] , width= width, label='Standalone RARE', color="silver",linewidth = 1,edgecolor = 'black') 75 | 76 | 77 | 78 | 79 | fsize =25 80 | 81 | 82 | # plt.grid(True) #'major', 'minor', 'both' 83 | 84 | # plt.xlabel('Model', fontsize=fsize) 85 | plt.ylabel('R-Latency (%)', fontsize=fsize) 86 | # plt.yscale('log') 87 | plt.yticks([15,30,45,60], fontsize=fsize-1) 88 | plt.xticks([1,2,3,4,5],labels=model,rotation=-20, fontsize=fsize-1) 89 | plt.xlim(0.3,5.7) 90 | plt.ylim(0,75) 91 | plt.legend(loc='lower right', ncol=1, fontsize=fsize-8) 92 | # 93 | 94 | # plt.legend(bbox_to_anchor=(1.05, 0), loc=3,ncol=5, borderaxespad=0, fontsize=fsize) 95 | plt.grid(which ='major', axis='y',linestyle= ':') #'major', 'minor' , 'both' 96 | plt.savefig('../figures/Segment-Latency.pdf',dpi=600,format='pdf', bbox_inches='tight') 97 | -------------------------------------------------------------------------------- /src/eval/Throughput-Latency/Model_name-Throughput.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | 4 | # warnings.filterwarnings('ignore') 5 | import matplotlib 6 | import numpy as np 7 | import json 8 | from math import sqrt 9 | # warnings.filterwarnings('ignore') 10 | 11 | 12 | 13 | fsize =25 14 | 15 | model = ['Seg0', 'Seg1', 'Seg2', 'Seg3' , 'RARE' ] 16 | x = [1,2,3,4] 17 | 18 | seg0 = (1596590+1596481+1596436+1596594)/1000000 19 | seg1 = (1596392+1596402+1596475+1596385)/1000000 20 | seg2 = (1596490+1596531+1596532+1596485)/1000000 21 | seg3 = (1596242+1596400+1596387+1596204)/1000000 22 | 23 | switch = (1596380+1596393+1596439+1596345)/1000000 24 | 25 | ASIC = [seg0, seg1,seg2, seg3] 26 | 27 | fig, ax = plt.subplots(figsize=(6, 3)) 28 | plt.rcParams['pdf.fonttype'] = 42 29 | plt.rcParams['ps.fonttype'] = 42 30 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 31 | 32 | 33 | plt.hlines(6.4,0,6, linestyle="--" , color = 'red') 34 | plt.text(3.9, 6.6, 'Line rate', fontsize=fsize-1 , color = 'red') 35 | 36 | width = 0.26 37 | x_n = [i-0*width for i in x] 38 | plt.bar(x_n,ASIC , width= width, label='Coexist with RARE',color = 'lightskyblue', linewidth = 1,edgecolor = 'black') 39 | 40 | 41 | plt.bar([5],[switch] , width= width, label='Standalone RARE', color="silver",linewidth = 1,edgecolor = 'black') 42 | 43 | 44 | 45 | 46 | 47 | 48 | # plt.grid(True) #'major', 'minor', 'both' 49 | 50 | # plt.xlabel('Model', fontsize=fsize) 51 | plt.ylabel('Throughput', fontsize=fsize-1) 52 | # plt.yscale('log') 53 | plt.yticks([1.5,3,4.5,6], fontsize=fsize-1) 54 | plt.xticks([1,2,3,4,5],labels=model,rotation=-20, fontsize=fsize-1) 55 | plt.xlim(0.3,5.7) 56 | plt.ylim(0,7.5) 57 | plt.legend(loc='lower right', ncol=1, fontsize=fsize-8) 58 | # 59 | 60 | # plt.legend(bbox_to_anchor=(1.05, 0), loc=3,ncol=5, borderaxespad=0, fontsize=fsize) 61 | plt.grid(which ='major', axis='y',linestyle= ':') #'major', 'minor' , 'both' 62 | plt.savefig('../figures/Segment-Throughput.pdf',dpi=600,format='pdf', bbox_inches='tight') 63 | -------------------------------------------------------------------------------- /src/eval/Time-Path_Segments/Time-Edge_Clos.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | import matplotlib 4 | import numpy as np 5 | import json 6 | from math import sqrt 7 | 8 | fsize =25 9 | lw=2 10 | ms = 6 11 | mes = 1 12 | lw=2 13 | 14 | 15 | 16 | 17 | model = ['1', '2', '3', '4', '5'] 18 | x = [1,2,3,4,5] 19 | 20 | # 0.10952112674713135, 0.12678711414337157, 0.13884289264678956, 0.16474764347076415, 0.17274291515350343] 21 | # 0.0032471952915711067, 0.0006922912296972685, 0.001049483076647019, 0.004338363073341647, 0.0010001896391073721] 22 | # 36,72,108,140,172 23 | 24 | 25 | time = [0.0030060768127441405, 0.004389834403991699, 0.005976200103759766, 0.007393336296081543, 0.008810830116271973] 26 | 27 | var = [0.00021867281575554406, 0.00019698073314995026, 0.0003215019508841349, 0.0002193663278438717, 0.00029543081091567815] 28 | 29 | 30 | path = [18,36,54,72,90] 31 | 32 | fig, ax1 = plt.subplots(figsize=(5, 3)) 33 | ax2 = ax1.twinx() 34 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 35 | # plt.rcParams['mathtext.fontset']= 'custom' 36 | plt.rcParams['pdf.fonttype'] = 42 37 | plt.rcParams['ps.fonttype'] = 42 38 | width = 0.26 39 | # cm stic stixsans custom 40 | x_n = [i-0*width for i in x] 41 | ax1.bar(x_n,time ,width=width, label='Time (s)', color="lightskyblue" ,linewidth = 1,edgecolor = 'black' ,yerr=var, error_kw=dict(lw=1, capsize=2.5, capthick=1)) 42 | 43 | 44 | 45 | l1 = ax2.plot(x, path, '--', label='Paths', marker = 's', ms=ms, markeredgecolor='black', markeredgewidth=mes, color="#ff7f0e",linewidth = lw) 46 | 47 | 48 | 49 | 50 | fsize+=2 51 | plt.xlabel('Model', fontsize=fsize+1) 52 | ax1.set_xticks(x) 53 | ax1.set_xticklabels(labels=model,rotation=-0, fontsize=fsize+1) 54 | ax1.set_xlabel('Num of Edge Nodes', fontsize=fsize+1) 55 | 56 | ax1.set_yscale('log') 57 | ax1.set_ylabel('Time (s)', fontsize=fsize+1) 58 | ax1.set_yticks([10**-3,10**-2,10**-1,10**0]) 59 | ax1.set_yticklabels(labels=['10$^{-3}$','10$^{-2}$','10$^{-1}$','10$^{-0}$'], fontsize=fsize+1) 60 | ax1.set_ylim(10**-4,10**1) 61 | 62 | 63 | ax2.set_ylabel('Paths', fontsize=fsize+1) 64 | ax2.set_yticks([50,100,150,200]) 65 | ax2.set_yticklabels(labels=['30','50','70','90'], fontsize=fsize+1) 66 | ax2.set_ylim(0,250) 67 | 68 | 69 | plt.xlim(0.3,5.7) 70 | 71 | 72 | lines, labels = ax1.get_legend_handles_labels() 73 | lines2, labels2 = ax2.get_legend_handles_labels() 74 | f_line = lines + lines2 75 | # f_line[1] = lines[0] 76 | # f_line[0] = lines2[0] 77 | # f_line[3] = lines[1] 78 | # f_line[2] = lines2[1] 79 | f_lable = labels + labels2 80 | # f_lable[1] = labels[0] 81 | # f_lable[0] = labels2[0] 82 | # f_lable[3] = labels[1] 83 | # f_lable[2] = labels2[1] 84 | ax2.legend(f_line, f_lable, fancybox=True, fontsize=fsize-8,loc = "upper left", ncol=1) 85 | 86 | plt.grid(which ='major', linestyle= ':') #'major', 'minor' , 'both' 87 | plt.savefig('../figures/Time-Edge_clos.pdf',dpi=600,format='pdf', bbox_inches='tight') 88 | # plt.show() 89 | -------------------------------------------------------------------------------- /src/eval/Time-Path_Segments/Time-Segments_BT.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | import matplotlib 4 | import numpy as np 5 | import json 6 | from math import sqrt 7 | 8 | fsize =25 9 | lw=2 10 | ms = 6 11 | mes = 1 12 | lw=2 13 | 14 | 15 | 16 | 17 | model = ['2', '3', '4', '5', '6'] 18 | x = [2,3,4,5,6] 19 | 20 | 21 | 22 | 23 | 24 | # 2.585120415687561, 9.731816864013672, 16.573393726348876, 29.22371470928192, 56.68120107650757, 25 | # 0.005196774484805836, 0.23781882269492483, 0.9169319803730787, 2.6102297522511937, 0.5890758830975283, 26 | # 26512, 26512, 26512,26512,26512 27 | 28 | time = [2.585120415687561, 9.731816864013672, 16.573393726348876, 29.22371470928192, 56.68120107650757] 29 | 30 | var = [0.005196774484805836, 0.23781882269492483, 0.9169319803730787, 2.6102297522511937, 0.5890758830975283] 31 | 32 | 33 | path = [26512, 26512, 26512,26512,26512] 34 | 35 | fig, ax1 = plt.subplots(figsize=(5, 3)) 36 | ax2 = ax1.twinx() 37 | plt.rcParams['pdf.fonttype'] = 42 38 | plt.rcParams['ps.fonttype'] = 42 39 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 40 | # plt.rcParams['mathtext.fontset']= 'custom' 41 | width = 0.26 42 | # cm stic stixsans custom 43 | x_n = [i-0*width for i in x] 44 | ax1.bar(x_n,time ,width=width, label='Time (s)', color="lightskyblue" ,linewidth = 1,edgecolor = 'black' ,yerr=var, error_kw=dict(lw=1, capsize=2.5, capthick=1)) 45 | 46 | 47 | 48 | l1 = ax2.plot(x, path, '--', label='Paths', marker = 's', ms=ms, markeredgecolor='black', markeredgewidth=mes, color="#ff7f0e",linewidth = lw) 49 | 50 | 51 | 52 | 53 | fsize+=2 54 | plt.xlabel('Model', fontsize=fsize+1) 55 | ax1.set_xticks(x) 56 | ax1.set_xticklabels(labels=model,rotation=-0, fontsize=fsize+1) 57 | ax1.set_xlabel('Num of Segments', fontsize=fsize+1) 58 | 59 | ax1.set_yscale('log') 60 | ax1.set_ylabel('Time (s)', fontsize=fsize+1) 61 | ax1.set_yticks([10**-2,10**-1,10**-0,10**1]) 62 | ax1.set_yticklabels(labels=['10$^{-2}$','10$^{-1}$','10$^{-0}$','10$^{+1}$'], fontsize=fsize+1) 63 | ax1.set_ylim(10**-3,10**2) 64 | 65 | 66 | ax2.set_ylabel('Paths', fontsize=fsize+1) 67 | ax2.set_yticks([8000,16000,24000,32000]) 68 | ax2.set_yticklabels(labels=['8k','16k','24k','32k'], fontsize=fsize+1) 69 | ax2.set_ylim(0,40000) 70 | 71 | 72 | plt.xlim(1.3,6.7) 73 | 74 | 75 | lines, labels = ax1.get_legend_handles_labels() 76 | lines2, labels2 = ax2.get_legend_handles_labels() 77 | f_line = lines + lines2 78 | # f_line[1] = lines[0] 79 | # f_line[0] = lines2[0] 80 | # f_line[3] = lines[1] 81 | # f_line[2] = lines2[1] 82 | f_lable = labels + labels2 83 | # f_lable[1] = labels[0] 84 | # f_lable[0] = labels2[0] 85 | # f_lable[3] = labels[1] 86 | # f_lable[2] = labels2[1] 87 | ax2.legend(f_line, f_lable, fancybox=True, fontsize=fsize-8,loc = "upper left", ncol=1) 88 | 89 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 90 | plt.savefig('../figures/Time_Segments_BT.pdf',dpi=600,format='pdf', bbox_inches='tight') 91 | # plt.show() 92 | -------------------------------------------------------------------------------- /src/eval/Time-Path_Segments/Time-Segments_Clos.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | import matplotlib 4 | import numpy as np 5 | import json 6 | from math import sqrt 7 | 8 | fsize =25 9 | lw=2 10 | ms = 6 11 | mes = 1 12 | lw=2 13 | 14 | 15 | 16 | 17 | model = ['2', '3', '4', '5', '6'] 18 | x = [2,3,4,5,6] 19 | 20 | 21 | 22 | 23 | 24 | # 2.585120415687561, 9.731816864013672, 16.573393726348876, 29.22371470928192, 56.68120107650757, 25 | # 0.005196774484805836, 0.23781882269492483, 0.9169319803730787, 2.6102297522511937, 0.5890758830975283, 26 | # 26512, 26512, 26512,26512,26512 27 | 28 | time = [0.018982672691345216, 0.03157079219818115, 0.056016731262207034, 0.6151327133178711, 0.46450252532958985] 29 | 30 | var = [0.002364916477176542, 0.00048190334584875144, 0.00046240761646514295, 0.0022740877306276484, 0.00422413055839856] 31 | 32 | 33 | path = [432,432,432,432,432] 34 | 35 | fig, ax1 = plt.subplots(figsize=(5, 3)) 36 | ax2 = ax1.twinx() 37 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 38 | # plt.rcParams['mathtext.fontset']= 'custom' 39 | plt.rcParams['pdf.fonttype'] = 42 40 | plt.rcParams['ps.fonttype'] = 42 41 | width = 0.26 42 | # cm stic stixsans custom 43 | x_n = [i-0*width for i in x] 44 | ax1.bar(x_n,time ,width=width, label='Time (s)', color="lightskyblue" ,linewidth = 1,edgecolor = 'black' ,yerr=var, error_kw=dict(lw=1, capsize=2.5, capthick=1)) 45 | 46 | 47 | 48 | l1 = ax2.plot(x, path, '--', label='Paths', marker = 's', ms=ms, markeredgecolor='black', markeredgewidth=mes, color="#ff7f0e",linewidth = lw) 49 | 50 | 51 | 52 | 53 | fsize+=2 54 | plt.xlabel('Model', fontsize=fsize+1) 55 | ax1.set_xticks(x) 56 | ax1.set_xticklabels(labels=model,rotation=-0, fontsize=fsize+1) 57 | ax1.set_xlabel('Num of Segments', fontsize=fsize+1) 58 | 59 | ax1.set_yscale('log') 60 | ax1.set_ylabel('Time (s)', fontsize=fsize+1) 61 | ax1.set_yticks([10**-2,10**-1,10**-0,10**1]) 62 | ax1.set_yticklabels(labels=['10$^{-2}$','10$^{-1}$','10$^{-0}$','10$^{+1}$'], fontsize=fsize+1) 63 | ax1.set_ylim(10**-3,10**2) 64 | 65 | 66 | ax2.set_ylabel('Paths', fontsize=fsize+1) 67 | ax2.set_yticks([8000,16000,24000,32000]) 68 | ax2.set_yticklabels(labels=['8k','16k','24k','32k'], fontsize=fsize+1) 69 | ax2.set_ylim(0,40000) 70 | 71 | 72 | plt.xlim(1.3,6.7) 73 | 74 | 75 | lines, labels = ax1.get_legend_handles_labels() 76 | lines2, labels2 = ax2.get_legend_handles_labels() 77 | f_line = lines + lines2 78 | # f_line[1] = lines[0] 79 | # f_line[0] = lines2[0] 80 | # f_line[3] = lines[1] 81 | # f_line[2] = lines2[1] 82 | f_lable = labels + labels2 83 | # f_lable[1] = labels[0] 84 | # f_lable[0] = labels2[0] 85 | # f_lable[3] = labels[1] 86 | # f_lable[2] = labels2[1] 87 | ax2.legend(f_line, f_lable, fancybox=True, fontsize=fsize-8,loc = "upper left", ncol=1) 88 | 89 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 90 | plt.savefig('../figures/Time_Segments_clos.pdf',dpi=600,format='pdf', bbox_inches='tight') 91 | # plt.show() 92 | -------------------------------------------------------------------------------- /src/eval/Time-Path_Segments/Time-Tier1_BT.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import warnings 3 | import matplotlib 4 | import numpy as np 5 | import json 6 | from math import sqrt 7 | 8 | fsize =25 9 | lw=2 10 | ms = 6 11 | mes = 1 12 | lw=2 13 | 14 | 15 | 16 | 17 | model = ['1', '2', '3', '4', '5'] 18 | x = [1,2,3,4,5] 19 | 20 | # 0.10952112674713135, 0.12678711414337157, 0.13884289264678956, 0.16474764347076415, 0.17274291515350343] 21 | # 0.0032471952915711067, 0.0006922912296972685, 0.001049483076647019, 0.004338363073341647, 0.0010001896391073721] 22 | # 36,72,108,140,172 23 | 24 | 25 | time = [0.10952112674713135, 0.12678711414337157, 0.13884289264678956, 0.16474764347076415, 0.17274291515350343] 26 | 27 | var = [0.0032471952915711067, 0.0006922912296972685, 0.001049483076647019, 0.004338363073341647, 0.0010001896391073721] 28 | 29 | 30 | path = [36,72,108,140,172] 31 | 32 | fig, ax1 = plt.subplots(figsize=(5, 3)) 33 | ax2 = ax1.twinx() 34 | # plt.rcParams['font.sans-serif'] = 'Times New Roman' 35 | # plt.rcParams['mathtext.fontset']= 'custom' 36 | plt.rcParams['pdf.fonttype'] = 42 37 | plt.rcParams['ps.fonttype'] = 42 38 | width = 0.26 39 | # cm stic stixsans custom 40 | x_n = [i-0*width for i in x] 41 | ax1.bar(x_n,time ,width=width, label='Time (s)', color="lightskyblue" ,linewidth = 1,edgecolor = 'black' ,yerr=var, error_kw=dict(lw=1, capsize=2.5, capthick=1)) 42 | 43 | 44 | 45 | l1 = ax2.plot(x, path, '--', label='Paths', marker = 's', ms=ms, markeredgecolor='black', markeredgewidth=mes, color="#ff7f0e",linewidth = lw) 46 | 47 | 48 | 49 | 50 | fsize+=2 51 | plt.xlabel('Model', fontsize=fsize+1) 52 | ax1.set_xticks(x) 53 | ax1.set_xticklabels(labels=model,rotation=-0, fontsize=fsize+1) 54 | ax1.set_xlabel('Num of Tier 1 Nodes', fontsize=fsize+1) 55 | 56 | ax1.set_yscale('log') 57 | ax1.set_ylabel('Time (s)', fontsize=fsize+1) 58 | ax1.set_yticks([10**-3,10**-2,10**-1,10**0]) 59 | ax1.set_yticklabels(labels=['10$^{-3}$','10$^{-2}$','10$^{-1}$','10$^{-0}$'], fontsize=fsize+1) 60 | ax1.set_ylim(10**-4,10**1) 61 | 62 | 63 | ax2.set_ylabel('Paths', fontsize=fsize+1) 64 | ax2.set_yticks([50,100,150,200]) 65 | ax2.set_yticklabels(labels=['30','50','70','90'], fontsize=fsize+1) 66 | ax2.set_ylim(0,250) 67 | 68 | 69 | 70 | plt.xlim(0.3,5.7) 71 | 72 | 73 | lines, labels = ax1.get_legend_handles_labels() 74 | lines2, labels2 = ax2.get_legend_handles_labels() 75 | f_line = lines + lines2 76 | # f_line[1] = lines[0] 77 | # f_line[0] = lines2[0] 78 | # f_line[3] = lines[1] 79 | # f_line[2] = lines2[1] 80 | f_lable = labels + labels2 81 | # f_lable[1] = labels[0] 82 | # f_lable[0] = labels2[0] 83 | # f_lable[3] = labels[1] 84 | # f_lable[2] = labels2[1] 85 | ax2.legend(f_line, f_lable, fancybox=True, fontsize=fsize-8,loc = "upper left", ncol=1) 86 | 87 | plt.grid(which ='major',linestyle= ':') #'major', 'minor' , 'both' 88 | plt.savefig('../figures/Time-Tier1_BT.pdf',dpi=600,format='pdf', bbox_inches='tight') 89 | # plt.show() 90 | -------------------------------------------------------------------------------- /src/eval/evaluation.md: -------------------------------------------------------------------------------- 1 | # DINC Supports 2 | ![Planter Logo](../images/logo.png) 3 | 4 | ## A Guide to Evaluation Reproduction. 5 | 6 | All figures (Figure 12- 7 | 17 and Table 3) can be generated by the Python files in ```./src/eva/*/*.py```, where the raw experiment data is hardcoded directly. All data can be generated by DINC, with detailed instructions available in ```./README.md```. A detailed explanation of the DINC's configuration for each experiment is provided below, aiding in the replication of the results used in the figures and tables. 8 | 9 | There are two options to reproduce the evaluation, use the predefined configuration file or manually input all the configurations: 10 | 11 | ### Option I. Utilise The Predefined Configuration File (without -m). 12 | Some of the already filled configuration files are under ```./src/eva/Configurations/``` (e.g., ```Table3_RF_DINC_config.json```), please use them to replace ```./src/configs/DINC_config.json```. Before running the framework, change the ```work``` under ```directory config``` in the JSON file. After preparing, activate the DINC framework by using ```python3 DINC.py``` directly. Please note that ```-m``` is not needed if you use the predefined configurations. 13 | 14 | 15 | ### Option II. Manually Input Configuration by Using DINC CLI (with -m) 16 | **Important Configurations:** For most of unmentioned configurations, please use the default option. 17 | 18 | * **Topology**: Please use ```BT-ASP``` and ```Folded-Clos-ASP``` for evaluation. When slecting BT topology, please select ```False``` in _display plot_. When select Clos topology, apply switch number```3```, ```6```, and ```24``` in each layer. 19 | * **Planner**: Please use ```ILP``` and ```Type_1```. 20 | * **Input & Output Device List**: For the BT topology, please follows the guide from the CLI. For the Folded Clos topology (as shown in the Figure (a) and (b) below), _all C_ means ```[0,1,2]``` and _all E_ meanse ```[9,10,...,32]```. For the case of _any C_ or _E_, random slect one from previous list repectively. The input device list refers to nodes that have packets come in and the output device list shows packet egress nodes in the topology. 21 | * **Resources should be considered? (stage/memory?)**: Please use the default number from the framework. 22 | * **Result**: Choose ```True``` in _test ILP_ to display results. 23 | * **Example Algorithms**: Example algorithms are provided under ```./src/sample/*/*.p4```. All these algorithms are annotated with basic manually added markers. Beyond the generation of deployment strategy, to ensure the distributed in-network computing program works, for most of the provided example p4 programs, more comprehensive annotations should be added, and the generated program should be manually debugged. 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/eval/figures/BT-UK-topo-nouk_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/BT-UK-topo-nouk_v2.png -------------------------------------------------------------------------------- /src/eval/figures/Coefficent-hops_BT.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Coefficent-hops_BT.pdf -------------------------------------------------------------------------------- /src/eval/figures/Coefficent-hops_Clos.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Coefficent-hops_Clos.pdf -------------------------------------------------------------------------------- /src/eval/figures/DINC_Flightplan_Dup.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/DINC_Flightplan_Dup.pdf -------------------------------------------------------------------------------- /src/eval/figures/DINC_Flightplan_Hop.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/DINC_Flightplan_Hop.pdf -------------------------------------------------------------------------------- /src/eval/figures/DINC_Flightplan_Node.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/DINC_Flightplan_Node.pdf -------------------------------------------------------------------------------- /src/eval/figures/Segment-Latency.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Segment-Latency.pdf -------------------------------------------------------------------------------- /src/eval/figures/Segment-Throughput.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Segment-Throughput.pdf -------------------------------------------------------------------------------- /src/eval/figures/Setup-Hops_BT.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Setup-Hops_BT.pdf -------------------------------------------------------------------------------- /src/eval/figures/Setup-Hops_Clos.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Setup-Hops_Clos.pdf -------------------------------------------------------------------------------- /src/eval/figures/Setups_label.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Setups_label.pdf -------------------------------------------------------------------------------- /src/eval/figures/Split_mem.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Split_mem.pdf -------------------------------------------------------------------------------- /src/eval/figures/Split_stage.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Split_stage.pdf -------------------------------------------------------------------------------- /src/eval/figures/Split_stage_with_switch_p4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Split_stage_with_switch_p4.pdf -------------------------------------------------------------------------------- /src/eval/figures/Time-Edge_clos.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Time-Edge_clos.pdf -------------------------------------------------------------------------------- /src/eval/figures/Time-Segment_Fat-Tree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Time-Segment_Fat-Tree.pdf -------------------------------------------------------------------------------- /src/eval/figures/Time-Tier1_BT.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Time-Tier1_BT.pdf -------------------------------------------------------------------------------- /src/eval/figures/Time_Segments_BT.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Time_Segments_BT.pdf -------------------------------------------------------------------------------- /src/eval/figures/Time_Segments_clos.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/Time_Segments_clos.pdf -------------------------------------------------------------------------------- /src/eval/figures/ml_scaling.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/ml_scaling.pdf -------------------------------------------------------------------------------- /src/eval/figures/rare_heatmap_v3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/eval/figures/rare_heatmap_v3.pdf -------------------------------------------------------------------------------- /src/functions/add_license.py: -------------------------------------------------------------------------------- 1 | def add_license(fname, first_line = True): 2 | if first_line: 3 | operation = 'w' 4 | else: 5 | operation = 'a' 6 | with open(fname, operation) as file: 7 | file.write("########################################################################\n" 8 | "# This program is a free software tool, which does ensemble in-network machine learning.\n" 9 | "# licensed under Apache-2.0\n" 10 | "#\n" 11 | "# Copyright (c) 2020-2021 Changgang Zheng\n" 12 | "# Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & YINS, Yale University\n" 13 | "# E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024),\n" 14 | "# changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date)\n" 15 | "#########################################################################\n" 16 | "# This file was autogenerated\n\n" 17 | ) -------------------------------------------------------------------------------- /src/functions/cmd_related.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Planter extend project: DINC. 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | import json 10 | import os 11 | import time 12 | import subprocess as sub 13 | 14 | def run_command(command, root): 15 | sub.run(command, cwd = root) 16 | 17 | def print_log_file(file_name): 18 | while True: 19 | if os.path.exists(file_name): 20 | time.sleep(1) 21 | break 22 | with open(file_name, 'r') as file: 23 | for i, line in enumerate(file.readlines()): 24 | print(line, end="") -------------------------------------------------------------------------------- /src/functions/config_modification.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Planter extend project: DINC. 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | 10 | import os 11 | import json 12 | from src.functions.json_encoder import * 13 | 14 | def reload_DINC_config(config_file_dir): 15 | if os.path.exists(config_file_dir): 16 | DINC_config = json.load(open(config_file_dir, 'r')) 17 | else: 18 | DINC_config = {} 19 | return DINC_config 20 | 21 | 22 | def dump_DINC_config(DINC_config, config_file_dir, print_log = False): 23 | json.dump(DINC_config, open(config_file_dir, 'w'), indent=4, cls=NpEncoder) 24 | if print_log: 25 | print('Dump the targets info to '+config_file_dir) -------------------------------------------------------------------------------- /src/functions/directory_management.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Planter project. 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | 10 | import os 11 | 12 | def find_folder_options(f): 13 | fs = os.listdir(f) 14 | print(" What option is available: ",end="") 15 | first = True 16 | for f1 in fs: 17 | tmp_path = os.path.join(f, f1) 18 | if os.path.isdir(tmp_path): 19 | if "__" not in f1: 20 | if first: 21 | print(f1,end="") 22 | first=False 23 | else: 24 | print(", "+f1,end="") 25 | print(".") 26 | 27 | 28 | def find_file_options(f): 29 | fs = os.listdir(f) 30 | print(" What option is available: ",end="") 31 | first = True 32 | for f1 in fs: 33 | tmp_path = os.path.join(f, f1) 34 | if not os.path.isdir(tmp_path): 35 | if first: 36 | print(f1,end="") 37 | first=False 38 | else: 39 | print(", "+f1,end="") 40 | print(" ") 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/functions/figure_to_ASCII.py: -------------------------------------------------------------------------------- 1 | def print_logo(): 2 | print("\n ,---, ,---, ,--.'| ,----.. \n" 3 | " .' .' `\ ,`--.' | ,--,: : | / / \\ \n" 4 | ",---.' \ | : : ,`--.'`| ' : | : : \n" 5 | "| | .`\ | : | ' | : : | | . | ;. / \n" 6 | ": : | ' | | : | : | \ | : . ; /--` \n" 7 | "| ' ' ; : ' ' ; | : ' '; | ; | ; \n" 8 | "' | ; . | | | | ' ' ;. ; | : | \n" 9 | "| | : | ' ' : ; | | | \ | . | '___ \n" 10 | "' : | / ; | | ' ' : | ; .' ' ; : .'| \n" 11 | "| | '` ,/ ' : | | | '`--' ' | '/ : \n" 12 | "; : .' ; |.' ' : | | : / \n" 13 | "| ,.' '---' ; |.' \ \ .' \n" 14 | "'---' '---' `---` DINC version 0 \n") 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/functions/input_CLI.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Planter extend project: DINC. 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | 10 | import os 11 | import copy 12 | import numpy as np 13 | from src.functions.directory_management import * 14 | 15 | def CLI_loop(question, default, check_dir_existance, check_available_options, option_address): 16 | while True: 17 | if check_available_options: 18 | CLI_input = input('+ ' + question + ' (default = ' + str(default) + ' | options = -h) ') or default 19 | else: 20 | CLI_input = input('+ ' + question + ' (default = ' + str(default) + ') ') or default 21 | if check_dir_existance: 22 | if not check_available_options: 23 | if not os.path.exists(CLI_input): 24 | print(' Warning! The input does not exist, please input again.') 25 | else: 26 | break 27 | else: 28 | input_dir = os.getcwd() + option_address + '/' + CLI_input 29 | if not os.path.exists(input_dir): 30 | if CLI_input != "-h": 31 | print(' Warning! The input: ' + CLI_input + ' does not available, please input again.') 32 | find_folder_options(os.getcwd() + option_address) 33 | else: 34 | break 35 | else: 36 | break 37 | return CLI_input 38 | 39 | 40 | def take_CLI_input(DINC_config, config_type, config_name, question, default, manully_input, check_dir_existance = False, check_available_options = False, option_address = '', numeric = False): 41 | if not manully_input: 42 | try: 43 | CLI_input = DINC_config[config_type][config_name] 44 | print('= Config type: \''+config_type+'\' config name: \''+config_name+'\' is auto filled with: ' + str(CLI_input)) 45 | except Exception as e: 46 | try: 47 | _ = DINC_config[config_type] 48 | except Exception as e: 49 | DINC_config[config_type] = {} 50 | CLI_input = CLI_loop(question, default, check_dir_existance, check_available_options, option_address) 51 | else: 52 | try: 53 | _ = DINC_config[config_type] 54 | except Exception as e: 55 | DINC_config[config_type] = {} 56 | CLI_input = CLI_loop(question, default, check_dir_existance, check_available_options, option_address) 57 | if numeric: 58 | CLI_input = int(CLI_input) 59 | DINC_config[config_type][config_name] = CLI_input 60 | return DINC_config 61 | 62 | 63 | def try_convert_str_input_to_int(input): 64 | if input.isdigit(): 65 | return copy.deepcopy(int(input)) 66 | return copy.deepcopy(input) 67 | 68 | def str_to_array(input, margine = 1, marker = ','): 69 | if type(input) == str: 70 | if margine != 0: 71 | input = input[margine:-margine].split(marker) 72 | else: 73 | input = input.split(marker) 74 | for i, content in enumerate(input): 75 | input[i] = content.lstrip().rstrip() 76 | if input[i].isdigit(): 77 | input[i] = int(input[i]) 78 | return copy.deepcopy(input) -------------------------------------------------------------------------------- /src/functions/json_encoder.py: -------------------------------------------------------------------------------- 1 | import json 2 | import numpy as np 3 | 4 | class NpEncoder(json.JSONEncoder): 5 | def default(self, obj): 6 | if isinstance(obj, np.integer): 7 | return int(obj) 8 | if isinstance(obj, np.floating): 9 | return float(obj) 10 | if isinstance(obj, np.ndarray): 11 | return obj.tolist() 12 | return super(NpEncoder, self).default(obj) -------------------------------------------------------------------------------- /src/functions/write_file.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Planter project. 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | 10 | import os 11 | import glob 12 | from src.functions.add_license import * 13 | 14 | def open_new_file(fname): 15 | with open(fname, 'w') as file: 16 | file.write("") 17 | 18 | def write_line(line, file_name, first_line_of_file = False, add_license_txt = False): 19 | if first_line_of_file: 20 | open_new_file(file_name) 21 | if add_license_txt: 22 | add_license(file_name, first_line = first_line_of_file) 23 | with open(file_name, 'a') as file: 24 | file.write(line) 25 | 26 | def clean_dir(dir, type = '.p4'): 27 | files = glob.glob(dir+'/*'+type, recursive=True) 28 | for f in files: 29 | try: 30 | print('- Remove file: '+f) 31 | os.remove(f) 32 | except OSError as e: 33 | print("Error: %s : %s" % (f, e.strerror)) 34 | 35 | 36 | def write_p4_file_with_space(p4_file_name, before_p4_leading_space, space_gap, target_file): 37 | with open(p4_file_name, 'r') as file: 38 | First_Line = True 39 | for line_idx, line in enumerate(file.readlines()): 40 | # if 'default_class' in line: 41 | # pass 42 | if First_Line: 43 | p4_leading_space = len(line) - len(line.lstrip(' ')) 44 | extra_space = space_gap + before_p4_leading_space - p4_leading_space 45 | if len(set(line)) > 1: 46 | First_Line = False 47 | # if extra_space == 4: 48 | # pass 49 | 50 | # print(extra_space, space_gap, before_p4_leading_space, p4_leading_space) 51 | # print(line) 52 | if extra_space < 0: 53 | target_file.write(line[abs(extra_space):]) 54 | else: 55 | target_file.write(extra_space * ' ' + line) -------------------------------------------------------------------------------- /src/help/DINC_Supports/DINC_Supported_Architectures.md: -------------------------------------------------------------------------------- 1 | # DINC Supports 2 | ![DINC Logo](../../images/logo.png) 3 | 7 | 8 | ## Supported Architectures 9 | The architectures here are indicative of the architecture used in your p4 file (e.g., ```#include ```). It is located under the ```./src/architectures/``` folder. Recommended architectures are marked with 🔥. 10 | 11 | 12 | **1. TNA 🔥** [Folder](../../architecture/tna) - The Tofino Native Architecture (TNA) [Link](https://github.com/barefootnetworks/Open-Tofino/blob/master/PUBLIC_Tofino-Native-Arch-Document.pdf) is an architecture designed for Intel Tofino harware and emulation targets. One example is the Tofino Switch. 13 | 14 | **2. v1model 🔥** [Folder](../../architecture/v1model) - The v1model [Link](https://sdn.systemsapproach.org/switch.html) was originally designed to support P414 and later to support P416. It is used in BMv2, P4Pi-enabled BMv2, and P4Pi-enabled T4P4S. 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/help/DINC_Supports/DINC_Supported_Topologies.md: -------------------------------------------------------------------------------- 1 | # DINC Supports 2 | ![DINC Logo](../../images/logo.png) 3 | 7 | 8 | 9 | ## Supported Network Topologies 10 | 11 | 14 | 15 | The recommended variation for each model is marked with 🔥. 16 | 17 | **1. Fat Tree Topology** 18 | 19 | - **Fat-Tree [[Folder]](../../topologies/Fat-Tree):** This case using `nx.all_simple_paths()` funtion to find the paths. 20 | 21 | We will mainly shows the piecture of Folded-Clos and BT ISP topology, as shown in the picture below: 22 | 23 | 24 | **2. Folded Clos Topology** 25 | 26 | - **Folded-Clos-All:** All possible none loop paths with out duplication nodes. This case using `nx.all_simple_paths()` funtion to find the paths. 27 | - **Folded-Clos [[Folder]](../../topologies/Folded-Clos) 🔥:** Only sigle direction from device-to-core/core-to-device and avioid valley free routing for device to device case. This case using `nx.all_simple_paths()` funtion to find the paths. 28 | - **Folded-Clos-ASP** Same as Folded-Clos but using `nx.all_shortest_paths()` funtion to find the paths. 29 | 30 | **3. BT Topology** 31 | 32 | - **BT [[Folder]](../../topologies/BT) 🔥:** This case using `nx.all_simple_paths()` funtion to find the paths. 33 | - **BT-ASP** Same as BT but using `nx.all_shortest_paths()` funtion to find the paths. 34 | 35 | We also shows a detailed aerial view of the BT ISP topology. 36 | 37 | -------------------------------------------------------------------------------- /src/help/DINC_Supports/DINC_Supported_Use_Cases.md: -------------------------------------------------------------------------------- 1 | # DINC Supports 2 | ![DINC Logo](../../images/logo.png) 3 | 7 | 8 | 9 | ## Supported use cases 10 | DINC currently support three use cases. Hot use cases are marked with 🔥. 11 | 12 | **1. Standard Block 🔥** [Folder](../../use_cases/standard_block) - This use case is for functionality verification. In this case, the switching functionality will be simple ipv4 forwarding table. 13 | 14 | **2. switch.p4** - This use case is for functionality verification. In this case, the distributed segmentations will coexist with an L2/L3 reference designed by Intel Tofino. 15 | 16 | **3. RARE** - This use case is for functionality verification. In this case, the distributed segmentations will coexist with the RARE open-source router [Link](http://docs.freertr.org/). 17 | -------------------------------------------------------------------------------- /src/help/Zheng_et_al_2023_DINC_toward_distributed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/help/Zheng_et_al_2023_DINC_toward_distributed.pdf -------------------------------------------------------------------------------- /src/images/BT-UK-topo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/images/BT-UK-topo.png -------------------------------------------------------------------------------- /src/images/DINC_framework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/images/DINC_framework.png -------------------------------------------------------------------------------- /src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/images/logo.png -------------------------------------------------------------------------------- /src/images/sample_marking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/images/sample_marking.png -------------------------------------------------------------------------------- /src/images/topos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/images/topos.png -------------------------------------------------------------------------------- /src/logs/DT_performance_Iris_Fat-Tree_3depth_2branch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/logs/DT_performance_Iris_Fat-Tree_3depth_2branch.pdf -------------------------------------------------------------------------------- /src/temp/P4/E0_control-apply.p4: -------------------------------------------------------------------------------- 1 | lookup_feature0.apply(); 2 | lookup_feature1.apply(); 3 | -------------------------------------------------------------------------------- /src/temp/P4/E0_control.p4: -------------------------------------------------------------------------------- 1 | action extract_feature0(out bit<1> meta_code, bit<1> tree){ 2 | meta_code = tree; 3 | } 4 | action extract_feature1(out bit<2> meta_code, bit<2> tree){ 5 | meta_code = tree; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | table lookup_feature0 { 13 | key = { meta.feature0:ternary; } 14 | actions = { 15 | extract_feature0(meta.code_f0); 16 | NoAction; 17 | } 18 | size = 8; 19 | default_action = NoAction; 20 | } 21 | 22 | table lookup_feature1 { 23 | key = { meta.feature1:ternary; } 24 | actions = { 25 | extract_feature1(meta.code_f1); 26 | NoAction; 27 | } 28 | size = 7; 29 | default_action = NoAction; 30 | } 31 | -------------------------------------------------------------------------------- /src/temp/P4/E1_control-apply.p4: -------------------------------------------------------------------------------- 1 | lookup_feature2.apply(); 2 | lookup_feature3.apply(); 3 | -------------------------------------------------------------------------------- /src/temp/P4/E1_control.p4: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | action extract_feature2(out bit<3> meta_code, bit<3> tree){ 5 | meta_code = tree; 6 | } 7 | 8 | action extract_feature3(out bit<3> meta_code, bit<3> tree){ 9 | meta_code = tree; 10 | } 11 | 12 | 13 | table lookup_feature2 { 14 | key = { meta.feature2:ternary; } 15 | actions = { 16 | extract_feature2(meta.code_f2); 17 | NoAction; 18 | } 19 | size = 15; 20 | default_action = NoAction; 21 | } 22 | 23 | table lookup_feature3 { 24 | key = { meta.feature3:ternary; } 25 | actions = { 26 | extract_feature3(meta.code_f3); 27 | NoAction; 28 | } 29 | size = 10; 30 | default_action = NoAction; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/temp/P4/E2_control-apply.p4: -------------------------------------------------------------------------------- 1 | decision.apply(); 2 | -------------------------------------------------------------------------------- /src/temp/P4/E2_control.p4: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | action write_default_class() { 5 | meta.result = 1; 6 | } 7 | 8 | action read_lable(bit<32> label){ 9 | meta.result = label; 10 | } 11 | 12 | table decision { 13 | key = { meta.code_f0[0:0]:exact; 14 | meta.code_f1[1:0]:exact; 15 | meta.code_f2[2:0]:exact; 16 | meta.code_f3[2:0]:exact; 17 | } 18 | actions={ 19 | read_lable; 20 | write_default_class; 21 | } 22 | size = 13; 23 | default_action = write_default_class; 24 | } 25 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/Makefile: -------------------------------------------------------------------------------- 1 | BMV2_SWITCH_EXE = simple_switch_grpc 2 | 3 | 4 | include ../utils/Makefile 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/P4/s10.p4: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & YINS, Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | ######################################################################### 10 | # This file was autogenerated 11 | 12 | #include 13 | #include 14 | 15 | /************************************************************************* 16 | ***************************** constants ********************************** 17 | *************************************************************************/ 18 | 19 | const bit<16> TYPE_IPV4 = 0x800; 20 | 21 | typedef bit<9> egressSpec_t; 22 | typedef bit<48> macAddr_t; 23 | typedef bit<32> ip4Addr_t; 24 | 25 | /************************************************************************* 26 | ****************************** headers *********************************** 27 | *************************************************************************/ 28 | 29 | header ethernet_h { 30 | macAddr_t dstAddr; 31 | macAddr_t srcAddr; 32 | bit<16> etherType; 33 | } 34 | 35 | header ipv4_h{ 36 | bit < 4 > version; 37 | bit < 4 > ihl; 38 | bit < 8 > diffserv; 39 | bit < 16 > totalLen; 40 | bit < 16 > identification; 41 | bit < 3 > flags; 42 | bit < 13 > fragOffset; 43 | bit < 8 > ttl; 44 | bit < 8 > protocol; 45 | bit < 16 > hdrChecksum; 46 | ip4Addr_t srcAddr; 47 | ip4Addr_t dstAddr; 48 | } 49 | 50 | struct header_t { 51 | ethernet_h ethernet; 52 | ipv4_h ipv4; 53 | } 54 | 55 | /************************************************************************* 56 | ***************************** metadata ********************************** 57 | *************************************************************************/ 58 | 59 | struct metadata_t { 60 | } 61 | 62 | /************************************************************************* 63 | *********************** Ingress Parser *********************************** 64 | *************************************************************************/ 65 | 66 | parser SwitchParser( 67 | packet_in pkt, 68 | out header_t hdr, 69 | inout metadata_t meta, 70 | inout standard_metadata_t ig_intr_md) { 71 | 72 | state start { 73 | transition parse_ethernet; 74 | } 75 | 76 | state parse_ethernet { 77 | pkt.extract(hdr.ethernet); 78 | transition select(hdr.ethernet.etherType) { 79 | TYPE_IPV4 : parse_ipv4; 80 | default : accept; 81 | } 82 | } 83 | 84 | state parse_ipv4 { 85 | pkt.extract(hdr.ipv4); 86 | transition accept; 87 | } 88 | 89 | } 90 | 91 | /************************************************************************* 92 | *********************** Egress Deparser ********************************* 93 | **************************************************************************/ 94 | 95 | control SwitchDeparser( 96 | packet_out pkt, 97 | in header_t hdr) { 98 | apply { 99 | pkt.emit(hdr); 100 | } 101 | } 102 | 103 | /************************************************************************* 104 | ********************** Checksum Verification ***************************** 105 | *************************************************************************/ 106 | 107 | control SwitchVerifyChecksum(inout header_t hdr, 108 | inout metadata_t meta) { 109 | apply {} 110 | } 111 | /************************************************************************* 112 | ********************** Checksum Computation ****************************** 113 | *************************************************************************/ 114 | 115 | control SwitchComputeChecksum(inout header_t hdr, 116 | inout metadata_t meta) { 117 | apply { 118 | update_checksum( 119 | hdr.ipv4.isValid(), 120 | { hdr.ipv4.version, 121 | hdr.ipv4.ihl, 122 | hdr.ipv4.diffserv, 123 | hdr.ipv4.totalLen, 124 | hdr.ipv4.identification, 125 | hdr.ipv4.flags, 126 | hdr.ipv4.fragOffset, 127 | hdr.ipv4.ttl, 128 | hdr.ipv4.protocol, 129 | hdr.ipv4.srcAddr, 130 | hdr.ipv4.dstAddr }, 131 | hdr.ipv4.hdrChecksum, 132 | HashAlgorithm.csum16); 133 | } 134 | } 135 | /************************************************************************* 136 | *********************** Ingress Processing******************************** 137 | **************************************************************************/ 138 | 139 | control SwitchIngress( 140 | inout header_t hdr, 141 | inout metadata_t meta, 142 | inout standard_metadata_t ig_intr_md) { 143 | 144 | action drop() { 145 | mark_to_drop(ig_intr_md); 146 | } 147 | 148 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 149 | ig_intr_md.egress_spec = port; 150 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 151 | hdr.ethernet.dstAddr = dstAddr; 152 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 153 | } 154 | 155 | table ipv4_lpm { 156 | key = { 157 | hdr.ipv4.dstAddr: lpm; 158 | } 159 | actions = { 160 | ipv4_forward; 161 | drop; 162 | NoAction; 163 | } 164 | size = 1024; 165 | default_action = drop(); 166 | } 167 | 168 | apply{ 169 | if (hdr.ipv4.isValid() && hdr.ipv4.ttl > 0) { 170 | ipv4_lpm.apply(); 171 | } 172 | 173 | } 174 | } 175 | /************************************************************************* 176 | *********************** egress Processing******************************** 177 | **************************************************************************/ 178 | 179 | control SwitchEgress(inout header_t hdr, 180 | inout metadata_t meta, 181 | inout standard_metadata_t eg_intr_md) { 182 | apply { 183 | } 184 | } 185 | /************************************************************************* 186 | *********************** S W I T C H ************************************ 187 | *************************************************************************/ 188 | 189 | V1Switch( 190 | SwitchParser(), 191 | SwitchVerifyChecksum(), 192 | SwitchIngress(), 193 | SwitchEgress(), 194 | SwitchComputeChecksum(), 195 | SwitchDeparser() 196 | ) main; -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/P4/s11.p4: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & YINS, Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | ######################################################################### 10 | # This file was autogenerated 11 | 12 | #include 13 | #include 14 | 15 | /************************************************************************* 16 | ***************************** constants ********************************** 17 | *************************************************************************/ 18 | 19 | const bit<16> TYPE_IPV4 = 0x800; 20 | 21 | typedef bit<9> egressSpec_t; 22 | typedef bit<48> macAddr_t; 23 | typedef bit<32> ip4Addr_t; 24 | 25 | /************************************************************************* 26 | ****************************** headers *********************************** 27 | *************************************************************************/ 28 | 29 | header ethernet_h { 30 | macAddr_t dstAddr; 31 | macAddr_t srcAddr; 32 | bit<16> etherType; 33 | } 34 | 35 | header ipv4_h{ 36 | bit < 4 > version; 37 | bit < 4 > ihl; 38 | bit < 8 > diffserv; 39 | bit < 16 > totalLen; 40 | bit < 16 > identification; 41 | bit < 3 > flags; 42 | bit < 13 > fragOffset; 43 | bit < 8 > ttl; 44 | bit < 8 > protocol; 45 | bit < 16 > hdrChecksum; 46 | ip4Addr_t srcAddr; 47 | ip4Addr_t dstAddr; 48 | } 49 | 50 | struct header_t { 51 | ethernet_h ethernet; 52 | ipv4_h ipv4; 53 | } 54 | 55 | /************************************************************************* 56 | ***************************** metadata ********************************** 57 | *************************************************************************/ 58 | 59 | struct metadata_t { 60 | } 61 | 62 | /************************************************************************* 63 | *********************** Ingress Parser *********************************** 64 | *************************************************************************/ 65 | 66 | parser SwitchParser( 67 | packet_in pkt, 68 | out header_t hdr, 69 | inout metadata_t meta, 70 | inout standard_metadata_t ig_intr_md) { 71 | 72 | state start { 73 | transition parse_ethernet; 74 | } 75 | 76 | state parse_ethernet { 77 | pkt.extract(hdr.ethernet); 78 | transition select(hdr.ethernet.etherType) { 79 | TYPE_IPV4 : parse_ipv4; 80 | default : accept; 81 | } 82 | } 83 | 84 | state parse_ipv4 { 85 | pkt.extract(hdr.ipv4); 86 | transition accept; 87 | } 88 | 89 | } 90 | 91 | /************************************************************************* 92 | *********************** Egress Deparser ********************************* 93 | **************************************************************************/ 94 | 95 | control SwitchDeparser( 96 | packet_out pkt, 97 | in header_t hdr) { 98 | apply { 99 | pkt.emit(hdr); 100 | } 101 | } 102 | 103 | /************************************************************************* 104 | ********************** Checksum Verification ***************************** 105 | *************************************************************************/ 106 | 107 | control SwitchVerifyChecksum(inout header_t hdr, 108 | inout metadata_t meta) { 109 | apply {} 110 | } 111 | /************************************************************************* 112 | ********************** Checksum Computation ****************************** 113 | *************************************************************************/ 114 | 115 | control SwitchComputeChecksum(inout header_t hdr, 116 | inout metadata_t meta) { 117 | apply { 118 | update_checksum( 119 | hdr.ipv4.isValid(), 120 | { hdr.ipv4.version, 121 | hdr.ipv4.ihl, 122 | hdr.ipv4.diffserv, 123 | hdr.ipv4.totalLen, 124 | hdr.ipv4.identification, 125 | hdr.ipv4.flags, 126 | hdr.ipv4.fragOffset, 127 | hdr.ipv4.ttl, 128 | hdr.ipv4.protocol, 129 | hdr.ipv4.srcAddr, 130 | hdr.ipv4.dstAddr }, 131 | hdr.ipv4.hdrChecksum, 132 | HashAlgorithm.csum16); 133 | } 134 | } 135 | /************************************************************************* 136 | *********************** Ingress Processing******************************** 137 | **************************************************************************/ 138 | 139 | control SwitchIngress( 140 | inout header_t hdr, 141 | inout metadata_t meta, 142 | inout standard_metadata_t ig_intr_md) { 143 | 144 | action drop() { 145 | mark_to_drop(ig_intr_md); 146 | } 147 | 148 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 149 | ig_intr_md.egress_spec = port; 150 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 151 | hdr.ethernet.dstAddr = dstAddr; 152 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 153 | } 154 | 155 | table ipv4_lpm { 156 | key = { 157 | hdr.ipv4.dstAddr: lpm; 158 | } 159 | actions = { 160 | ipv4_forward; 161 | drop; 162 | NoAction; 163 | } 164 | size = 1024; 165 | default_action = drop(); 166 | } 167 | 168 | apply{ 169 | if (hdr.ipv4.isValid() && hdr.ipv4.ttl > 0) { 170 | ipv4_lpm.apply(); 171 | } 172 | 173 | } 174 | } 175 | /************************************************************************* 176 | *********************** egress Processing******************************** 177 | **************************************************************************/ 178 | 179 | control SwitchEgress(inout header_t hdr, 180 | inout metadata_t meta, 181 | inout standard_metadata_t eg_intr_md) { 182 | apply { 183 | } 184 | } 185 | /************************************************************************* 186 | *********************** S W I T C H ************************************ 187 | *************************************************************************/ 188 | 189 | V1Switch( 190 | SwitchParser(), 191 | SwitchVerifyChecksum(), 192 | SwitchIngress(), 193 | SwitchEgress(), 194 | SwitchComputeChecksum(), 195 | SwitchDeparser() 196 | ) main; -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/P4/s12.p4: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & YINS, Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | ######################################################################### 10 | # This file was autogenerated 11 | 12 | #include 13 | #include 14 | 15 | /************************************************************************* 16 | ***************************** constants ********************************** 17 | *************************************************************************/ 18 | 19 | const bit<16> TYPE_IPV4 = 0x800; 20 | 21 | typedef bit<9> egressSpec_t; 22 | typedef bit<48> macAddr_t; 23 | typedef bit<32> ip4Addr_t; 24 | 25 | /************************************************************************* 26 | ****************************** headers *********************************** 27 | *************************************************************************/ 28 | 29 | header ethernet_h { 30 | macAddr_t dstAddr; 31 | macAddr_t srcAddr; 32 | bit<16> etherType; 33 | } 34 | 35 | header ipv4_h{ 36 | bit < 4 > version; 37 | bit < 4 > ihl; 38 | bit < 8 > diffserv; 39 | bit < 16 > totalLen; 40 | bit < 16 > identification; 41 | bit < 3 > flags; 42 | bit < 13 > fragOffset; 43 | bit < 8 > ttl; 44 | bit < 8 > protocol; 45 | bit < 16 > hdrChecksum; 46 | ip4Addr_t srcAddr; 47 | ip4Addr_t dstAddr; 48 | } 49 | 50 | struct header_t { 51 | ethernet_h ethernet; 52 | ipv4_h ipv4; 53 | } 54 | 55 | /************************************************************************* 56 | ***************************** metadata ********************************** 57 | *************************************************************************/ 58 | 59 | struct metadata_t { 60 | } 61 | 62 | /************************************************************************* 63 | *********************** Ingress Parser *********************************** 64 | *************************************************************************/ 65 | 66 | parser SwitchParser( 67 | packet_in pkt, 68 | out header_t hdr, 69 | inout metadata_t meta, 70 | inout standard_metadata_t ig_intr_md) { 71 | 72 | state start { 73 | transition parse_ethernet; 74 | } 75 | 76 | state parse_ethernet { 77 | pkt.extract(hdr.ethernet); 78 | transition select(hdr.ethernet.etherType) { 79 | TYPE_IPV4 : parse_ipv4; 80 | default : accept; 81 | } 82 | } 83 | 84 | state parse_ipv4 { 85 | pkt.extract(hdr.ipv4); 86 | transition accept; 87 | } 88 | 89 | } 90 | 91 | /************************************************************************* 92 | *********************** Egress Deparser ********************************* 93 | **************************************************************************/ 94 | 95 | control SwitchDeparser( 96 | packet_out pkt, 97 | in header_t hdr) { 98 | apply { 99 | pkt.emit(hdr); 100 | } 101 | } 102 | 103 | /************************************************************************* 104 | ********************** Checksum Verification ***************************** 105 | *************************************************************************/ 106 | 107 | control SwitchVerifyChecksum(inout header_t hdr, 108 | inout metadata_t meta) { 109 | apply {} 110 | } 111 | /************************************************************************* 112 | ********************** Checksum Computation ****************************** 113 | *************************************************************************/ 114 | 115 | control SwitchComputeChecksum(inout header_t hdr, 116 | inout metadata_t meta) { 117 | apply { 118 | update_checksum( 119 | hdr.ipv4.isValid(), 120 | { hdr.ipv4.version, 121 | hdr.ipv4.ihl, 122 | hdr.ipv4.diffserv, 123 | hdr.ipv4.totalLen, 124 | hdr.ipv4.identification, 125 | hdr.ipv4.flags, 126 | hdr.ipv4.fragOffset, 127 | hdr.ipv4.ttl, 128 | hdr.ipv4.protocol, 129 | hdr.ipv4.srcAddr, 130 | hdr.ipv4.dstAddr }, 131 | hdr.ipv4.hdrChecksum, 132 | HashAlgorithm.csum16); 133 | } 134 | } 135 | /************************************************************************* 136 | *********************** Ingress Processing******************************** 137 | **************************************************************************/ 138 | 139 | control SwitchIngress( 140 | inout header_t hdr, 141 | inout metadata_t meta, 142 | inout standard_metadata_t ig_intr_md) { 143 | 144 | action drop() { 145 | mark_to_drop(ig_intr_md); 146 | } 147 | 148 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 149 | ig_intr_md.egress_spec = port; 150 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 151 | hdr.ethernet.dstAddr = dstAddr; 152 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 153 | } 154 | 155 | table ipv4_lpm { 156 | key = { 157 | hdr.ipv4.dstAddr: lpm; 158 | } 159 | actions = { 160 | ipv4_forward; 161 | drop; 162 | NoAction; 163 | } 164 | size = 1024; 165 | default_action = drop(); 166 | } 167 | 168 | apply{ 169 | if (hdr.ipv4.isValid() && hdr.ipv4.ttl > 0) { 170 | ipv4_lpm.apply(); 171 | } 172 | 173 | } 174 | } 175 | /************************************************************************* 176 | *********************** egress Processing******************************** 177 | **************************************************************************/ 178 | 179 | control SwitchEgress(inout header_t hdr, 180 | inout metadata_t meta, 181 | inout standard_metadata_t eg_intr_md) { 182 | apply { 183 | } 184 | } 185 | /************************************************************************* 186 | *********************** S W I T C H ************************************ 187 | *************************************************************************/ 188 | 189 | V1Switch( 190 | SwitchParser(), 191 | SwitchVerifyChecksum(), 192 | SwitchIngress(), 193 | SwitchEgress(), 194 | SwitchComputeChecksum(), 195 | SwitchDeparser() 196 | ) main; -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/P4/s13.p4: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & YINS, Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | ######################################################################### 10 | # This file was autogenerated 11 | 12 | #include 13 | #include 14 | 15 | /************************************************************************* 16 | ***************************** constants ********************************** 17 | *************************************************************************/ 18 | 19 | const bit<16> TYPE_IPV4 = 0x800; 20 | 21 | typedef bit<9> egressSpec_t; 22 | typedef bit<48> macAddr_t; 23 | typedef bit<32> ip4Addr_t; 24 | 25 | /************************************************************************* 26 | ****************************** headers *********************************** 27 | *************************************************************************/ 28 | 29 | header ethernet_h { 30 | macAddr_t dstAddr; 31 | macAddr_t srcAddr; 32 | bit<16> etherType; 33 | } 34 | 35 | header ipv4_h{ 36 | bit < 4 > version; 37 | bit < 4 > ihl; 38 | bit < 8 > diffserv; 39 | bit < 16 > totalLen; 40 | bit < 16 > identification; 41 | bit < 3 > flags; 42 | bit < 13 > fragOffset; 43 | bit < 8 > ttl; 44 | bit < 8 > protocol; 45 | bit < 16 > hdrChecksum; 46 | ip4Addr_t srcAddr; 47 | ip4Addr_t dstAddr; 48 | } 49 | 50 | struct header_t { 51 | ethernet_h ethernet; 52 | ipv4_h ipv4; 53 | } 54 | 55 | /************************************************************************* 56 | ***************************** metadata ********************************** 57 | *************************************************************************/ 58 | 59 | struct metadata_t { 60 | } 61 | 62 | /************************************************************************* 63 | *********************** Ingress Parser *********************************** 64 | *************************************************************************/ 65 | 66 | parser SwitchParser( 67 | packet_in pkt, 68 | out header_t hdr, 69 | inout metadata_t meta, 70 | inout standard_metadata_t ig_intr_md) { 71 | 72 | state start { 73 | transition parse_ethernet; 74 | } 75 | 76 | state parse_ethernet { 77 | pkt.extract(hdr.ethernet); 78 | transition select(hdr.ethernet.etherType) { 79 | TYPE_IPV4 : parse_ipv4; 80 | default : accept; 81 | } 82 | } 83 | 84 | state parse_ipv4 { 85 | pkt.extract(hdr.ipv4); 86 | transition accept; 87 | } 88 | 89 | } 90 | 91 | /************************************************************************* 92 | *********************** Egress Deparser ********************************* 93 | **************************************************************************/ 94 | 95 | control SwitchDeparser( 96 | packet_out pkt, 97 | in header_t hdr) { 98 | apply { 99 | pkt.emit(hdr); 100 | } 101 | } 102 | 103 | /************************************************************************* 104 | ********************** Checksum Verification ***************************** 105 | *************************************************************************/ 106 | 107 | control SwitchVerifyChecksum(inout header_t hdr, 108 | inout metadata_t meta) { 109 | apply {} 110 | } 111 | /************************************************************************* 112 | ********************** Checksum Computation ****************************** 113 | *************************************************************************/ 114 | 115 | control SwitchComputeChecksum(inout header_t hdr, 116 | inout metadata_t meta) { 117 | apply { 118 | update_checksum( 119 | hdr.ipv4.isValid(), 120 | { hdr.ipv4.version, 121 | hdr.ipv4.ihl, 122 | hdr.ipv4.diffserv, 123 | hdr.ipv4.totalLen, 124 | hdr.ipv4.identification, 125 | hdr.ipv4.flags, 126 | hdr.ipv4.fragOffset, 127 | hdr.ipv4.ttl, 128 | hdr.ipv4.protocol, 129 | hdr.ipv4.srcAddr, 130 | hdr.ipv4.dstAddr }, 131 | hdr.ipv4.hdrChecksum, 132 | HashAlgorithm.csum16); 133 | } 134 | } 135 | /************************************************************************* 136 | *********************** Ingress Processing******************************** 137 | **************************************************************************/ 138 | 139 | control SwitchIngress( 140 | inout header_t hdr, 141 | inout metadata_t meta, 142 | inout standard_metadata_t ig_intr_md) { 143 | 144 | action drop() { 145 | mark_to_drop(ig_intr_md); 146 | } 147 | 148 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 149 | ig_intr_md.egress_spec = port; 150 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 151 | hdr.ethernet.dstAddr = dstAddr; 152 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 153 | } 154 | 155 | table ipv4_lpm { 156 | key = { 157 | hdr.ipv4.dstAddr: lpm; 158 | } 159 | actions = { 160 | ipv4_forward; 161 | drop; 162 | NoAction; 163 | } 164 | size = 1024; 165 | default_action = drop(); 166 | } 167 | 168 | apply{ 169 | if (hdr.ipv4.isValid() && hdr.ipv4.ttl > 0) { 170 | ipv4_lpm.apply(); 171 | } 172 | 173 | } 174 | } 175 | /************************************************************************* 176 | *********************** egress Processing******************************** 177 | **************************************************************************/ 178 | 179 | control SwitchEgress(inout header_t hdr, 180 | inout metadata_t meta, 181 | inout standard_metadata_t eg_intr_md) { 182 | apply { 183 | } 184 | } 185 | /************************************************************************* 186 | *********************** S W I T C H ************************************ 187 | *************************************************************************/ 188 | 189 | V1Switch( 190 | SwitchParser(), 191 | SwitchVerifyChecksum(), 192 | SwitchIngress(), 193 | SwitchEgress(), 194 | SwitchComputeChecksum(), 195 | SwitchDeparser() 196 | ) main; -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/P4/s14.p4: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # This program is a free software tool, which does ensemble in-network machine learning. 3 | # licensed under Apache-2.0 4 | # 5 | # Copyright (c) 2020-2021 Changgang Zheng 6 | # Copyright (c) Computing Infrastructure Group, Department of Engineering Science, University of Oxford & YINS, Yale University 7 | # E-mail: changgang.zheng@eng.ox.ac.uk (valid until July 2024), 8 | # changgang.zheng@yale.edu (valid until October 2022) or changgangzheng@qq.com (no expiration date) 9 | ######################################################################### 10 | # This file was autogenerated 11 | 12 | #include 13 | #include 14 | 15 | /************************************************************************* 16 | ***************************** constants ********************************** 17 | *************************************************************************/ 18 | 19 | const bit<16> TYPE_IPV4 = 0x800; 20 | 21 | typedef bit<9> egressSpec_t; 22 | typedef bit<48> macAddr_t; 23 | typedef bit<32> ip4Addr_t; 24 | 25 | /************************************************************************* 26 | ****************************** headers *********************************** 27 | *************************************************************************/ 28 | 29 | header ethernet_h { 30 | macAddr_t dstAddr; 31 | macAddr_t srcAddr; 32 | bit<16> etherType; 33 | } 34 | 35 | header ipv4_h{ 36 | bit < 4 > version; 37 | bit < 4 > ihl; 38 | bit < 8 > diffserv; 39 | bit < 16 > totalLen; 40 | bit < 16 > identification; 41 | bit < 3 > flags; 42 | bit < 13 > fragOffset; 43 | bit < 8 > ttl; 44 | bit < 8 > protocol; 45 | bit < 16 > hdrChecksum; 46 | ip4Addr_t srcAddr; 47 | ip4Addr_t dstAddr; 48 | } 49 | 50 | struct header_t { 51 | ethernet_h ethernet; 52 | ipv4_h ipv4; 53 | } 54 | 55 | /************************************************************************* 56 | ***************************** metadata ********************************** 57 | *************************************************************************/ 58 | 59 | struct metadata_t { 60 | } 61 | 62 | /************************************************************************* 63 | *********************** Ingress Parser *********************************** 64 | *************************************************************************/ 65 | 66 | parser SwitchParser( 67 | packet_in pkt, 68 | out header_t hdr, 69 | inout metadata_t meta, 70 | inout standard_metadata_t ig_intr_md) { 71 | 72 | state start { 73 | transition parse_ethernet; 74 | } 75 | 76 | state parse_ethernet { 77 | pkt.extract(hdr.ethernet); 78 | transition select(hdr.ethernet.etherType) { 79 | TYPE_IPV4 : parse_ipv4; 80 | default : accept; 81 | } 82 | } 83 | 84 | state parse_ipv4 { 85 | pkt.extract(hdr.ipv4); 86 | transition accept; 87 | } 88 | 89 | } 90 | 91 | /************************************************************************* 92 | *********************** Egress Deparser ********************************* 93 | **************************************************************************/ 94 | 95 | control SwitchDeparser( 96 | packet_out pkt, 97 | in header_t hdr) { 98 | apply { 99 | pkt.emit(hdr); 100 | } 101 | } 102 | 103 | /************************************************************************* 104 | ********************** Checksum Verification ***************************** 105 | *************************************************************************/ 106 | 107 | control SwitchVerifyChecksum(inout header_t hdr, 108 | inout metadata_t meta) { 109 | apply {} 110 | } 111 | /************************************************************************* 112 | ********************** Checksum Computation ****************************** 113 | *************************************************************************/ 114 | 115 | control SwitchComputeChecksum(inout header_t hdr, 116 | inout metadata_t meta) { 117 | apply { 118 | update_checksum( 119 | hdr.ipv4.isValid(), 120 | { hdr.ipv4.version, 121 | hdr.ipv4.ihl, 122 | hdr.ipv4.diffserv, 123 | hdr.ipv4.totalLen, 124 | hdr.ipv4.identification, 125 | hdr.ipv4.flags, 126 | hdr.ipv4.fragOffset, 127 | hdr.ipv4.ttl, 128 | hdr.ipv4.protocol, 129 | hdr.ipv4.srcAddr, 130 | hdr.ipv4.dstAddr }, 131 | hdr.ipv4.hdrChecksum, 132 | HashAlgorithm.csum16); 133 | } 134 | } 135 | /************************************************************************* 136 | *********************** Ingress Processing******************************** 137 | **************************************************************************/ 138 | 139 | control SwitchIngress( 140 | inout header_t hdr, 141 | inout metadata_t meta, 142 | inout standard_metadata_t ig_intr_md) { 143 | 144 | action drop() { 145 | mark_to_drop(ig_intr_md); 146 | } 147 | 148 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 149 | ig_intr_md.egress_spec = port; 150 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 151 | hdr.ethernet.dstAddr = dstAddr; 152 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 153 | } 154 | 155 | table ipv4_lpm { 156 | key = { 157 | hdr.ipv4.dstAddr: lpm; 158 | } 159 | actions = { 160 | ipv4_forward; 161 | drop; 162 | NoAction; 163 | } 164 | size = 1024; 165 | default_action = drop(); 166 | } 167 | 168 | apply{ 169 | if (hdr.ipv4.isValid() && hdr.ipv4.ttl > 0) { 170 | ipv4_lpm.apply(); 171 | } 172 | 173 | } 174 | } 175 | /************************************************************************* 176 | *********************** egress Processing******************************** 177 | **************************************************************************/ 178 | 179 | control SwitchEgress(inout header_t hdr, 180 | inout metadata_t meta, 181 | inout standard_metadata_t eg_intr_md) { 182 | apply { 183 | } 184 | } 185 | /************************************************************************* 186 | *********************** S W I T C H ************************************ 187 | *************************************************************************/ 188 | 189 | V1Switch( 190 | SwitchParser(), 191 | SwitchVerifyChecksum(), 192 | SwitchIngress(), 193 | SwitchEgress(), 194 | SwitchComputeChecksum(), 195 | SwitchDeparser() 196 | ) main; -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s0.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => 10:00:00:00:00:00 88 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.2/32 => c8:00:00:00:01:01 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.3/32 => c8:00:00:00:01:01 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:01:04 2 5 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.6/32 => c8:00:00:00:01:04 2 6 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s1.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:01:00 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.2/32 => c8:00:00:00:01:02 2 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.3/32 => c8:00:00:00:01:03 3 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:01:00 1 5 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.6/32 => c8:00:00:00:01:00 1 6 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s10.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:02:09 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:02:09 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:02:09 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => c8:00:00:00:02:09 1 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s11.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:03:09 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:03:09 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:03:09 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => c8:00:00:00:03:09 1 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s12.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:03:08 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:03:08 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:03:08 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => c8:00:00:00:03:08 1 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s13.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:02:0c 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:02:0c 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:02:0c 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => c8:00:00:00:02:0c 1 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s14.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:03:0c 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:03:0c 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:03:0c 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => c8:00:00:00:03:0c 1 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s2.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:02:01 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.2/32 => 10:00:00:00:00:02 88 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.3/32 => c8:00:00:00:02:01 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:02:01 1 5 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.6/32 => c8:00:00:00:02:01 1 6 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s3.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:03:01 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.2/32 => c8:00:00:00:03:01 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.3/32 => 10:00:00:00:00:03 88 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:03:01 1 5 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.6/32 => c8:00:00:00:03:01 1 6 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s4.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:02:00 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.2/32 => c8:00:00:00:02:00 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.3/32 => c8:00:00:00:02:00 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:01:05 2 5 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.6/32 => c8:00:00:00:01:06 3 6 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s5.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:02:04 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.2/32 => c8:00:00:00:02:04 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.3/32 => c8:00:00:00:02:04 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => 10:00:00:00:00:05 88 5 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.6/32 => c8:00:00:00:02:04 1 6 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s6.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:03:04 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.2/32 => c8:00:00:00:03:04 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.3/32 => c8:00:00:00:03:04 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:03:04 1 5 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.6/32 => 10:00:00:00:00:06 88 6 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s7.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:03:05 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:03:05 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:03:05 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => 10:00:00:00:00:07 88 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s8.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:02:00 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:02:00 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:02:00 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => c8:00:00:00:02:00 1 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/commands/s9.txt: -------------------------------------------------------------------------------- 1 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.254/32 => c8:00:00:00:02:08 1 2 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.4/32 => c8:00:00:00:02:08 1 3 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.5/32 => c8:00:00:00:02:08 1 4 | table_add SwitchIngress.ipv4_lpm SwitchIngress.ipv4_forward 10.0.0.7/32 => c8:00:00:00:02:08 1 5 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/insert_rules.sh: -------------------------------------------------------------------------------- 1 | simple_switch_CLI --thrift-port 9090 < ./commands/s0.txt 2 | simple_switch_CLI --thrift-port 9091 < ./commands/s1.txt 3 | simple_switch_CLI --thrift-port 9092 < ./commands/s2.txt 4 | simple_switch_CLI --thrift-port 9093 < ./commands/s3.txt 5 | simple_switch_CLI --thrift-port 9094 < ./commands/s4.txt 6 | simple_switch_CLI --thrift-port 9095 < ./commands/s5.txt 7 | simple_switch_CLI --thrift-port 9096 < ./commands/s6.txt 8 | -------------------------------------------------------------------------------- /src/test/BMv2/test_environment/run_demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | BMV2_PATH=/home/jesu3779/mysde/behavioral-model-1.15.0 3 | SWITCH_PATH=$BMV2_PATH/targets/simple_switch/simple_switch 4 | echo 'passcode' | sudo -S $SWITCH_PATH >/dev/null 2>&1 5 | sudo make clean 6 | sudo PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python3 main.py --behavioral-exe $SWITCH_PATH 7 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR = build 2 | PCAP_DIR = pcaps 3 | LOG_DIR = logs 4 | 5 | P4C = p4c-bm2-ss 6 | P4C_ARGS += --p4runtime-files $(BUILD_DIR)/$(basename $@).p4.p4info.txt 7 | 8 | RUN_SCRIPT = ../../utils/run_exercise.py 9 | 10 | ifndef TOPO 11 | TOPO = topology.json 12 | endif 13 | 14 | source = $(wildcard *.p4) 15 | compiled_json := $(source:.p4=.json) 16 | 17 | ifndef DEFAULT_PROG 18 | DEFAULT_PROG = $(wildcard *.p4) 19 | endif 20 | DEFAULT_JSON = $(BUILD_DIR)/$(DEFAULT_PROG:.p4=.json) 21 | 22 | # Define NO_P4 to start BMv2 without a program 23 | ifndef NO_P4 24 | run_args += -j $(DEFAULT_JSON) 25 | endif 26 | 27 | # Set BMV2_SWITCH_EXE to override the BMv2 target 28 | ifdef BMV2_SWITCH_EXE 29 | run_args += -b $(BMV2_SWITCH_EXE) 30 | endif 31 | 32 | all: run 33 | 34 | run: build 35 | sudo python3 $(RUN_SCRIPT) -t $(TOPO) $(run_args) 36 | 37 | stop: 38 | sudo mn -c 39 | 40 | build: dirs $(compiled_json) 41 | 42 | %.json: %.p4 43 | $(P4C) --p4v 16 $(P4C_ARGS) -o $(BUILD_DIR)/$@ $< 44 | 45 | dirs: 46 | mkdir -p $(BUILD_DIR) $(PCAP_DIR) $(LOG_DIR) 47 | 48 | clean: stop 49 | rm -f *.pcap 50 | rm -rf $(BUILD_DIR) $(PCAP_DIR) $(LOG_DIR) 51 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/architecture/psa/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR = build 2 | PCAP_DIR = pcaps 3 | LOG_DIR = logs 4 | 5 | P4C = p4c-bm2-psa 6 | P4C_ARGS += --p4runtime-files $(BUILD_DIR)/$(basename $@).p4.p4info.txt 7 | 8 | RUN_SCRIPT = ../../utils/run_exercise.py 9 | 10 | ifndef TOPO 11 | TOPO = topology.json 12 | endif 13 | 14 | source = $(wildcard *.p4) 15 | compiled_json := $(source:.p4=.json) 16 | 17 | ifndef DEFAULT_PROG 18 | DEFAULT_PROG = $(wildcard *.p4) 19 | endif 20 | DEFAULT_JSON = $(BUILD_DIR)/$(DEFAULT_PROG:.p4=.json) 21 | 22 | # Define NO_P4 to start BMv2 without a program 23 | ifndef NO_P4 24 | run_args += -j $(DEFAULT_JSON) 25 | endif 26 | 27 | # Set BMV2_SWITCH_EXE to override the BMv2 target 28 | ifdef BMV2_SWITCH_EXE 29 | run_args += -b $(BMV2_SWITCH_EXE) 30 | endif 31 | 32 | all: run 33 | 34 | run: build 35 | sudo python3 $(RUN_SCRIPT) -t $(TOPO) $(run_args) 36 | 37 | stop: 38 | sudo mn -c 39 | 40 | build: dirs $(compiled_json) 41 | 42 | %.json: %.p4 43 | $(P4C) --p4v 16 $(P4C_ARGS) -o $(BUILD_DIR)/$@ $< 44 | 45 | dirs: 46 | mkdir -p $(BUILD_DIR) $(PCAP_DIR) $(LOG_DIR) 47 | 48 | clean: stop 49 | rm -f *.pcap 50 | rm -rf $(BUILD_DIR) $(PCAP_DIR) $(LOG_DIR) 51 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/architecture/v1model/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_DIR = build 2 | PCAP_DIR = pcaps 3 | LOG_DIR = logs 4 | 5 | P4C = p4c-bm2-ss 6 | P4C_ARGS += --p4runtime-files $(BUILD_DIR)/$(basename $@).p4.p4info.txt 7 | 8 | RUN_SCRIPT = ../../utils/run_exercise.py 9 | 10 | ifndef TOPO 11 | TOPO = topology.json 12 | endif 13 | 14 | source = $(wildcard *.p4) 15 | compiled_json := $(source:.p4=.json) 16 | 17 | ifndef DEFAULT_PROG 18 | DEFAULT_PROG = $(wildcard *.p4) 19 | endif 20 | DEFAULT_JSON = $(BUILD_DIR)/$(DEFAULT_PROG:.p4=.json) 21 | 22 | # Define NO_P4 to start BMv2 without a program 23 | ifndef NO_P4 24 | run_args += -j $(DEFAULT_JSON) 25 | endif 26 | 27 | # Set BMV2_SWITCH_EXE to override the BMv2 target 28 | ifdef BMV2_SWITCH_EXE 29 | run_args += -b $(BMV2_SWITCH_EXE) 30 | endif 31 | 32 | all: run 33 | 34 | run: build 35 | sudo python3 $(RUN_SCRIPT) -t $(TOPO) $(run_args) 36 | 37 | stop: 38 | sudo mn -c 39 | 40 | build: dirs $(compiled_json) 41 | 42 | %.json: %.p4 43 | $(P4C) --p4v 16 $(P4C_ARGS) -o $(BUILD_DIR)/$@ $< 44 | 45 | dirs: 46 | mkdir -p $(BUILD_DIR) $(PCAP_DIR) $(LOG_DIR) 47 | 48 | clean: stop 49 | rm -f *.pcap 50 | rm -rf $(BUILD_DIR) $(PCAP_DIR) $(LOG_DIR) 51 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/actions.txt: -------------------------------------------------------------------------------- 1 | // Inputs provided by control-plane 2 | action set_next_hop(bit<32> next_hop) { 3 | if (next_hop == 0) { 4 | metadata.next_hop = hdr.ipv4.dst; 5 | } else { 6 | metadata.next_hop = next_hop; 7 | } 8 | } 9 | 10 | // Inputs provided by data-plane 11 | action swap_mac(inout bit<48> x, 12 | inout bit<48> y) { 13 | bit<48> tmp = x; 14 | x = y; 15 | y = tmp; 16 | } 17 | 18 | // Inputs provided by control/data-plane 19 | action forward(in bit<9> p, bit<48> d) { 20 | standard_metadata.egress_spec = p; 21 | headers.ethernet.dstAddr = d; 22 | } 23 | 24 | // Remove header from packet 25 | action decap_ip_ip() { 26 | hdr.ipv4 = hdr.inner_ipv4; 27 | hdr.inner_ipv4.setInvalid(); 28 | } 29 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/adv_parsing.txt: -------------------------------------------------------------------------------- 1 | // common defns for IPv4 and IPv6 2 | header ip46_t { 3 | bit<4> version; 4 | bit<4> reserved; 5 | } 6 | 7 | // header stack parsing 8 | state parse_labels { 9 | packet.extract(hdr.labels.next); 10 | transition select(hdr.labels.last.bos) { 11 | 0: parse_labels; // create loop 12 | 1: guess_labels_payload; 13 | } 14 | } 15 | 16 | // lookahead parsing 17 | state guess_labels_payload { 18 | transition select(packet.lookahead().version) { 19 | 4 : parse_inner_ipv4; 20 | 6 : parse_inner_ipv6; 21 | default : parse_inner_ethernet; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/architecture.txt: -------------------------------------------------------------------------------- 1 | // common externs 2 | extern void truncate(in bit<32> length); 3 | extern void resubmit(in T x); 4 | extern void recirculate(in T x); 5 | enum CloneType { I2E, E2I } 6 | extern void clone(in CloneType type, 7 | in bit<32> session); 8 | 9 | // v1model pipeline elements 10 | parser Parser( 11 | packet_in pkt, 12 | out H hdr, 13 | inout M meta, 14 | inout standard_metadata_t std_meta 15 | ); 16 | control VerifyChecksum( 17 | inout H hdr, 18 | inout M meta 19 | ); 20 | control Ingress( 21 | inout H hdr, 22 | inout M meta, 23 | inout standard_metadata_t std_meta 24 | ); 25 | control Egress( 26 | inout H hdr, 27 | inout M meta, 28 | inout standard_metadata_t std_meta 29 | ); 30 | control ComputeChecksum( 31 | inout H hdr, 32 | inout M meta 33 | ); 34 | control Deparser( 35 | packet_out b, in H hdr 36 | ); 37 | 38 | // v1model switch 39 | package V1Switch( 40 | Parser p, 41 | VerifyChecksum vr, 42 | Ingress ig, 43 | Egress eg, 44 | ComputeChecksum ck, 45 | Deparser d 46 | ); 47 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/control_flow.txt: -------------------------------------------------------------------------------- 1 | apply { 2 | // branch on header validity 3 | if (hdr.ipv4.isValid()) { 4 | ipv4_lpm.apply(); 5 | } 6 | // branch on table hit result 7 | if (local_ip_table.apply().hit) { 8 | send_to_cpu(); 9 | } 10 | // branch on table action invocation 11 | switch (table1.apply().action_run) { 12 | action1: { table2.apply(); } 13 | action2: { table3.apply(); } 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/counters.txt: -------------------------------------------------------------------------------- 1 | // counters 2 | counter(8192, CounterType.packets) c; 3 | 4 | action count(bit<32> index) { 5 | //increment counter at index 6 | c.count(index); 7 | } 8 | 9 | // registers 10 | register>(16384) r; 11 | 12 | action ipg(out bit<48> ival, bit<32> x) { 13 | bit<48> last; 14 | bit<48> now; 15 | r.read(last, x); 16 | now = std_meta.ingress_global_timestamp; 17 | ival = now - last; 18 | r.write(x, now); 19 | } 20 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/data_types.txt: -------------------------------------------------------------------------------- 1 | // typedef: introduces alternate type name 2 | typedef bit<48> macAddr_t; 3 | typedef bit<32> ip4Addr_t; 4 | 5 | // headers: ordered collection of members 6 | // operations test and set validity bits: 7 | // isValid(), setValid(), setInvalid() 8 | header ethernet_t { 9 | macAddr_t dstAddr; 10 | macAddr_t srcAddr; 11 | bit<16> type; 12 | } 13 | 14 | // variable declaration and member access 15 | ethernet_t ethernet; 16 | macAddr_t src = ethernet.srcAddr; 17 | 18 | // struct: unordered collection of members 19 | struct headers_t { 20 | ethernet_t ethernet; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/deparsing.txt: -------------------------------------------------------------------------------- 1 | // packet_out: extern for output packet 2 | extern packet_out { 3 | void emit(in T hdr); 4 | } 5 | 6 | apply { 7 | // insert headers into pkt if valid 8 | packet.emit(hdr.ethernet); 9 | } -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/expressions.txt: -------------------------------------------------------------------------------- 1 | // Local metadata declaration, assignment 2 | bit<16> tmp1; bit<16> tmp2; 3 | tmp1 = hdr.ethernet.type; 4 | 5 | // bit slicing, concatenation 6 | tmp2 = tmp1[7:0] ++ tmp1[15:8]; 7 | 8 | // addition, subtraction, casts 9 | tmp2 = tmp1 + tmp1 - (bit<16>)tmp1[7:0]; 10 | 11 | // bitwise operators 12 | tmp2 = (~tmp1 & tmp1) | (tmp1 ^ tmp1); 13 | tmp2 = tmp1 << 3; -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/header_stack.txt: -------------------------------------------------------------------------------- 1 | // header stack declaration 2 | header label_t { 3 | bit<20> label; 4 | bit bos; 5 | } 6 | struct header_t { 7 | label_t[10] labels; 8 | } 9 | header_t hdr; 10 | 11 | // remove from header stack 12 | action pop_label() { 13 | hdr.labels.pop_front(1); 14 | } 15 | 16 | // add to header stack 17 | action push_label(in bit<20> label) { 18 | hdr.labels.push_front(1); 19 | hdr.labels[0].setValid(); 20 | hdr.labels[0] = { label, 0}; 21 | } 22 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/parsers.txt: -------------------------------------------------------------------------------- 1 | // packet_in: extern for input packet 2 | extern packet_in { 3 | void extract(out T hdr); 4 | void extract(out T hdr,in bit<32> n); 5 | T lookahead(); 6 | void advance(in bit<32> n); 7 | bit<32> length(); 8 | } 9 | 10 | // parser: begins in special "start" state 11 | state start { 12 | transition parse_ethernet; 13 | } 14 | 15 | // User-defined parser state 16 | state parse_ethernet { 17 | packet.extract(hdr.ethernet); 18 | transition select(hdr.ethernet.type) { 19 | 0x800: parse_ipv4; 20 | default: accept; 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/tables.txt: -------------------------------------------------------------------------------- 1 | table ipv4_lpm { 2 | key = { 3 | hdr.ipv4.dstAddr : lpm; 4 | // standard match kinds: 5 | // exact, ternary, lpm 6 | } 7 | // actions that can be invoked 8 | actions = { 9 | ipv4_forward; 10 | drop; 11 | NoAction; 12 | } 13 | // table properties 14 | size = 1024; 15 | default_action = NoAction(); 16 | } -------------------------------------------------------------------------------- /src/test/BMv2/utils/cheat_sheet_src/src/v1model_std_metadata.txt: -------------------------------------------------------------------------------- 1 | struct standard_metadata_t { 2 | // For more details see docs/simple_switch.md 3 | // in https://github.com/p4lang/behavioral-model 4 | 5 | // Should only read, ingress or egress 6 | bit<9> ingress_port; 7 | bit<32> instance_type; 8 | bit<32> packet_length; 9 | bit<48> ingress_global_timestamp; 10 | bit<1> checksum_error; 11 | error parser_error; 12 | 13 | // In ingress, read or write. 14 | // In egress, should only read. 15 | bit<9> egress_spec; 16 | bit<16> mcast_grp; 17 | 18 | // Should only read, only in egress 19 | bit<9> egress_port; 20 | bit<16> egress_rid; 21 | bit<48> egress_global_timestamp; 22 | bit<32> enq_timestamp; 23 | bit<19> enq_qdepth; 24 | bit<32> deq_timedelta; 25 | bit<19> deq_qdepth; 26 | } 27 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/mininet/appcontroller.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | from shortest_path import ShortestPath 4 | 5 | class AppController: 6 | 7 | def __init__(self, manifest=None, target=None, topo=None, net=None, links=None): 8 | self.manifest = manifest 9 | self.target = target 10 | self.conf = manifest['targets'][target] 11 | self.topo = topo 12 | self.net = net 13 | self.links = links 14 | 15 | def read_entries(self, filename): 16 | entries = [] 17 | with open(filename, 'r') as f: 18 | for line in f: 19 | line = line.strip() 20 | if line == '': continue 21 | entries.append(line) 22 | return entries 23 | 24 | def add_entries(self, thrift_port=9090, sw=None, entries=None): 25 | assert entries 26 | if sw: thrift_port = sw.thrift_port 27 | 28 | print('\n'.join(entries)) 29 | p = subprocess.Popen(['simple_switch_CLI', '--thrift-port', str(thrift_port)], stdin=subprocess.PIPE) 30 | p.communicate(input='\n'.join(entries)) 31 | 32 | def read_register(self, register, idx, thrift_port=9090, sw=None): 33 | if sw: thrift_port = sw.thrift_port 34 | p = subprocess.Popen(['simple_switch_CLI', '--thrift-port', str(thrift_port)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 35 | stdout, stderr = p.communicate(input="register_read %s %d" % (register, idx)) 36 | reg_val = [l for l in stdout.split('\n') if ' %s[%d]' % (register, idx) in l][0].split('= ', 1)[1] 37 | return int(reg_val) 38 | 39 | def start(self): 40 | shortestpath = ShortestPath(self.links) 41 | entries = {} 42 | for sw in self.topo.switches(): 43 | entries[sw] = [] 44 | if 'switches' in self.conf and sw in self.conf['switches'] and 'entries' in self.conf['switches'][sw]: 45 | extra_entries = self.conf['switches'][sw]['entries'] 46 | if type(extra_entries) == list: # array of entries 47 | entries[sw] += extra_entries 48 | else: # path to file that contains entries 49 | entries[sw] += self.read_entries(extra_entries) 50 | #entries[sw] += [ 51 | # 'table_set_default send_frame _drop', 52 | # 'table_set_default forward _drop', 53 | # 'table_set_default ipv4_lpm _drop'] 54 | 55 | for host_name in self.topo._host_links: 56 | h = self.net.get(host_name) 57 | for link in list(self.topo._host_links[host_name].values()): 58 | sw = link['sw'] 59 | #entries[sw].append('table_add send_frame rewrite_mac %d => %s' % (link['sw_port'], link['sw_mac'])) 60 | #entries[sw].append('table_add forward set_dmac %s => %s' % (link['host_ip'], link['host_mac'])) 61 | #entries[sw].append('table_add ipv4_lpm set_nhop %s/32 => %s %d' % (link['host_ip'], link['host_ip'], link['sw_port'])) 62 | iface = h.intfNames()[link['idx']] 63 | # use mininet to set ip and mac to let it know the change 64 | h.setIP(link['host_ip'], 24) 65 | h.setMAC(link['host_mac']) 66 | #h.cmd('ifconfig %s %s hw ether %s' % (iface, link['host_ip'], link['host_mac'])) 67 | h.cmd('arp -i %s -s %s %s' % (iface, link['sw_ip'], link['sw_mac'])) 68 | h.cmd('ethtool --offload %s rx off tx off' % iface) 69 | h.cmd('ip route add %s dev %s' % (link['sw_ip'], iface)) 70 | h.setDefaultRoute("via %s" % link['sw_ip']) 71 | 72 | for h in self.net.hosts: 73 | h_link = list(self.topo._host_links[h.name].values())[0] 74 | for sw in self.net.switches: 75 | path = shortestpath.get(sw.name, h.name, exclude=lambda n: n[0]=='h') 76 | if not path: continue 77 | if not path[1][0] == 's': continue # next hop is a switch 78 | sw_link = self.topo._sw_links[sw.name][path[1]] 79 | #entries[sw.name].append('table_add send_frame rewrite_mac %d => %s' % (sw_link[0]['port'], sw_link[0]['mac'])) 80 | #entries[sw.name].append('table_add forward set_dmac %s => %s' % (h_link['host_ip'], sw_link[1]['mac'])) 81 | #entries[sw.name].append('table_add ipv4_lpm set_nhop %s/32 => %s %d' % (h_link['host_ip'], h_link['host_ip'], sw_link[0]['port'])) 82 | 83 | for h2 in self.net.hosts: 84 | if h == h2: continue 85 | path = shortestpath.get(h.name, h2.name, exclude=lambda n: n[0]=='h') 86 | if not path: continue 87 | h_link = self.topo._host_links[h.name][path[1]] 88 | h2_link = list(self.topo._host_links[h2.name].values())[0] 89 | h.cmd('ip route add %s via %s' % (h2_link['host_ip'], h_link['sw_ip'])) 90 | 91 | 92 | print("**********") 93 | print("Configuring entries in p4 tables") 94 | for sw_name in entries: 95 | print() 96 | print("Configuring switch... %s" % sw_name) 97 | sw = self.net.get(sw_name) 98 | if entries[sw_name]: 99 | self.add_entries(sw=sw, entries=entries[sw_name]) 100 | print("Configuration complete.") 101 | print("**********") 102 | 103 | def stop(self): 104 | pass 105 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/mininet/apptopo.py: -------------------------------------------------------------------------------- 1 | from mininet.topo import Topo 2 | 3 | class AppTopo(Topo): 4 | 5 | def __init__(self, links, latencies={}, manifest=None, target=None, 6 | log_dir="/tmp", bws={}, **opts): 7 | Topo.__init__(self, **opts) 8 | 9 | nodes = sum(list(map(list, list(zip(*links)))), []) 10 | host_names = sorted(list(set([n for n in nodes if n[0] == 'h']))) 11 | sw_names = sorted(list(set([n for n in nodes if n[0] == 's']))) 12 | sw_ports = dict([(sw, []) for sw in sw_names]) 13 | 14 | self._host_links = {} 15 | self._sw_links = dict([(sw, {}) for sw in sw_names]) 16 | 17 | for sw_name in sw_names: 18 | self.addSwitch(sw_name, log_file="%s/%s.log" %(log_dir, sw_name)) 19 | 20 | for host_name in host_names: 21 | host_num = int(host_name[1:]) 22 | 23 | self.addHost(host_name) 24 | 25 | self._host_links[host_name] = {} 26 | host_links = [l for l in links if l[0]==host_name or l[1]==host_name] 27 | 28 | sw_idx = 0 29 | for link in host_links: 30 | sw = link[0] if link[0] != host_name else link[1] 31 | sw_num = int(sw[1:]) 32 | assert sw[0]=='s', "Hosts should be connected to switches, not " + str(sw) 33 | host_ip = "10.0.%d.%d" % (sw_num, host_num) 34 | host_mac = '00:00:00:00:%02x:%02x' % (sw_num, host_num) 35 | delay_key = ''.join([host_name, sw]) 36 | delay = latencies[delay_key] if delay_key in latencies else '0ms' 37 | bw = bws[delay_key] if delay_key in bws else None 38 | sw_ports[sw].append(host_name) 39 | self._host_links[host_name][sw] = dict( 40 | idx=sw_idx, 41 | host_mac = host_mac, 42 | host_ip = host_ip, 43 | sw = sw, 44 | sw_mac = "00:00:00:00:%02x:%02x" % (sw_num, host_num), 45 | sw_ip = "10.0.%d.%d" % (sw_num, 254), 46 | sw_port = sw_ports[sw].index(host_name)+1 47 | ) 48 | self.addLink(host_name, sw, delay=delay, bw=bw, 49 | addr1=host_mac, addr2=self._host_links[host_name][sw]['sw_mac']) 50 | sw_idx += 1 51 | 52 | for link in links: # only check switch-switch links 53 | sw1, sw2 = link 54 | if sw1[0] != 's' or sw2[0] != 's': continue 55 | 56 | delay_key = ''.join(sorted([sw1, sw2])) 57 | delay = latencies[delay_key] if delay_key in latencies else '0ms' 58 | bw = bws[delay_key] if delay_key in bws else None 59 | 60 | self.addLink(sw1, sw2, delay=delay, bw=bw)#, max_queue_size=10) 61 | sw_ports[sw1].append(sw2) 62 | sw_ports[sw2].append(sw1) 63 | 64 | sw1_num, sw2_num = int(sw1[1:]), int(sw2[1:]) 65 | sw1_port = dict(mac="00:00:00:%02x:%02x:00" % (sw1_num, sw2_num), port=sw_ports[sw1].index(sw2)+1) 66 | sw2_port = dict(mac="00:00:00:%02x:%02x:00" % (sw2_num, sw1_num), port=sw_ports[sw2].index(sw1)+1) 67 | 68 | self._sw_links[sw1][sw2] = [sw1_port, sw2_port] 69 | self._sw_links[sw2][sw1] = [sw2_port, sw1_port] 70 | 71 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/mininet/p4_mininet.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013-present Barefoot Networks, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | 16 | from mininet.net import Mininet 17 | from mininet.node import Switch, Host 18 | from mininet.log import setLogLevel, info, error, debug 19 | from mininet.moduledeps import pathCheck 20 | from sys import exit 21 | from time import sleep 22 | import os 23 | import tempfile 24 | import socket 25 | 26 | class P4Host(Host): 27 | def config(self, **params): 28 | r = super(P4Host, self).config(**params) 29 | 30 | for off in ["rx", "tx", "sg"]: 31 | cmd = "/sbin/ethtool --offload %s %s off" % (self.defaultIntf().name, off) 32 | self.cmd(cmd) 33 | 34 | # disable IPv6 35 | self.cmd("sysctl -w net.ipv6.conf.all.disable_ipv6=1") 36 | self.cmd("sysctl -w net.ipv6.conf.default.disable_ipv6=1") 37 | self.cmd("sysctl -w net.ipv6.conf.lo.disable_ipv6=1") 38 | 39 | return r 40 | 41 | def describe(self, sw_addr=None, sw_mac=None): 42 | print("**********") 43 | print("Network configuration for: %s" % self.name) 44 | print("Default interface: %s\t%s\t%s" %( 45 | self.defaultIntf().name, 46 | self.defaultIntf().IP(), 47 | self.defaultIntf().MAC() 48 | )) 49 | if sw_addr is not None or sw_mac is not None: 50 | print("Default route to switch: %s (%s)" % (sw_addr, sw_mac)) 51 | print("**********") 52 | 53 | class P4Switch(Switch): 54 | """P4 virtual switch""" 55 | device_id = 0 56 | 57 | def __init__(self, name, sw_path = None, json_path = None, 58 | log_file = None, 59 | thrift_port = None, 60 | pcap_dump = False, 61 | log_console = False, 62 | verbose = False, 63 | device_id = None, 64 | enable_debugger = False, 65 | **kwargs): 66 | Switch.__init__(self, name, **kwargs) 67 | assert(sw_path) 68 | assert(json_path) 69 | # make sure that the provided sw_path is valid 70 | pathCheck(sw_path) 71 | # make sure that the provided JSON file exists 72 | if not os.path.isfile(json_path): 73 | error("Invalid JSON file.\n") 74 | exit(1) 75 | self.sw_path = sw_path 76 | self.json_path = json_path 77 | self.verbose = verbose 78 | self.log_file = log_file 79 | if self.log_file is None: 80 | self.log_file = "/tmp/p4s.{}.log".format(self.name) 81 | self.output = open(self.log_file, 'w') 82 | self.thrift_port = thrift_port 83 | self.pcap_dump = pcap_dump 84 | self.enable_debugger = enable_debugger 85 | self.log_console = log_console 86 | if device_id is not None: 87 | self.device_id = device_id 88 | P4Switch.device_id = max(P4Switch.device_id, device_id) 89 | else: 90 | self.device_id = P4Switch.device_id 91 | P4Switch.device_id += 1 92 | self.nanomsg = "ipc:///tmp/bm-{}-log.ipc".format(self.device_id) 93 | 94 | @classmethod 95 | def setup(cls): 96 | pass 97 | 98 | def check_switch_started(self, pid): 99 | """While the process is running (pid exists), we check if the Thrift 100 | server has been started. If the Thrift server is ready, we assume that 101 | the switch was started successfully. This is only reliable if the Thrift 102 | server is started at the end of the init process""" 103 | while True: 104 | if not os.path.exists(os.path.join("/proc", str(pid))): 105 | return False 106 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 107 | sock.settimeout(0.5) 108 | result = sock.connect_ex(("localhost", self.thrift_port)) 109 | if result == 0: 110 | return True 111 | 112 | def start(self, controllers): 113 | "Start up a new P4 switch" 114 | info("Starting P4 switch {}.\n".format(self.name)) 115 | args = [self.sw_path] 116 | for port, intf in list(self.intfs.items()): 117 | if not intf.IP(): 118 | args.extend(['-i', str(port) + "@" + intf.name]) 119 | if self.pcap_dump: 120 | args.append("--pcap") 121 | # args.append("--useFiles") 122 | if self.thrift_port: 123 | args.extend(['--thrift-port', str(self.thrift_port)]) 124 | if self.nanomsg: 125 | args.extend(['--nanolog', self.nanomsg]) 126 | args.extend(['--device-id', str(self.device_id)]) 127 | P4Switch.device_id += 1 128 | args.append(self.json_path) 129 | if self.enable_debugger: 130 | args.append("--debugger") 131 | if self.log_console: 132 | args.append("--log-console") 133 | info(' '.join(args) + "\n") 134 | 135 | pid = None 136 | with tempfile.NamedTemporaryFile() as f: 137 | # self.cmd(' '.join(args) + ' > /dev/null 2>&1 &') 138 | self.cmd(' '.join(args) + ' >' + self.log_file + ' 2>&1 & echo $! >> ' + f.name) 139 | pid = int(f.read()) 140 | debug("P4 switch {} PID is {}.\n".format(self.name, pid)) 141 | sleep(1) 142 | if not self.check_switch_started(pid): 143 | error("P4 switch {} did not start correctly." 144 | "Check the switch log file.\n".format(self.name)) 145 | exit(1) 146 | info("P4 switch {} has been started.\n".format(self.name)) 147 | 148 | def stop(self): 149 | "Terminate P4 switch." 150 | self.output.flush() 151 | self.cmd('kill %' + self.sw_path) 152 | self.cmd('wait') 153 | self.deleteIntfs() 154 | 155 | def attach(self, intf): 156 | "Connect a data port" 157 | assert(0) 158 | 159 | def detach(self, intf): 160 | "Disconnect a data port" 161 | assert(0) 162 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/mininet/shortest_path.py: -------------------------------------------------------------------------------- 1 | class ShortestPath: 2 | 3 | def __init__(self, edges=[]): 4 | self.neighbors = {} 5 | for edge in edges: 6 | self.addEdge(*edge) 7 | 8 | def addEdge(self, a, b): 9 | if a not in self.neighbors: self.neighbors[a] = [] 10 | if b not in self.neighbors[a]: self.neighbors[a].append(b) 11 | 12 | if b not in self.neighbors: self.neighbors[b] = [] 13 | if a not in self.neighbors[b]: self.neighbors[b].append(a) 14 | 15 | def get(self, a, b, exclude=lambda node: False): 16 | # Shortest path from a to b 17 | return self._recPath(a, b, [], exclude) 18 | 19 | def _recPath(self, a, b, visited, exclude): 20 | if a == b: return [a] 21 | new_visited = visited + [a] 22 | paths = [] 23 | for neighbor in self.neighbors[a]: 24 | if neighbor in new_visited: continue 25 | if exclude(neighbor) and neighbor != b: continue 26 | path = self._recPath(neighbor, b, new_visited, exclude) 27 | if path: paths.append(path) 28 | 29 | paths.sort(key=len) 30 | return [a] + paths[0] if len(paths) else None 31 | 32 | if __name__ == '__main__': 33 | 34 | edges = [ 35 | (1, 2), 36 | (1, 3), 37 | (1, 5), 38 | (2, 4), 39 | (3, 4), 40 | (3, 5), 41 | (3, 6), 42 | (4, 6), 43 | (5, 6), 44 | (7, 8) 45 | 46 | ] 47 | sp = ShortestPath(edges) 48 | 49 | assert sp.get(1, 1) == [1] 50 | assert sp.get(2, 2) == [2] 51 | 52 | assert sp.get(1, 2) == [1, 2] 53 | assert sp.get(2, 1) == [2, 1] 54 | 55 | assert sp.get(1, 3) == [1, 3] 56 | assert sp.get(3, 1) == [3, 1] 57 | 58 | assert sp.get(4, 6) == [4, 6] 59 | assert sp.get(6, 4) == [6, 4] 60 | 61 | assert sp.get(2, 6) == [2, 4, 6] 62 | assert sp.get(6, 2) == [6, 4, 2] 63 | 64 | assert sp.get(1, 6) in [[1, 3, 6], [1, 5, 6]] 65 | assert sp.get(6, 1) in [[6, 3, 1], [6, 5, 1]] 66 | 67 | assert sp.get(2, 5) == [2, 1, 5] 68 | assert sp.get(5, 2) == [5, 1, 2] 69 | 70 | assert sp.get(4, 5) in [[4, 3, 5], [4, 6, 5]] 71 | assert sp.get(5, 4) in [[5, 3, 4], [6, 6, 4]] 72 | 73 | assert sp.get(7, 8) == [7, 8] 74 | assert sp.get(8, 7) == [8, 7] 75 | 76 | assert sp.get(1, 7) == None 77 | assert sp.get(7, 2) == None 78 | 79 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/mininet/single_switch_mininet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | from mininet.net import Mininet 19 | from mininet.topo import Topo 20 | from mininet.log import setLogLevel, info 21 | from mininet.cli import CLI 22 | 23 | from p4_mininet import P4Switch, P4Host 24 | 25 | import argparse 26 | from subprocess import PIPE, Popen 27 | from time import sleep 28 | 29 | parser = argparse.ArgumentParser(description='Mininet demo') 30 | parser.add_argument('--behavioral-exe', help='Path to behavioral executable', 31 | type=str, action="store", required=True) 32 | parser.add_argument('--thrift-port', help='Thrift server port for table updates', 33 | type=int, action="store", default=9090) 34 | parser.add_argument('--num-hosts', help='Number of hosts to connect to switch', 35 | type=int, action="store", default=2) 36 | parser.add_argument('--mode', choices=['l2', 'l3'], type=str, default='l3') 37 | parser.add_argument('--json', help='Path to JSON config file', 38 | type=str, action="store", required=True) 39 | parser.add_argument('--log-file', help='Path to write the switch log file', 40 | type=str, action="store", required=False) 41 | parser.add_argument('--pcap-dump', help='Dump packets on interfaces to pcap files', 42 | type=str, action="store", required=False, default=False) 43 | parser.add_argument('--switch-config', help='simple_switch_CLI script to configure switch', 44 | type=str, action="store", required=False, default=False) 45 | parser.add_argument('--cli-message', help='Message to print before starting CLI', 46 | type=str, action="store", required=False, default=False) 47 | 48 | args = parser.parse_args() 49 | 50 | 51 | class SingleSwitchTopo(Topo): 52 | "Single switch connected to n (< 256) hosts." 53 | def __init__(self, sw_path, json_path, log_file, 54 | thrift_port, pcap_dump, n, **opts): 55 | # Initialize topology and default options 56 | Topo.__init__(self, **opts) 57 | 58 | switch = self.addSwitch('s1', 59 | sw_path = sw_path, 60 | json_path = json_path, 61 | log_console = True, 62 | log_file = log_file, 63 | thrift_port = thrift_port, 64 | enable_debugger = False, 65 | pcap_dump = pcap_dump) 66 | 67 | for h in range(n): 68 | host = self.addHost('h%d' % (h + 1), 69 | ip = "10.0.%d.10/24" % h, 70 | mac = '00:04:00:00:00:%02x' %h) 71 | print("Adding host", str(host)) 72 | self.addLink(host, switch) 73 | 74 | def main(): 75 | num_hosts = args.num_hosts 76 | mode = args.mode 77 | 78 | topo = SingleSwitchTopo(args.behavioral_exe, 79 | args.json, 80 | args.log_file, 81 | args.thrift_port, 82 | args.pcap_dump, 83 | num_hosts) 84 | net = Mininet(topo = topo, 85 | host = P4Host, 86 | switch = P4Switch, 87 | controller = None) 88 | net.start() 89 | 90 | 91 | sw_mac = ["00:aa:bb:00:00:%02x" % n for n in range(num_hosts)] 92 | 93 | sw_addr = ["10.0.%d.1" % n for n in range(num_hosts)] 94 | 95 | for n in range(num_hosts): 96 | h = net.get('h%d' % (n + 1)) 97 | if mode == "l2": 98 | h.setDefaultRoute("dev %s" % h.defaultIntf().name) 99 | else: 100 | h.setARP(sw_addr[n], sw_mac[n]) 101 | h.setDefaultRoute("dev %s via %s" % (h.defaultIntf().name, sw_addr[n])) 102 | 103 | for n in range(num_hosts): 104 | h = net.get('h%d' % (n + 1)) 105 | h.describe(sw_addr[n], sw_mac[n]) 106 | 107 | sleep(1) 108 | 109 | if args.switch_config is not None: 110 | print() 111 | print("Reading switch configuration script:", args.switch_config) 112 | with open(args.switch_config, 'r') as config_file: 113 | switch_config = config_file.read() 114 | 115 | print("Configuring switch...") 116 | proc = Popen(["simple_switch_CLI"], stdin=PIPE) 117 | proc.communicate(input=switch_config) 118 | 119 | print("Configuration complete.") 120 | print() 121 | 122 | print("Ready !") 123 | 124 | if args.cli_message is not None: 125 | with open(args.cli_message, 'r') as message_file: 126 | print(message_file.read()) 127 | 128 | CLI( net ) 129 | net.stop() 130 | 131 | if __name__ == '__main__': 132 | setLogLevel( 'info' ) 133 | main() 134 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/netstat.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-present Open Networking Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | 16 | import psutil 17 | def check_listening_on_port(port): 18 | for c in psutil.net_connections(kind='inet'): 19 | if c.status == 'LISTEN' and c.laddr[1] == port: 20 | return True 21 | return False 22 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4_mininet.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013-present Barefoot Networks, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | 16 | from mininet.net import Mininet 17 | from mininet.node import Switch, Host 18 | from mininet.log import setLogLevel, info, error, debug 19 | from mininet.moduledeps import pathCheck 20 | from sys import exit 21 | import os 22 | import tempfile 23 | import socket 24 | from time import sleep 25 | 26 | from netstat import check_listening_on_port 27 | 28 | SWITCH_START_TIMEOUT = 10 # seconds 29 | 30 | class P4Host(Host): 31 | def config(self, **params): 32 | r = super(Host, self).config(**params) 33 | 34 | self.defaultIntf().rename("eth0") 35 | 36 | for off in ["rx", "tx", "sg"]: 37 | cmd = "/sbin/ethtool --offload eth0 %s off" % off 38 | self.cmd(cmd) 39 | 40 | # disable IPv6 41 | self.cmd("sysctl -w net.ipv6.conf.all.disable_ipv6=1") 42 | self.cmd("sysctl -w net.ipv6.conf.default.disable_ipv6=1") 43 | self.cmd("sysctl -w net.ipv6.conf.lo.disable_ipv6=1") 44 | 45 | return r 46 | 47 | def describe(self): 48 | print("**********") 49 | print(self.name) 50 | print("default interface: %s\t%s\t%s" %( 51 | self.defaultIntf().name, 52 | self.defaultIntf().IP(), 53 | self.defaultIntf().MAC() 54 | )) 55 | print("**********") 56 | 57 | class P4Switch(Switch): 58 | """P4 virtual switch""" 59 | device_id = 0 60 | 61 | def __init__(self, name, sw_path = None, json_path = None, 62 | thrift_port = None, 63 | pcap_dump = False, 64 | log_console = False, 65 | log_file = None, 66 | verbose = False, 67 | device_id = None, 68 | enable_debugger = False, 69 | **kwargs): 70 | Switch.__init__(self, name, **kwargs) 71 | assert(sw_path) 72 | assert(json_path) 73 | # make sure that the provided sw_path is valid 74 | pathCheck(sw_path) 75 | # make sure that the provided JSON file exists 76 | if not os.path.isfile(json_path): 77 | error("Invalid JSON file.\n") 78 | exit(1) 79 | self.sw_path = sw_path 80 | self.json_path = json_path 81 | self.verbose = verbose 82 | logfile = "/tmp/p4s.{}.log".format(self.name) 83 | self.output = open(logfile, 'w') 84 | self.thrift_port = thrift_port 85 | if check_listening_on_port(self.thrift_port): 86 | error('%s cannot bind port %d because it is bound by another process\n' % (self.name, self.grpc_port)) 87 | exit(1) 88 | self.pcap_dump = pcap_dump 89 | self.enable_debugger = enable_debugger 90 | self.log_console = log_console 91 | if log_file is not None: 92 | self.log_file = log_file 93 | else: 94 | self.log_file = "/tmp/p4s.{}.log".format(self.name) 95 | if device_id is not None: 96 | self.device_id = device_id 97 | P4Switch.device_id = max(P4Switch.device_id, device_id) 98 | else: 99 | self.device_id = P4Switch.device_id 100 | P4Switch.device_id += 1 101 | self.nanomsg = "ipc:///tmp/bm-{}-log.ipc".format(self.device_id) 102 | 103 | @classmethod 104 | def setup(cls): 105 | pass 106 | 107 | def check_switch_started(self, pid): 108 | """While the process is running (pid exists), we check if the Thrift 109 | server has been started. If the Thrift server is ready, we assume that 110 | the switch was started successfully. This is only reliable if the Thrift 111 | server is started at the end of the init process""" 112 | while True: 113 | if not os.path.exists(os.path.join("/proc", str(pid))): 114 | return False 115 | if check_listening_on_port(self.thrift_port): 116 | return True 117 | sleep(0.5) 118 | 119 | def start(self, controllers): 120 | "Start up a new P4 switch" 121 | info("Starting P4 switch {}.\n".format(self.name)) 122 | args = [self.sw_path] 123 | for port, intf in list(self.intfs.items()): 124 | if not intf.IP(): 125 | args.extend(['-i', str(port) + "@" + intf.name]) 126 | if self.pcap_dump: 127 | args.append("--pcap %s" % self.pcap_dump) 128 | if self.thrift_port: 129 | args.extend(['--thrift-port', str(self.thrift_port)]) 130 | if self.nanomsg: 131 | args.extend(['--nanolog', self.nanomsg]) 132 | args.extend(['--device-id', str(self.device_id)]) 133 | P4Switch.device_id += 1 134 | args.append(self.json_path) 135 | if self.enable_debugger: 136 | args.append("--debugger") 137 | if self.log_console: 138 | args.append("--log-console") 139 | info(' '.join(args) + "\n") 140 | 141 | pid = None 142 | with tempfile.NamedTemporaryFile() as f: 143 | # self.cmd(' '.join(args) + ' > /dev/null 2>&1 &') 144 | self.cmd(' '.join(args) + ' >' + self.log_file + ' 2>&1 & echo $! >> ' + f.name) 145 | pid = int(f.read()) 146 | debug("P4 switch {} PID is {}.\n".format(self.name, pid)) 147 | if not self.check_switch_started(pid): 148 | error("P4 switch {} did not start correctly.\n".format(self.name)) 149 | exit(1) 150 | info("P4 switch {} has been started.\n".format(self.name)) 151 | 152 | def stop(self): 153 | "Terminate P4 switch." 154 | self.output.flush() 155 | self.cmd('kill %' + self.sw_path) 156 | self.cmd('wait') 157 | self.deleteIntfs() 158 | 159 | def attach(self, intf): 160 | "Connect a data port" 161 | assert(0) 162 | 163 | def detach(self, intf): 164 | "Disconnect a data port" 165 | assert(0) 166 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4_program.py: -------------------------------------------------------------------------------- 1 | import os 2 | from p4app_util import run_command 3 | 4 | class P4Program: 5 | 6 | def __init__(self, prog_filename, version=16, compile_flags=[]): 7 | self.prog_filename = os.path.join('/p4app', prog_filename) 8 | 9 | assert isinstance(version, str) or isinstance(version, int) 10 | if version in [14, '14', 'P4_14']: 11 | self.version = 14 12 | elif version in [16, '16', 'P4_16']: 13 | self.version = 16 14 | else: 15 | raise Exception("Unrecognized P4 version: " + str(version)) 16 | 17 | self.compile_flags = compile_flags 18 | assert isinstance(compile_flags, list) 19 | self._json_path = None 20 | self._p4info_path = None 21 | 22 | def name(self): 23 | return os.path.basename(self.prog_filename).rstrip('.p4') 24 | 25 | def compile(self): 26 | compiler_args = [] 27 | 28 | compiler_args.append('--std p4-%d' % self.version) 29 | 30 | compiler_args.extend(self.compile_flags) 31 | 32 | # Compile the program. 33 | self._json_path = os.path.join('/tmp/p4app-logs', self.name() + '.json') 34 | compiler_args.append('"%s"' % self.prog_filename) 35 | compiler_args.append('-o "%s"' % self._json_path) 36 | if self.supportsP4Runtime(): 37 | self._p4info_path = os.path.join('/tmp/p4app-logs', self.name() + '.p4info.txt') 38 | compiler_args.append('--p4runtime-files "%s"' % self._p4info_path) 39 | rv = run_command('p4c-bm2-ss %s' % ' '.join(compiler_args)) 40 | 41 | if rv != 0: 42 | raise Exception("Compile failed. Compiler return value: %d" % rv) 43 | 44 | def json(self): 45 | if self._json_path is None: 46 | self.compile() 47 | return self._json_path 48 | 49 | def p4info(self): 50 | if not self.supportsP4Runtime(): return None 51 | if self._p4info_path is None: 52 | self.compile() 53 | return self._p4info_path 54 | 55 | def supportsP4Runtime(self): 56 | return self.version == 16 57 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4app_util.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import os 3 | 4 | def log(*items): 5 | print(*items) 6 | 7 | def log_error(*items): 8 | print(*items, file=sys.stderr) 9 | 10 | def run_command(command): 11 | log('>', command) 12 | return os.WEXITSTATUS(os.system(command)) 13 | 14 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4runtime_lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/In-Network-Machine-Learning/DINC/9f0b89dd239a097954fb0d302c45be23f7b53ad2/src/test/BMv2/utils/p4runtime_lib/__init__.py -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4runtime_lib/bmv2.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-present Open Networking Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | from . import switch 16 | from .switch import SwitchConnection 17 | from p4.tmp import p4config_pb2 18 | 19 | 20 | def buildDeviceConfig(bmv2_json_file_path=None): 21 | "Builds the device config for BMv2" 22 | device_config = p4config_pb2.P4DeviceConfig() 23 | device_config.reassign = True 24 | with open(bmv2_json_file_path) as f: 25 | device_config.device_data = f.read().encode('utf-8') 26 | return device_config 27 | 28 | 29 | class Bmv2SwitchConnection(SwitchConnection): 30 | def buildDeviceConfig(self, **kwargs): 31 | return buildDeviceConfig(**kwargs) 32 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4runtime_lib/convert-modified.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-present Open Networking Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | import re 16 | import socket 17 | 18 | import math 19 | 20 | ''' 21 | This package contains several helper functions for encoding to and decoding from byte strings: 22 | - integers 23 | - IPv4 address strings 24 | - Ethernet address strings 25 | ''' 26 | 27 | mac_pattern = re.compile('^([\da-fA-F]{2}:){5}([\da-fA-F]{2})$') 28 | def matchesMac(mac_addr_string): 29 | return mac_pattern.match(mac_addr_string) is not None 30 | 31 | def encodeMac(mac_addr_string): 32 | return bytes.fromhex(mac_addr_string.replace(':', '')) 33 | 34 | def decodeMac(encoded_mac_addr): 35 | return ':'.join(s.hex() for s in encoded_mac_addr) 36 | 37 | ip_pattern = re.compile('^(\d{1,3}\.){3}(\d{1,3})$') 38 | def matchesIPv4(ip_addr_string): 39 | return ip_pattern.match(ip_addr_string) is not None 40 | 41 | def encodeIPv4(ip_addr_string): 42 | return socket.inet_aton(ip_addr_string) 43 | 44 | def decodeIPv4(encoded_ip_addr): 45 | return socket.inet_ntoa(encoded_ip_addr) 46 | 47 | def bitwidthToBytes(bitwidth): 48 | return int(math.ceil(bitwidth / 8.0)) 49 | 50 | def encodeNum(number, bitwidth): 51 | byte_len = bitwidthToBytes(bitwidth) 52 | num_str = '%x' % number 53 | print (number) 54 | if number >= 2 ** bitwidth: 55 | raise Exception("Number, %d, does not fit in %d bits" % (number, bitwidth)) 56 | return ('0' * (byte_len * 2 - len(num_str)) + num_str).encode()#.decode('hex') 57 | 58 | def decodeNum(encoded_number): 59 | return int(encoded_number.encode('hex'), 16) 60 | 61 | def encode(x, bitwidth): 62 | 'Tries to infer the type of `x` and encode it' 63 | byte_len = bitwidthToBytes(bitwidth) 64 | if (type(x) == list or type(x) == tuple) and len(x) == 1: 65 | x = x[0] 66 | encoded_bytes = None 67 | if type(x) == str: 68 | if matchesMac(x): 69 | encoded_bytes = encodeMac(x) 70 | elif matchesIPv4(x): 71 | encoded_bytes = encodeIPv4(x) 72 | else: 73 | # Assume that the string is already encoded 74 | encoded_bytes = x 75 | elif type(x) == int: 76 | encoded_bytes = encodeNum(x, bitwidth) 77 | print ("Convert the entered valus to hexadecimal: ", encoded_bytes) 78 | print ("Length after encoding: ", len(encoded_bytes)) 79 | print ("Length of the header", byte_len) 80 | else: 81 | raise Exception("Encoding objects of %r is not supported" % type(x)) 82 | assert(len(encoded_bytes) == byte_len) 83 | return encoded_bytes 84 | 85 | 86 | if __name__ == '__main__': 87 | # TODO These tests should be moved out of main eventually 88 | mac = "aa:bb:cc:dd:ee:ff" 89 | enc_mac = encodeMac(mac) 90 | assert(enc_mac == '\xaa\xbb\xcc\xdd\xee\xff') 91 | dec_mac = decodeMac(enc_mac) 92 | assert(mac == dec_mac) 93 | 94 | ip = "10.0.0.1" 95 | enc_ip = encodeIPv4(ip) 96 | assert(enc_ip == '\x0a\x00\x00\x01') 97 | dec_ip = decodeIPv4(enc_ip) 98 | assert(ip == dec_ip) 99 | 100 | num = 1337 101 | byte_len = 5 102 | enc_num = encodeNum(num, byte_len * 8) 103 | assert(enc_num == '\x00\x00\x00\x05\x39') 104 | dec_num = decodeNum(enc_num) 105 | assert(num == dec_num) 106 | 107 | assert(matchesIPv4('10.0.0.1')) 108 | assert(not matchesIPv4('10.0.0.1.5')) 109 | assert(not matchesIPv4('1000.0.0.1')) 110 | assert(not matchesIPv4('10001')) 111 | 112 | assert(encode(mac, 6 * 8) == enc_mac) 113 | assert(encode(ip, 4 * 8) == enc_ip) 114 | assert(encode(num, 5 * 8) == enc_num) 115 | assert(encode((num,), 5 * 8) == enc_num) 116 | assert(encode([num], 5 * 8) == enc_num) 117 | 118 | num = 256 119 | byte_len = 2 120 | try: 121 | enc_num = encodeNum(num, 8) 122 | raise Exception("expected exception") 123 | except Exception as e: 124 | print(e) 125 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4runtime_lib/convert.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-present Open Networking Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | import re 16 | import socket 17 | 18 | import math 19 | 20 | ''' 21 | This package contains several helper functions for encoding to and decoding from byte strings: 22 | - integers 23 | - IPv4 address strings 24 | - Ethernet address strings 25 | ''' 26 | 27 | mac_pattern = re.compile('^([\da-fA-F]{2}:){5}([\da-fA-F]{2})$') 28 | def matchesMac(mac_addr_string): 29 | return mac_pattern.match(mac_addr_string) is not None 30 | 31 | def encodeMac(mac_addr_string): 32 | return bytes.fromhex(mac_addr_string.replace(':', '')) 33 | 34 | def decodeMac(encoded_mac_addr): 35 | return ':'.join(s.hex() for s in encoded_mac_addr) 36 | 37 | ip_pattern = re.compile('^(\d{1,3}\.){3}(\d{1,3})$') 38 | def matchesIPv4(ip_addr_string): 39 | return ip_pattern.match(ip_addr_string) is not None 40 | 41 | def encodeIPv4(ip_addr_string): 42 | return socket.inet_aton(ip_addr_string) 43 | 44 | def decodeIPv4(encoded_ip_addr): 45 | return socket.inet_ntoa(encoded_ip_addr) 46 | 47 | def bitwidthToBytes(bitwidth): 48 | return int(math.ceil(bitwidth / 8.0)) 49 | 50 | def encodeNum(number, bitwidth): 51 | byte_len = bitwidthToBytes(bitwidth) 52 | num_str = '%x' % number 53 | if number >= 2 ** bitwidth: 54 | raise Exception("Number, %d, does not fit in %d bits" % (number, bitwidth)) 55 | return bytes.fromhex('0' * (byte_len * 2 - len(num_str)) + num_str) 56 | 57 | def decodeNum(encoded_number): 58 | return int(encoded_number.hex(), 16) 59 | 60 | def encode(x, bitwidth): 61 | 'Tries to infer the type of `x` and encode it' 62 | byte_len = bitwidthToBytes(bitwidth) 63 | if (type(x) == list or type(x) == tuple) and len(x) == 1: 64 | x = x[0] 65 | encoded_bytes = None 66 | if type(x) == str: 67 | if matchesMac(x): 68 | encoded_bytes = encodeMac(x) 69 | # print("x1 ", x) 70 | elif matchesIPv4(x): 71 | encoded_bytes = encodeIPv4(x) 72 | # print("x2 ", x) 73 | else: 74 | # Assume that the string is already encoded 75 | encoded_bytes = x 76 | # print("x3 ", x) 77 | elif type(x) == int: 78 | encoded_bytes = encodeNum(x, bitwidth) 79 | # print("x4 ", x) 80 | else: 81 | raise Exception("Encoding objects of %r is not supported" % type(x)) 82 | 83 | # print ("Convert the entered valus to hexadecimal: ", encoded_bytes) 84 | # print ("Length after encoding: ", len(encoded_bytes)) 85 | # print ("Length of the header", byte_len) 86 | assert(len(encoded_bytes) == byte_len) 87 | return encoded_bytes 88 | 89 | if __name__ == '__main__': 90 | # TODO These tests should be moved out of main eventually 91 | mac = "aa:bb:cc:dd:ee:ff" 92 | enc_mac = encodeMac(mac) 93 | assert(enc_mac == '\xaa\xbb\xcc\xdd\xee\xff') 94 | dec_mac = decodeMac(enc_mac) 95 | assert(mac == dec_mac) 96 | 97 | ip = "10.0.0.1" 98 | enc_ip = encodeIPv4(ip) 99 | assert(enc_ip == '\x0a\x00\x00\x01') 100 | dec_ip = decodeIPv4(enc_ip) 101 | assert(ip == dec_ip) 102 | 103 | num = 1337 104 | byte_len = 5 105 | enc_num = encodeNum(num, byte_len * 8) 106 | assert(enc_num == '\x00\x00\x00\x05\x39') 107 | dec_num = decodeNum(enc_num) 108 | assert(num == dec_num) 109 | 110 | assert(matchesIPv4('10.0.0.1')) 111 | assert(not matchesIPv4('10.0.0.1.5')) 112 | assert(not matchesIPv4('1000.0.0.1')) 113 | assert(not matchesIPv4('10001')) 114 | 115 | assert(encode(mac, 6 * 8) == enc_mac) 116 | assert(encode(ip, 4 * 8) == enc_ip) 117 | assert(encode(num, 5 * 8) == enc_num) 118 | assert(encode((num,), 5 * 8) == enc_num) 119 | assert(encode([num], 5 * 8) == enc_num) 120 | 121 | num = 256 122 | byte_len = 2 123 | try: 124 | enc_num = encodeNum(num, 8) 125 | raise Exception("expected exception") 126 | except Exception as e: 127 | print(e) 128 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4runtime_lib/error_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013-present Barefoot Networks, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | 16 | import sys 17 | 18 | from google.rpc import status_pb2, code_pb2 19 | import grpc 20 | from p4.v1 import p4runtime_pb2 21 | from p4.v1 import p4runtime_pb2_grpc 22 | 23 | # Used to indicate that the gRPC error Status object returned by the server has 24 | # an incorrect format. 25 | class P4RuntimeErrorFormatException(Exception): 26 | def __init__(self, message): 27 | super(P4RuntimeErrorFormatException, self).__init__(message) 28 | 29 | 30 | # Parse the binary details of the gRPC error. This is required to print some 31 | # helpful debugging information in tha case of batched Write / Read 32 | # requests. Returns None if there are no useful binary details and throws 33 | # P4RuntimeErrorFormatException if the error is not formatted 34 | # properly. Otherwise, returns a list of tuples with the first element being the 35 | # index of the operation in the batch that failed and the second element being 36 | # the p4.Error Protobuf message. 37 | def parseGrpcErrorBinaryDetails(grpc_error): 38 | if grpc_error.code() != grpc.StatusCode.UNKNOWN: 39 | return None 40 | 41 | error = None 42 | # The gRPC Python package does not have a convenient way to access the 43 | # binary details for the error: they are treated as trailing metadata. 44 | for meta in grpc_error.trailing_metadata(): 45 | if meta[0] == "grpc-status-details-bin": 46 | error = status_pb2.Status() 47 | error.ParseFromString(meta[1]) 48 | break 49 | if error is None: # no binary details field 50 | return None 51 | if len(error.details) == 0: 52 | # binary details field has empty Any details repeated field 53 | return None 54 | 55 | indexed_p4_errors = [] 56 | for idx, one_error_any in enumerate(error.details): 57 | p4_error = p4runtime_pb2.Error() 58 | if not one_error_any.Unpack(p4_error): 59 | raise P4RuntimeErrorFormatException( 60 | "Cannot convert Any message to p4.Error") 61 | if p4_error.canonical_code == code_pb2.OK: 62 | continue 63 | indexed_p4_errors += [(idx, p4_error)] 64 | 65 | return indexed_p4_errors 66 | 67 | 68 | # P4Runtime uses a 3-level message in case of an error during the processing of 69 | # a write batch. This means that some care is required when printing the 70 | # exception if we do not want to end-up with a non-helpful message in case of 71 | # failure as only the first level will be printed. In this function, we extract 72 | # the nested error message when present (one for each operation included in the 73 | # batch) in order to print error code + user-facing message. See P4Runtime 74 | # documentation for more details on error-reporting. 75 | def printGrpcError(grpc_error): 76 | print("gRPC Error", grpc_error.details(), end=' ') 77 | status_code = grpc_error.code() 78 | print("({})".format(status_code.name), end=' ') 79 | traceback = sys.exc_info()[2] 80 | print("[{}:{}]".format( 81 | traceback.tb_frame.f_code.co_filename, traceback.tb_lineno)) 82 | if status_code != grpc.StatusCode.UNKNOWN: 83 | return 84 | p4_errors = parseGrpcErrorBinaryDetails(grpc_error) 85 | if p4_errors is None: 86 | return 87 | print("Errors in batch:") 88 | for idx, p4_error in p4_errors: 89 | code_name = code_pb2._CODE.values_by_number[ 90 | p4_error.canonical_code].name 91 | print("\t* At index {}: {}, '{}'\n".format( 92 | idx, code_name, p4_error.message)) 93 | -------------------------------------------------------------------------------- /src/test/BMv2/utils/p4runtime_switch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-present Barefoot Networks, Inc. 2 | # Copyright 2017-present Open Networking Foundation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | import sys, os, tempfile, socket 18 | from time import sleep 19 | 20 | from mininet.node import Switch 21 | from mininet.moduledeps import pathCheck 22 | from mininet.log import info, error, debug 23 | 24 | from p4_mininet import P4Switch, SWITCH_START_TIMEOUT 25 | from netstat import check_listening_on_port 26 | 27 | class P4RuntimeSwitch(P4Switch): 28 | "BMv2 switch with gRPC support" 29 | next_grpc_port = 50051 30 | next_thrift_port = 9090 31 | 32 | def __init__(self, name, sw_path = None, json_path = None, 33 | grpc_port = None, 34 | thrift_port = None, 35 | pcap_dump = False, 36 | log_console = False, 37 | verbose = False, 38 | device_id = None, 39 | enable_debugger = False, 40 | log_file = None, 41 | **kwargs): 42 | Switch.__init__(self, name, **kwargs) 43 | assert (sw_path) 44 | self.sw_path = sw_path 45 | # make sure that the provided sw_path is valid 46 | pathCheck(sw_path) 47 | 48 | if json_path is not None: 49 | # make sure that the provided JSON file exists 50 | if not os.path.isfile(json_path): 51 | error("Invalid JSON file: {}\n".format(json_path)) 52 | exit(1) 53 | self.json_path = json_path 54 | else: 55 | self.json_path = None 56 | 57 | if grpc_port is not None: 58 | self.grpc_port = grpc_port 59 | else: 60 | self.grpc_port = P4RuntimeSwitch.next_grpc_port 61 | P4RuntimeSwitch.next_grpc_port += 1 62 | 63 | if thrift_port is not None: 64 | self.thrift_port = thrift_port 65 | else: 66 | self.thrift_port = P4RuntimeSwitch.next_thrift_port 67 | P4RuntimeSwitch.next_thrift_port += 1 68 | 69 | if check_listening_on_port(self.grpc_port): 70 | error('%s cannot bind port %d because it is bound by another process\n' % (self.name, self.grpc_port)) 71 | exit(1) 72 | 73 | self.verbose = verbose 74 | logfile = "/tmp/p4s.{}.log".format(self.name) 75 | self.output = open(logfile, 'w') 76 | self.pcap_dump = pcap_dump 77 | self.enable_debugger = enable_debugger 78 | self.log_console = log_console 79 | if log_file is not None: 80 | self.log_file = log_file 81 | else: 82 | self.log_file = "/tmp/p4s.{}.log".format(self.name) 83 | if device_id is not None: 84 | self.device_id = device_id 85 | P4Switch.device_id = max(P4Switch.device_id, device_id) 86 | else: 87 | self.device_id = P4Switch.device_id 88 | P4Switch.device_id += 1 89 | self.nanomsg = "ipc:///tmp/bm-{}-log.ipc".format(self.device_id) 90 | 91 | 92 | def check_switch_started(self, pid): 93 | for _ in range(SWITCH_START_TIMEOUT * 2): 94 | if not os.path.exists(os.path.join("/proc", str(pid))): 95 | return False 96 | if check_listening_on_port(self.grpc_port): 97 | return True 98 | sleep(0.5) 99 | 100 | def start(self, controllers): 101 | info("Starting P4 switch {}.\n".format(self.name)) 102 | args = [self.sw_path] 103 | for port, intf in list(self.intfs.items()): 104 | if not intf.IP(): 105 | args.extend(['-i', str(port) + "@" + intf.name]) 106 | if self.pcap_dump: 107 | args.append("--pcap %s" % self.pcap_dump) 108 | if self.nanomsg: 109 | args.extend(['--nanolog', self.nanomsg]) 110 | args.extend(['--device-id', str(self.device_id)]) 111 | P4Switch.device_id += 1 112 | if self.json_path: 113 | args.append(self.json_path) 114 | else: 115 | args.append("--no-p4") 116 | if self.enable_debugger: 117 | args.append("--debugger") 118 | if self.log_console: 119 | args.append("--log-console") 120 | if self.thrift_port: 121 | args.append('--thrift-port ' + str(self.thrift_port)) 122 | if self.grpc_port: 123 | args.append("-- --grpc-server-addr 0.0.0.0:" + str(self.grpc_port)) 124 | cmd = ' '.join(args) 125 | info(cmd + "\n") 126 | 127 | 128 | pid = None 129 | with tempfile.NamedTemporaryFile() as f: 130 | self.cmd(cmd + ' >' + self.log_file + ' 2>&1 & echo $! >> ' + f.name) 131 | pid = int(f.read()) 132 | debug("P4 switch {} PID is {}.\n".format(self.name, pid)) 133 | if not self.check_switch_started(pid): 134 | error("P4 switch {} did not start correctly.\n".format(self.name)) 135 | exit(1) 136 | info("P4 switch {} has been started.\n".format(self.name)) 137 | 138 | --------------------------------------------------------------------------------