├── .gitignore ├── LICENSE ├── README.md ├── eval_scripts ├── __init__.py ├── eval.py └── plotting.py ├── evaluate.sh ├── exampleOutputs ├── 1000pps │ ├── iperf3.pdf │ ├── pcapBandwidth.pdf │ ├── pcapInBandwidth.pdf │ ├── pcapQueueDelay.pdf │ └── pcapTrace.pdf └── 2000pps │ ├── iperf3.pdf │ ├── pcapBandwidth.pdf │ ├── pcapInBandwidth.pdf │ ├── pcapQueueDelay.pdf │ └── pcapTrace.pdf ├── linux_run.sh ├── p4_14_run.sh ├── p4_14_simple_run.sh ├── rtt_run.sh ├── run.sh ├── simple_run.sh ├── srcP4 ├── codel.p4 ├── commandsCodelRouter.txt ├── commandsRouterSimple.txt ├── header.p4 ├── queue_measurement.p4 ├── router.p4 ├── simple_router.p4 └── tcp_checksum.p4 ├── srcP4_14 ├── codel.p4 ├── commandsCodelRouter.txt ├── commandsRouterSimple.txt ├── header.p4 ├── queue_measurement.p4 ├── router.p4 ├── simple_router.p4 └── tcp_checksum.p4 ├── srcPython ├── linuxrouter.py ├── ping.py └── toposetup.py ├── start_bmv2_CLI.sh └── targets └── tofino ├── .gitignore ├── Readme.md ├── p4_build.sh ├── pd_fixed ├── __init__.py ├── pd_fixed_api.py ├── tm.py └── ttypes.py ├── run_switchd.sh ├── set_shape_rate.py └── srcP4 ├── CoDel.p4 ├── header.p4 └── l1switchCodel.p4 /.gitignore: -------------------------------------------------------------------------------- 1 | router_compiled.json 2 | *.pcap 3 | 4 | \.idea/ 5 | *.iml 6 | 7 | *.pyc 8 | out/ 9 | 10 | *.ods# 11 | *.swp 12 | *.DS_Store 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # P4 Codel Implementation 2 | Detailed description of P4 concepts: [Paper](https://ieeexplore.ieee.org/document/8725736) 3 | 4 | Detailed description of Intel Tofino realization: [Paper](https://ieeexplore.ieee.org/abstract/document/9500943) 5 | 6 | 7 | ## Install 8 | For simple tests we recommend the use of our preinstalled VM. 9 | 10 | ### Preinstalled VM 11 | A completely set up VM for P4_16 can be downloaded here: 12 | 13 | ``` 14 | ftp://ftp.kom.tu-darmstadt.de/VMs/p4_16-codel.ova 15 | ``` 16 | *Username:* **sdn** 17 | *Password:* **vm** 18 | 19 | and a legacy VM for P4_14 (used for the creation of the Paper results): 20 | ``` 21 | ftp://ftp.kom.tu-darmstadt.de/VMs/P4-Codel.ova 22 | ``` 23 | *Username:* **codel** 24 | *Password:* **p4** 25 | 26 | The VM is testet with Virtualbox. For Linux Users we recommend the use of a Host-only network and a ssh connection to the VM with X-forwarding. 27 | ``` 28 | ssh -X codel@192.168.xxx.xxx 29 | ``` 30 | 31 | Please go to the codel folder and follow the Run-instructions of this Readme. 32 | ``` 33 | cd p4-codel 34 | ``` 35 | 36 | If you want to reproduce the results shown in the paper this virtual machine is not powerful enough. We recommend a bare-metal server with at least 6 cores for no thread interference. 37 | 38 | ### Setup 39 | 1. Install the following required tools: 40 | * [Mininet](https://github.com/mininet/mininet) - including **make install** 41 | * [P4 compiler bm](https://github.com/p4lang/p4c-bm) 42 | * [P4 behavioral model](https://github.com/p4lang/behavioral-model) 43 | 44 | 2. and in advance the following packages: 45 | ``` 46 | sudo apt-get install openvswitch-testcontroller python-tk iperf3 xterm 47 | python -mpip install matplotlib 48 | pip install scapy 49 | ``` 50 | 51 | 3. Clone the repository in the same parental folder than the 'behavioral-model'. 52 | 53 | ## Run 54 | * Run Mininet with the P4(bmv2) CoDel implementation 55 | ``` 56 | ./run.sh [--nocli, --nopcap, --iperft N] 57 | ``` 58 | Normally this script generates PCAP files for evaluation and enters the Mininet CLI mode for debugging. 59 | With the optional command line parameters, this behavior can be changed. 60 | * Run Mininet with a simple P4(bmv2) router (fixed-sized FIFO) 61 | ``` 62 | ./simple_run.sh [--nocli, --nopcap, --iperft N] 63 | ``` 64 | * Run Mininet with the Linux kernel CoDel implementation 65 | ``` 66 | ./linux_run.sh [--nocli, --nopcap, --iperft N] 67 | ``` 68 | * Run Mininet with the P4(bmv2) CoDel implementation with different RTTs 69 | ``` 70 | ./rtt_run.sh [--nocli, --nopcap, --iperft N] 71 | ``` 72 | 73 | ## Evaluate 74 | To evaluate the measured results run: 75 | ``` 76 | ./evaluate.sh [--gui] 77 | ``` 78 | With the parameter '--gui' the generated plots will be displayed in a GUI. 79 | In the folder 'exampleOutputs' you can find results for 1000 pps and 2000 pps bottleneck speed produced on a 8 core bare-metal server. 80 | 81 | ### Debug 82 | If the Mininet CLI mode is active, you can look into the running p4-appliction with: 83 | ``` 84 | ./start_bmv2_CLI.sh 85 | ``` 86 | 87 | ### P4_14 support in p4c 88 | The new p4c compiler supports P4_14 and P4_16. However, there are some issues with with p4_14 code. Therefore the scripts for P4_14 code are still using the p4c-bm compiler. If you want to use the p4c compiler with p4_14 code, please use the following command in the run scripts: 89 | ``` 90 | p4c srcP4_14/simple_router.p4 --target bmv2 --arch v1model --p4runtime-format json --std p4-14 91 | ``` 92 | and modify the json file name in the run script. 93 | -------------------------------------------------------------------------------- /eval_scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/eval_scripts/__init__.py -------------------------------------------------------------------------------- /eval_scripts/eval.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 argparse 16 | import os, sys 17 | import json 18 | from plotting import * 19 | from scapy.all import * 20 | 21 | 22 | def parse_multi_iperf3_json(folder): 23 | range = [0, 2, 5, 10, 20, 50] 24 | all_runs = {} 25 | for i in range: 26 | path = os.path.join(folder, "iperf_output"+str(i)+".json") 27 | if not os.path.isfile(path): 28 | return None 29 | parse_result = parse_iperf3_json(path) 30 | all_runs[i] = parse_result 31 | return all_runs 32 | 33 | 34 | 35 | def parse_iperf3_json(path): 36 | content = readFiletoString(path) 37 | content = json.loads(content) 38 | #now content is a dict 39 | loRawInputs = content['intervals'] 40 | resLst = [] 41 | for x in loRawInputs: 42 | innerLst = [] 43 | for y in x['streams']: 44 | innerLst.append(y) #TODO hier wird nur der erste Stream geparst 45 | resLst.append(innerLst) 46 | return resLst 47 | 48 | def parse_ping_trace(folder, dropFirstN=0): 49 | content = readFiletoString(os.path.join(folder, "ping_out.txt")) 50 | lines=content.splitlines() 51 | del lines[0] #"'PING 10.0.0.4 (10.0.0.4) 56(84) bytes of data.'" 52 | del lines[:dropFirstN] 53 | del lines[-4:] #delete last lines 54 | result = [] 55 | for line in lines: 56 | splitline = line.split(" ") 57 | ping_time = splitline[6].replace("time=", "") 58 | result.append(float(ping_time)) 59 | return result 60 | 61 | def parse_pcap_trace(folder): 62 | packets_in = rdpcap(os.path.join(folder, "r1-eth1_out.pcap")) 63 | packets_out = rdpcap(os.path.join(folder, "r1-eth2_in.pcap")) 64 | out_pointer = 0 65 | print("number ingoing packets: "+str(len(packets_in))) 66 | print("number outgoing packets: "+str(len(packets_out))) 67 | resLst = [] 68 | length = len(packets_out) 69 | dropLst = [] 70 | basePacket = packets_in[0] 71 | counterDrops = 0 72 | for packet in packets_in: 73 | if (length == out_pointer): 74 | break 75 | out_packet = packets_out[out_pointer] 76 | tcp_in = packet['TCP'] 77 | tcp_out = out_packet['TCP'] 78 | match = tcp_in.seq == tcp_out.seq 79 | if(match): 80 | out_pointer+=1 81 | resLst.append((packet, out_packet)) 82 | else: 83 | counterDrops = counterDrops + 1 84 | print("Packet dropped: " + str(packet.time - basePacket.time)) 85 | dropLst.append(packet) 86 | print("number drops: " + str(counterDrops)) 87 | print("number matched packets: "+str(len(resLst))) 88 | return packets_in, resLst 89 | 90 | def readFiletoString(file_name): 91 | file = open(file_name, "r") 92 | content = file.read() 93 | return content 94 | 95 | 96 | 97 | def evaluate(folder): 98 | if not check_for_pcap(folder): 99 | return 100 | out_folder = os.path.join(os.getcwd(), folder) 101 | #evaluate_iperf(out_folder) 102 | #pingResLst = parse_ping_trace(out_folder) 103 | 104 | pcap_in_trace, pcap_trace = parse_pcap_trace(out_folder) 105 | plotPcapTrace(pcap_trace) 106 | plotPcapInBandwidth(pcap_in_trace) 107 | plotPcapBandwidth(pcap_trace) 108 | plotPcapQueueDelay(pcap_trace) 109 | 110 | def evaluate_iperf(folder): 111 | out_folder = os.path.join(os.getcwd(), folder) 112 | iperf3_file = os.path.join(out_folder, "iperf_output.json") 113 | if not os.path.isfile(iperf3_file): 114 | return 115 | iperf3ResLst = parse_iperf3_json(iperf3_file) 116 | plotIperf3(iperf3ResLst) 117 | 118 | def evaluate_multi_iperf(folder): 119 | res = parse_multi_iperf3_json(folder) 120 | if res != None: 121 | plot_multiple_iperf3_runs(res) 122 | 123 | def check_for_pcap(folder): 124 | packets_in = os.path.join(folder, "r1-eth1_out.pcap") 125 | packets_out = os.path.join(folder, "r1-eth2_in.pcap") 126 | if not os.path.isfile(packets_in): 127 | return False 128 | if not os.path.isfile(packets_out): 129 | return False 130 | return True 131 | 132 | if __name__ == '__main__': 133 | parser = argparse.ArgumentParser(description='Processes the mininet out files and creates statistics') 134 | parser.add_argument('Path', nargs='?', default="out", help='path to out folder') 135 | parser.add_argument('--gui', help='Show plots in a GUI', 136 | type=bool, action="store") 137 | parser.set_defaults(gui=False) 138 | args = parser.parse_args() 139 | folder = args.Path 140 | 141 | evaluate_multi_iperf(folder) 142 | 143 | evaluate_iperf(folder) 144 | 145 | evaluate(folder) 146 | 147 | if args.gui: 148 | show_plots() 149 | -------------------------------------------------------------------------------- /eval_scripts/plotting.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 matplotlib 16 | import os 17 | if "DISPLAY" not in os.environ: 18 | matplotlib.use('Agg') 19 | import matplotlib.pyplot as plt 20 | from scapy.utils import hexdump 21 | from scapy.all import * 22 | 23 | import numpy as np 24 | 25 | noTitle = True 26 | legendCenter = False 27 | 28 | def plotIperf3(raw_data): 29 | 30 | plt.figure(1) 31 | fig = plt.gcf() 32 | fig.canvas.set_window_title('IPerf3') 33 | plt.subplot(211) 34 | 35 | x_values = [0] 36 | y_values = [0] 37 | for data in raw_data: 38 | x_val = data[0]['start'] 39 | y_val = 0 40 | for x in data: 41 | y_val += x['rtt']/1000.0 42 | y_val = y_val/len(data) 43 | x_values.append(x_val) 44 | y_values.append(y_val) 45 | plt.plot(x_values, y_values) 46 | plt.ylim(ymin = 0) 47 | plt.ylabel('RTT [ms]') 48 | ax = plt.gca() 49 | ax.set_xticklabels([]) 50 | 51 | plt.subplot(212) 52 | x_values = [0] 53 | y_values = [0] 54 | for data in raw_data: 55 | x_val = data[0]['start'] 56 | y_val = 0 57 | for x in data: 58 | y_val += x['bytes'] / x['seconds'] 59 | y_val = y_val/1000 60 | x_values.append(x_val) 61 | y_values.append(y_val) 62 | plt.plot(x_values, y_values) 63 | plt.ylim(ymin = 0) 64 | plt.xlabel('time [s]') 65 | plt.ylabel('Throughput [kbytes/s]') 66 | if not noTitle: 67 | plt.suptitle('iperf3 json output') 68 | fig = plt.gcf() 69 | fig.set_size_inches(6, 3, forward=True) 70 | plt.savefig('out/iperf3.pdf', bbox_inches='tight') 71 | 72 | def plot_multiple_iperf3_runs(runs): 73 | 74 | plt.figure(2) 75 | fig = plt.gcf() 76 | fig.canvas.set_window_title('Multiple Iperf Runs') 77 | x_vals = [] 78 | run_ids = [10, 20, 50] #TODO 79 | i = 0 80 | style_list = ['-', '--', ':'] 81 | for x in runs[0]: 82 | x_vals.append(x[0]['start']) #start time of first tcp flow in this time section 83 | print("print all runs in a single graph here") 84 | for run_id in run_ids: 85 | y_vals = [] 86 | for x in runs[run_id]: 87 | y_val = 0.0 88 | for y in x: 89 | y_val += y['rtt'] / 1000.0 90 | y_val = y_val / len(x) 91 | y_vals.append(y_val) 92 | rtt = run_id 93 | plt.plot(x_vals, y_vals, style_list[i], label = "link delay = "+str(rtt)+" ms") 94 | i+=1 95 | plt.ylim(ymin=0) 96 | plt.ylabel('RTT [ms]') 97 | plt.xlabel('time [s]') 98 | if legendCenter: 99 | plt.legend(shadow=True, bbox_to_anchor=[0.5, 0.6], 100 | loc='center', ncol=2) #, fontsize='x-large' 101 | else: 102 | plt.legend(shadow=True, bbox_to_anchor=[1, 0.63], 103 | loc='right', ncol=1) # , fontsize='x-large' 104 | fig = plt.gcf() 105 | fig.set_size_inches(6, 3, forward=True) 106 | plt.savefig('out/multipleIperfRuns.pdf', bbox_inches='tight') 107 | 108 | 109 | def plotPcapTrace(trace): 110 | plt.figure(3) 111 | fig = plt.gcf() 112 | fig.canvas.set_window_title('Pcap Trace') 113 | plt.subplot(211) 114 | 115 | x_values = [] 116 | y_values = [] 117 | basetime = trace[0][0].time 118 | for tuple in trace: 119 | a = tuple[0] 120 | b = tuple[1] 121 | diff = float(b.time - a.time)*1000.0 122 | x_val = (a.time - basetime) 123 | y_val = diff 124 | x_values.append(x_val) 125 | y_values.append(y_val) 126 | plt.plot(x_values, y_values) 127 | plt.ylim(ymin = 0) 128 | plt.ylabel('delay [ms]') 129 | # plt.xlabel('time [s]') 130 | ax = plt.gca() 131 | ax.set_xticklabels([]) 132 | 133 | plt.subplot(212) 134 | x_values = [] 135 | y_values = [] 136 | basetime = trace[0][0].time 137 | p = [] 138 | n = 10 139 | for i in range(0, n): 140 | p.append(trace[0][1]) 141 | i = 0.0 142 | for tuple in trace: 143 | i += 1 144 | p[n - 1] = tuple[1] 145 | if (i < n): 146 | diff = float(p[n - 1].time - p[0].time) / i # error correction for the n first entries 147 | else: 148 | diff = float(p[n - 1].time - p[0].time) / n # microseconds per packet 149 | x_val = (p[n - 1].time - basetime) 150 | if diff == 0: 151 | y_val = 0 152 | else: 153 | y_val = 1 / diff 154 | x_values.append(x_val) 155 | y_values.append(y_val) 156 | for j in range(0, n - 1): 157 | p[j] = p[j + 1] 158 | plt.plot(x_values, y_values) 159 | plt.ylim(ymin = 0) 160 | plt.ylabel('rate [pps]') 161 | plt.xlabel('time [s]') 162 | if not noTitle: 163 | plt.suptitle('bmv2 pcap analysis') 164 | fig = plt.gcf() 165 | fig.set_size_inches(6, 3, forward=True) 166 | plt.savefig('out/pcapTrace.pdf', bbox_inches='tight') 167 | 168 | def plotPcapBandwidth(trace): 169 | plt.figure(4) 170 | fig = plt.gcf() 171 | fig.canvas.set_window_title('Pcap Out Bandwidth') 172 | x_values = [] 173 | y_values = [] 174 | basetime = trace[0][0].time 175 | p = [] 176 | n = 50 177 | for i in range(0, n): 178 | p.append(trace[0][1]) 179 | i = 0 180 | for tuple in trace: 181 | i+=1 182 | p[n-1] = tuple[1] 183 | if(i < n): 184 | diff = (p[n - 1].time - p[0].time) / i #error correction for the n first entries 185 | else: 186 | diff = (p[n-1].time - p[0].time)/n # microseconds per packet 187 | x_val = (p[n-1].time - basetime) 188 | if diff == 0: 189 | y_val = 0 190 | else: 191 | y_val = 1/diff 192 | x_values.append(x_val) 193 | y_values.append(y_val) 194 | for j in range(0, n-1): 195 | p[j] = p[j+1] 196 | plt.plot(x_values, y_values) 197 | plt.ylabel('rate [pps]') 198 | plt.xlabel('time [s]') 199 | if not noTitle: 200 | plt.title('pcap outgoing bandwidth') 201 | fig = plt.gcf() 202 | fig.set_size_inches(6, 3, forward=True) 203 | plt.savefig('out/pcapBandwidth.pdf', bbox_inches='tight') 204 | 205 | def plotPcapInBandwidth(in_trace): 206 | plt.figure(5) 207 | fig = plt.gcf() 208 | fig.canvas.set_window_title('Pcap In Bandwidth') 209 | x_values = [] 210 | y_values = [] 211 | basetime = in_trace[0].time 212 | p = [] 213 | n = 50 214 | for i in range(0, n): 215 | p.append(in_trace[0]) 216 | i = 0 217 | for p_in in in_trace: 218 | i+=1 219 | p[n-1] = p_in 220 | if(i < n): 221 | diff = (p[n - 1].time - p[0].time) / i #error correction for the n first entries 222 | else: 223 | diff = (p[n-1].time - p[0].time)/n # microseconds per packet 224 | x_val = (p[n-1].time - basetime) 225 | if diff == 0: 226 | y_val = 0 227 | else: 228 | y_val = 1/diff 229 | x_values.append(x_val) 230 | y_values.append(y_val) 231 | for j in range(0, n-1): 232 | p[j] = p[j+1] 233 | plt.plot(x_values, y_values) 234 | plt.ylabel('rate [pps]') 235 | plt.xlabel('time [s]') 236 | if not noTitle: 237 | plt.title('pcap ingoing bandwidth') 238 | fig = plt.gcf() 239 | fig.set_size_inches(6, 3, forward=True) 240 | plt.savefig('out/pcapInBandwidth.pdf', bbox_inches='tight') 241 | 242 | def plotPcapQueueDelay(trace): 243 | plt.figure(6) 244 | fig = plt.gcf() 245 | fig.canvas.set_window_title('Pcap Queue Delay') 246 | x_values = [] 247 | y_values = [] 248 | basetime = trace[0][0].time 249 | for tuple in trace: 250 | packet = tuple[1] ##only egress is interesting for us 251 | x_val = float(packet.time-basetime) 252 | if packet['IP'].len < 500: 253 | continue 254 | tcp = packet['TCP'] 255 | payload = tcp.payload 256 | data = raw(payload) 257 | a = orb(data[0]) 258 | b = orb(data[1]) 259 | c = orb(data[2]) 260 | d = orb(data[3]) 261 | delay = (a << 24) + (b << 16) + (c << 8) + d 262 | y_val = delay/1000.0 263 | x_values.append(x_val) 264 | y_values.append(y_val) 265 | 266 | plt.plot(x_values, y_values) 267 | plt.plot([0, x_values[len(x_values) - 1] + 0.2], [5, 5], '--', color='C5') 268 | plt.ylabel('queue delay [ms]') 269 | plt.xlabel('time [s]') 270 | if not noTitle: 271 | plt.title('p4 queue delay') 272 | fig = plt.gcf() 273 | fig.set_size_inches(6, 3, forward=True) 274 | plt.savefig('out/pcapQueueDelay.pdf', bbox_inches='tight') 275 | 276 | def show_plots(): 277 | plt.show() 278 | -------------------------------------------------------------------------------- /evaluate.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | argsCommand="" 16 | 17 | if [ "$1" = "--gui" ]; then 18 | argsCommand=$1" True" 19 | fi 20 | sudo python eval_scripts/eval.py out/ $argsCommand 21 | -------------------------------------------------------------------------------- /exampleOutputs/1000pps/iperf3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/1000pps/iperf3.pdf -------------------------------------------------------------------------------- /exampleOutputs/1000pps/pcapBandwidth.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/1000pps/pcapBandwidth.pdf -------------------------------------------------------------------------------- /exampleOutputs/1000pps/pcapInBandwidth.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/1000pps/pcapInBandwidth.pdf -------------------------------------------------------------------------------- /exampleOutputs/1000pps/pcapQueueDelay.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/1000pps/pcapQueueDelay.pdf -------------------------------------------------------------------------------- /exampleOutputs/1000pps/pcapTrace.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/1000pps/pcapTrace.pdf -------------------------------------------------------------------------------- /exampleOutputs/2000pps/iperf3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/2000pps/iperf3.pdf -------------------------------------------------------------------------------- /exampleOutputs/2000pps/pcapBandwidth.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/2000pps/pcapBandwidth.pdf -------------------------------------------------------------------------------- /exampleOutputs/2000pps/pcapInBandwidth.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/2000pps/pcapInBandwidth.pdf -------------------------------------------------------------------------------- /exampleOutputs/2000pps/pcapQueueDelay.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/2000pps/pcapQueueDelay.pdf -------------------------------------------------------------------------------- /exampleOutputs/2000pps/pcapTrace.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/exampleOutputs/2000pps/pcapTrace.pdf -------------------------------------------------------------------------------- /linux_run.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | argsCommand="" 16 | 17 | if [ "$1" = "--nopcap" ] || [ "$1" = "--nocli" ]; then 18 | argsCommand=$1" True" 19 | fi 20 | 21 | if [ "$1" = "--iperft" ]; then 22 | argsCommand="--iperft "$2 23 | fi 24 | 25 | if [ "$2" = "--nopcap" ] || [ "$2" = "--nocli" ]; then 26 | argsCommand=$argsCommand" "$2" True" 27 | fi 28 | 29 | if [ "$2" = "--iperft" ]; then 30 | argsCommand=$argsCommand" --iperft "$3 31 | fi 32 | 33 | if [ "$3" = "--nopcap" ] || [ "$3" = "--nocli" ]; then 34 | argsCommand=$argsCommand" "$3" True" 35 | fi 36 | 37 | if [ "$3" = "--iperft" ]; then 38 | argsCommand=$argsCommand" --iperft "$4 39 | fi 40 | 41 | if [ "$4" = "--nopcap" ] || [ "$4" = "--nocli" ]; then 42 | argsCommand=$argsCommand" "$4" True" 43 | fi 44 | 45 | #delete old pcap files 46 | sudo rm out/*.pcap 47 | sudo killall ovs-testcontroller 48 | sudo mn -c 49 | #start mininet environment 50 | sudo PYTHONPATH=$PYTHONPATH:../p4-behavioral-model/mininet/ \ 51 | python srcPython/toposetup.py \ 52 | --json ./DOESNOTEXIST.json \ 53 | --cli DOESNOTEXIST \ 54 | --cliCmd DOESNOTEXIST.txt \ 55 | $argsCommand 56 | -------------------------------------------------------------------------------- /p4_14_run.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | argsCommand="" 16 | 17 | if [ "$1" = "--nopcap" ] || [ "$1" = "--nocli" ]; then 18 | argsCommand=$1" True" 19 | fi 20 | 21 | if [ "$1" = "--iperft" ]; then 22 | argsCommand="--iperft "$2 23 | fi 24 | 25 | if [ "$2" = "--nopcap" ] || [ "$2" = "--nocli" ]; then 26 | argsCommand=$argsCommand" "$2" True" 27 | fi 28 | 29 | if [ "$2" = "--iperft" ]; then 30 | argsCommand=$argsCommand" --iperft "$3 31 | fi 32 | 33 | if [ "$3" = "--nopcap" ] || [ "$3" = "--nocli" ]; then 34 | argsCommand=$argsCommand" "$3" True" 35 | fi 36 | 37 | if [ "$3" = "--iperft" ]; then 38 | argsCommand=$argsCommand" --iperft "$4 39 | fi 40 | 41 | if [ "$4" = "--nopcap" ] || [ "$4" = "--nocli" ]; then 42 | argsCommand=$argsCommand" "$4" True" 43 | fi 44 | 45 | 46 | #compile p4 file 47 | [ -e router_compiled.json ] && sudo rm -f router_compiled.json 48 | p4c-bmv2 srcP4_14/router.p4 --json router_compiled.json 49 | 50 | #delete old pcap files 51 | sudo rm out/*.pcap 52 | 53 | sudo killall ovs-testcontroller 54 | sudo mn -c 55 | #start mininet environment 56 | sudo PYTHONPATH=$PYTHONPATH:../behavioral-model/mininet/ \ 57 | python srcPython/toposetup.py \ 58 | --swpath ../behavioral-model/targets/simple_switch/simple_switch \ 59 | --json ./router_compiled.json -p4 \ 60 | --cli simple_switch_CLI \ 61 | --cliCmd srcP4_14/commandsCodelRouter.txt \ 62 | $argsCommand 63 | -------------------------------------------------------------------------------- /p4_14_simple_run.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | argsCommand="" 16 | 17 | if [ "$1" = "--nopcap" ] || [ "$1" = "--nocli" ]; then 18 | argsCommand=$1" True" 19 | fi 20 | 21 | if [ "$1" = "--iperft" ]; then 22 | argsCommand="--iperft "$2 23 | fi 24 | 25 | if [ "$2" = "--nopcap" ] || [ "$2" = "--nocli" ]; then 26 | argsCommand=$argsCommand" "$2" True" 27 | fi 28 | 29 | if [ "$2" = "--iperft" ]; then 30 | argsCommand=$argsCommand" --iperft "$3 31 | fi 32 | 33 | if [ "$3" = "--nopcap" ] || [ "$3" = "--nocli" ]; then 34 | argsCommand=$argsCommand" "$3" True" 35 | fi 36 | 37 | if [ "$3" = "--iperft" ]; then 38 | argsCommand=$argsCommand" --iperft "$4 39 | fi 40 | 41 | if [ "$4" = "--nopcap" ] || [ "$4" = "--nocli" ]; then 42 | argsCommand=$argsCommand" "$4" True" 43 | fi 44 | 45 | 46 | #compile p4 file 47 | [ -e router_compiled.json ] && rm router_compiled.json 48 | p4c-bmv2 srcP4_14/simple_router.p4 --json router_compiled.json 49 | 50 | sudo killall ovs-testcontroller 51 | sudo mn -c 52 | #start mininet environment 53 | sudo PYTHONPATH=$PYTHONPATH:../behavioral-model/mininet/ \ 54 | python srcPython/toposetup.py \ 55 | --swpath ../behavioral-model/targets/simple_switch/simple_switch \ 56 | -p4 \ 57 | --json ./router_compiled.json \ 58 | --cli simple_switch_CLI \ 59 | --cliCmd srcP4_14/commandsRouterSimple.txt \ 60 | $argsCommand 61 | -------------------------------------------------------------------------------- /rtt_run.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | argsCommand="" 16 | 17 | if [ "$1" = "--nopcap" ]; then 18 | argsCommand=$1" True" 19 | fi 20 | 21 | if [ "$1" = "--iperft" ]; then 22 | argsCommand="--iperft "$2 23 | fi 24 | 25 | if [ "$2" = "--nopcap" ]; then 26 | argsCommand=$argsCommand" "$2" True" 27 | fi 28 | 29 | if [ "$2" = "--iperft" ]; then 30 | argsCommand=$argsCommand" --iperft "$3 31 | fi 32 | 33 | if [ "$3" = "--nopcap" ]; then 34 | argsCommand=$argsCommand" "$3" True" 35 | fi 36 | 37 | argsCommand=$argsCommand" --nocli True" 38 | 39 | 40 | #compile p4 file 41 | [ -e router_compiled.json ] && sudo rm -f router_compiled.json 42 | p4c-bm2-ss srcP4/router.p4 --std p4-16 -o router_compiled.json 43 | 44 | # Delays 0, 2, 5, 10, 20, 50 45 | arr=("0" "2" "5" "10" "20" "50") 46 | 47 | for i in "${arr[@]}" 48 | do 49 | echo "Run: $i" 50 | #delete old pcap files 51 | sudo rm out/*.pcap 52 | 53 | sudo killall ovs-testcontroller 54 | sudo mn -c 55 | #start mininet environment 56 | sudo PYTHONPATH=$PYTHONPATH:../p4-behavioral-model-performance/mininet/ \ 57 | python srcPython/toposetup.py \ 58 | --swpath ../p4-behavioral-model-performance/targets/simple_switch/simple_switch \ 59 | --json ./router_compiled.json -p4 \ 60 | --cli ../p4-behavioral-model-performance/targets/simple_switch/sswitch_CLI \ 61 | --cliCmd srcP4/commandsCodelRouter.txt \ 62 | $argsCommand \ 63 | --h3delay $i"ms" 64 | filename="iperf_output"$i".json" 65 | sudo mv out/iperf_output.json out/$filename 66 | done 67 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | argsCommand="" 16 | 17 | if [ "$1" = "--nopcap" ] || [ "$1" = "--nocli" ]; then 18 | argsCommand=$1" True" 19 | fi 20 | 21 | if [ "$1" = "--iperft" ]; then 22 | argsCommand="--iperft "$2 23 | fi 24 | 25 | if [ "$2" = "--nopcap" ] || [ "$2" = "--nocli" ]; then 26 | argsCommand=$argsCommand" "$2" True" 27 | fi 28 | 29 | if [ "$2" = "--iperft" ]; then 30 | argsCommand=$argsCommand" --iperft "$3 31 | fi 32 | 33 | if [ "$3" = "--nopcap" ] || [ "$3" = "--nocli" ]; then 34 | argsCommand=$argsCommand" "$3" True" 35 | fi 36 | 37 | if [ "$3" = "--iperft" ]; then 38 | argsCommand=$argsCommand" --iperft "$4 39 | fi 40 | 41 | if [ "$4" = "--nopcap" ] || [ "$4" = "--nocli" ]; then 42 | argsCommand=$argsCommand" "$4" True" 43 | fi 44 | 45 | 46 | #compile p4 file 47 | [ -e router_compiled.json ] && sudo rm -f router_compiled.json 48 | p4c-bm2-ss srcP4/router.p4 --std p4-16 -o router_compiled.json 49 | 50 | sudo killall ovs-testcontroller 51 | sudo mn -c 52 | #start mininet environment 53 | sudo PYTHONPATH=$PYTHONPATH:../p4-behavioral-model-performance/mininet/ \ 54 | python srcPython/toposetup.py \ 55 | --swpath ../p4-behavioral-model-performance/targets/simple_switch/simple_switch \ 56 | -p4 \ 57 | --json ./router_compiled.json \ 58 | --cli ../p4-behavioral-model-performance/targets/simple_switch/sswitch_CLI \ 59 | --cliCmd srcP4/commandsCodelRouter.txt \ 60 | $argsCommand 61 | -------------------------------------------------------------------------------- /simple_run.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | argsCommand="" 16 | 17 | if [ "$1" = "--nopcap" ] || [ "$1" = "--nocli" ]; then 18 | argsCommand=$1" True" 19 | fi 20 | 21 | if [ "$1" = "--iperft" ]; then 22 | argsCommand="--iperft "$2 23 | fi 24 | 25 | if [ "$2" = "--nopcap" ] || [ "$2" = "--nocli" ]; then 26 | argsCommand=$argsCommand" "$2" True" 27 | fi 28 | 29 | if [ "$2" = "--iperft" ]; then 30 | argsCommand=$argsCommand" --iperft "$3 31 | fi 32 | 33 | if [ "$3" = "--nopcap" ] || [ "$3" = "--nocli" ]; then 34 | argsCommand=$argsCommand" "$3" True" 35 | fi 36 | 37 | if [ "$3" = "--iperft" ]; then 38 | argsCommand=$argsCommand" --iperft "$4 39 | fi 40 | 41 | if [ "$4" = "--nopcap" ] || [ "$4" = "--nocli" ]; then 42 | argsCommand=$argsCommand" "$4" True" 43 | fi 44 | 45 | 46 | #compile p4 file 47 | [ -e router_compiled.json ] && sudo rm -f router_compiled.json 48 | p4c-bm2-ss srcP4/simple_router.p4 --std p4-16 -o router_compiled.json 49 | 50 | sudo killall ovs-testcontroller 51 | sudo mn -c 52 | #start mininet environment 53 | sudo PYTHONPATH=$PYTHONPATH:../p4-behavioral-model/mininet/ \ 54 | python srcPython/toposetup.py \ 55 | --swpath ../p4-behavioral-model/targets/simple_switch/simple_switch \ 56 | -p4 \ 57 | --json ./router_compiled.json \ 58 | --cli ../p4-behavioral-model/targets/simple_switch/sswitch_CLI \ 59 | --cliCmd srcP4/commandsRouterSimple.txt \ 60 | $argsCommand 61 | -------------------------------------------------------------------------------- /srcP4/codel.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Nikolas Eller 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 | #define SOJOURN_TARGET 5000 //in usec - 5ms 18 | #define CONTROL_INTERVAL 48w100000 //in usec - 100 ms - Changes must be done here AND in commandsCodelRouter.txt 19 | #define INTERFACE_MTU 1500 20 | #define NO_QUEUE_ID 32w64 21 | 22 | register>(NO_QUEUE_ID) r_drop_count; 23 | register>(NO_QUEUE_ID) r_drop_time; 24 | register>(NO_QUEUE_ID) r_last_drop_count; 25 | register>(NO_QUEUE_ID) r_next_drop; 26 | register>(NO_QUEUE_ID) r_state_dropping; 27 | 28 | control c_codel(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 29 | 30 | action a_codel_control_law(bit<48> value) { 31 | meta.codel.drop_next = meta.codel.time_now + value; 32 | r_next_drop.write((bit<32>)meta.codel.queue_id, (bit<48>)meta.codel.drop_next); 33 | } 34 | 35 | action a_codel_init() { 36 | meta.codel.ok_to_drop = 1w0; 37 | meta.codel.time_now = (bit<48>)standard_metadata.enq_timestamp + (bit<48>)standard_metadata.deq_timedelta; 38 | meta.codel.new_drop_time = meta.codel.time_now + CONTROL_INTERVAL; 39 | r_state_dropping.read(meta.codel.state_dropping, (bit<32>)meta.codel.queue_id); 40 | r_drop_count.read(meta.codel.drop_cnt, (bit<32>)meta.codel.queue_id); 41 | r_last_drop_count.read(meta.codel.last_drop_cnt, (bit<32>)meta.codel.queue_id); 42 | r_next_drop.read(meta.codel.drop_next, (bit<32>)meta.codel.queue_id); 43 | r_drop_time.read(meta.codel.drop_time, (bit<32>)meta.codel.queue_id); 44 | } 45 | 46 | action a_go_to_drop_state() { 47 | mark_to_drop(standard_metadata); 48 | r_state_dropping.write((bit<32>)meta.codel.queue_id, (bit<1>)1); 49 | meta.codel.delta = meta.codel.drop_cnt - meta.codel.last_drop_cnt; 50 | meta.codel.time_since_last_dropping = meta.codel.time_now - meta.codel.drop_next; 51 | meta.codel.drop_cnt = 32w1; 52 | r_drop_count.write((bit<32>)meta.codel.queue_id, (bit<32>)1); 53 | } 54 | 55 | table t_codel_control_law { 56 | actions = { 57 | a_codel_control_law; 58 | } 59 | key = { 60 | meta.codel.drop_cnt: lpm; 61 | } 62 | size = 32; 63 | } 64 | 65 | apply { 66 | a_codel_init(); 67 | if (standard_metadata.deq_timedelta < SOJOURN_TARGET ) { //|| standard_metadata.deq_qdepth < 19w1 68 | meta.codel.reset_drop_time = 1w1; 69 | } 70 | 71 | if (meta.codel.reset_drop_time == 1w1) { 72 | r_drop_time.write((bit<32>)meta.codel.queue_id, (bit<48>)0); 73 | meta.codel.drop_time = 48w0; 74 | } 75 | else { 76 | if (meta.codel.drop_time == 48w0) { 77 | r_drop_time.write((bit<32>)meta.codel.queue_id, (bit<48>)meta.codel.new_drop_time); 78 | meta.codel.drop_time = meta.codel.new_drop_time; 79 | } 80 | else { //if (meta.codel.drop_time > 48w0) 81 | if (meta.codel.time_now >= meta.codel.drop_time) { 82 | meta.codel.ok_to_drop = 1w1; 83 | } 84 | } 85 | } 86 | 87 | if (meta.codel.state_dropping == 1w1) { 88 | if (meta.codel.ok_to_drop == 1w0) { 89 | r_state_dropping.write((bit<32>)meta.codel.queue_id, (bit<1>)0); //leave drop state 90 | } 91 | else { 92 | if (meta.codel.time_now >= meta.codel.drop_next) { 93 | mark_to_drop(standard_metadata); 94 | meta.codel.drop_cnt = meta.codel.drop_cnt + 32w1; 95 | r_drop_count.write((bit<32>)meta.codel.queue_id, (bit<32>)meta.codel.drop_cnt); 96 | t_codel_control_law.apply(); 97 | } 98 | } 99 | } 100 | else { 101 | if (meta.codel.ok_to_drop == 1w1) { 102 | a_go_to_drop_state(); 103 | if (meta.codel.delta > 32w1 && meta.codel.time_since_last_dropping < CONTROL_INTERVAL*16) { 104 | r_drop_count.write((bit<32>)meta.codel.queue_id, (bit<32>)meta.codel.delta); 105 | meta.codel.drop_cnt = meta.codel.delta; 106 | } 107 | r_last_drop_count.write((bit<32>)meta.codel.queue_id, (bit<32>)meta.codel.drop_cnt); 108 | t_codel_control_law.apply(); 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /srcP4/commandsCodelRouter.txt: -------------------------------------------------------------------------------- 1 | port_add r1-eth1 1 2 | port_add r1-eth2 2 3 | table_add forwarding forward 1 10.0.3.1 => 2 00:00:00:00:02:01 4 | table_add forwarding forward 1 10.0.3.2 => 2 00:00:00:00:02:02 5 | table_add forwarding forward 2 10.0.1.1 => 1 00:00:00:00:01:01 6 | table_add forwarding forward 2 10.0.1.2 => 1 00:00:00:00:01:02 7 | set_queue_rate 300 2 //in pps 8 | set_queue_depth 10000 2 //in nb_pkts 9 | table_set_default t_codel_control_law a_codel_control_law 552 10 | table_add t_codel_control_law a_codel_control_law 0/17 => 781 11 | table_add t_codel_control_law a_codel_control_law 0/18 => 1104 12 | table_add t_codel_control_law a_codel_control_law 0/19 => 1562 13 | table_add t_codel_control_law a_codel_control_law 0/20 => 2209 14 | table_add t_codel_control_law a_codel_control_law 0/21 => 3125 15 | table_add t_codel_control_law a_codel_control_law 0/22 => 4419 16 | table_add t_codel_control_law a_codel_control_law 0/23 => 6250 17 | table_add t_codel_control_law a_codel_control_law 0/24 => 8838 18 | table_add t_codel_control_law a_codel_control_law 0/25 => 12500 19 | table_add t_codel_control_law a_codel_control_law 0/26 => 17677 20 | table_add t_codel_control_law a_codel_control_law 0/27 => 25000 21 | table_add t_codel_control_law a_codel_control_law 0/28 => 35355 22 | table_add t_codel_control_law a_codel_control_law 0/29 => 50000 23 | table_add t_codel_control_law a_codel_control_law 0/30 => 70710 24 | table_add t_codel_control_law a_codel_control_law 0/31 => 100000 25 | table_add t_codel_control_law a_codel_control_law 0/32 => 100000 26 | -------------------------------------------------------------------------------- /srcP4/commandsRouterSimple.txt: -------------------------------------------------------------------------------- 1 | port_add r1-eth1 1 2 | port_add r1-eth2 2 3 | 4 | table_add ingress.forwarding ingress.forward 1 10.0.3.1 => 2 00:00:00:00:02:01 5 | table_add ingress.forwarding ingress.forward 1 10.0.3.2 => 2 00:00:00:00:02:02 6 | table_add ingress.forwarding ingress.forward 2 10.0.1.1 => 1 00:00:00:00:01:01 7 | table_add ingress.forwarding ingress.forward 2 10.0.1.2 => 1 00:00:00:00:01:02 8 | 9 | 10 | set_queue_rate 1000 2 //in pps 11 | set_queue_depth 10000 2 //in nb_pkts 12 | 13 | -------------------------------------------------------------------------------- /srcP4/header.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Nikolas Eller 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 | struct routing_metadata_t { 18 | bit<16> tcpLength; 19 | } 20 | 21 | struct codel_t { 22 | bit<48> drop_time; 23 | bit<48> time_now; 24 | bit<1> ok_to_drop; 25 | bit<1> state_dropping; 26 | bit<32> delta; 27 | bit<48> time_since_last_dropping; 28 | bit<48> drop_next; 29 | bit<32> drop_cnt; 30 | bit<32> last_drop_cnt; 31 | bit<1> reset_drop_time; 32 | bit<48> new_drop_time; 33 | bit<48> new_drop_time_helper; 34 | bit<9> queue_id; 35 | } 36 | 37 | header ethernet_t { 38 | bit<48> dst_addr; 39 | bit<48> src_addr; 40 | bit<16> ethertype; 41 | } 42 | 43 | header ipv4_t { 44 | bit<4> version; 45 | bit<4> ihl; 46 | bit<8> diffserv; 47 | bit<16> totalLen; 48 | bit<16> identification; 49 | bit<3> flags; 50 | bit<13> fragOffset; 51 | bit<8> ttl; 52 | bit<8> protocol; 53 | bit<16> hdrChecksum; 54 | bit<32> srcAddr; 55 | bit<32> dstAddr; 56 | } 57 | 58 | header udp_t { 59 | bit<16> sourcePort; 60 | bit<16> destPort; 61 | bit<16> length_; 62 | bit<16> checksum; 63 | } 64 | 65 | header tcp_t { 66 | bit<16> srcPort; 67 | bit<16> dstPort; 68 | bit<32> seqNo; 69 | bit<32> ackNo; 70 | bit<4> dataOffset; 71 | bit<4> res; 72 | bit<8> flags; 73 | bit<16> window; 74 | bit<16> checksum; 75 | bit<16> urgentPtr; 76 | } 77 | 78 | header tcp_opt_t { 79 | bit<32> a; 80 | bit<32> b; 81 | bit<32> c; 82 | } 83 | 84 | header queue_delay_t { 85 | bit<32> delay; 86 | } 87 | 88 | struct headers { 89 | ethernet_t ethernet; 90 | ipv4_t ipv4; 91 | queue_delay_t queue_delay; 92 | tcp_t tcp; 93 | tcp_opt_t tcp_options; 94 | udp_t udp; 95 | } 96 | 97 | struct metadata { 98 | codel_t codel; 99 | routing_metadata_t routing_metadata; 100 | } 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /srcP4/queue_measurement.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Nikolas Eller 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 | control c_add_queue_delay(inout headers hdr, inout standard_metadata_t standard_metadata) { 18 | apply { 19 | if (hdr.ipv4.totalLen > 16w500) { 20 | if (hdr.queue_delay.isValid()) { 21 | hdr.queue_delay.delay = standard_metadata.deq_timedelta; 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /srcP4/router.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Nikolas Eller 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 | #include 18 | #include 19 | 20 | #define add_queue_delay //uncomment this line, if the queue delays should be stored in the TCP packets 21 | 22 | #include "header.p4" 23 | #include "codel.p4" 24 | 25 | #ifdef add_queue_delay 26 | #include "queue_measurement.p4" 27 | #include "tcp_checksum.p4" 28 | #endif 29 | 30 | parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 31 | state parse_ipv4 { 32 | packet.extract(hdr.ipv4); 33 | meta.routing_metadata.tcpLength = hdr.ipv4.totalLen; 34 | transition select(hdr.ipv4.protocol) { 35 | 8w17: parse_udp; 36 | 8w6: parse_tcp; 37 | default: accept; 38 | } 39 | } 40 | state parse_payload { 41 | packet.extract(hdr.tcp_options); 42 | #ifdef add_queue_delay 43 | packet.extract(hdr.queue_delay); 44 | #endif 45 | transition accept; 46 | } 47 | state parse_tcp { 48 | packet.extract(hdr.tcp); 49 | #ifdef add_queue_delay 50 | transition select(hdr.tcp.dataOffset) { 51 | 4w0x8: parse_payload; 52 | default: accept; 53 | } 54 | #else 55 | transition accept; 56 | #endif 57 | } 58 | state parse_udp { 59 | packet.extract(hdr.udp); 60 | /*transition select(hdr.udp.destPort) { 61 | default: accept; 62 | }*/ 63 | transition accept; 64 | } 65 | state start { 66 | packet.extract(hdr.ethernet); 67 | transition select(hdr.ethernet.ethertype) { 68 | 16w0x800: parse_ipv4; 69 | default: accept; 70 | } 71 | } 72 | } 73 | 74 | control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 75 | c_checksum() c_checksum_0; 76 | c_codel() c_codel_0; 77 | c_add_queue_delay() c_add_queue_delay_0; 78 | apply { 79 | if (standard_metadata.ingress_port == 9w1) { 80 | meta.codel.queue_id = standard_metadata.egress_port; 81 | c_codel_0.apply(hdr, meta, standard_metadata); 82 | } 83 | #ifdef add_queue_delay 84 | c_add_queue_delay_0.apply(hdr, standard_metadata); 85 | c_checksum_0.apply(hdr, meta); 86 | #endif 87 | } 88 | } 89 | 90 | control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 91 | action forward(bit<9> egress_spec, bit<48> dst_mac) { 92 | standard_metadata.egress_spec = egress_spec; 93 | hdr.ethernet.dst_addr = dst_mac; 94 | } 95 | table forwarding { 96 | actions = { 97 | forward; 98 | } 99 | key = { 100 | standard_metadata.ingress_port: exact; 101 | hdr.ipv4.dstAddr : exact; 102 | } 103 | } 104 | apply { 105 | forwarding.apply(); 106 | } 107 | } 108 | 109 | control DeparserImpl(packet_out packet, in headers hdr) { 110 | apply { 111 | packet.emit(hdr.ethernet); 112 | packet.emit(hdr.ipv4); 113 | packet.emit(hdr.tcp); 114 | packet.emit(hdr.tcp_options); 115 | packet.emit(hdr.queue_delay); 116 | packet.emit(hdr.udp); 117 | } 118 | } 119 | 120 | V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; 121 | 122 | -------------------------------------------------------------------------------- /srcP4/simple_router.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Nikolas Eller 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 | #include 18 | #include 19 | 20 | #define add_queue_delay 21 | 22 | #include "header.p4" 23 | 24 | #ifdef add_queue_delay 25 | #include "queue_measurement.p4" 26 | #include "tcp_checksum.p4" 27 | #endif 28 | 29 | parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 30 | state parse_ipv4 { 31 | packet.extract(hdr.ipv4); 32 | meta.routing_metadata.tcpLength = hdr.ipv4.totalLen; 33 | transition select(hdr.ipv4.protocol) { 34 | 8w17: parse_udp; 35 | 8w6: parse_tcp; 36 | default: accept; 37 | } 38 | } 39 | state parse_payload { 40 | packet.extract(hdr.tcp_options); 41 | #ifdef add_queue_delay 42 | packet.extract(hdr.queue_delay); 43 | #endif 44 | transition accept; 45 | } 46 | state parse_tcp { 47 | packet.extract(hdr.tcp); 48 | #ifdef add_queue_delay 49 | transition select(hdr.tcp.dataOffset) { 50 | 4w0x8: parse_payload; 51 | default: accept; 52 | } 53 | #else 54 | transition accept; 55 | #endif 56 | } 57 | state parse_udp { 58 | packet.extract(hdr.udp); 59 | transition select(hdr.udp.destPort) { 60 | default: accept; 61 | } 62 | } 63 | state start { 64 | packet.extract(hdr.ethernet); 65 | transition select(hdr.ethernet.ethertype) { 66 | 16w0x800: parse_ipv4; 67 | default: accept; 68 | } 69 | } 70 | } 71 | 72 | control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 73 | c_checksum() c_checksum_0; 74 | c_add_queue_delay() c_add_queue_delay_0; 75 | apply { 76 | #ifdef add_queue_delay 77 | c_add_queue_delay_0.apply(hdr, standard_metadata); 78 | c_checksum_0.apply(hdr, meta); 79 | #endif 80 | } 81 | } 82 | 83 | control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 84 | action forward(bit<9> egress_spec, bit<48> dst_mac) { 85 | standard_metadata.egress_spec = egress_spec; 86 | hdr.ethernet.dst_addr = dst_mac; 87 | } 88 | table forwarding { 89 | actions = { 90 | forward; 91 | } 92 | key = { 93 | standard_metadata.ingress_port: exact; 94 | hdr.ipv4.dstAddr : exact; 95 | } 96 | } 97 | apply { 98 | forwarding.apply(); 99 | } 100 | } 101 | 102 | control DeparserImpl(packet_out packet, in headers hdr) { 103 | apply { 104 | packet.emit(hdr.ethernet); 105 | packet.emit(hdr.ipv4); 106 | packet.emit(hdr.tcp); 107 | packet.emit(hdr.tcp_options); 108 | packet.emit(hdr.queue_delay); 109 | packet.emit(hdr.udp); 110 | } 111 | } 112 | 113 | V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; 114 | 115 | -------------------------------------------------------------------------------- /srcP4/tcp_checksum.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Nikolas Eller 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 | control verifyChecksum(inout headers hdr, inout metadata meta) { 18 | apply { 19 | } 20 | } 21 | 22 | control computeChecksum(inout headers hdr, inout metadata meta) { 23 | apply { 24 | update_checksum(true, { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffserv, 25 | hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, 26 | hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }, 27 | hdr.ipv4.hdrChecksum, HashAlgorithm.csum16); 28 | update_checksum_with_payload(hdr.tcp.isValid(), { hdr.ipv4.srcAddr, hdr.ipv4.dstAddr, 29 | 8w0, hdr.ipv4.protocol, meta.routing_metadata.tcpLength, hdr.tcp.srcPort, hdr.tcp.dstPort, 30 | hdr.tcp.seqNo, hdr.tcp.ackNo, hdr.tcp.dataOffset, hdr.tcp.res, hdr.tcp.flags, hdr.tcp.window, 31 | hdr.tcp.urgentPtr, hdr.tcp_options, hdr.queue_delay }, hdr.tcp.checksum, HashAlgorithm.csum16); 32 | } 33 | } 34 | 35 | control c_checksum(inout headers hdr, inout metadata meta) { 36 | apply { 37 | meta.routing_metadata.tcpLength = meta.routing_metadata.tcpLength - 16w20; 38 | } 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /srcP4_14/codel.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Jeremias Blendin 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 | #define SOJOURN_TARGET 5000 //in usec - 5ms 18 | #define CONTROL_INTERVAL 100000 //in usec - 100 ms - Changes must be done here AND in commandsCodelRouter.txt 19 | #define INTERFACE_MTU 1500 20 | 21 | header_type codel_t { 22 | fields { 23 | drop_time: 48; 24 | time_now : 48; 25 | ok_to_drop: 1; 26 | state_dropping: 1; 27 | delta: 32; 28 | time_since_last_dropping: 48; 29 | 30 | drop_next : 48; 31 | drop_cnt : 32; 32 | last_drop_cnt: 32; 33 | 34 | reset_drop_time : 1; 35 | new_drop_time : 48; 36 | 37 | // Control law variables 38 | new_drop_time_helper: 48; 39 | } 40 | } 41 | 42 | metadata codel_t codel; 43 | 44 | action a_codel_init() { 45 | //for debugging 46 | modify_field(codel.ok_to_drop, 0); 47 | add(codel.time_now, queueing_metadata.enq_timestamp, queueing_metadata.deq_timedelta); 48 | add(codel.new_drop_time, codel.time_now, CONTROL_INTERVAL); 49 | register_read(codel.state_dropping , r_state_dropping, 0); 50 | register_read(codel.drop_cnt, r_drop_count, 0); 51 | register_read(codel.last_drop_cnt, r_last_drop_count, 0); 52 | register_read(codel.drop_next, r_next_drop, 0); 53 | register_read(codel.drop_time, r_drop_time, 0); 54 | } 55 | action a_codel_init_no_sojourn_violation() { 56 | a_codel_init(); 57 | modify_field(codel.reset_drop_time, 1); 58 | //inc_reg_statistic(0); 59 | } 60 | action a_codel_init_sojourn_violation() { 61 | a_codel_init(); 62 | modify_field(codel.reset_drop_time, 0); 63 | //inc_reg_statistic(1); 64 | } 65 | 66 | table t_codel_init_no_sojourn_violation { 67 | actions { 68 | a_codel_init_no_sojourn_violation; 69 | } 70 | } 71 | table t_codel_init_sojourn_violation { 72 | actions { 73 | a_codel_init_sojourn_violation; 74 | } 75 | } 76 | 77 | 78 | register r_drop_time { 79 | width: 48; 80 | // static: t_drop_time; 81 | instance_count: 1; //one per queue? 82 | } 83 | 84 | 85 | table t_set_drop_time { 86 | actions { 87 | a_set_drop_time; 88 | } 89 | } 90 | table t_reset_drop_time { 91 | actions { 92 | a_reset_drop_time; 93 | } 94 | } 95 | action a_set_drop_time (){ //TODO add queue id 96 | register_write(r_drop_time, 0, codel.new_drop_time); 97 | modify_field(codel.drop_time, codel.new_drop_time); 98 | } 99 | action a_reset_drop_time (){ //TODO add queue id 100 | register_write(r_drop_time, 0, 0); 101 | modify_field(codel.drop_time, 0); 102 | } 103 | 104 | table t_set_ok_to_drop { 105 | actions { 106 | a_set_ok_to_drop; 107 | } 108 | } 109 | action a_set_ok_to_drop (){ 110 | modify_field(codel.ok_to_drop, 1); 111 | //inc_reg_statistic(2); 112 | } 113 | 114 | register r_state_dropping { 115 | width: 1; 116 | instance_count: 1; //one per queue? 117 | } 118 | 119 | control c_codel { 120 | //stage 0: 121 | if (queueing_metadata.deq_timedelta < SOJOURN_TARGET or queueing_metadata.deq_qdepth < 1) { //TODO: check if it works correctly 122 | apply(t_codel_init_no_sojourn_violation); 123 | } else { 124 | apply(t_codel_init_sojourn_violation); 125 | } 126 | //stage 1: 127 | if (codel.reset_drop_time == 1) { 128 | apply(t_reset_drop_time); 129 | } else { 130 | if(codel.drop_time == 0){ 131 | apply(t_set_drop_time); 132 | } 133 | } 134 | 135 | //stage 2: 136 | if (codel.reset_drop_time == 0) { 137 | if(codel.drop_time > 0){ 138 | if(codel.time_now >= codel.drop_time){ 139 | apply(t_set_ok_to_drop); 140 | } 141 | } 142 | } 143 | 144 | //stage 3: 145 | if(codel.state_dropping == 1){ 146 | if(codel.ok_to_drop == 0){ 147 | apply(t_stop_dropping); 148 | } else if (codel.time_now >= codel.drop_next) { 149 | apply(t_drop); 150 | apply(t_codel_control_law); //TODO 151 | } 152 | } else { 153 | if(codel.ok_to_drop == 1){ 154 | //start dropping 155 | apply(t_start_dropping); 156 | //stage 4: 157 | if(codel.delta > 1 and codel.time_since_last_dropping < CONTROL_INTERVAL*16){ 158 | apply(t_start_dropping_hard); 159 | } 160 | apply(t_codel_set_last_drpcnt); 161 | apply(t_codel_control_law); //TODO 162 | } 163 | } 164 | //if(...) { //every time we dropped ... 165 | //apply(t_codel_control_law); 166 | //} 167 | } 168 | 169 | table t_start_dropping { 170 | actions{ 171 | a_go_to_drop_state; 172 | } 173 | } 174 | 175 | table t_stop_dropping{ 176 | actions{ 177 | a_go_to_idle_state; 178 | } 179 | } 180 | register r_drop_count { 181 | width: 32; 182 | instance_count: 1; //one per queue? 183 | } 184 | register r_last_drop_count { 185 | width: 32; 186 | instance_count: 1; //one per queue? 187 | } 188 | 189 | register r_next_drop { 190 | width: 48; 191 | instance_count: 1; //one per queue? 192 | } 193 | 194 | action a_go_to_idle_state (){ 195 | register_write(r_state_dropping, 0, 0); //go to idle state 196 | //inc_reg_statistic(7); 197 | } 198 | 199 | action a_go_to_drop_state (){ 200 | drop(); 201 | register_write(r_state_dropping, 0, 1); //go to drop state 202 | subtract(codel.delta, codel.drop_cnt, codel.last_drop_cnt); 203 | subtract(codel.time_since_last_dropping, codel.time_now, codel.drop_next); 204 | modify_field(codel.drop_cnt, 1); 205 | register_write(r_drop_count, 0, 1); 206 | //inc_reg_statistic(9); 207 | } 208 | 209 | table t_start_dropping_hard { 210 | actions { 211 | a_start_hard_dropping; 212 | } 213 | } 214 | 215 | action a_start_hard_dropping (){ 216 | register_write(r_drop_count, 0 , codel.delta); 217 | modify_field(codel.drop_cnt, codel.delta); 218 | } 219 | 220 | table t_codel_set_last_drpcnt { 221 | actions{ a_codel_set_last_drpcnt;} 222 | } 223 | 224 | action a_codel_set_last_drpcnt (){ 225 | register_write(r_last_drop_count, 0, codel.drop_cnt); 226 | //inc_reg_statistic(8); 227 | } 228 | 229 | //counter c_codel_control_law { 230 | // type : packets; 231 | // direct : t_codel_control_law; 232 | //} 233 | 234 | table t_codel_control_law { 235 | reads { 236 | codel.drop_cnt : lpm; 237 | } 238 | actions { 239 | a_codel_control_law; 240 | } 241 | size : 32; 242 | } 243 | 244 | 245 | action a_codel_control_law(value) { 246 | add(codel.drop_next, codel.time_now , value); 247 | register_write(r_next_drop, 0, codel.drop_next); 248 | } 249 | 250 | //for all drops n >= 3, first drop is done by a_go_to_drop_state 251 | table t_drop { 252 | actions { 253 | a_drop_normal; 254 | } 255 | } 256 | 257 | register r_statistic { 258 | width: 32; 259 | instance_count: 11; 260 | } 261 | 262 | action a_drop_normal(){ 263 | drop(); 264 | add(codel.drop_cnt, codel.drop_cnt, 1); 265 | register_write(r_drop_count,0, codel.drop_cnt); 266 | //inc_reg_statistic(10); 267 | } 268 | 269 | //header_type foo_t { 270 | // fields { 271 | // foo: 32; 272 | // } 273 | //} 274 | //metadata foo_t foo; 275 | //action inc_reg_statistic (i){ 276 | // register_read(foo.foo, r_statistic, i); 277 | // modify_field(foo.foo, foo.foo + 1); 278 | // register_write(r_statistic, i, foo.foo); 279 | //} 280 | -------------------------------------------------------------------------------- /srcP4_14/commandsCodelRouter.txt: -------------------------------------------------------------------------------- 1 | table_add forwarding forward 1 10.0.2.1 => 2 00:00:00:00:02:01 2 | table_add forwarding forward 1 10.0.2.2 => 2 00:00:00:00:02:02 3 | table_add forwarding forward 2 10.0.1.1 => 1 00:00:00:00:01:01 4 | table_add forwarding forward 2 10.0.1.2 => 1 00:00:00:00:01:02 5 | 6 | 7 | set_queue_rate 2000 2 //in pps 8 | set_queue_depth 10000 2 //in nb_pkts 9 | 10 | table_set_default t_addQueueDelay addQueueDelay 11 | table_set_default t_checksum a_checksum 12 | 13 | table_set_default t_codel_init_no_sojourn_violation a_codel_init_no_sojourn_violation 14 | table_set_default t_codel_init_sojourn_violation a_codel_init_sojourn_violation 15 | 16 | table_set_default t_set_drop_time a_set_drop_time 17 | table_set_default t_reset_drop_time a_reset_drop_time 18 | table_set_default t_set_ok_to_drop a_set_ok_to_drop 19 | 20 | 21 | table_set_default t_start_dropping a_go_to_drop_state 22 | table_set_default t_stop_dropping a_go_to_idle_state 23 | table_set_default t_start_dropping_hard a_start_hard_dropping 24 | table_set_default t_codel_set_last_drpcnt a_codel_set_last_drpcnt 25 | table_set_default t_drop a_drop_normal 26 | 27 | table_set_default t_codel_control_law a_codel_control_law 552 28 | 29 | table_add t_codel_control_law a_codel_control_law 0/17 => 781 30 | table_add t_codel_control_law a_codel_control_law 0/18 => 1104 31 | table_add t_codel_control_law a_codel_control_law 0/19 => 1562 32 | 33 | table_add t_codel_control_law a_codel_control_law 0/20 => 2209 34 | table_add t_codel_control_law a_codel_control_law 0/21 => 3125 35 | table_add t_codel_control_law a_codel_control_law 0/22 => 4419 36 | 37 | table_add t_codel_control_law a_codel_control_law 0/23 => 6250 38 | table_add t_codel_control_law a_codel_control_law 0/24 => 8838 39 | table_add t_codel_control_law a_codel_control_law 0/25 => 12500 40 | 41 | table_add t_codel_control_law a_codel_control_law 0/26 => 17677 42 | table_add t_codel_control_law a_codel_control_law 0/27 => 25000 43 | table_add t_codel_control_law a_codel_control_law 0/28 => 35355 44 | 45 | table_add t_codel_control_law a_codel_control_law 0/29 => 50000 46 | table_add t_codel_control_law a_codel_control_law 0/30 => 70710 47 | table_add t_codel_control_law a_codel_control_law 0/31 => 100000 48 | //this should never happen ... 49 | table_add t_codel_control_law a_codel_control_law 0/32 => 100000 50 | -------------------------------------------------------------------------------- /srcP4_14/commandsRouterSimple.txt: -------------------------------------------------------------------------------- 1 | table_add forwarding forward 1 10.0.2.1 => 2 00:00:00:00:02:01 2 | table_add forwarding forward 1 10.0.2.2 => 2 00:00:00:00:02:02 3 | table_add forwarding forward 2 10.0.1.1 => 1 00:00:00:00:01:01 4 | table_add forwarding forward 2 10.0.1.2 => 1 00:00:00:00:01:02 5 | 6 | 7 | set_queue_rate 1000 2 //in pps 8 | set_queue_depth 10000 2 //in nb_pkts 9 | 10 | 11 | table_set_default t_addQueueDelay addQueueDelay 12 | table_set_default t_checksum a_checksum 13 | -------------------------------------------------------------------------------- /srcP4_14/header.p4: -------------------------------------------------------------------------------- 1 | header_type ethernet_t { 2 | fields { 3 | dst_addr : 48; // width in bits 4 | src_addr : 48; 5 | ethertype : 16; 6 | } 7 | } 8 | 9 | header_type ipv4_t { 10 | fields { 11 | version : 4; 12 | ihl : 4; 13 | diffserv : 8; 14 | totalLen : 16; 15 | identification : 16; 16 | flags : 3; 17 | fragOffset : 13; 18 | ttl : 8; 19 | protocol : 8; 20 | hdrChecksum : 16; 21 | srcAddr : 32; 22 | dstAddr: 32; 23 | } 24 | } 25 | 26 | header_type routing_metadata_t { 27 | fields { 28 | tcpLength : 16; 29 | } 30 | } 31 | 32 | metadata routing_metadata_t routing_metadata; 33 | 34 | 35 | header_type udp_t { 36 | fields { 37 | sourcePort : 16; 38 | destPort : 16; 39 | length_ : 16; 40 | checksum : 16; 41 | } 42 | } 43 | 44 | header_type tcp_t { 45 | fields { 46 | srcPort : 16; 47 | dstPort : 16; 48 | seqNo : 32; 49 | ackNo : 32; 50 | dataOffset : 4; 51 | res : 4; 52 | flags : 8; 53 | //ecn : 2; 54 | //ctrl : 6; 55 | window : 16; 56 | checksum : 16; 57 | urgentPtr : 16; 58 | } 59 | } 60 | header_type tcp_opt_t { 61 | fields { 62 | a : 32; 63 | b : 32; 64 | c : 32; 65 | } 66 | } 67 | 68 | header_type queue_delay_t { 69 | fields { 70 | delay : 32; 71 | } 72 | } 73 | 74 | header_type queueing_metadata_t { 75 | fields { 76 | enq_timestamp : 48; 77 | enq_qdepth : 16; 78 | deq_timedelta : 32; 79 | deq_qdepth : 16; 80 | qid : 8; 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /srcP4_14/queue_measurement.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel 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 | header queue_delay_t queue_delay; 18 | 19 | control c_add_queue_delay { 20 | if(ipv4.totalLen > 500){ 21 | if(valid(queue_delay)){ 22 | apply(t_addQueueDelay); 23 | } 24 | } 25 | } 26 | 27 | table t_addQueueDelay { 28 | actions { 29 | addQueueDelay; 30 | } 31 | } 32 | 33 | action addQueueDelay(){ 34 | modify_field(queue_delay.delay , queueing_metadata.deq_timedelta); 35 | } 36 | -------------------------------------------------------------------------------- /srcP4_14/router.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Jeremias Blendin 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 | #define add_queue_delay 17 | 18 | #include "header.p4" 19 | #include "codel.p4" 20 | 21 | #ifdef add_queue_delay 22 | #include "tcp_checksum.p4" 23 | #include "queue_measurement.p4" 24 | #endif 25 | 26 | header ethernet_t ethernet; 27 | header ipv4_t ipv4; 28 | header udp_t udp; 29 | header tcp_t tcp; 30 | header tcp_opt_t tcp_options; 31 | metadata queueing_metadata_t queueing_metadata; 32 | 33 | ///////////////////////////////// 34 | // begin parser // 35 | ///////////////////////////////// 36 | 37 | parser start { 38 | extract(ethernet); 39 | return select(ethernet.ethertype){ 40 | 0x0800: parse_ipv4; 41 | default: ingress; 42 | } 43 | } 44 | 45 | parser parse_ipv4 { 46 | extract(ipv4); 47 | set_metadata(routing_metadata.tcpLength, latest.totalLen); 48 | return select(ipv4.protocol){ 49 | 17: parse_udp; 50 | 6: parse_tcp; 51 | default: ingress; 52 | } 53 | } 54 | 55 | parser parse_udp { 56 | extract(udp); 57 | return select(udp.destPort){ 58 | //1234: parse_delay; 59 | default: ingress; 60 | } 61 | } 62 | 63 | parser parse_tcp { 64 | extract(tcp); 65 | #ifdef add_queue_delay 66 | return select(tcp.dataOffset){ 67 | 0x8: parse_payload; 68 | default: ingress; 69 | } 70 | #else 71 | return ingress; 72 | #endif 73 | } 74 | parser parse_payload { 75 | extract(tcp_options); 76 | #ifdef add_queue_delay 77 | extract(queue_delay); 78 | #endif 79 | return ingress; 80 | } 81 | 82 | ///////////////////////////////// 83 | // end parser // 84 | ///////////////////////////////// 85 | 86 | 87 | ///////////////////////////////// 88 | // begin tables // 89 | ///////////////////////////////// 90 | 91 | table forwarding { 92 | reads { 93 | standard_metadata.ingress_port : exact; 94 | ipv4.dstAddr : exact; 95 | } 96 | actions { 97 | forward; 98 | } 99 | } 100 | 101 | //Drops at the beginning with src_mac 102 | action forward(egress_spec, dst_mac) { 103 | modify_field(standard_metadata.egress_spec, egress_spec); 104 | modify_field(ethernet.dst_addr, dst_mac); 105 | } 106 | 107 | action _drop () { 108 | drop() ; 109 | } 110 | action nop(){ 111 | } 112 | 113 | 114 | 115 | ///////////////////////////////// 116 | // end tables // 117 | ///////////////////////////////// 118 | 119 | 120 | control ingress { 121 | apply(forwarding); 122 | } 123 | 124 | control egress { 125 | if (standard_metadata.ingress_port == 1) { 126 | c_codel(); 127 | } 128 | #ifdef add_queue_delay 129 | c_add_queue_delay(); 130 | apply(t_checksum); 131 | #endif 132 | } 133 | -------------------------------------------------------------------------------- /srcP4_14/simple_router.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present Ralf Kundel, Jeremias Blendin 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 | #define add_queue_delay 17 | 18 | #include "header.p4" 19 | 20 | #ifdef add_queue_delay 21 | #include "tcp_checksum.p4" 22 | #include "queue_measurement.p4" 23 | #endif 24 | 25 | ///////////////////////////////// 26 | // begin parser // 27 | ///////////////////////////////// 28 | header ipv4_t ipv4; 29 | header ethernet_t ethernet; 30 | header udp_t udp; 31 | header tcp_t tcp; 32 | header tcp_opt_t tcp_options; 33 | metadata queueing_metadata_t queueing_metadata; 34 | 35 | parser start { 36 | extract(ethernet); 37 | return select(ethernet.ethertype){ 38 | 0x0800: parse_ipv4; 39 | default: ingress; 40 | } 41 | } 42 | 43 | parser parse_ipv4 { 44 | extract(ipv4); 45 | set_metadata(routing_metadata.tcpLength, latest.totalLen); 46 | return select(ipv4.protocol){ 47 | 17: parse_udp; 48 | 6: parse_tcp; 49 | default: ingress; 50 | } 51 | } 52 | 53 | parser parse_udp { 54 | extract(udp); 55 | return select(udp.destPort){ 56 | //1234: parse_delay; 57 | default: ingress; 58 | } 59 | } 60 | 61 | parser parse_tcp { 62 | extract(tcp); 63 | #ifdef add_queue_delay 64 | return select(tcp.dataOffset){ 65 | 0x8: parse_payload; 66 | default: ingress; 67 | } 68 | #else 69 | return ingress; 70 | #endif 71 | } 72 | parser parse_payload { 73 | extract(tcp_options); 74 | #ifdef add_queue_delay 75 | extract(queue_delay); 76 | #endif 77 | return ingress; 78 | } 79 | ///////////////////////////////// 80 | // end parser // 81 | ///////////////////////////////// 82 | 83 | 84 | ///////////////////////////////// 85 | // begin tables // 86 | ///////////////////////////////// 87 | 88 | table forwarding { 89 | reads { 90 | standard_metadata.ingress_port : exact; 91 | ipv4.dstAddr : exact; 92 | } 93 | actions { 94 | forward; 95 | } 96 | } 97 | 98 | action forward(egress_spec, dst_mac) { 99 | modify_field(standard_metadata.egress_spec, egress_spec); 100 | modify_field(ethernet.dst_addr, dst_mac); 101 | } 102 | 103 | ///////////////////////////////// 104 | // end tables // 105 | ///////////////////////////////// 106 | 107 | control ingress { 108 | apply(forwarding); 109 | } 110 | 111 | control egress { 112 | #ifdef add_queue_delay 113 | c_add_queue_delay(); 114 | apply(t_checksum); 115 | #endif 116 | } 117 | -------------------------------------------------------------------------------- /srcP4_14/tcp_checksum.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Original file with no license text 'https://github.com/p4lang/p4c-bm/blob/master/tests/p4_programs/tcp_checksum.p4' 3 | */ 4 | 5 | /* 6 | * Modifications copyright 2018-present Ralf Kundel, Jeremias Blendin 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | field_list ipv4_checksum_list { 22 | ipv4.version; 23 | ipv4.ihl; 24 | ipv4.diffserv; 25 | ipv4.totalLen; 26 | ipv4.identification; 27 | ipv4.flags; 28 | ipv4.fragOffset; 29 | ipv4.ttl; 30 | ipv4.protocol; 31 | ipv4.srcAddr; 32 | ipv4.dstAddr; 33 | } 34 | 35 | field_list_calculation ipv4_checksum { 36 | input { 37 | ipv4_checksum_list; 38 | } 39 | algorithm : csum16; 40 | output_width : 16; 41 | } 42 | 43 | calculated_field ipv4.hdrChecksum { 44 | update ipv4_checksum; 45 | } 46 | 47 | 48 | 49 | field_list tcp_checksum_list { 50 | ipv4.srcAddr; 51 | ipv4.dstAddr; 52 | 8'0; 53 | ipv4.protocol; 54 | routing_metadata.tcpLength; 55 | tcp.srcPort; 56 | tcp.dstPort; 57 | tcp.seqNo; 58 | tcp.ackNo; 59 | tcp.dataOffset; 60 | tcp.res; 61 | tcp.flags; 62 | tcp.window; 63 | tcp.urgentPtr; 64 | payload; 65 | } 66 | 67 | field_list_calculation tcp_checksum { 68 | input { 69 | tcp_checksum_list; 70 | } 71 | algorithm : csum16; 72 | output_width : 16; 73 | } 74 | 75 | calculated_field tcp.checksum { 76 | update tcp_checksum if(valid(tcp)); 77 | } 78 | 79 | table t_checksum { 80 | actions { 81 | a_checksum; 82 | } 83 | } 84 | action a_checksum(){ 85 | subtract(routing_metadata.tcpLength, routing_metadata.tcpLength, 20); 86 | } 87 | -------------------------------------------------------------------------------- /srcPython/linuxrouter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | from mininet.node import Node 18 | 19 | class LinuxRouter( Node ): 20 | "A Node with IP forwarding enabled." 21 | # taken from 22 | # https://github.com/mininet/mininet/blob/f530c99415d8215a0ab7dba4b55e7a64297dd268/examples/linuxrouter.py 23 | 24 | def config( self, **params ): 25 | super( LinuxRouter, self).config( **params ) 26 | # Enable forwarding on the router 27 | self.cmd( 'sysctl net.ipv4.ip_forward=1' ) 28 | #http://man7.org/linux/man-pages/man8/tc-codel.8.html 29 | 30 | self.cmd('tc qdisc add dev r1-eth2 handle 1: root htb default 11') 31 | self.cmd('tc class add dev r1-eth2 parent 1: classid 1:11 htb rate 24224kbit') 32 | self.cmd('tc qdisc add dev r1-eth2 parent 1:11 handle 2:0 codel limit 100000') 33 | print self.cmd('tc qdisc') 34 | 35 | 36 | def start(self): 37 | ret = self.cmd('tcpdump -i r1-eth1 -w r1-eth1_out.pcap not ether src 00:00:00:00:01:fe &') 38 | print(ret) 39 | ret = self.cmd('tcpdump -i r1-eth2 -w r1-eth2_in.pcap not ether dst 00:00:00:00:02:fe &') 40 | print(ret) 41 | 42 | def terminate( self ): 43 | self.cmd( 'sysctl net.ipv4.ip_forward=0' ) 44 | print("terminate LinuxRouter") 45 | -------------------------------------------------------------------------------- /srcPython/ping.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 subprocess 16 | import time 17 | import os, sys, glob 18 | 19 | class IperfTest(): 20 | def IperfTest(self, a, b, c, d, transmit_time): 21 | #self.startPingTest(c, d) 22 | #time.sleep(2) 23 | self.startIperfTest(a, b, transmit_time) 24 | #time.sleep(1) 25 | #self.stopPingTest(c) 26 | self.copyFiles() 27 | 28 | def copyFiles(self): #dirty workaround 29 | for file in glob.glob("*.pcap"): 30 | os.rename(file, "out/"+file) 31 | 32 | # data are transmitted from a to b 33 | def startIperfTest(self, a, b, transmit_time): 34 | cmd1 = ["iperf3", "-s", "&"] 35 | b.cmd(cmd1) 36 | print('start iperf3 test') 37 | cmd2 = ["iperf3", "-c", str(b.IP()), "-J", "-t " + str(transmit_time), "-i 0.1", "-P 1"] 38 | print(cmd2) 39 | out = a.cmd(cmd2) 40 | b.sendInt() 41 | print("finished iperf3 test") 42 | self.writeStringToFile("out/iperf_output.json", out) 43 | #print(out) 44 | 45 | def startPingTest(self, a, b): 46 | cmd = ["ping", str(b.IP()), "-i 0.1"] 47 | output = a.sendCmd(cmd) 48 | print(output) 49 | 50 | def stopPingTest(self, a): 51 | a.sendInt() 52 | time.sleep(1) 53 | out = a.waitOutput() 54 | self.writeStringToFile("out/ping_out.txt", out) 55 | print(out) 56 | 57 | def writeStringToFile(self, file_name, content): 58 | if not os.path.exists(os.path.dirname(file_name)): 59 | os.mkdir(os.path.dirname(file_name)) 60 | file = open(file_name, "w") 61 | file.write(content) 62 | file.close() 63 | -------------------------------------------------------------------------------- /srcPython/toposetup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | from mininet.node import Node 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 | from mininet.link import TCLink 23 | 24 | from p4_mininet import P4Switch, P4Host 25 | from ping import * 26 | from linuxrouter import LinuxRouter 27 | 28 | from eval_scripts.eval import * 29 | 30 | import argparse 31 | from time import sleep 32 | import os 33 | import subprocess 34 | 35 | _THIS_DIR = os.path.dirname(os.path.realpath(__file__)) 36 | 37 | parser = argparse.ArgumentParser(description='Mininet demo') 38 | parser.add_argument('--json', help='Path to JSON config file', 39 | type=str, action="store", required=True) 40 | parser.add_argument('--swpath', help='Path to the switch which should be used in this exercise', 41 | type=str, action="store") 42 | parser.set_defaults(swpath="simple_switch") 43 | parser.add_argument('--cli', help='Path to BM CLI', 44 | type=str, action="store", required=True) 45 | parser.add_argument('--cliCmd', help='Path to cli instructions', 46 | type=str, action="store", required=True) 47 | parser.add_argument("-p4", "--useP4", action="count", 48 | help="use the p4 switch") 49 | parser.add_argument('--nopcap', help='Deactivates the switch PCAP logging', 50 | type=bool, action="store") 51 | parser.set_defaults(nopcap=False) 52 | parser.add_argument('--nocli', help='Deactivates the mininet CLI', 53 | type=bool, action="store") 54 | parser.set_defaults(nocli=False) 55 | parser.add_argument('--h3delay', help='The delay between h3 and s2. Example: "30ms"', 56 | type=str, action="store") 57 | parser.set_defaults(h3delay="2ms") 58 | parser.add_argument('--iperft', help='The transmit time of iperf3 in seconds. Example: 30', 59 | type=int, action="store") 60 | parser.set_defaults(iperft=10) 61 | 62 | args = parser.parse_args() 63 | 64 | 65 | class MyTopo(Topo): 66 | def __init__(self, json_path, p4=True, **opts): 67 | # Initialize topology and default options 68 | Topo.__init__(self, **opts) 69 | s1 = self.addSwitch('s1') 70 | 71 | aqm_switch = None 72 | if p4: 73 | aqm_switch = self.addSwitch('r1', 74 | cls=P4Switch, 75 | sw_path = args.swpath, 76 | json_path = json_path, 77 | thrift_port = 22222, 78 | pcap_dump = not args.nopcap, 79 | #pcap_dir = "out", 80 | log_console = False, #TODO 81 | enable_debugger = False) 82 | else: 83 | aqm_switch = self.addNode( 'r1', cls=LinuxRouter ) 84 | 85 | s2 = self.addSwitch('s2') 86 | 87 | h1 = self.addHost('h1', ip = '10.0.1.1/24', 88 | mac = '00:00:00:00:01:01', 89 | defaultRoute='via 10.0.1.254 dev eth0') 90 | h2 = self.addHost('h2', ip = '10.0.1.2/24', 91 | mac = '00:00:00:00:01:02', 92 | defaultRoute='via 10.0.1.254 dev eth0') 93 | h3 = self.addHost('h3', ip = '10.0.3.1/24', 94 | mac = '00:00:00:00:02:01', 95 | defaultRoute='via 10.0.3.254 dev eth0') 96 | h4 = self.addHost('h4', ip = '10.0.3.2/24', 97 | mac = '00:00:00:00:02:02', 98 | defaultRoute='via 10.0.3.254 dev eth0') 99 | 100 | self.addLink(h1, s1, delay='0ms') 101 | self.addLink(h2, s1, delay='0ms') 102 | self.addLink(h3, s2, delay=args.h3delay) 103 | self.addLink(h4, s2, delay='0ms') 104 | 105 | self.addLink(s1, aqm_switch, 106 | intfName2='r1-eth1', 107 | addr2="00:00:00:00:01:fe") 108 | self.addLink(s2, aqm_switch, 109 | intfName2='r1-eth2', 110 | addr2="00:00:00:00:02:fe") 111 | def main(): 112 | p4 = True if args.useP4 is not None else False 113 | 114 | 115 | topo = MyTopo(json_path = args.json, 116 | p4=p4) 117 | mn = Mininet(topo = topo, 118 | link = TCLink, 119 | host = P4Host, 120 | autoStaticArp=True ) 121 | 122 | internet_hosts = ["h1", "h2"] 123 | homenet_hosts = ["h3", "h4"] 124 | routers = ["r1"] 125 | for h in mn.hosts: 126 | print("disable ipv6") 127 | h.cmd("sysctl -w net.ipv6.conf.all.disable_ipv6=1") 128 | h.cmd("sysctl -w net.ipv6.conf.default.disable_ipv6=1") 129 | h.cmd("sysctl -w net.ipv6.conf.lo.disable_ipv6=1") 130 | if h.name in internet_hosts: 131 | h.setARP("10.0.1.254", "00:00:00:00:01:fe") 132 | h.setDefaultRoute("via 10.0.1.254 dev eth0") 133 | elif h.name in homenet_hosts: 134 | h.setARP("10.0.2.254", "00:00:00:00:02:fe") 135 | h.setDefaultRoute("via 10.0.3.254 dev eth0") 136 | elif h.name in routers: #in case of linux kernel router 137 | print("router") 138 | h.setMAC("00:00:00:00:01:fe", intf="r1-eth1") 139 | h.setMAC("00:00:00:00:02:fe", intf="r1-eth2") 140 | h.setIP(ip="10.0.1.254", prefixLen=24, intf="r1-eth1") 141 | h.setIP(ip="10.0.3.254", prefixLen=24, intf="r1-eth2") 142 | h.setARP("10.0.1.1", "00:00:00:00:01:01") 143 | h.setARP("10.0.1.2", "00:00:00:00:01:02") 144 | h.setARP("10.0.3.1", "00:00:00:00:02:01") 145 | h.setARP("10.0.3.2", "00:00:00:00:02:02") 146 | 147 | for sw in mn.switches: 148 | print("disable ipv6") 149 | print(sw) 150 | sw.cmd("sysctl -w net.ipv6.conf.all.disable_ipv6=1") 151 | sw.cmd("sysctl -w net.ipv6.conf.default.disable_ipv6=1") 152 | sw.cmd("sysctl -w net.ipv6.conf.lo.disable_ipv6=1") 153 | 154 | 155 | mn.start() 156 | if not p4 and not args.nopcap: 157 | r1 = mn.getNodeByName('r1') 158 | r1.start() 159 | 160 | 161 | iperfTest = IperfTest() 162 | 163 | if p4: 164 | sleep(1) 165 | r1 = mn.getNodeByName('r1') 166 | r1.setIP(ip="10.0.1.254", prefixLen=24, intf="r1-eth1") 167 | r1.setIP(ip="10.0.3.254", prefixLen=24, intf="r1-eth2") 168 | cmd = [args.cli, args.json, str(22222)] 169 | with open(args.cliCmd, "r") as f: 170 | print(" ".join(cmd)) 171 | try: 172 | print("Running %s" % cmd) 173 | output = subprocess.check_output(cmd, stdin = f) 174 | print(output) 175 | except subprocess.CalledProcessError as e: 176 | print(e) 177 | print(e.output) 178 | 179 | 180 | 181 | sleep(1) 182 | 183 | print("Now the iperf test starts !") 184 | iperfTest.IperfTest(mn.getNodeByName('h1'), mn.getNodeByName('h3'), mn.getNodeByName('h2'), mn.getNodeByName('h4'), args.iperft) 185 | if not args.nocli: 186 | CLI( mn ) 187 | mn.stop() 188 | 189 | if __name__ == '__main__': 190 | setLogLevel( 'info' ) 191 | main() 192 | -------------------------------------------------------------------------------- /start_bmv2_CLI.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2018-present Ralf Kundel, Jeremias Blendin, Nikolas Eller 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 | ../p4-behavioral-model-performance/targets/simple_switch/sswitch_CLI router_compiled.json 22222 15 | -------------------------------------------------------------------------------- /targets/tofino/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | zlog-cfg-cur 3 | pd_fixed/__pycache__/* 4 | compile/* 5 | 6 | -------------------------------------------------------------------------------- /targets/tofino/Readme.md: -------------------------------------------------------------------------------- 1 | # P4 CoDel for Barefoot Tofino 2 | This code is a P4 CoDel implementation for Barefoot Tofino. 3 | Last tested SDE is version 9.1.1. The SDE should be best compiled with all additional packages (such as thrift & grpc support). 4 | 5 | ## Preparation 6 | 7 | ### Compile 8 | In order to compile, use the build script provided by the SDE: 9 | ``` 10 | ./p4_build.sh 11 | ``` 12 | 13 | ### Window 1: switch control daemon 14 | ``` 15 | ./run_switchd.sh 16 | ``` 17 | This will take a few seconds. After the initialization process is finished, configure the ports. In this example, we will use port 64/0 and 64/1 for packet ingress and egress. 18 | 19 | ``` 20 | ucli 21 | pm 22 | port-add 64/- 10G NONE 23 | port-enb 64/0 24 | port-enb 64/1 25 | show 26 | ``` 27 | After a few seconds the show command should show that the corresponding interfaces are up. If not, you can stop here and start debugging your physical links ;-) 28 | 29 | ### Window 2: switch control daemon 30 | In a second window start the barefoot CLI with the following command in the SDE: 31 | ``` 32 | ./run_bfshell.sh 33 | ``` 34 | 35 | In order to benefit from a lot of (python) features, we will do the following steps with the python runtime. This can be started within the bfshell: 36 | ``` 37 | bfrt_python 38 | ``` 39 | Now enter the following commands in order to fill the Layer-1 routing tables. In fact, this table performs simple port bridging. E.g. all packets ingressing on port 412 will be sent out on port 413. The pipeline port mapping on phyiscal ports can be seen in Window 1, as described above. 40 | ``` 41 | bfrt.l1switchCodel.pipe.SwitchIngress.t_l1_forwarding.clear() 42 | bfrt.l1switchCodel.pipe.SwitchIngress.t_l1_forwarding.add_with_send(ingress_port=412, egress_port=413) 43 | bfrt.l1switchCodel.pipe.SwitchIngress.t_l1_forwarding.add_with_send(ingress_port=413, egress_port=412) 44 | ``` 45 | 46 | ### Window 3: Enable Port Shaping 47 | The CoDel algorithm itself is on a per port base and do not require any table entries. However, the corresponding egress port queue must be configured to shape the traffic in order to build up a queue. For that, in a third window, start the following script of the SDE: 48 | ``` 49 | python3 set_shape_rate.py 50 | ``` 51 | and adapt the port and shaper rate in this script before (default: port==153, rate==100 Mbit/s). 52 | 53 | 54 | alternatively, you can use the run_pd_rpc.py script (part of older SDE util scripts collections): 55 | 56 | ``` 57 | ./run_pd_rpc.py 58 | ``` 59 | and enter the following commands: 60 | ``` 61 | tm.set_port_shaping_rate(412, False, 1600, 100000) 62 | tm.enable_port_shaping(412) 63 | ``` 64 | 65 | ## Run it 66 | After setting it up, simply run your desired TCP load generator which is sending traffic over the two configured ports. E.g. iperf3 is a nice tool for testing the shaping behavior. 67 | 68 | However, in order to observe the queueing delay, a tool like MoonGen or P4STA is needed. The iperf3 latency output is around one order of magnitude higher (30 to 100 ms) than the queueing delay (5 to 10 ms), caused by non-constant measurement errors. 69 | 70 | -------------------------------------------------------------------------------- /targets/tofino/p4_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # set SDE and SDE_INSTALL variable to default values 3 | : ${SDE=/opt/bf-sde-9.9.1} 4 | : ${SDE_INSTALL=$SDE/install} 5 | mkdir -p compile 6 | $SDE_INSTALL/bin/bf-p4c -v -o $PWD/compile/ srcP4/l1switchCodel.p4 7 | -------------------------------------------------------------------------------- /targets/tofino/pd_fixed/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ralfkundel/p4-codel/686ec046ea35cab4400f3067636bad87fb8f774c/targets/tofino/pd_fixed/__init__.py -------------------------------------------------------------------------------- /targets/tofino/pd_fixed/pd_fixed_api.py: -------------------------------------------------------------------------------- 1 | from thrift.transport import TSocket 2 | from thrift.transport import TTransport 3 | from thrift.protocol import TBinaryProtocol 4 | from thrift.protocol import TMultiplexedProtocol 5 | from pd_fixed.tm import Client 6 | import inspect 7 | import traceback 8 | 9 | 10 | class PDFixedConnect: 11 | # connects directly to tm_api_rpc 12 | def __init__(self, thrift_ip, port=9090): 13 | try: 14 | transport = TTransport.TBufferedTransport( 15 | TSocket.TSocket(thrift_ip, port)) 16 | transport.open() 17 | bproto = TBinaryProtocol.TBinaryProtocol(transport) 18 | proto = TMultiplexedProtocol.TMultiplexedProtocol(bproto, "tm") 19 | thr = Client(proto) 20 | self.meth_dict = dict(inspect.getmembers(thr, inspect.ismethod)) 21 | self.error = False 22 | self.error_message = "" 23 | except Exception: 24 | message = traceback.format_exc() 25 | print(message) 26 | self.error = True 27 | self.error_message = message 28 | 29 | def set_port_shaping_rate(self, port, rate): 30 | # rate limit over 100 Gbit/s is not possible 31 | if rate > 100000000: 32 | rate = 100000000 33 | cells = int(rate / 300) 34 | if cells > 250000: 35 | # more doesn't make sense 36 | cells = 250000 37 | elif cells < 300: 38 | cells = 300 39 | print("Set Tofino Shaping Rate: " + str(rate/1000) + "Mbit/s | Cells: " 40 | + str(cells) + " for port " + str(port)) 41 | self.meth_dict["tm_set_port_shaping_rate"](0, port, False, 1600, rate) 42 | self.meth_dict["tm_set_ingress_port_drop_limit"](0, port, cells) 43 | 44 | def enable_port_shaping(self, port): 45 | self.meth_dict["tm_enable_port_shaping"](0, port) 46 | 47 | def disable_port_shaping(self, port): 48 | self.meth_dict["tm_disable_port_shaping"](0, port) 49 | -------------------------------------------------------------------------------- /targets/tofino/pd_fixed/ttypes.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift Compiler (0.9.2) 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | # options string: py 7 | # 8 | 9 | from thrift.Thrift import TType, TMessageType, TException, TApplicationException 10 | 11 | from thrift.transport import TTransport 12 | from thrift.protocol import TBinaryProtocol, TProtocol 13 | try: 14 | from thrift.protocol import fastbinary 15 | except: 16 | fastbinary = None 17 | 18 | 19 | 20 | class InvalidTmOperation(TException): 21 | """ 22 | Attributes: 23 | - code 24 | """ 25 | 26 | thrift_spec = ( 27 | None, # 0 28 | (1, TType.I32, 'code', None, None, ), # 1 29 | ) 30 | 31 | def __init__(self, code=None,): 32 | self.code = code 33 | 34 | def read(self, iprot): 35 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 36 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 37 | return 38 | iprot.readStructBegin() 39 | while True: 40 | (fname, ftype, fid) = iprot.readFieldBegin() 41 | if ftype == TType.STOP: 42 | break 43 | if fid == 1: 44 | if ftype == TType.I32: 45 | self.code = iprot.readI32(); 46 | else: 47 | iprot.skip(ftype) 48 | else: 49 | iprot.skip(ftype) 50 | iprot.readFieldEnd() 51 | iprot.readStructEnd() 52 | 53 | def write(self, oprot): 54 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 55 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 56 | return 57 | oprot.writeStructBegin('InvalidTmOperation') 58 | if self.code is not None: 59 | oprot.writeFieldBegin('code', TType.I32, 1) 60 | oprot.writeI32(self.code) 61 | oprot.writeFieldEnd() 62 | oprot.writeFieldStop() 63 | oprot.writeStructEnd() 64 | 65 | def validate(self): 66 | return 67 | 68 | 69 | def __str__(self): 70 | return repr(self) 71 | 72 | def __hash__(self): 73 | value = 17 74 | value = (value * 31) ^ hash(self.code) 75 | return value 76 | 77 | def __repr__(self): 78 | L = ['%s=%r' % (key, value) 79 | for key, value in self.__dict__.items()] 80 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 81 | 82 | def __eq__(self, other): 83 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 84 | 85 | def __ne__(self, other): 86 | return not (self == other) 87 | 88 | class tm_pfc_cos_map_t: 89 | """ 90 | Attributes: 91 | - CoS0_to_iCos 92 | - CoS1_to_iCos 93 | - CoS2_to_iCos 94 | - CoS3_to_iCos 95 | - CoS4_to_iCos 96 | - CoS5_to_iCos 97 | - CoS6_to_iCos 98 | - CoS7_to_iCos 99 | """ 100 | 101 | thrift_spec = ( 102 | None, # 0 103 | (1, TType.I32, 'CoS0_to_iCos', None, None, ), # 1 104 | (2, TType.I32, 'CoS1_to_iCos', None, None, ), # 2 105 | (3, TType.I32, 'CoS2_to_iCos', None, None, ), # 3 106 | (4, TType.I32, 'CoS3_to_iCos', None, None, ), # 4 107 | (5, TType.I32, 'CoS4_to_iCos', None, None, ), # 5 108 | (6, TType.I32, 'CoS5_to_iCos', None, None, ), # 6 109 | (7, TType.I32, 'CoS6_to_iCos', None, None, ), # 7 110 | (8, TType.I32, 'CoS7_to_iCos', None, None, ), # 8 111 | ) 112 | 113 | def __init__(self, CoS0_to_iCos=None, CoS1_to_iCos=None, CoS2_to_iCos=None, CoS3_to_iCos=None, CoS4_to_iCos=None, CoS5_to_iCos=None, CoS6_to_iCos=None, CoS7_to_iCos=None,): 114 | self.CoS0_to_iCos = CoS0_to_iCos 115 | self.CoS1_to_iCos = CoS1_to_iCos 116 | self.CoS2_to_iCos = CoS2_to_iCos 117 | self.CoS3_to_iCos = CoS3_to_iCos 118 | self.CoS4_to_iCos = CoS4_to_iCos 119 | self.CoS5_to_iCos = CoS5_to_iCos 120 | self.CoS6_to_iCos = CoS6_to_iCos 121 | self.CoS7_to_iCos = CoS7_to_iCos 122 | 123 | def read(self, iprot): 124 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 125 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 126 | return 127 | iprot.readStructBegin() 128 | while True: 129 | (fname, ftype, fid) = iprot.readFieldBegin() 130 | if ftype == TType.STOP: 131 | break 132 | if fid == 1: 133 | if ftype == TType.I32: 134 | self.CoS0_to_iCos = iprot.readI32(); 135 | else: 136 | iprot.skip(ftype) 137 | elif fid == 2: 138 | if ftype == TType.I32: 139 | self.CoS1_to_iCos = iprot.readI32(); 140 | else: 141 | iprot.skip(ftype) 142 | elif fid == 3: 143 | if ftype == TType.I32: 144 | self.CoS2_to_iCos = iprot.readI32(); 145 | else: 146 | iprot.skip(ftype) 147 | elif fid == 4: 148 | if ftype == TType.I32: 149 | self.CoS3_to_iCos = iprot.readI32(); 150 | else: 151 | iprot.skip(ftype) 152 | elif fid == 5: 153 | if ftype == TType.I32: 154 | self.CoS4_to_iCos = iprot.readI32(); 155 | else: 156 | iprot.skip(ftype) 157 | elif fid == 6: 158 | if ftype == TType.I32: 159 | self.CoS5_to_iCos = iprot.readI32(); 160 | else: 161 | iprot.skip(ftype) 162 | elif fid == 7: 163 | if ftype == TType.I32: 164 | self.CoS6_to_iCos = iprot.readI32(); 165 | else: 166 | iprot.skip(ftype) 167 | elif fid == 8: 168 | if ftype == TType.I32: 169 | self.CoS7_to_iCos = iprot.readI32(); 170 | else: 171 | iprot.skip(ftype) 172 | else: 173 | iprot.skip(ftype) 174 | iprot.readFieldEnd() 175 | iprot.readStructEnd() 176 | 177 | def write(self, oprot): 178 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 179 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 180 | return 181 | oprot.writeStructBegin('tm_pfc_cos_map_t') 182 | if self.CoS0_to_iCos is not None: 183 | oprot.writeFieldBegin('CoS0_to_iCos', TType.I32, 1) 184 | oprot.writeI32(self.CoS0_to_iCos) 185 | oprot.writeFieldEnd() 186 | if self.CoS1_to_iCos is not None: 187 | oprot.writeFieldBegin('CoS1_to_iCos', TType.I32, 2) 188 | oprot.writeI32(self.CoS1_to_iCos) 189 | oprot.writeFieldEnd() 190 | if self.CoS2_to_iCos is not None: 191 | oprot.writeFieldBegin('CoS2_to_iCos', TType.I32, 3) 192 | oprot.writeI32(self.CoS2_to_iCos) 193 | oprot.writeFieldEnd() 194 | if self.CoS3_to_iCos is not None: 195 | oprot.writeFieldBegin('CoS3_to_iCos', TType.I32, 4) 196 | oprot.writeI32(self.CoS3_to_iCos) 197 | oprot.writeFieldEnd() 198 | if self.CoS4_to_iCos is not None: 199 | oprot.writeFieldBegin('CoS4_to_iCos', TType.I32, 5) 200 | oprot.writeI32(self.CoS4_to_iCos) 201 | oprot.writeFieldEnd() 202 | if self.CoS5_to_iCos is not None: 203 | oprot.writeFieldBegin('CoS5_to_iCos', TType.I32, 6) 204 | oprot.writeI32(self.CoS5_to_iCos) 205 | oprot.writeFieldEnd() 206 | if self.CoS6_to_iCos is not None: 207 | oprot.writeFieldBegin('CoS6_to_iCos', TType.I32, 7) 208 | oprot.writeI32(self.CoS6_to_iCos) 209 | oprot.writeFieldEnd() 210 | if self.CoS7_to_iCos is not None: 211 | oprot.writeFieldBegin('CoS7_to_iCos', TType.I32, 8) 212 | oprot.writeI32(self.CoS7_to_iCos) 213 | oprot.writeFieldEnd() 214 | oprot.writeFieldStop() 215 | oprot.writeStructEnd() 216 | 217 | def validate(self): 218 | return 219 | 220 | 221 | def __hash__(self): 222 | value = 17 223 | value = (value * 31) ^ hash(self.CoS0_to_iCos) 224 | value = (value * 31) ^ hash(self.CoS1_to_iCos) 225 | value = (value * 31) ^ hash(self.CoS2_to_iCos) 226 | value = (value * 31) ^ hash(self.CoS3_to_iCos) 227 | value = (value * 31) ^ hash(self.CoS4_to_iCos) 228 | value = (value * 31) ^ hash(self.CoS5_to_iCos) 229 | value = (value * 31) ^ hash(self.CoS6_to_iCos) 230 | value = (value * 31) ^ hash(self.CoS7_to_iCos) 231 | return value 232 | 233 | def __repr__(self): 234 | L = ['%s=%r' % (key, value) 235 | for key, value in self.__dict__.items()] 236 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 237 | 238 | def __eq__(self, other): 239 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 240 | 241 | def __ne__(self, other): 242 | return not (self == other) 243 | 244 | class tm_q_map_t: 245 | """ 246 | Attributes: 247 | - md_qid0_to_tm_q 248 | - md_qid1_to_tm_q 249 | - md_qid2_to_tm_q 250 | - md_qid3_to_tm_q 251 | - md_qid4_to_tm_q 252 | - md_qid5_to_tm_q 253 | - md_qid6_to_tm_q 254 | - md_qid7_to_tm_q 255 | - md_qid8_to_tm_q 256 | - md_qid9_to_tm_q 257 | - md_qid10_to_tm_q 258 | - md_qid11_to_tm_q 259 | - md_qid12_to_tm_q 260 | - md_qid13_to_tm_q 261 | - md_qid14_to_tm_q 262 | - md_qid15_to_tm_q 263 | - md_qid16_to_tm_q 264 | - md_qid17_to_tm_q 265 | - md_qid18_to_tm_q 266 | - md_qid19_to_tm_q 267 | - md_qid20_to_tm_q 268 | - md_qid21_to_tm_q 269 | - md_qid22_to_tm_q 270 | - md_qid23_to_tm_q 271 | - md_qid24_to_tm_q 272 | - md_qid25_to_tm_q 273 | - md_qid26_to_tm_q 274 | - md_qid27_to_tm_q 275 | - md_qid28_to_tm_q 276 | - md_qid29_to_tm_q 277 | - md_qid30_to_tm_q 278 | - md_qid31_to_tm_q 279 | - q_count 280 | """ 281 | 282 | thrift_spec = ( 283 | None, # 0 284 | (1, TType.I32, 'md_qid0_to_tm_q', None, None, ), # 1 285 | (2, TType.I32, 'md_qid1_to_tm_q', None, None, ), # 2 286 | (3, TType.I32, 'md_qid2_to_tm_q', None, None, ), # 3 287 | (4, TType.I32, 'md_qid3_to_tm_q', None, None, ), # 4 288 | (5, TType.I32, 'md_qid4_to_tm_q', None, None, ), # 5 289 | (6, TType.I32, 'md_qid5_to_tm_q', None, None, ), # 6 290 | (7, TType.I32, 'md_qid6_to_tm_q', None, None, ), # 7 291 | (8, TType.I32, 'md_qid7_to_tm_q', None, None, ), # 8 292 | (9, TType.I32, 'md_qid8_to_tm_q', None, None, ), # 9 293 | (10, TType.I32, 'md_qid9_to_tm_q', None, None, ), # 10 294 | (11, TType.I32, 'md_qid10_to_tm_q', None, None, ), # 11 295 | (12, TType.I32, 'md_qid11_to_tm_q', None, None, ), # 12 296 | (13, TType.I32, 'md_qid12_to_tm_q', None, None, ), # 13 297 | (14, TType.I32, 'md_qid13_to_tm_q', None, None, ), # 14 298 | (15, TType.I32, 'md_qid14_to_tm_q', None, None, ), # 15 299 | (16, TType.I32, 'md_qid15_to_tm_q', None, None, ), # 16 300 | (17, TType.I32, 'md_qid16_to_tm_q', None, None, ), # 17 301 | (18, TType.I32, 'md_qid17_to_tm_q', None, None, ), # 18 302 | (19, TType.I32, 'md_qid18_to_tm_q', None, None, ), # 19 303 | (20, TType.I32, 'md_qid19_to_tm_q', None, None, ), # 20 304 | (21, TType.I32, 'md_qid20_to_tm_q', None, None, ), # 21 305 | (22, TType.I32, 'md_qid21_to_tm_q', None, None, ), # 22 306 | (23, TType.I32, 'md_qid22_to_tm_q', None, None, ), # 23 307 | (24, TType.I32, 'md_qid23_to_tm_q', None, None, ), # 24 308 | (25, TType.I32, 'md_qid24_to_tm_q', None, None, ), # 25 309 | (26, TType.I32, 'md_qid25_to_tm_q', None, None, ), # 26 310 | (27, TType.I32, 'md_qid26_to_tm_q', None, None, ), # 27 311 | (28, TType.I32, 'md_qid27_to_tm_q', None, None, ), # 28 312 | (29, TType.I32, 'md_qid28_to_tm_q', None, None, ), # 29 313 | (30, TType.I32, 'md_qid29_to_tm_q', None, None, ), # 30 314 | (31, TType.I32, 'md_qid30_to_tm_q', None, None, ), # 31 315 | (32, TType.I32, 'md_qid31_to_tm_q', None, None, ), # 32 316 | (33, TType.I32, 'q_count', None, None, ), # 33 317 | ) 318 | 319 | def __init__(self, md_qid0_to_tm_q=None, md_qid1_to_tm_q=None, md_qid2_to_tm_q=None, md_qid3_to_tm_q=None, md_qid4_to_tm_q=None, md_qid5_to_tm_q=None, md_qid6_to_tm_q=None, md_qid7_to_tm_q=None, md_qid8_to_tm_q=None, md_qid9_to_tm_q=None, md_qid10_to_tm_q=None, md_qid11_to_tm_q=None, md_qid12_to_tm_q=None, md_qid13_to_tm_q=None, md_qid14_to_tm_q=None, md_qid15_to_tm_q=None, md_qid16_to_tm_q=None, md_qid17_to_tm_q=None, md_qid18_to_tm_q=None, md_qid19_to_tm_q=None, md_qid20_to_tm_q=None, md_qid21_to_tm_q=None, md_qid22_to_tm_q=None, md_qid23_to_tm_q=None, md_qid24_to_tm_q=None, md_qid25_to_tm_q=None, md_qid26_to_tm_q=None, md_qid27_to_tm_q=None, md_qid28_to_tm_q=None, md_qid29_to_tm_q=None, md_qid30_to_tm_q=None, md_qid31_to_tm_q=None, q_count=None,): 320 | self.md_qid0_to_tm_q = md_qid0_to_tm_q 321 | self.md_qid1_to_tm_q = md_qid1_to_tm_q 322 | self.md_qid2_to_tm_q = md_qid2_to_tm_q 323 | self.md_qid3_to_tm_q = md_qid3_to_tm_q 324 | self.md_qid4_to_tm_q = md_qid4_to_tm_q 325 | self.md_qid5_to_tm_q = md_qid5_to_tm_q 326 | self.md_qid6_to_tm_q = md_qid6_to_tm_q 327 | self.md_qid7_to_tm_q = md_qid7_to_tm_q 328 | self.md_qid8_to_tm_q = md_qid8_to_tm_q 329 | self.md_qid9_to_tm_q = md_qid9_to_tm_q 330 | self.md_qid10_to_tm_q = md_qid10_to_tm_q 331 | self.md_qid11_to_tm_q = md_qid11_to_tm_q 332 | self.md_qid12_to_tm_q = md_qid12_to_tm_q 333 | self.md_qid13_to_tm_q = md_qid13_to_tm_q 334 | self.md_qid14_to_tm_q = md_qid14_to_tm_q 335 | self.md_qid15_to_tm_q = md_qid15_to_tm_q 336 | self.md_qid16_to_tm_q = md_qid16_to_tm_q 337 | self.md_qid17_to_tm_q = md_qid17_to_tm_q 338 | self.md_qid18_to_tm_q = md_qid18_to_tm_q 339 | self.md_qid19_to_tm_q = md_qid19_to_tm_q 340 | self.md_qid20_to_tm_q = md_qid20_to_tm_q 341 | self.md_qid21_to_tm_q = md_qid21_to_tm_q 342 | self.md_qid22_to_tm_q = md_qid22_to_tm_q 343 | self.md_qid23_to_tm_q = md_qid23_to_tm_q 344 | self.md_qid24_to_tm_q = md_qid24_to_tm_q 345 | self.md_qid25_to_tm_q = md_qid25_to_tm_q 346 | self.md_qid26_to_tm_q = md_qid26_to_tm_q 347 | self.md_qid27_to_tm_q = md_qid27_to_tm_q 348 | self.md_qid28_to_tm_q = md_qid28_to_tm_q 349 | self.md_qid29_to_tm_q = md_qid29_to_tm_q 350 | self.md_qid30_to_tm_q = md_qid30_to_tm_q 351 | self.md_qid31_to_tm_q = md_qid31_to_tm_q 352 | self.q_count = q_count 353 | 354 | def read(self, iprot): 355 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 356 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 357 | return 358 | iprot.readStructBegin() 359 | while True: 360 | (fname, ftype, fid) = iprot.readFieldBegin() 361 | if ftype == TType.STOP: 362 | break 363 | if fid == 1: 364 | if ftype == TType.I32: 365 | self.md_qid0_to_tm_q = iprot.readI32(); 366 | else: 367 | iprot.skip(ftype) 368 | elif fid == 2: 369 | if ftype == TType.I32: 370 | self.md_qid1_to_tm_q = iprot.readI32(); 371 | else: 372 | iprot.skip(ftype) 373 | elif fid == 3: 374 | if ftype == TType.I32: 375 | self.md_qid2_to_tm_q = iprot.readI32(); 376 | else: 377 | iprot.skip(ftype) 378 | elif fid == 4: 379 | if ftype == TType.I32: 380 | self.md_qid3_to_tm_q = iprot.readI32(); 381 | else: 382 | iprot.skip(ftype) 383 | elif fid == 5: 384 | if ftype == TType.I32: 385 | self.md_qid4_to_tm_q = iprot.readI32(); 386 | else: 387 | iprot.skip(ftype) 388 | elif fid == 6: 389 | if ftype == TType.I32: 390 | self.md_qid5_to_tm_q = iprot.readI32(); 391 | else: 392 | iprot.skip(ftype) 393 | elif fid == 7: 394 | if ftype == TType.I32: 395 | self.md_qid6_to_tm_q = iprot.readI32(); 396 | else: 397 | iprot.skip(ftype) 398 | elif fid == 8: 399 | if ftype == TType.I32: 400 | self.md_qid7_to_tm_q = iprot.readI32(); 401 | else: 402 | iprot.skip(ftype) 403 | elif fid == 9: 404 | if ftype == TType.I32: 405 | self.md_qid8_to_tm_q = iprot.readI32(); 406 | else: 407 | iprot.skip(ftype) 408 | elif fid == 10: 409 | if ftype == TType.I32: 410 | self.md_qid9_to_tm_q = iprot.readI32(); 411 | else: 412 | iprot.skip(ftype) 413 | elif fid == 11: 414 | if ftype == TType.I32: 415 | self.md_qid10_to_tm_q = iprot.readI32(); 416 | else: 417 | iprot.skip(ftype) 418 | elif fid == 12: 419 | if ftype == TType.I32: 420 | self.md_qid11_to_tm_q = iprot.readI32(); 421 | else: 422 | iprot.skip(ftype) 423 | elif fid == 13: 424 | if ftype == TType.I32: 425 | self.md_qid12_to_tm_q = iprot.readI32(); 426 | else: 427 | iprot.skip(ftype) 428 | elif fid == 14: 429 | if ftype == TType.I32: 430 | self.md_qid13_to_tm_q = iprot.readI32(); 431 | else: 432 | iprot.skip(ftype) 433 | elif fid == 15: 434 | if ftype == TType.I32: 435 | self.md_qid14_to_tm_q = iprot.readI32(); 436 | else: 437 | iprot.skip(ftype) 438 | elif fid == 16: 439 | if ftype == TType.I32: 440 | self.md_qid15_to_tm_q = iprot.readI32(); 441 | else: 442 | iprot.skip(ftype) 443 | elif fid == 17: 444 | if ftype == TType.I32: 445 | self.md_qid16_to_tm_q = iprot.readI32(); 446 | else: 447 | iprot.skip(ftype) 448 | elif fid == 18: 449 | if ftype == TType.I32: 450 | self.md_qid17_to_tm_q = iprot.readI32(); 451 | else: 452 | iprot.skip(ftype) 453 | elif fid == 19: 454 | if ftype == TType.I32: 455 | self.md_qid18_to_tm_q = iprot.readI32(); 456 | else: 457 | iprot.skip(ftype) 458 | elif fid == 20: 459 | if ftype == TType.I32: 460 | self.md_qid19_to_tm_q = iprot.readI32(); 461 | else: 462 | iprot.skip(ftype) 463 | elif fid == 21: 464 | if ftype == TType.I32: 465 | self.md_qid20_to_tm_q = iprot.readI32(); 466 | else: 467 | iprot.skip(ftype) 468 | elif fid == 22: 469 | if ftype == TType.I32: 470 | self.md_qid21_to_tm_q = iprot.readI32(); 471 | else: 472 | iprot.skip(ftype) 473 | elif fid == 23: 474 | if ftype == TType.I32: 475 | self.md_qid22_to_tm_q = iprot.readI32(); 476 | else: 477 | iprot.skip(ftype) 478 | elif fid == 24: 479 | if ftype == TType.I32: 480 | self.md_qid23_to_tm_q = iprot.readI32(); 481 | else: 482 | iprot.skip(ftype) 483 | elif fid == 25: 484 | if ftype == TType.I32: 485 | self.md_qid24_to_tm_q = iprot.readI32(); 486 | else: 487 | iprot.skip(ftype) 488 | elif fid == 26: 489 | if ftype == TType.I32: 490 | self.md_qid25_to_tm_q = iprot.readI32(); 491 | else: 492 | iprot.skip(ftype) 493 | elif fid == 27: 494 | if ftype == TType.I32: 495 | self.md_qid26_to_tm_q = iprot.readI32(); 496 | else: 497 | iprot.skip(ftype) 498 | elif fid == 28: 499 | if ftype == TType.I32: 500 | self.md_qid27_to_tm_q = iprot.readI32(); 501 | else: 502 | iprot.skip(ftype) 503 | elif fid == 29: 504 | if ftype == TType.I32: 505 | self.md_qid28_to_tm_q = iprot.readI32(); 506 | else: 507 | iprot.skip(ftype) 508 | elif fid == 30: 509 | if ftype == TType.I32: 510 | self.md_qid29_to_tm_q = iprot.readI32(); 511 | else: 512 | iprot.skip(ftype) 513 | elif fid == 31: 514 | if ftype == TType.I32: 515 | self.md_qid30_to_tm_q = iprot.readI32(); 516 | else: 517 | iprot.skip(ftype) 518 | elif fid == 32: 519 | if ftype == TType.I32: 520 | self.md_qid31_to_tm_q = iprot.readI32(); 521 | else: 522 | iprot.skip(ftype) 523 | elif fid == 33: 524 | if ftype == TType.I32: 525 | self.q_count = iprot.readI32(); 526 | else: 527 | iprot.skip(ftype) 528 | else: 529 | iprot.skip(ftype) 530 | iprot.readFieldEnd() 531 | iprot.readStructEnd() 532 | 533 | def write(self, oprot): 534 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 535 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 536 | return 537 | oprot.writeStructBegin('tm_q_map_t') 538 | if self.md_qid0_to_tm_q is not None: 539 | oprot.writeFieldBegin('md_qid0_to_tm_q', TType.I32, 1) 540 | oprot.writeI32(self.md_qid0_to_tm_q) 541 | oprot.writeFieldEnd() 542 | if self.md_qid1_to_tm_q is not None: 543 | oprot.writeFieldBegin('md_qid1_to_tm_q', TType.I32, 2) 544 | oprot.writeI32(self.md_qid1_to_tm_q) 545 | oprot.writeFieldEnd() 546 | if self.md_qid2_to_tm_q is not None: 547 | oprot.writeFieldBegin('md_qid2_to_tm_q', TType.I32, 3) 548 | oprot.writeI32(self.md_qid2_to_tm_q) 549 | oprot.writeFieldEnd() 550 | if self.md_qid3_to_tm_q is not None: 551 | oprot.writeFieldBegin('md_qid3_to_tm_q', TType.I32, 4) 552 | oprot.writeI32(self.md_qid3_to_tm_q) 553 | oprot.writeFieldEnd() 554 | if self.md_qid4_to_tm_q is not None: 555 | oprot.writeFieldBegin('md_qid4_to_tm_q', TType.I32, 5) 556 | oprot.writeI32(self.md_qid4_to_tm_q) 557 | oprot.writeFieldEnd() 558 | if self.md_qid5_to_tm_q is not None: 559 | oprot.writeFieldBegin('md_qid5_to_tm_q', TType.I32, 6) 560 | oprot.writeI32(self.md_qid5_to_tm_q) 561 | oprot.writeFieldEnd() 562 | if self.md_qid6_to_tm_q is not None: 563 | oprot.writeFieldBegin('md_qid6_to_tm_q', TType.I32, 7) 564 | oprot.writeI32(self.md_qid6_to_tm_q) 565 | oprot.writeFieldEnd() 566 | if self.md_qid7_to_tm_q is not None: 567 | oprot.writeFieldBegin('md_qid7_to_tm_q', TType.I32, 8) 568 | oprot.writeI32(self.md_qid7_to_tm_q) 569 | oprot.writeFieldEnd() 570 | if self.md_qid8_to_tm_q is not None: 571 | oprot.writeFieldBegin('md_qid8_to_tm_q', TType.I32, 9) 572 | oprot.writeI32(self.md_qid8_to_tm_q) 573 | oprot.writeFieldEnd() 574 | if self.md_qid9_to_tm_q is not None: 575 | oprot.writeFieldBegin('md_qid9_to_tm_q', TType.I32, 10) 576 | oprot.writeI32(self.md_qid9_to_tm_q) 577 | oprot.writeFieldEnd() 578 | if self.md_qid10_to_tm_q is not None: 579 | oprot.writeFieldBegin('md_qid10_to_tm_q', TType.I32, 11) 580 | oprot.writeI32(self.md_qid10_to_tm_q) 581 | oprot.writeFieldEnd() 582 | if self.md_qid11_to_tm_q is not None: 583 | oprot.writeFieldBegin('md_qid11_to_tm_q', TType.I32, 12) 584 | oprot.writeI32(self.md_qid11_to_tm_q) 585 | oprot.writeFieldEnd() 586 | if self.md_qid12_to_tm_q is not None: 587 | oprot.writeFieldBegin('md_qid12_to_tm_q', TType.I32, 13) 588 | oprot.writeI32(self.md_qid12_to_tm_q) 589 | oprot.writeFieldEnd() 590 | if self.md_qid13_to_tm_q is not None: 591 | oprot.writeFieldBegin('md_qid13_to_tm_q', TType.I32, 14) 592 | oprot.writeI32(self.md_qid13_to_tm_q) 593 | oprot.writeFieldEnd() 594 | if self.md_qid14_to_tm_q is not None: 595 | oprot.writeFieldBegin('md_qid14_to_tm_q', TType.I32, 15) 596 | oprot.writeI32(self.md_qid14_to_tm_q) 597 | oprot.writeFieldEnd() 598 | if self.md_qid15_to_tm_q is not None: 599 | oprot.writeFieldBegin('md_qid15_to_tm_q', TType.I32, 16) 600 | oprot.writeI32(self.md_qid15_to_tm_q) 601 | oprot.writeFieldEnd() 602 | if self.md_qid16_to_tm_q is not None: 603 | oprot.writeFieldBegin('md_qid16_to_tm_q', TType.I32, 17) 604 | oprot.writeI32(self.md_qid16_to_tm_q) 605 | oprot.writeFieldEnd() 606 | if self.md_qid17_to_tm_q is not None: 607 | oprot.writeFieldBegin('md_qid17_to_tm_q', TType.I32, 18) 608 | oprot.writeI32(self.md_qid17_to_tm_q) 609 | oprot.writeFieldEnd() 610 | if self.md_qid18_to_tm_q is not None: 611 | oprot.writeFieldBegin('md_qid18_to_tm_q', TType.I32, 19) 612 | oprot.writeI32(self.md_qid18_to_tm_q) 613 | oprot.writeFieldEnd() 614 | if self.md_qid19_to_tm_q is not None: 615 | oprot.writeFieldBegin('md_qid19_to_tm_q', TType.I32, 20) 616 | oprot.writeI32(self.md_qid19_to_tm_q) 617 | oprot.writeFieldEnd() 618 | if self.md_qid20_to_tm_q is not None: 619 | oprot.writeFieldBegin('md_qid20_to_tm_q', TType.I32, 21) 620 | oprot.writeI32(self.md_qid20_to_tm_q) 621 | oprot.writeFieldEnd() 622 | if self.md_qid21_to_tm_q is not None: 623 | oprot.writeFieldBegin('md_qid21_to_tm_q', TType.I32, 22) 624 | oprot.writeI32(self.md_qid21_to_tm_q) 625 | oprot.writeFieldEnd() 626 | if self.md_qid22_to_tm_q is not None: 627 | oprot.writeFieldBegin('md_qid22_to_tm_q', TType.I32, 23) 628 | oprot.writeI32(self.md_qid22_to_tm_q) 629 | oprot.writeFieldEnd() 630 | if self.md_qid23_to_tm_q is not None: 631 | oprot.writeFieldBegin('md_qid23_to_tm_q', TType.I32, 24) 632 | oprot.writeI32(self.md_qid23_to_tm_q) 633 | oprot.writeFieldEnd() 634 | if self.md_qid24_to_tm_q is not None: 635 | oprot.writeFieldBegin('md_qid24_to_tm_q', TType.I32, 25) 636 | oprot.writeI32(self.md_qid24_to_tm_q) 637 | oprot.writeFieldEnd() 638 | if self.md_qid25_to_tm_q is not None: 639 | oprot.writeFieldBegin('md_qid25_to_tm_q', TType.I32, 26) 640 | oprot.writeI32(self.md_qid25_to_tm_q) 641 | oprot.writeFieldEnd() 642 | if self.md_qid26_to_tm_q is not None: 643 | oprot.writeFieldBegin('md_qid26_to_tm_q', TType.I32, 27) 644 | oprot.writeI32(self.md_qid26_to_tm_q) 645 | oprot.writeFieldEnd() 646 | if self.md_qid27_to_tm_q is not None: 647 | oprot.writeFieldBegin('md_qid27_to_tm_q', TType.I32, 28) 648 | oprot.writeI32(self.md_qid27_to_tm_q) 649 | oprot.writeFieldEnd() 650 | if self.md_qid28_to_tm_q is not None: 651 | oprot.writeFieldBegin('md_qid28_to_tm_q', TType.I32, 29) 652 | oprot.writeI32(self.md_qid28_to_tm_q) 653 | oprot.writeFieldEnd() 654 | if self.md_qid29_to_tm_q is not None: 655 | oprot.writeFieldBegin('md_qid29_to_tm_q', TType.I32, 30) 656 | oprot.writeI32(self.md_qid29_to_tm_q) 657 | oprot.writeFieldEnd() 658 | if self.md_qid30_to_tm_q is not None: 659 | oprot.writeFieldBegin('md_qid30_to_tm_q', TType.I32, 31) 660 | oprot.writeI32(self.md_qid30_to_tm_q) 661 | oprot.writeFieldEnd() 662 | if self.md_qid31_to_tm_q is not None: 663 | oprot.writeFieldBegin('md_qid31_to_tm_q', TType.I32, 32) 664 | oprot.writeI32(self.md_qid31_to_tm_q) 665 | oprot.writeFieldEnd() 666 | if self.q_count is not None: 667 | oprot.writeFieldBegin('q_count', TType.I32, 33) 668 | oprot.writeI32(self.q_count) 669 | oprot.writeFieldEnd() 670 | oprot.writeFieldStop() 671 | oprot.writeStructEnd() 672 | 673 | def validate(self): 674 | return 675 | 676 | 677 | def __hash__(self): 678 | value = 17 679 | value = (value * 31) ^ hash(self.md_qid0_to_tm_q) 680 | value = (value * 31) ^ hash(self.md_qid1_to_tm_q) 681 | value = (value * 31) ^ hash(self.md_qid2_to_tm_q) 682 | value = (value * 31) ^ hash(self.md_qid3_to_tm_q) 683 | value = (value * 31) ^ hash(self.md_qid4_to_tm_q) 684 | value = (value * 31) ^ hash(self.md_qid5_to_tm_q) 685 | value = (value * 31) ^ hash(self.md_qid6_to_tm_q) 686 | value = (value * 31) ^ hash(self.md_qid7_to_tm_q) 687 | value = (value * 31) ^ hash(self.md_qid8_to_tm_q) 688 | value = (value * 31) ^ hash(self.md_qid9_to_tm_q) 689 | value = (value * 31) ^ hash(self.md_qid10_to_tm_q) 690 | value = (value * 31) ^ hash(self.md_qid11_to_tm_q) 691 | value = (value * 31) ^ hash(self.md_qid12_to_tm_q) 692 | value = (value * 31) ^ hash(self.md_qid13_to_tm_q) 693 | value = (value * 31) ^ hash(self.md_qid14_to_tm_q) 694 | value = (value * 31) ^ hash(self.md_qid15_to_tm_q) 695 | value = (value * 31) ^ hash(self.md_qid16_to_tm_q) 696 | value = (value * 31) ^ hash(self.md_qid17_to_tm_q) 697 | value = (value * 31) ^ hash(self.md_qid18_to_tm_q) 698 | value = (value * 31) ^ hash(self.md_qid19_to_tm_q) 699 | value = (value * 31) ^ hash(self.md_qid20_to_tm_q) 700 | value = (value * 31) ^ hash(self.md_qid21_to_tm_q) 701 | value = (value * 31) ^ hash(self.md_qid22_to_tm_q) 702 | value = (value * 31) ^ hash(self.md_qid23_to_tm_q) 703 | value = (value * 31) ^ hash(self.md_qid24_to_tm_q) 704 | value = (value * 31) ^ hash(self.md_qid25_to_tm_q) 705 | value = (value * 31) ^ hash(self.md_qid26_to_tm_q) 706 | value = (value * 31) ^ hash(self.md_qid27_to_tm_q) 707 | value = (value * 31) ^ hash(self.md_qid28_to_tm_q) 708 | value = (value * 31) ^ hash(self.md_qid29_to_tm_q) 709 | value = (value * 31) ^ hash(self.md_qid30_to_tm_q) 710 | value = (value * 31) ^ hash(self.md_qid31_to_tm_q) 711 | value = (value * 31) ^ hash(self.q_count) 712 | return value 713 | 714 | def __repr__(self): 715 | L = ['%s=%r' % (key, value) 716 | for key, value in self.__dict__.items()] 717 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 718 | 719 | def __eq__(self, other): 720 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 721 | 722 | def __ne__(self, other): 723 | return not (self == other) 724 | 725 | class tm_shaper_rate_t: 726 | """ 727 | Attributes: 728 | - pps 729 | - burst_size 730 | - rate 731 | """ 732 | 733 | thrift_spec = ( 734 | None, # 0 735 | (1, TType.BOOL, 'pps', None, None, ), # 1 736 | (2, TType.I32, 'burst_size', None, None, ), # 2 737 | (3, TType.I32, 'rate', None, None, ), # 3 738 | ) 739 | 740 | def __init__(self, pps=None, burst_size=None, rate=None,): 741 | self.pps = pps 742 | self.burst_size = burst_size 743 | self.rate = rate 744 | 745 | def read(self, iprot): 746 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 747 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 748 | return 749 | iprot.readStructBegin() 750 | while True: 751 | (fname, ftype, fid) = iprot.readFieldBegin() 752 | if ftype == TType.STOP: 753 | break 754 | if fid == 1: 755 | if ftype == TType.BOOL: 756 | self.pps = iprot.readBool(); 757 | else: 758 | iprot.skip(ftype) 759 | elif fid == 2: 760 | if ftype == TType.I32: 761 | self.burst_size = iprot.readI32(); 762 | else: 763 | iprot.skip(ftype) 764 | elif fid == 3: 765 | if ftype == TType.I32: 766 | self.rate = iprot.readI32(); 767 | else: 768 | iprot.skip(ftype) 769 | else: 770 | iprot.skip(ftype) 771 | iprot.readFieldEnd() 772 | iprot.readStructEnd() 773 | 774 | def write(self, oprot): 775 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 776 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 777 | return 778 | oprot.writeStructBegin('tm_shaper_rate_t') 779 | if self.pps is not None: 780 | oprot.writeFieldBegin('pps', TType.BOOL, 1) 781 | oprot.writeBool(self.pps) 782 | oprot.writeFieldEnd() 783 | if self.burst_size is not None: 784 | oprot.writeFieldBegin('burst_size', TType.I32, 2) 785 | oprot.writeI32(self.burst_size) 786 | oprot.writeFieldEnd() 787 | if self.rate is not None: 788 | oprot.writeFieldBegin('rate', TType.I32, 3) 789 | oprot.writeI32(self.rate) 790 | oprot.writeFieldEnd() 791 | oprot.writeFieldStop() 792 | oprot.writeStructEnd() 793 | 794 | def validate(self): 795 | return 796 | 797 | 798 | def __hash__(self): 799 | value = 17 800 | value = (value * 31) ^ hash(self.pps) 801 | value = (value * 31) ^ hash(self.burst_size) 802 | value = (value * 31) ^ hash(self.rate) 803 | return value 804 | 805 | def __repr__(self): 806 | L = ['%s=%r' % (key, value) 807 | for key, value in self.__dict__.items()] 808 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 809 | 810 | def __eq__(self, other): 811 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 812 | 813 | def __ne__(self, other): 814 | return not (self == other) 815 | 816 | class tm_pool_usage_t: 817 | """ 818 | Attributes: 819 | - pool 820 | - base_use_limit 821 | - dynamic_baf 822 | - hysteresis 823 | """ 824 | 825 | thrift_spec = ( 826 | None, # 0 827 | (1, TType.I32, 'pool', None, None, ), # 1 828 | (2, TType.I32, 'base_use_limit', None, None, ), # 2 829 | (3, TType.I32, 'dynamic_baf', None, None, ), # 3 830 | (4, TType.I32, 'hysteresis', None, None, ), # 4 831 | ) 832 | 833 | def __init__(self, pool=None, base_use_limit=None, dynamic_baf=None, hysteresis=None,): 834 | self.pool = pool 835 | self.base_use_limit = base_use_limit 836 | self.dynamic_baf = dynamic_baf 837 | self.hysteresis = hysteresis 838 | 839 | def read(self, iprot): 840 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 841 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 842 | return 843 | iprot.readStructBegin() 844 | while True: 845 | (fname, ftype, fid) = iprot.readFieldBegin() 846 | if ftype == TType.STOP: 847 | break 848 | if fid == 1: 849 | if ftype == TType.I32: 850 | self.pool = iprot.readI32(); 851 | else: 852 | iprot.skip(ftype) 853 | elif fid == 2: 854 | if ftype == TType.I32: 855 | self.base_use_limit = iprot.readI32(); 856 | else: 857 | iprot.skip(ftype) 858 | elif fid == 3: 859 | if ftype == TType.I32: 860 | self.dynamic_baf = iprot.readI32(); 861 | else: 862 | iprot.skip(ftype) 863 | elif fid == 4: 864 | if ftype == TType.I32: 865 | self.hysteresis = iprot.readI32(); 866 | else: 867 | iprot.skip(ftype) 868 | else: 869 | iprot.skip(ftype) 870 | iprot.readFieldEnd() 871 | iprot.readStructEnd() 872 | 873 | def write(self, oprot): 874 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 875 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 876 | return 877 | oprot.writeStructBegin('tm_pool_usage_t') 878 | if self.pool is not None: 879 | oprot.writeFieldBegin('pool', TType.I32, 1) 880 | oprot.writeI32(self.pool) 881 | oprot.writeFieldEnd() 882 | if self.base_use_limit is not None: 883 | oprot.writeFieldBegin('base_use_limit', TType.I32, 2) 884 | oprot.writeI32(self.base_use_limit) 885 | oprot.writeFieldEnd() 886 | if self.dynamic_baf is not None: 887 | oprot.writeFieldBegin('dynamic_baf', TType.I32, 3) 888 | oprot.writeI32(self.dynamic_baf) 889 | oprot.writeFieldEnd() 890 | if self.hysteresis is not None: 891 | oprot.writeFieldBegin('hysteresis', TType.I32, 4) 892 | oprot.writeI32(self.hysteresis) 893 | oprot.writeFieldEnd() 894 | oprot.writeFieldStop() 895 | oprot.writeStructEnd() 896 | 897 | def validate(self): 898 | return 899 | 900 | 901 | def __hash__(self): 902 | value = 17 903 | value = (value * 31) ^ hash(self.pool) 904 | value = (value * 31) ^ hash(self.base_use_limit) 905 | value = (value * 31) ^ hash(self.dynamic_baf) 906 | value = (value * 31) ^ hash(self.hysteresis) 907 | return value 908 | 909 | def __repr__(self): 910 | L = ['%s=%r' % (key, value) 911 | for key, value in self.__dict__.items()] 912 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 913 | 914 | def __eq__(self, other): 915 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 916 | 917 | def __ne__(self, other): 918 | return not (self == other) 919 | 920 | class tm_ppg_usage_t: 921 | """ 922 | Attributes: 923 | - gmin_count 924 | - shared_count 925 | - skid_count 926 | - wm 927 | """ 928 | 929 | thrift_spec = ( 930 | None, # 0 931 | (1, TType.I32, 'gmin_count', None, None, ), # 1 932 | (2, TType.I32, 'shared_count', None, None, ), # 2 933 | (3, TType.I32, 'skid_count', None, None, ), # 3 934 | (4, TType.I32, 'wm', None, None, ), # 4 935 | ) 936 | 937 | def __init__(self, gmin_count=None, shared_count=None, skid_count=None, wm=None,): 938 | self.gmin_count = gmin_count 939 | self.shared_count = shared_count 940 | self.skid_count = skid_count 941 | self.wm = wm 942 | 943 | def read(self, iprot): 944 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 945 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 946 | return 947 | iprot.readStructBegin() 948 | while True: 949 | (fname, ftype, fid) = iprot.readFieldBegin() 950 | if ftype == TType.STOP: 951 | break 952 | if fid == 1: 953 | if ftype == TType.I32: 954 | self.gmin_count = iprot.readI32(); 955 | else: 956 | iprot.skip(ftype) 957 | elif fid == 2: 958 | if ftype == TType.I32: 959 | self.shared_count = iprot.readI32(); 960 | else: 961 | iprot.skip(ftype) 962 | elif fid == 3: 963 | if ftype == TType.I32: 964 | self.skid_count = iprot.readI32(); 965 | else: 966 | iprot.skip(ftype) 967 | elif fid == 4: 968 | if ftype == TType.I32: 969 | self.wm = iprot.readI32(); 970 | else: 971 | iprot.skip(ftype) 972 | else: 973 | iprot.skip(ftype) 974 | iprot.readFieldEnd() 975 | iprot.readStructEnd() 976 | 977 | def write(self, oprot): 978 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 979 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 980 | return 981 | oprot.writeStructBegin('tm_ppg_usage_t') 982 | if self.gmin_count is not None: 983 | oprot.writeFieldBegin('gmin_count', TType.I32, 1) 984 | oprot.writeI32(self.gmin_count) 985 | oprot.writeFieldEnd() 986 | if self.shared_count is not None: 987 | oprot.writeFieldBegin('shared_count', TType.I32, 2) 988 | oprot.writeI32(self.shared_count) 989 | oprot.writeFieldEnd() 990 | if self.skid_count is not None: 991 | oprot.writeFieldBegin('skid_count', TType.I32, 3) 992 | oprot.writeI32(self.skid_count) 993 | oprot.writeFieldEnd() 994 | if self.wm is not None: 995 | oprot.writeFieldBegin('wm', TType.I32, 4) 996 | oprot.writeI32(self.wm) 997 | oprot.writeFieldEnd() 998 | oprot.writeFieldStop() 999 | oprot.writeStructEnd() 1000 | 1001 | def validate(self): 1002 | return 1003 | 1004 | 1005 | def __hash__(self): 1006 | value = 17 1007 | value = (value * 31) ^ hash(self.gmin_count) 1008 | value = (value * 31) ^ hash(self.shared_count) 1009 | value = (value * 31) ^ hash(self.skid_count) 1010 | value = (value * 31) ^ hash(self.wm) 1011 | return value 1012 | 1013 | def __repr__(self): 1014 | L = ['%s=%r' % (key, value) 1015 | for key, value in self.__dict__.items()] 1016 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 1017 | 1018 | def __eq__(self, other): 1019 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 1020 | 1021 | def __ne__(self, other): 1022 | return not (self == other) 1023 | 1024 | class tm_usage_t: 1025 | """ 1026 | Attributes: 1027 | - count 1028 | - wm 1029 | """ 1030 | 1031 | thrift_spec = ( 1032 | None, # 0 1033 | (1, TType.I32, 'count', None, None, ), # 1 1034 | (2, TType.I32, 'wm', None, None, ), # 2 1035 | ) 1036 | 1037 | def __init__(self, count=None, wm=None,): 1038 | self.count = count 1039 | self.wm = wm 1040 | 1041 | def read(self, iprot): 1042 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 1043 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 1044 | return 1045 | iprot.readStructBegin() 1046 | while True: 1047 | (fname, ftype, fid) = iprot.readFieldBegin() 1048 | if ftype == TType.STOP: 1049 | break 1050 | if fid == 1: 1051 | if ftype == TType.I32: 1052 | self.count = iprot.readI32(); 1053 | else: 1054 | iprot.skip(ftype) 1055 | elif fid == 2: 1056 | if ftype == TType.I32: 1057 | self.wm = iprot.readI32(); 1058 | else: 1059 | iprot.skip(ftype) 1060 | else: 1061 | iprot.skip(ftype) 1062 | iprot.readFieldEnd() 1063 | iprot.readStructEnd() 1064 | 1065 | def write(self, oprot): 1066 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 1067 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 1068 | return 1069 | oprot.writeStructBegin('tm_usage_t') 1070 | if self.count is not None: 1071 | oprot.writeFieldBegin('count', TType.I32, 1) 1072 | oprot.writeI32(self.count) 1073 | oprot.writeFieldEnd() 1074 | if self.wm is not None: 1075 | oprot.writeFieldBegin('wm', TType.I32, 2) 1076 | oprot.writeI32(self.wm) 1077 | oprot.writeFieldEnd() 1078 | oprot.writeFieldStop() 1079 | oprot.writeStructEnd() 1080 | 1081 | def validate(self): 1082 | return 1083 | 1084 | 1085 | def __hash__(self): 1086 | value = 17 1087 | value = (value * 31) ^ hash(self.count) 1088 | value = (value * 31) ^ hash(self.wm) 1089 | return value 1090 | 1091 | def __repr__(self): 1092 | L = ['%s=%r' % (key, value) 1093 | for key, value in self.__dict__.items()] 1094 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 1095 | 1096 | def __eq__(self, other): 1097 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 1098 | 1099 | def __ne__(self, other): 1100 | return not (self == other) 1101 | -------------------------------------------------------------------------------- /targets/tofino/run_switchd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # set SDE and SDE_INSTALL variable to default values 3 | : ${SDE=/opt/bf-sde-9.9.1} 4 | : ${SDE_INSTALL=$SDE/install} 5 | 6 | $SDE/run_switchd.sh -c compile/l1switchCodel.conf 7 | -------------------------------------------------------------------------------- /targets/tofino/set_shape_rate.py: -------------------------------------------------------------------------------- 1 | from pd_fixed.pd_fixed_api import PDFixedConnect 2 | 3 | if __name__ == '__main__': 4 | pd = PDFixedConnect("127.0.0.1") 5 | pd.set_port_shaping_rate(153, 100000) 6 | pd.enable_port_shaping(153) 7 | -------------------------------------------------------------------------------- /targets/tofino/srcP4/CoDel.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-present Ralf Kundel 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 | #define SOJOURN_TARGET 5000000 //in nsec 18 | #define CONTROL_INTERVAL 100000000 //in nsec 19 | 20 | struct register_operations { 21 | bit<32> val1; 22 | bit<32> val2; 23 | } 24 | 25 | struct codel_metadata_t{ 26 | bit<32> egress_tstamp; 27 | bit<32> queue_delay; 28 | bit<32> sojourn_remainder; 29 | bit<1> sojourn_violation; 30 | bit<1> first_sojourn_violation; 31 | bit<1> codel_drop; 32 | } 33 | 34 | control CoDelEgress (in bit<48> ingress_tstamp, 35 | in bit<48> egress_tstamp, 36 | in bit<9> egress_port, 37 | inout egress_intrinsic_metadata_for_deparser_t eg_intr_md_for_dprsr){ 38 | 39 | codel_metadata_t codel_metadata; 40 | 41 | //Stateful ALU1 42 | Register< bit<32>, bit<9> > (32w512) codel_drop_state; 43 | RegisterAction, bit<9>, bit<1> >(codel_drop_state) codel_drop_state_action = { 44 | void apply(inout bit<32> drop_state, out bit<1> first_soujourn_violation){ 45 | if(drop_state== 32w0x0 && codel_metadata.sojourn_violation == 1w0x1){ 46 | first_soujourn_violation = 1w0x1; 47 | }else{ 48 | first_soujourn_violation = 1w0x0; 49 | } 50 | if(codel_metadata.sojourn_violation == 1w0x1){ 51 | drop_state = 32w0x1; 52 | }else { 53 | drop_state = 32w0x0; 54 | } 55 | } 56 | 57 | }; 58 | 59 | //Stateful ALU2 60 | MathUnit< bit<32> > (true, -1, 20, 61 | {0x46, 0x48, 0x4b, 0x4e, 62 | 0x52, 0x56, 0x5a, 0x60, 63 | 0x66, 0x6f, 0x79, 0x87, 64 | 0x0, 0x0, 0x0, 0x0}) sqrtn; 65 | Register< register_operations, bit<9>> (32w512) codel_salu_2; 66 | RegisterAction, bit<1> >(codel_salu_2) codel_salu_2_action = { 67 | void apply(inout register_operations inout_vals, out bit<1> out_val){ 68 | //val2 == drop count 69 | //val1 == next_drop_time 70 | out_val = 1w0x0; 71 | if(codel_metadata.first_sojourn_violation == 1w0x1){ 72 | inout_vals.val1 = codel_metadata.egress_tstamp + CONTROL_INTERVAL; 73 | inout_vals.val2 = 1; 74 | } else 75 | if(codel_metadata.egress_tstamp > inout_vals.val1) { 76 | //we want to drop 77 | inout_vals.val2 = inout_vals.val2 + 1; 78 | inout_vals.val1 = inout_vals.val1 + sqrtn.execute(inout_vals.val2); 79 | out_val = 1w0x1; 80 | } 81 | } 82 | 83 | }; 84 | 85 | action a_compute_remainder(){ 86 | codel_metadata.sojourn_remainder = SOJOURN_TARGET |-| codel_metadata.queue_delay; 87 | } 88 | 89 | table t_compute_remainder { 90 | actions = { 91 | a_compute_remainder; 92 | } 93 | default_action = a_compute_remainder; 94 | } 95 | 96 | action a_drop(){ 97 | eg_intr_md_for_dprsr.drop_ctl = 3w0x1; 98 | } 99 | 100 | apply{ 101 | eg_intr_md_for_dprsr.drop_ctl = 3w0x0; //default value, otherwise the value is undefined in case of "non dropping" and everything can happen 102 | 103 | codel_metadata.egress_tstamp = (bit<32>) egress_tstamp; 104 | codel_metadata.queue_delay = (bit<32>)(egress_tstamp - ingress_tstamp); 105 | 106 | t_compute_remainder.apply(); 107 | if(codel_metadata.sojourn_remainder == 0){ 108 | codel_metadata.sojourn_violation = 1w0x1; 109 | }else{ 110 | codel_metadata.sojourn_violation = 1w0x0; 111 | } 112 | codel_metadata.first_sojourn_violation = codel_drop_state_action.execute(egress_port); 113 | codel_metadata.codel_drop = codel_salu_2_action.execute(egress_port); 114 | if( (codel_metadata.codel_drop == 1w0x1) && (codel_metadata.sojourn_violation == 1w0x1) ){ 115 | a_drop(); 116 | } 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /targets/tofino/srcP4/header.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-present Ralf Kundel 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 | header ethernet_t { 18 | bit<48> dstAddr; 19 | bit<48> srcAddr; 20 | bit<16> etherType; 21 | } 22 | 23 | 24 | struct headers_t { 25 | ethernet_t ethernet; 26 | } 27 | 28 | header bridged_metadata_t { 29 | bit<48> ingress_tstamp; 30 | } 31 | 32 | struct my_metadata_t { 33 | bridged_metadata_t bridged_metadata; 34 | } 35 | -------------------------------------------------------------------------------- /targets/tofino/srcP4/l1switchCodel.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-present Ralf Kundel 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 | #include 18 | #include 19 | #include "header.p4" 20 | #include "CoDel.p4" 21 | 22 | parser SwitchIngressParser(packet_in packet, out headers_t hdr, out my_metadata_t meta, out ingress_intrinsic_metadata_t ig_intr_md) { 23 | 24 | state start { 25 | packet.extract(ig_intr_md); 26 | packet.advance(PORT_METADATA_SIZE); 27 | packet.extract(hdr.ethernet); 28 | transition accept; 29 | } 30 | 31 | } 32 | 33 | control SwitchIngress( 34 | inout headers_t hdr, 35 | inout my_metadata_t meta, 36 | in ingress_intrinsic_metadata_t ig_intr_md, 37 | in ingress_intrinsic_metadata_from_parser_t ig_intr_parser_md, 38 | inout ingress_intrinsic_metadata_for_deparser_t ig_intr_md_for_dprsr, 39 | inout ingress_intrinsic_metadata_for_tm_t ig_intr_tm_md) { 40 | 41 | action send(bit<9> egress_port) { 42 | ig_intr_tm_md.ucast_egress_port = egress_port; 43 | } 44 | 45 | table t_l1_forwarding { 46 | key = { 47 | ig_intr_md.ingress_port : exact; 48 | } 49 | actions = { 50 | send; 51 | } 52 | size = 64; 53 | } 54 | 55 | 56 | 57 | apply{ 58 | t_l1_forwarding.apply(); 59 | meta.bridged_metadata.setValid(); 60 | meta.bridged_metadata.ingress_tstamp = ig_intr_parser_md.global_tstamp; 61 | } 62 | } 63 | 64 | control SwitchIngressDeparser(packet_out packet, inout headers_t hdr, in my_metadata_t meta, in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 65 | apply { 66 | packet.emit(meta.bridged_metadata); 67 | packet.emit(hdr); 68 | } 69 | 70 | } 71 | 72 | parser SwitchEgressParser(packet_in packet, out headers_t hdr, out my_metadata_t meta, out egress_intrinsic_metadata_t eg_intr_md) { 73 | state start { 74 | packet.extract(eg_intr_md); 75 | packet.extract(meta.bridged_metadata); 76 | packet.extract(hdr.ethernet); 77 | transition accept; 78 | } 79 | 80 | } 81 | 82 | 83 | control SwitchEgress( 84 | inout headers_t hdr, 85 | inout my_metadata_t meta, 86 | in egress_intrinsic_metadata_t eg_intr_md, 87 | in egress_intrinsic_metadata_from_parser_t eg_intr_parser_md, 88 | inout egress_intrinsic_metadata_for_deparser_t eg_intr_md_for_dprsr, 89 | inout egress_intrinsic_metadata_for_output_port_t eg_intr_md_for_oport) { 90 | 91 | CoDelEgress() codel_egress; 92 | 93 | apply{ 94 | codel_egress.apply( meta.bridged_metadata.ingress_tstamp, 95 | eg_intr_parser_md.global_tstamp, 96 | eg_intr_md.egress_port, 97 | eg_intr_md_for_dprsr); 98 | } 99 | 100 | } 101 | 102 | control SwitchEgressDeparser(packet_out packet, inout headers_t hdr, in my_metadata_t meta, in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) { 103 | apply { 104 | packet.emit(hdr); 105 | } 106 | 107 | } 108 | 109 | 110 | Pipeline(SwitchIngressParser(), 111 | SwitchIngress(), 112 | SwitchIngressDeparser(), 113 | SwitchEgressParser(), 114 | SwitchEgress(), 115 | SwitchEgressDeparser()) pipe; 116 | 117 | Switch(pipe) main; 118 | --------------------------------------------------------------------------------