├── .gitignore ├── Makefile ├── README.md ├── src ├── hyperv.p4 └── include │ ├── action.p4 │ ├── checksum.p4 │ ├── config.p4 │ ├── control.p4 │ ├── define.p4 │ ├── execute.p4 │ ├── field-lists.p4 │ ├── headers.p4 │ ├── intrinsic.p4 │ ├── metadata.p4 │ ├── parser.p4 │ ├── stateful.p4 │ └── template.p4 ├── tests ├── hyperv │ ├── arp_proxy │ │ ├── commands │ │ └── conf.json │ ├── firewall │ │ ├── commands │ │ └── conf.json │ ├── l2_switch │ │ ├── commands │ │ └── conf.json │ ├── l2_with_fw │ │ ├── commands │ │ └── conf.json │ ├── napt │ │ ├── commands │ │ └── conf.json │ ├── nat │ │ ├── commands │ │ └── conf.json │ ├── router │ │ ├── commands │ │ └── conf.json │ └── stateful_tcp_firewall │ │ └── conf.json └── p4 │ ├── arp_proxy │ ├── arp_proxy.p4 │ └── commands │ ├── firewall │ ├── commands │ ├── conf.json │ └── firewall.p4 │ ├── l2_switch │ ├── commands │ ├── conf.json │ └── l2_switch.p4 │ ├── l2_with_fw │ ├── commands │ ├── conf.json │ └── l2_with_fw.p4 │ ├── napt │ ├── commands │ └── napt.p4 │ ├── nat │ ├── commands │ ├── conf.json │ └── nat.p4 │ ├── router │ ├── commands │ ├── conf.json │ └── router.p4 │ └── stateful_tcp_firewall │ ├── commands │ └── stateful_tcp_firewall.p4 └── tools ├── clear ├── populate └── setup /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | cmake-build-debug/ 3 | CMakeLists.txt 4 | bmv2/.idea 5 | bmv2/cmake-build-debug/ 6 | controller/.idea/ 7 | controller/cmake-build-debug/ 8 | controller/CMakeLists.txt 9 | controller/hyperv/controller 10 | controller/hyper4/controller 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BMv2_DIR=/home/netarchlab/behavioral-model/targets/simple_switch 2 | MAIN_FILE=hyperv.p4 3 | COMMIT_REASON=?"defaut commit" 4 | LOG="--log-console" 5 | INTF1="-i 1@p4p1" 6 | INTF2="-i 2@p4p2" 7 | 8 | 9 | compile: 10 | @mkdir -p build 11 | @p4c-bmv2 src/${MAIN_FILE} --json build/hyperv.json 12 | 13 | clean: 14 | @rm -rf build 15 | 16 | git: 17 | @git add -A 18 | @git commit -a -m $COMMIT_REASON 19 | @git push -u origin master 20 | 21 | run: 22 | @cp build/hyperv.json $(BMv2_DIR) 23 | @cd $(BMv2_DIR)&&sudo bash simple_switch hyperv.json $(INTF1) $(INTF2) $(LOG) 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HyperV: High-Performance Virtualization of the Programmable Data Plane 2 | 3 | 4 | ## NOTICE 5 | 6 | As the codebase of HyperV has changed a lot since ICCCN'17, the [test cases](/tests) are not modified accordingly. So we are not sure that the test cases can work. However, we provide a [runtime controller](https://github.com/HyperVDP/HyperV-Controller.git) which provisions a high-level abstraction of HyperV based on [P4Runtime](https://github.com/p4lang/PI). We will give a logn-term support to the runtime controller. Thus we recommand you to use the runtime controller to manage the hypervisor. If you have any question, please refer Cheng Zhang at [cheng-zhang13@mails.tsinghua.edu.cn](cheng-zhang13@mails.tsinghua.edu.cn), or Yu Zhou at [y-zhou16@mails.tsinghua.edu.cn](y-zhou16@mails.tsinghua.edu.cn). We are very glad to offer our help and will try our best to answer your questions. 7 | 8 | ## About HyperV 9 | 10 | HyperV is a high-performance hypervisor provisions non-exclusive data plane abstraction and uninterrupted reconfigurability for the programmable data plane. 11 | 12 | ## The project 13 | 14 | ### [src](/src) 15 | 16 | The source code of HyperV. 17 | 18 | ### [tests](/tests) 19 | 20 | The test cases for HyperV. 21 | 22 | ### [tools](/tools) 23 | 24 | The scripts for creating the testing environment. 25 | 26 | -------------------------------------------------------------------------------- /src/hyperv.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2016-present NetArch Lab, Tsinghua University. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include "include/intrinsic.p4" 17 | #include "include/define.p4" 18 | #include "include/action.p4" 19 | #include "include/config.p4" 20 | #include "include/stateful.p4" 21 | #include "include/control.p4" 22 | #include "include/headers.p4" 23 | #include "include/field-lists.p4" 24 | #include "include/metadata.p4" 25 | #include "include/template.p4" 26 | #include "include/execute.p4" 27 | #include "include/checksum.p4" 28 | #include "include/parser.p4" 29 | 30 | //--------------------------------ingress-------------------------- 31 | control ingress { 32 | if (PROG_ID == 0) { 33 | apply(table_config_at_initial); 34 | } 35 | if (PROG_ID != 0 and PROG_ID != 0xFF) { 36 | //--------------------stage 1----------------- 37 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 38 | CONST_CONDITIONAL_STAGE_1) { 39 | conditional_stage1(); 40 | } 41 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 42 | CONST_STAGE_1) { 43 | match_action_stage1(); 44 | } 45 | 46 | //--------------------stage 2----------------- 47 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 48 | CONST_CONDITIONAL_STAGE_2) { 49 | conditional_stage2(); 50 | } 51 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 52 | CONST_STAGE_2) { 53 | match_action_stage2(); 54 | } 55 | 56 | //--------------------stage 3----------------- 57 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 58 | CONST_CONDITIONAL_STAGE_3) { 59 | conditional_stage3(); 60 | } 61 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 62 | CONST_STAGE_3) { 63 | match_action_stage3(); 64 | } 65 | 66 | //--------------------stage 4----------------- 67 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 68 | CONST_CONDITIONAL_STAGE_4) { 69 | conditional_stage4(); 70 | } 71 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 72 | CONST_STAGE_4) { 73 | match_action_stage4(); 74 | } 75 | 76 | //--------------------stage 5----------------- 77 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 78 | CONST_CONDITIONAL_STAGE_5) { 79 | conditional_stage5(); 80 | } 81 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 82 | CONST_STAGE_5) { 83 | match_action_stage5(); 84 | } 85 | 86 | //--------------------stage 6----------------- 87 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 88 | CONST_CONDITIONAL_STAGE_6) { 89 | conditional_stage6(); 90 | } 91 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 92 | CONST_STAGE_6) { 93 | match_action_stage6(); 94 | } 95 | 96 | //--------------------stage 7----------------- 97 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 98 | CONST_CONDITIONAL_STAGE_7) { 99 | conditional_stage7(); 100 | } 101 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 102 | CONST_STAGE_7) { 103 | match_action_stage7(); 104 | } 105 | 106 | //--------------------stage 8----------------- 107 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 108 | CONST_CONDITIONAL_STAGE_8) { 109 | conditional_stage8(); 110 | } 111 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 112 | CONST_STAGE_8) { 113 | match_action_stage8(); 114 | } 115 | 116 | //--------------------stage 8----------------- 117 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 118 | CONST_CONDITIONAL_STAGE_9) { 119 | conditional_stage9(); 120 | } 121 | if (((vdp_metadata.stage_id & CONST_NUM_OF_STAGE)) == 122 | CONST_STAGE_9) { 123 | match_action_stage9(); 124 | } 125 | 126 | 127 | if ((REMOVE_OR_ADD_HEADER == 0) and (PROG_ID != 0xFF)) { 128 | apply(table_config_at_end); 129 | } 130 | } 131 | } 132 | 133 | //---------conditional stage 1------------------------- 134 | CONDITIONAL_STAGE(stage1) 135 | 136 | //---------conditional stage 2------------------------- 137 | CONDITIONAL_STAGE(stage2) 138 | 139 | //---------conditional stage 3------------------------- 140 | CONDITIONAL_STAGE(stage3) 141 | 142 | //---------conditional stage 4------------------------- 143 | CONDITIONAL_STAGE(stage4) 144 | //---------conditional stage 1------------------------- 145 | CONDITIONAL_STAGE(stage5) 146 | 147 | //---------conditional stage 2------------------------- 148 | CONDITIONAL_STAGE(stage6) 149 | 150 | //---------conditional stage 3------------------------- 151 | CONDITIONAL_STAGE(stage7) 152 | 153 | //---------conditional stage 4------------------------- 154 | CONDITIONAL_STAGE(stage8) 155 | 156 | //---------conditional stage 4------------------------- 157 | CONDITIONAL_STAGE(stage9) 158 | 159 | //---------stage 1-------------------------------------- 160 | STAGE(stage1) 161 | 162 | //---------stage 2-------------------------------------- 163 | STAGE(stage2) 164 | 165 | //---------stage 3-------------------------------------- 166 | STAGE(stage3) 167 | 168 | //---------stage 4-------------------------------------- 169 | STAGE(stage4) 170 | 171 | //---------stage 5-------------------------------------- 172 | STAGE(stage5) 173 | 174 | //---------stage 6-------------------------------------- 175 | STAGE(stage6) 176 | 177 | //---------stage 7-------------------------------------- 178 | STAGE(stage7) 179 | 180 | //---------stage 8-------------------------------------- 181 | STAGE(stage8) 182 | 183 | //---------stage 8-------------------------------------- 184 | STAGE(stage9) 185 | 186 | //------------------------egress----------------------- 187 | control egress { 188 | if (REMOVE_OR_ADD_HEADER == 1) { 189 | apply(table_config_at_egress); 190 | } 191 | else if (MOD_FLAG == 1) { 192 | recalculate_checksum(); 193 | apply(dh_deparse); 194 | } 195 | } -------------------------------------------------------------------------------- /src/include/action.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2016-present NetArch Lab, Tsinghua University. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | //*********************************************************** 17 | // HyperV primitives 18 | //*********************************************************** 19 | 20 | /** 21 | * No operation. 22 | */ 23 | action noop() { 24 | 25 | } 26 | 27 | /** 28 | * Count packets with global register. 29 | * @param index <> packet counter index. 30 | */ 31 | action packet_count(index) { 32 | register_read(context_metadata.count, global_register, index); 33 | register_write(global_register, // Global register 34 | index, 35 | context_metadata.count + 1); 36 | } 37 | 38 | /** 39 | * Clear packet counter. 40 | * @param index <> pakcet counter index 41 | */ 42 | action packet_count_clear(index) { 43 | register_write(global_register, index, 0); 44 | } 45 | 46 | /** 47 | * Loop back packets. 48 | */ 49 | action do_loopback() { 50 | modify_field(standard_metadata.egress_spec, 51 | standard_metadata.ingress_port); 52 | } 53 | 54 | 55 | /** 56 | * Set the multicast group. 57 | * @param mcast_grp <> multicast group ID. 58 | */ 59 | action do_multicast(mcast_grp) { 60 | modify_field(intrinsic_metadata.mcast_grp, mcast_grp); 61 | } 62 | 63 | /** 64 | * Set the queue id. 65 | * @param qid <> queue id 66 | */ 67 | action do_queue(qid) { 68 | modify_field(intrinsic_metadata.qid, qid); 69 | } 70 | 71 | /** 72 | * Forward packets 73 | * @param port destination ports 74 | */ 75 | action do_forward(port) { 76 | modify_field(standard_metadata.egress_spec, port); 77 | } 78 | 79 | /** 80 | * Drop packets. 81 | */ 82 | action do_drop() { 83 | drop(); 84 | } 85 | 86 | 87 | /** 88 | * Generate digest to the CPU receiver. 89 | * @param receiver 90 | */ 91 | action do_gen_digest(receiver) { 92 | generate_digest(receiver, digest_list); 93 | } 94 | 95 | 96 | /** 97 | * Add header fileds with const integers. 98 | * @param value1
value of the const. 99 | * @param mask1
value mask. 100 | */ 101 | action do_add_header_with_const(value1, mask1) { 102 | bit_or(HDR, HDR & (~mask1), 103 | (HDR + value1) & mask1); 104 | } 105 | 106 | /** 107 | * Add user-defined metadata with const integers. 108 | * @param value1 value of the const. 109 | * @param mask1 value mask. 110 | */ 111 | action do_add_meta_with_const(value1, mask1) { 112 | bit_or(META, META & (~mask1), 113 | (META + value1) & mask1); 114 | } 115 | 116 | /** 117 | * Add header with the header values. 118 | * @param left1
left shift 119 | * @param right1
right shift 120 | * @param mask1
value mask 121 | */ 122 | action do_add_header_with_header(left1, 123 | right1, 124 | mask1) { 125 | bit_or(HDR, HDR & (~mask1), 126 | (HDR + (((HDR<>right1)&mask1)) & mask1); 127 | } 128 | 129 | /** 130 | * Add user defiend metadata with the header values. 131 | * @param left1
left shift 132 | * @param right1
right shift 133 | * @param mask1
value mask 134 | */ 135 | action do_add_meta_with_header(left1, 136 | right1, 137 | mask1) { 138 | bit_or(META, META & (~mask1), 139 | (META + (((HDR<>right1)&mask1)) & mask1); 140 | } 141 | 142 | /** 143 | * Add header with the metadata values. 144 | * @param left1
left shift 145 | * @param right1
right shift 146 | * @param mask1
value mask 147 | */ 148 | action do_add_header_with_meta(left1, 149 | right1, 150 | mask1) { 151 | bit_or(HDR, HDR & (~mask1), 152 | (HDR + (((META<>right1)&mask1)) & mask1); 153 | } 154 | 155 | /** 156 | * Add metadata with the metadata values. 157 | * @param left1
left shift 158 | * @param right1
right shift 159 | * @param mask1
value mask 160 | */ 161 | action do_add_meta_with_meta(left1, 162 | right1, 163 | mask1) { 164 | bit_or(META, META & (~mask1), 165 | (META + (((META<>right1)&mask1)) & mask1); 166 | } 167 | 168 | /** 169 | * Substract header with the const values. 170 | * @param value1
the const value 171 | * @param mask1
value mask 172 | */ 173 | action do_subtract_const_from_header(value1, mask1) { 174 | bit_or(HDR, HDR & (~mask1), 175 | (HDR - value1) & mask1); 176 | } 177 | 178 | /** 179 | * Substract metadata with the const values. 180 | * @param value1
the const value 181 | * @param mask1
value mask 182 | */ 183 | action do_subtract_const_from_meta(value1, mask1) { 184 | bit_or(META, META & (~mask1), 185 | (META - value1) & mask1); 186 | } 187 | 188 | /** 189 | * Substract header with the header values. 190 | * @param left1
left shift 191 | * @param right1
right shift 192 | * @param mask1
value mask 193 | */ 194 | action do_subtract_header_from_header(left1, 195 | right1, 196 | mask1) { 197 | bit_or(HDR, HDR & (~mask1), 198 | (HDR - (((HDR<>right1)&mask1)) & mask1); 199 | } 200 | 201 | /** 202 | * Substract header with the metadata values. 203 | * @param left1
left shift 204 | * @param right1
right shift 205 | * @param mask1
value mask 206 | */ 207 | action do_subtract_header_from_meta(left1, 208 | right1, 209 | mask1) { 210 | bit_or(META, META & (~mask1), 211 | (META - (((HDR<>right1)&mask1)) & mask1); 212 | } 213 | 214 | 215 | /** 216 | * Substract metadata with the header values. 217 | * @param left1
left shift 218 | * @param right1
right shift 219 | * @param mask1
value mask 220 | */ 221 | action do_subtract_meta_from_header(left1, right1, mask1) { 222 | bit_or(HDR, HDR & (~mask1), 223 | (HDR - (((META<>right1)&mask1)) & mask1); 224 | } 225 | 226 | /** 227 | * Substract metadata with the metadata values. 228 | * @param left1
left shift 229 | * @param right1
right shift 230 | * @param mask1
value mask 231 | */ 232 | action do_subtract_meta_from_meta(left1, right1, mask1) { 233 | bit_or(META, META & (~mask1), 234 | (META - (((META<>right1)&mask1)) & mask1); 235 | } 236 | 237 | /** 238 | * Add a header into the packet. 239 | * @param value
left shift 240 | * @param mask1
value mask 241 | * @param mask2
value mask 242 | * @param length1
header length 243 | */ 244 | action do_add_header_1(value, 245 | mask1, 246 | mask2, 247 | length1) { 248 | push(byte_stack, length1*1); 249 | 250 | bit_or(HDR, HDR & mask1, 251 | (HDR & (~mask1) )>>(length1*8)); 252 | add_to_field(HEADER_LENGTH, length1); 253 | do_mod_header_with_const(value, mask2); 254 | modify_field(desc_hdr.len, HEADER_LENGTH); 255 | 256 | modify_field(REMOVE_OR_ADD_FLAG, 1); 257 | modify_field(MOD_FLAG, 1); 258 | } 259 | 260 | /** 261 | * Remove a header form the packet. 262 | * @param value1
left shift 263 | * @param mask1
value mask 264 | * @param mask2
value mask 265 | * @param length1
header length 266 | */ 267 | action do_remove_header_1(mask1, mask2, length1) { 268 | push(byte_stack, length1*1); 269 | subtract_from_field(HEADER_LENGTH, length1); 270 | 271 | modify_field(byte_stack[0].byte, HEADER_FLAG); 272 | modify_field(byte_stack[1].byte, HEADER_LENGTH); 273 | modify_field(byte_stack[2].byte, (POLICY_ID>>16)&0xFF); 274 | modify_field(byte_stack[3].byte, (POLICY_ID) & 0xFF); 275 | 276 | remove_header(desc_hdr); 277 | 278 | bit_or(HDR, HDR & mask1, 279 | (HDR & mask2)<<(length1*8)); 280 | 281 | modify_field(REMOVE_OR_ADD_FLAG, 1); 282 | modify_field(MOD_FLAG, 1); 283 | } 284 | 285 | /** 286 | * Modify header with one const value. 287 | * @param value
left shift 288 | * @param mask1
value mask 289 | * @param length1
value mask 290 | */ 291 | action do_mod_header_with_const(value, mask1) { 292 | bit_or(HDR, (HDR & (~mask1)), (value & mask1)); 293 | modify_field(MOD_FLAG, 1); 294 | } 295 | 296 | /** 297 | * Modify header with one const value, meanwhile re-calculate the checksum (inline). 298 | * @param value1
left shift 299 | * @param mask1
value mask 300 | * @param length1
value mask 301 | */ 302 | action do_mod_header_with_const_and_checksum(value, 303 | mask1, 304 | value1, 305 | value2, 306 | offset1) { 307 | do_mod_header_with_const(value, mask1); 308 | do_update_transport_checksum(value1, 309 | value2, offset1); 310 | } 311 | 312 | /** 313 | * Modify header with one const value, meanwhile re-calculate the checksum (inline). 314 | * @param value
the const value. 315 | * @param mask1
value mask 316 | */ 317 | action do_mod_meta_with_const(value, mask1) { 318 | bit_or(META, (META & ~mask1), 319 | (value & mask1)); 320 | } 321 | 322 | /** 323 | * Modify standard metadata fields. 324 | * @param val1 <> 325 | * @param mask1 <> 326 | * @param val2 <> 327 | * @param mask2 <> 328 | * @param val3 <> 329 | * @param mask3 <> 330 | * @param val4 <> 331 | * @param mask4 <> 332 | */ 333 | action do_mod_std_meta(val1, mask1, 334 | val2, mask2, 335 | val3, mask3, 336 | val4, mask4) { 337 | bit_or(standard_metadata.egress_spec, 338 | standard_metadata.egress_spec & (~mask1), val1 & mask1); 339 | bit_or(standard_metadata.egress_port, 340 | standard_metadata.egress_port & (~mask2), val2 & mask2); 341 | bit_or(standard_metadata.ingress_port, 342 | standard_metadata.ingress_port & (~mask3), val3 & mask3); 343 | bit_or(standard_metadata.packet_length, 344 | standard_metadata.packet_length & (~mask4), val4 & mask4); 345 | } 346 | 347 | /** 348 | * Modify header with the one metadata field. 349 | * @param value1
left shift 350 | * @param mask1
value mask 351 | * @param length1
value mask 352 | */ 353 | action do_mod_header_with_meta_1(left1, 354 | right1, 355 | mask1) { 356 | bit_or(HDR, (HDR & ~mask1), 357 | (((META << left1) >> right1) & mask1)); 358 | modify_field(MOD_FLAG, 1); 359 | } 360 | 361 | /** 362 | * Modify header with the two metadata fields. 363 | * @param left1
left shift 364 | * @param right1
right shift 365 | * @param mask1
value mask 366 | * @param left2
left shift 367 | * @param right2
right shift 368 | * @param mask2
value mask 369 | */ 370 | action do_mod_header_with_meta_2(left1, right1, mask1, 371 | left2, right2, mask2) { 372 | do_mod_header_with_meta_1(left1, right1, mask1); 373 | do_mod_header_with_meta_1(left2, right2, mask2); 374 | } 375 | 376 | /** 377 | * Modify header with the three metadata fields. 378 | * @param left1
left shift 379 | * @param right1
right shift 380 | * @param mask1
value mask 381 | * @param left2
left shift 382 | * @param right2
right shift 383 | * @param mask2
value mask 384 | * @param left3
left shift 385 | * @param right3
right shift 386 | * @param mask3
value mask 387 | */ 388 | action do_mod_header_with_meta_3(left1, right1, mask1, 389 | left2, right2, mask2, 390 | left3, right3, mask3) { 391 | do_mod_header_with_meta_1(left1, right1, mask1); 392 | do_mod_header_with_meta_1(left2, right2, mask2); 393 | do_mod_header_with_meta_1(left3, right3, mask3); 394 | } 395 | 396 | /** 397 | * Modify metadata with the one metadata field. 398 | * @param left1
left shift 399 | * @param right1
right shift 400 | * @param mask1
value mask 401 | */ 402 | action do_mod_meta_with_meta_1(left1, right1, mask1) { 403 | bit_or(META, (META & ~mask1), 404 | (((META << left1) >> right1) & mask1)); 405 | } 406 | 407 | /** 408 | * Modify metadata with the two metadata fields. 409 | * @param left1
left shift 410 | * @param right1
right shift 411 | * @param mask1
value mask 412 | * @param left2
left shift 413 | * @param right2
right shift 414 | * @param mask2
value mask 415 | */ 416 | action do_mod_meta_with_meta_2(left1, right1, mask1, 417 | left2, right2, mask2) { 418 | do_mod_meta_with_meta_1(left1, right1, mask1); 419 | do_mod_meta_with_meta_1(left2, right2, mask2); 420 | } 421 | 422 | /** 423 | * Modify metadata with the three metadata fields. 424 | * @param left1
left shift 425 | * @param right1
right shift 426 | * @param mask1
value mask 427 | * @param left2
left shift 428 | * @param right2
right shift 429 | * @param mask2
value mask 430 | * @param left3
left shift 431 | * @param right3
right shift 432 | * @param mask3
value mask 433 | */ 434 | action do_mod_meta_with_meta_3(left1, right1, mask1, 435 | left2, right2, mask2, 436 | left3, right3, mask3) { 437 | do_mod_meta_with_meta_1(left1, right1, mask1); 438 | do_mod_meta_with_meta_1(left2, right2, mask2); 439 | do_mod_meta_with_meta_1(left3, right3, mask3); 440 | } 441 | 442 | /** 443 | * Modify header with the one header field. 444 | * @param left1
left shift 445 | * @param right1
right shift 446 | * @param mask1
value mask 447 | */ 448 | action do_mod_header_with_header_1(left1, right1, mask1) { 449 | bit_or(META, (HDR & ~mask1), 450 | (((HDR << left1) >> right1) & mask1)); 451 | 452 | modify_field(MOD_FLAG, 1); 453 | } 454 | 455 | /** 456 | * Modify header with the three header fields. 457 | * @param left1
left shift 458 | * @param right1
right shift 459 | * @param mask1
value mask 460 | * @param left2
left shift 461 | * @param right2
right shift 462 | * @param mask2
value mask 463 | */ 464 | action do_mod_header_with_header_2(left1, right1, mask1, 465 | left2, right2, mask2) { 466 | do_mod_header_with_header_1(left1, right1, mask1); 467 | do_mod_header_with_header_1(left2, right2, mask2); 468 | } 469 | 470 | /** 471 | * Modify header with the three header fields. 472 | * @param left1
left shift 473 | * @param right1
right shift 474 | * @param mask1
value mask 475 | * @param left2
left shift 476 | * @param right2
right shift 477 | * @param mask2
value mask 478 | * @param left3
left shift 479 | * @param right3
right shift 480 | * @param mask3
value mask 481 | */ 482 | action do_mod_header_with_header_3(left1, right1, mask1, 483 | left2, right2, mask2, 484 | left3, right3, mask3) { 485 | do_mod_header_with_header_1(left1, right1, mask1); 486 | do_mod_header_with_header_1(left2, right2, mask2); 487 | do_mod_header_with_header_1(left3, right3, mask3); 488 | } 489 | 490 | /** 491 | * Modify metadata with the one header field. 492 | * @param left1
left shift 493 | * @param right1
right shift 494 | * @param mask1
value mask 495 | */ 496 | action do_mod_meta_with_header_1(left1, right1, mask1) { 497 | bit_or(META, (HDR & ~mask1), 498 | (((HDR << left1) >> right1) & mask1)); 499 | } 500 | 501 | /** 502 | * Modify metadata with the two header fields. 503 | * @param left1
left shift 504 | * @param right1
right shift 505 | * @param mask1
value mask 506 | * @param left2
left shift 507 | * @param right2
right shift 508 | * @param mask2
value mask 509 | */ 510 | action do_mod_meta_with_header_2(left1, right1, mask1, 511 | left2, right2, mask2) { 512 | do_mod_meta_with_header_1(left1, right1, mask1); 513 | do_mod_meta_with_header_1(left2, right2, mask2); 514 | } 515 | 516 | /** 517 | * Modify metadata with the three header fields. 518 | * @param left1
left shift 519 | * @param right1
right shift 520 | * @param mask1
value mask 521 | * @param left2
left shift 522 | * @param right2
right shift 523 | * @param mask2
value mask 524 | * @param left3
left shift 525 | * @param right3
right shift 526 | * @param mask3
value mask 527 | */ 528 | action do_mod_meta_with_header_3(left1, right1, mask1, 529 | left2, right2, mask2, left3, right3, mask3) { 530 | do_mod_meta_with_header_1(left1, right1, mask1); 531 | do_mod_meta_with_header_1(left2, right2, mask2); 532 | do_mod_meta_with_header_1(left3, right3, mask3); 533 | } 534 | 535 | 536 | /** 537 | * Recirculate packets at the egress pipeline. 538 | * @param progid Pragram ID 539 | */ 540 | action do_recirculate(progid) { 541 | modify_field(vdp_metadata.recirculation_flag, 1); 542 | modify_field(vdp_metadata.remove_or_add_flag, 0); 543 | modify_field(vdp_metadata.inst_id, progid); 544 | recirculate( flInstance_with_umeta ); 545 | } 546 | 547 | /** 548 | * Resubmit packet at the ingress pipeline. 549 | * @param progid Pragram ID 550 | */ 551 | action do_resubmit(progid) { 552 | modify_field(vdp_metadata.recirculation_flag, 1); 553 | modify_field(vdp_metadata.inst_id, progid); 554 | resubmit(flInstance_with_umeta); 555 | } 556 | 557 | /** 558 | * Load register value into the header. 559 | * @param index register index 560 | * @param left1 561 | * @param mask1 562 | */ 563 | action do_load_register_into_header(index, 564 | left1, 565 | mask1) { 566 | register_read(context_metadata.r5, global_register, index); 567 | bit_or(HDR, HDR & (~mask1), 568 | (context_metadata.r5<>right1) & mask1); 601 | } 602 | 603 | /** 604 | * Load the metadata field into the register. 605 | * @param index register index 606 | * @param left1 607 | * @param mask1 608 | */ 609 | action do_wirte_meta_into_register(index, right1, mask1) { 610 | register_write(global_register, index, 611 | (META>>right1) & mask1); 612 | } 613 | 614 | /** 615 | * Load the const value into the register. 616 | * @param index register index 617 | * @param value the const value to load 618 | */ 619 | action do_wirte_const_into_register(index, value) { 620 | register_write(global_register, index, value); 621 | } 622 | 623 | /** 624 | * Return the hash header. 625 | */ 626 | field_list hash_field_list { 627 | context_metadata.hash_header; 628 | } 629 | 630 | /** 631 | * Calculate the field list with CRC16 hash. 632 | */ 633 | field_list_calculation hash_crc16 { 634 | input { 635 | hash_field_list; 636 | } 637 | algorithm : crc16; 638 | output_width : 16; 639 | } 640 | 641 | /** 642 | * Calculate the field list with CRC32 hash. 643 | */ 644 | field_list_calculation hash_crc32 { 645 | input { 646 | hash_field_list; 647 | } 648 | algorithm : crc32; 649 | output_width : 32; 650 | } 651 | 652 | /** 653 | * Set the hash header. 654 | * @param hdr_mask 655 | */ 656 | action do_set_hash_hdr(hdr_mask) { 657 | modify_field(context_metadata.hash_header, HDR & hdr_mask); 658 | } 659 | 660 | 661 | /** 662 | * Calculate CRC16. 663 | */ 664 | action do_hash_crc16(hdr_mask) { 665 | do_set_hash_hdr(hdr_mask); 666 | modify_field_with_hash_based_offset(context_metadata.hash, 0, 667 | hash_crc16, 65536); 668 | } 669 | 670 | /** 671 | * Calculate CRC32. 672 | */ 673 | action do_hash_crc32(hdr_mask) { 674 | do_set_hash_hdr(hdr_mask); 675 | modify_field_with_hash_based_offset(context_metadata.hash, 0, 676 | hash_crc32, 0xFFFFFFFF); 677 | } 678 | 679 | /** 680 | * Select hash profile. 681 | */ 682 | action_profile hash_profile { 683 | actions { 684 | do_forward; 685 | noop; 686 | } 687 | 688 | dynamic_action_selection : hash_action_selector; 689 | } 690 | 691 | /** 692 | * Perform hash calculation. 693 | */ 694 | field_list_calculation hash_calculation { 695 | input { 696 | hash_field_list; 697 | } 698 | algorithm : crc16; 699 | output_width : 16; 700 | } 701 | 702 | /** 703 | * Select hash action. 704 | */ 705 | action_selector hash_action_selector { 706 | selection_key : hash_calculation; 707 | } 708 | -------------------------------------------------------------------------------- /src/include/checksum.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2016-present NetArch Lab, Tsinghua University. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #ifndef HYPERVISOR_CHEKSUM 17 | #define HYPERVISOR_CHEKSUM 18 | 19 | #define OFFSET context_metadata.r1 20 | #define SUM context_metadata.r5 21 | #define RESULT context_metadata.r2 22 | 23 | //----------------------------------------------------------- 24 | action do_ipv4_checksum(ipv4_offset) { 25 | modify_field(SUM, 0); 26 | modify_field(OFFSET, ipv4_offset); 27 | 28 | // DST 29 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 30 | add_to_field(OFFSET, 16); 31 | 32 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 33 | add_to_field(OFFSET, 16); 34 | 35 | // SRC 36 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 37 | add_to_field(OFFSET, 16); 38 | 39 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 40 | add_to_field(OFFSET, 16); 41 | 42 | // Checksum 43 | add_to_field(OFFSET, 16); 44 | 45 | // TTL + Protocol 46 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 47 | add_to_field(OFFSET, 16); 48 | 49 | // FRAG 50 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 51 | add_to_field(OFFSET, 16); 52 | 53 | // ID 54 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 55 | add_to_field(OFFSET, 16); 56 | 57 | // totalLen 58 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 59 | add_to_field(OFFSET, 16); 60 | 61 | // version+IHL+DSCP 62 | add_to_field(SUM, (HDR>>OFFSET) & 0xFFFF); 63 | add_to_field(OFFSET, 16); 64 | 65 | modify_field(RESULT, (SUM + (SUM>>16)) & 0xFFFF); 66 | 67 | do_mod_header_with_const(RESULT, 0xFFFF << (OFFSET + 32)); 68 | } 69 | 70 | //----------------------------------------------------------- 71 | action do_update_transport_checksum(value1, value2, offset) { 72 | modify_field(RESULT, value1); 73 | add_to_field(RESULT, ~value2); 74 | add_to_field(RESULT, (HDR >> offset) & 0xFFFF); 75 | do_mod_header_with_const(RESULT, 0xFFFF << offset); 76 | } 77 | 78 | 79 | control recalculate_checksum { 80 | apply(table_checksum); 81 | } 82 | 83 | table table_checksum { 84 | reads { 85 | POLICY_ID : exact; 86 | } 87 | actions { 88 | do_ipv4_checksum; 89 | do_update_transport_checksum; 90 | noop; 91 | } 92 | } 93 | 94 | #endif -------------------------------------------------------------------------------- /src/include/config.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2016-present NetArch Lab, Tsinghua University. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #ifndef HYPERVISOR_CONFIG 17 | #define HYPERVISOR_CONFIG 18 | 19 | // Register width 20 | #define REGISTER_WIDTH 32 21 | // Number of global registers 22 | #define REGISTER_NUMBER 65536 23 | 24 | 25 | 26 | 27 | #endif -------------------------------------------------------------------------------- /src/include/control.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2016-present NetArch Lab, Tsinghua University. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | 17 | #ifndef HYPERVISOR_CONTROL 18 | #define HYPERVISOR_CONTROL 19 | 20 | #include "define.p4" 21 | 22 | //----------------------------------------------------- 23 | // Actions for control logic 24 | //----------------------------------------------------- 25 | 26 | //----------------- ingress --------------------------- 27 | table table_config_at_initial { 28 | reads{ 29 | POLICY_ID : exact ; 30 | PROG_ID : exact ; 31 | STAGE_ID : exact ; 32 | } 33 | actions{ 34 | set_initial_config; 35 | set_initial_config_new; 36 | } 37 | } 38 | 39 | table table_config_at_end { 40 | reads{ 41 | POLICY_ID : exact ; 42 | PROG_ID : exact ; 43 | STAGE_ID : exact ; 44 | } 45 | actions{ 46 | do_resubmit; 47 | } 48 | } 49 | 50 | //----------------------------------------------------- 51 | action set_match_result (match_result) { 52 | bit_or(MATCH_RESULT, match_result, MATCH_RESULT); 53 | } 54 | 55 | //----------------------------------------------------- 56 | action set_action_id(match_result, action_bitmap, 57 | match_bitmap, next_stage, next_prog) { 58 | set_match_result(match_result); 59 | set_stage_and_bitmap(action_bitmap, 60 | match_bitmap, next_stage, next_prog); 61 | } 62 | 63 | //----------------------------------------------------- 64 | action set_next_stage(match_bitmap, next_stage, next_prog) { 65 | set_stage_and_bitmap(0, match_bitmap, 66 | next_stage, next_prog); 67 | } 68 | 69 | //----------------------------------------------------- 70 | action end(next_prog) { 71 | set_action_id(0, 0, 0 , 0, next_prog); 72 | } 73 | 74 | //----------------------------------------------------- 75 | action set_stage_and_bitmap (action_bitmap, 76 | match_bitmap , next_stage, next_prog) { 77 | modify_field(ACTION_BITMAP, action_bitmap); 78 | modify_field(MATCH_BITMAP, match_bitmap); 79 | modify_field(STAGE_ID, next_stage); 80 | modify_field(PROGRAM_ID, next_prog); 81 | modify_field(ACTION_ID, MATCH_RESULT); 82 | modify_field(MATCH_RESULT, 0); 83 | } 84 | 85 | //----------------------------------------------------- 86 | action set_action_id_direct (action_id, action_bitmap, 87 | match_bitmap , next_stage, next_prog) { 88 | modify_field(ACTION_BITMAP, action_bitmap); 89 | modify_field(MATCH_BITMAP, match_bitmap); 90 | modify_field(STAGE_ID, next_stage); 91 | modify_field(PROGRAM_ID, next_prog); 92 | modify_field(ACTION_ID, action_id); 93 | } 94 | 95 | //----------------------------------------------------- 96 | action set_match_result_with_next_stage (match_result, 97 | match_bitmap, next_stage) { 98 | modify_field(ACTION_BITMAP, 0); 99 | modify_field(MATCH_BITMAP, match_bitmap); 100 | modify_field(STAGE_ID, next_stage); 101 | modify_field(MATCH_RESULT, match_result); 102 | } 103 | 104 | 105 | //----------------------------------------------------- 106 | action set_initial_config (progid, initstage, 107 | match_bitmap) { 108 | modify_field(PROGRAM_ID , progid); 109 | modify_field(STAGE_ID, initstage); 110 | modify_field(MATCH_BITMAP, match_bitmap); 111 | } 112 | 113 | action set_initial_config_new (progid, initstage, 114 | match_bitmap) { 115 | modify_field(desc_hdr.vdp_id, vdp_metadata.vdp_id&0xFFEF); 116 | modify_field(PROGRAM_ID , progid); 117 | modify_field(STAGE_ID, initstage); 118 | modify_field(MATCH_BITMAP, match_bitmap); 119 | } 120 | 121 | //----------------- Egress ---------------------------- 122 | table table_config_at_egress { 123 | reads{ 124 | POLICY_ID : exact ; 125 | PROG_ID : exact ; 126 | STAGE_ID : exact ; 127 | } 128 | actions { 129 | do_recirculate; 130 | } 131 | } 132 | 133 | table dh_deparse { 134 | actions { 135 | do_dh_deparse; 136 | } 137 | } 138 | 139 | //----------------------------------------------------- 140 | action do_dh_deparse() { 141 | modify_field(HDR, desc_hdr.load_header); 142 | } 143 | 144 | 145 | //--------------Conditional Stage---------------------- 146 | 147 | //----------------------------------------------------- 148 | action set_expr_header_op_const(l_expr_offset, 149 | l_expr_mask, op, r_expr) { 150 | modify_field(context_metadata.left_expr, 151 | (HDR >> l_expr_offset)&l_expr_mask); 152 | modify_field(context_metadata.op, op); 153 | modify_field(context_metadata.right_expr, r_expr); 154 | } 155 | 156 | 157 | //----------------------------------------------------- 158 | action set_expr_counter_op_const(r_expr) { 159 | modify_field(context_metadata.left_expr, 160 | context_metadata.count); 161 | modify_field(context_metadata.right_expr, r_expr); 162 | } 163 | 164 | //----------------------------------------------------- 165 | action set_expr_meta_op_const(l_expr_offset, 166 | l_expr_mask, op, r_expr) { 167 | modify_field(context_metadata.left_expr, 168 | (META >> l_expr_offset)&l_expr_mask); 169 | modify_field(context_metadata.op, op); 170 | modify_field(context_metadata.right_expr, r_expr); 171 | } 172 | 173 | //----------------------------------------------------- 174 | action set_expr_header_op_header(l_expr_offset, 175 | l_expr_mask, op, r_expr_offset, r_expr_mask) { 176 | modify_field(context_metadata.left_expr, 177 | (HDR >> l_expr_offset) & l_expr_mask); 178 | modify_field(context_metadata.op, op); 179 | modify_field(context_metadata.right_expr, 180 | (HDR >> r_expr_offset) & r_expr_mask); 181 | 182 | } 183 | 184 | //----------------------------------------------------- 185 | action set_expr_meta_op_header(l_expr_offset, 186 | l_expr_mask, op, r_expr_offset, r_expr_mask) { 187 | modify_field(context_metadata.left_expr, 188 | (META >> l_expr_offset)&l_expr_mask); 189 | modify_field(context_metadata.op, op); 190 | modify_field(context_metadata.right_expr, 191 | (HDR >> r_expr_offset) & r_expr_mask); 192 | } 193 | 194 | //----------------------------------------------------- 195 | action set_expr_header_op_meta(l_expr_offset, 196 | l_expr_mask, op, r_expr_offset, r_expr_mask) { 197 | modify_field(context_metadata.left_expr, 198 | (HDR >> l_expr_offset)&l_expr_mask); 199 | modify_field(context_metadata.op, op); 200 | modify_field(context_metadata.right_expr, 201 | (META >> r_expr_offset) & r_expr_mask); 202 | } 203 | 204 | //----------------------------------------------------- 205 | action set_expr_meta_op_meta(l_expr_offset, 206 | l_expr_mask, op, r_expr_offset, r_expr_mask) { 207 | modify_field(context_metadata.left_expr, 208 | (META << l_expr_offset)&l_expr_mask); 209 | modify_field(context_metadata.op, op); 210 | modify_field(context_metadata.right_expr, 211 | (META << r_expr_offset) & r_expr_mask); 212 | } 213 | 214 | #endif -------------------------------------------------------------------------------- /src/include/define.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2016-present NetArch Lab, Tsinghua University. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | // primitive actions 17 | 18 | #define PRIMITIVE_ACTION_ADD_HEDAER 0 19 | #define PRIMITIVE_ACTION_COPY_HEADER 1 20 | #define PRIMITIVE_ACTION_REMOVE_HEDAER 2 21 | #define PRIMITIVE_ACTION_MODIFY_FIELD 3 22 | #define PRIMITIVE_ACTION_ADD_TO_FIELD 4 23 | #define PRIMITIVE_ACTION_ADD 5 24 | #define PRIMITIVE_ACTION_SUBTRACT_FROM_FIELD 6 25 | #define PRIMITIVE_ACTION_SUBTRACT 7 26 | #define PRIMITIVE_ACTION_MODIFY_FIELD_WITH_HASH_BASED_OFFSET 8 27 | #define PRIMITIVE_ACTION_MODIFY_FIELD_RNG_UNIFORM 9 28 | #define PRIMITIVE_ACTION_BIT_AND 10 29 | #define PRIMITIVE_ACTION_BIT_OR 11 30 | #define PRIMITIVE_ACTION_BIT_XOR 12 31 | #define PRIMITIVE_ACTION_SHIFT_LEFT 13 32 | #define PRIMITIVE_ACTION_SHIFT_RIGHT 14 33 | #define PRIMITIVE_ACTION_TRUNCATE 15 34 | #define PRIMITIVE_ACTION_DROP 16 35 | #define PRIMITIVE_ACTION_NO_OP 17 36 | #define PRIMITIVE_ACTION_PUSH 18 37 | #define PRIMITIVE_ACTION_POP 19 38 | #define PRIMITIVE_ACTION_COUNT 20 39 | #define PRIMITIVE_ACTION_EXECUTE_METER 21 40 | #define PRIMITIVE_ACTION_REGISTER_READ 22 41 | #define PRIMITIVE_ACTION_REGISTER_WRITE 23 42 | #define PRIMITIVE_ACTION_GENERATE_DIGEST 24 43 | #define PRIMITIVE_ACTION_RESUBMIT 25 44 | #define PRIMITIVE_ACTION_RECIRCULATE 26 45 | #define PRIMITIVE_ACTION_CLONE_I2I 27 46 | #define PRIMITIVE_ACTION_CLONE_E2I 28 47 | #define PRIMITIVE_ACTION_CLONE_I2E 29 48 | #define PRIMITIVE_ACTION_CLONE_E2E 30 49 | #define EXTEND_ACTION_MODIFY_HEADER_WITH_CONST 31 50 | #define EXTEND_ACTION_MODIFY_METADATA_WITH_CONST 32 51 | #define EXTEND_ACTION_MODIFY_HEADER_WITH_METADATA 33 52 | #define EXTEND_ACTION_MODIFY_METADATA_WITH_METADATA 34 53 | #define EXTEND_ACTION_MODIFY_HEADER_WITH_HEADER 35 54 | #define EXTEND_ACTION_MODIFY_METADATA_WITH_HEADER 36 55 | #define EXTEND_ACTION_MODIFY_STANDARD_METADATA 37 56 | #define EXTEND_ACTION_HASH 38 57 | #define EXTEND_ACTION_PROFILE 39 58 | 59 | // MASK 60 | #define BIT_MASK_MOD_HEADER_WITH_CONST (1< const, header <|=|> header, header <|=|> meta 112 | * counter can only be compared with const? 113 | */ 114 | #define CONDITIONAL_STAGE(X) \ 115 | control conditional_##X { \ 116 | apply(table_get_expression_##X); \ 117 | if (context_metadata.left_expr < context_metadata.right_expr) { \ 118 | apply(table_branch_1_##X); \ 119 | } \ 120 | else if(context_metadata.left_expr > context_metadata.right_expr) { \ 121 | apply(table_branch_2_##X); \ 122 | } \ 123 | else { \ 124 | apply(table_branch_3_##X); \ 125 | } \ 126 | } \ 127 | table table_get_expression_##X { \ 128 | reads { \ 129 | vdp_metadata.inst_id : exact ; \ 130 | vdp_metadata.stage_id : exact ; \ 131 | } \ 132 | actions { \ 133 | set_expr_header_op_const; \ 134 | set_expr_header_op_header; \ 135 | set_expr_header_op_meta; \ 136 | set_expr_meta_op_const; \ 137 | set_expr_meta_op_header; \ 138 | set_expr_meta_op_meta; \ 139 | set_expr_counter_op_const; \ 140 | } \ 141 | } \ 142 | table table_branch_1_##X { \ 143 | reads { \ 144 | vdp_metadata.inst_id : exact ; \ 145 | vdp_metadata.stage_id : exact ; \ 146 | } \ 147 | actions { \ 148 | set_next_stage; \ 149 | set_match_result; \ 150 | set_action_id; \ 151 | set_next_stage; \ 152 | end; \ 153 | } \ 154 | } \ 155 | table table_branch_2_##X { \ 156 | reads { \ 157 | vdp_metadata.inst_id : exact ; \ 158 | vdp_metadata.stage_id : exact ; \ 159 | } \ 160 | actions { \ 161 | set_next_stage; \ 162 | set_match_result; \ 163 | set_action_id; \ 164 | set_next_stage; \ 165 | end; \ 166 | } \ 167 | } \ 168 | table table_branch_3_##X { \ 169 | reads { \ 170 | vdp_metadata.inst_id : exact ; \ 171 | vdp_metadata.stage_id : exact ; \ 172 | } \ 173 | actions { \ 174 | set_next_stage; \ 175 | set_match_result; \ 176 | set_action_id; \ 177 | set_next_stage; \ 178 | end; \ 179 | } \ 180 | } 181 | 182 | 183 | //----------------------------------------------------------------------- 184 | /* 185 | * 186 | */ 187 | #define EXECUTE_ACTION(X) \ 188 | control execute_do_##X { \ 189 | if ((ACTION_BITMAP & BIT_MASK_MOD_HEADER_WITH_META) != 0) { \ 190 | apply(table_mod_header_with_meta_##X); \ 191 | } \ 192 | if ((ACTION_BITMAP & BIT_MASK_MOD_META_WITH_META) != 0) { \ 193 | apply(table_mod_meta_with_meta_##X); \ 194 | } \ 195 | if ((ACTION_BITMAP & BIT_MASK_MOD_HEADER_WITH_HEADER) != 0) { \ 196 | apply(table_mod_header_with_header_##X); \ 197 | } \ 198 | if ((ACTION_BITMAP & BIT_MASK_MOD_META_WITH_HEADER) != 0) { \ 199 | apply(table_mod_meta_with_header_##X); \ 200 | } \ 201 | if ((ACTION_BITMAP & BIT_MASK_MOD_HEADER_WITH_CONST) != 0) { \ 202 | apply(table_mod_header_with_const_##X); \ 203 | } \ 204 | if ((ACTION_BITMAP & BIT_MASK_MOD_META_WITH_CONST) != 0) { \ 205 | apply(table_mod_meta_with_const_##X); \ 206 | } \ 207 | if ((ACTION_BITMAP & BIT_MASK_ADD_HEDAER) != 0) { \ 208 | apply(table_add_header_##X); \ 209 | } \ 210 | if ((ACTION_BITMAP & BIT_MASK_REMOVE_HEADER) != 0) { \ 211 | apply(table_remove_header_##X); \ 212 | } \ 213 | if ((ACTION_BITMAP & BIT_MASK_MOD_STD_META) != 0) { \ 214 | apply(table_mod_std_meta_##X); \ 215 | } \ 216 | if ((ACTION_BITMAP & BIT_MASK_GENERATE_DIGIST) != 0) { \ 217 | apply(table_generate_digest_##X); \ 218 | } \ 219 | if ((ACTION_BITMAP & BIT_MASK_ADD ) != 0) { \ 220 | apply(table_add_##X); \ 221 | } \ 222 | if ((ACTION_BITMAP & BIT_MASK_SUBTRACT ) != 0) { \ 223 | apply(table_subtract_##X); \ 224 | } \ 225 | if ((ACTION_BITMAP & BIT_MASK_REGISTER) != 0) { \ 226 | apply(table_register_##X); \ 227 | } \ 228 | if ((ACTION_BITMAP & BIT_MASK_COUNTER) != 0) { \ 229 | apply(table_counter_##X); \ 230 | } \ 231 | if ((ACTION_BITMAP & BIT_MASK_HASH) != 0) { \ 232 | apply(table_hash_##X); \ 233 | } \ 234 | if ((ACTION_BITMAP & BIT_MASK_PROFILE) != 0) { \ 235 | apply(table_action_profile_##X); \ 236 | } \ 237 | } \ 238 | table table_add_##X { \ 239 | reads { \ 240 | ACTION_ID : exact; \ 241 | } \ 242 | actions { \ 243 | do_add_header_with_const; \ 244 | do_add_meta_with_const; \ 245 | do_add_header_with_header; \ 246 | do_add_meta_with_header; \ 247 | do_add_header_with_meta; \ 248 | do_add_meta_with_meta; \ 249 | } \ 250 | } \ 251 | table table_generate_digest_##X { \ 252 | reads { \ 253 | ACTION_ID : exact; \ 254 | } \ 255 | actions { \ 256 | do_gen_digest; \ 257 | } \ 258 | } \ 259 | table table_subtract_##X { \ 260 | reads { \ 261 | ACTION_ID : exact; \ 262 | } \ 263 | actions { \ 264 | do_subtract_const_from_header; \ 265 | do_subtract_const_from_meta; \ 266 | do_subtract_header_from_header; \ 267 | do_subtract_header_from_meta; \ 268 | do_subtract_meta_from_header; \ 269 | do_subtract_meta_from_meta; \ 270 | } \ 271 | } \ 272 | table table_mod_std_meta_##X { \ 273 | reads { \ 274 | ACTION_ID : exact; \ 275 | } \ 276 | actions { \ 277 | do_mod_std_meta; \ 278 | do_loopback; \ 279 | do_forward; \ 280 | do_queue; \ 281 | do_drop; \ 282 | do_multicast; \ 283 | } \ 284 | } \ 285 | table table_mod_header_with_const_##X { \ 286 | reads { \ 287 | ACTION_ID : exact; \ 288 | } \ 289 | actions { \ 290 | do_mod_header_with_const; \ 291 | do_mod_header_with_const_and_checksum; \ 292 | } \ 293 | } \ 294 | table table_mod_meta_with_const_##X { \ 295 | reads { \ 296 | ACTION_ID : exact; \ 297 | } \ 298 | actions { \ 299 | do_mod_meta_with_const; \ 300 | } \ 301 | } \ 302 | table table_mod_header_with_meta_##X { \ 303 | reads { \ 304 | ACTION_ID : exact; \ 305 | } \ 306 | actions { \ 307 | do_mod_header_with_meta_1; \ 308 | do_mod_header_with_meta_2; \ 309 | do_mod_header_with_meta_3; \ 310 | } \ 311 | } \ 312 | table table_mod_meta_with_meta_##X { \ 313 | reads { \ 314 | ACTION_ID : exact; \ 315 | } \ 316 | actions { \ 317 | do_mod_meta_with_meta_1; \ 318 | do_mod_meta_with_meta_2; \ 319 | do_mod_meta_with_meta_3; \ 320 | } \ 321 | } \ 322 | table table_mod_header_with_header_##X { \ 323 | reads { \ 324 | ACTION_ID : exact; \ 325 | } \ 326 | actions { \ 327 | do_mod_header_with_header_1; \ 328 | do_mod_header_with_header_2; \ 329 | do_mod_header_with_header_3; \ 330 | } \ 331 | } \ 332 | table table_mod_meta_with_header_##X { \ 333 | reads { \ 334 | ACTION_ID : exact; \ 335 | } \ 336 | actions { \ 337 | do_mod_meta_with_header_1; \ 338 | do_mod_meta_with_header_2; \ 339 | do_mod_meta_with_header_3; \ 340 | } \ 341 | } \ 342 | table table_add_header_##X { \ 343 | reads { \ 344 | ACTION_ID : exact; \ 345 | } \ 346 | actions { \ 347 | do_add_header_1; \ 348 | } \ 349 | } \ 350 | table table_remove_header_##X { \ 351 | reads { \ 352 | ACTION_ID : exact; \ 353 | } \ 354 | actions { \ 355 | do_remove_header_1; \ 356 | } \ 357 | } \ 358 | table table_hash_##X { \ 359 | reads { \ 360 | ACTION_ID : exact; \ 361 | } \ 362 | actions { \ 363 | do_hash_crc16; \ 364 | do_hash_crc32; \ 365 | } \ 366 | } \ 367 | table table_action_profile_##X { \ 368 | reads { \ 369 | ACTION_ID : exact; \ 370 | } \ 371 | action_profile : hash_profile; \ 372 | } \ 373 | table table_counter_##X { \ 374 | reads { \ 375 | ACTION_ID : exact; \ 376 | } \ 377 | actions { \ 378 | packet_count; \ 379 | packet_count_clear; \ 380 | } \ 381 | } \ 382 | table table_register_##X { \ 383 | reads { \ 384 | ACTION_ID : exact; \ 385 | } \ 386 | actions { \ 387 | do_load_register_into_header; \ 388 | do_load_register_into_meta; \ 389 | do_write_header_into_register; \ 390 | do_wirte_meta_into_register; \ 391 | do_wirte_const_into_register; \ 392 | } \ 393 | } \ 394 | counter counter_##X { \ 395 | type : packets_and_bytes; \ 396 | direct : table_counter_##X; \ 397 | } 398 | 399 | 400 | #endif -------------------------------------------------------------------------------- /tests/hyperv/arp_proxy/commands: -------------------------------------------------------------------------------- 1 | table_add table_config_at_initial action_set_initial_config 1 0 0 => 1 0 1 2 | table_add table_std_meta_match_stage1 action_set_action_id 1 0 1&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 1 0x0000002000000000 4 1 1 1 3 | table_add table_std_meta_match_stage1 action_set_action_id 1 0 2&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 2 0x0000002000000000 4 1 1 1 4 | table_add table_mod_std_meta_stage1 action_mod_std_meta 1 => 2 0xFF 2 0xFF 0 0 0 0 5 | table_add table_mod_std_meta_stage1 action_mod_std_meta 2 => 1 0xFF 1 0xFF 0 0 0 0 6 | table_add table_header_match_stage2 action_set_action_id 1 1 0x08060000000000000010000000000000000000000000000000000000000&&&0xFFFF000000000000FFFF0000000000000000000000000000000000000000 => 0x1000000000 0 4 2 1 1 7 | table_add table_header_match_stage2 action_end 1 1 0&&&0 => 0xFF 8 | table_add table_header_match_stage3 action_set_action_id 1 1 0x0a000001&&&0xFFFFFFFF => 0x1000000000 0x2880000000 0 0 0xFF 1 9 | table_add table_header_match_stage3 action_set_action_id 1 1 0x0a000002&&&0xFFFFFFFF => 0x2000000000 0x2880000000 0 0 0xFF 1 10 | table_add table_mod_std_meta_stage3 action_loopback 0x1000000000 => 11 | table_add table_mod_std_meta_stage3 action_loopback 0x2000000000 => 12 | table_add table_mod_header_with_header_stage3 action_mod_header_with_header_1 0x1000000000 => 0 80 0xFFFFFFFFFFFFFFFFFFFF 13 | table_add table_mod_header_with_header_stage3 action_mod_header_with_header_1 0x2000000000 => 0 80 0xFFFFFFFFFFFFFFFFFFFF 14 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x1000000000 => 0x0002082a0001000100000000000000000002082a000100010a00000100000000000000000000 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000 15 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x2000000000 => 0x0001082a0001000200000000000000000002082a000100020a00000200000000000000000000 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000 16 | table_set_default table_checksum noop 17 | table_set_default dh_deparse action_dh_deparse -------------------------------------------------------------------------------- /tests/hyperv/firewall/commands: -------------------------------------------------------------------------------- 1 | able_add table_config_at_initial action_set_initial_config 1 0 0 => 1 0 1 2 | able_add table_config_at_initial action_set_initial_config 1 2 0 => 2 0 1 3 | table_add table_std_meta_match_stage1 action_set_action_id 1 0 1&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 1 0x0000002000000000 4 1 1 1 4 | table_add table_std_meta_match_stage1 action_set_action_id 1 0 2&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 2 0x0000002000000000 4 1 1 1 5 | table_add table_mod_std_meta_stage1 action_forward 1 => 2 6 | table_add table_mod_std_meta_stage1 action_forward 2 => 1 7 | table_add table_header_match_stage2 action_set_action_id 1 1 0x080000000000000000000011000000000000000000000000000000000000000000000000000000000000&&&0xFFFF000000000000000000FF000000000000000000000000000000000000000000000000000000000000 => 0x1000000000 0 4 2 1 1 8 | table_add table_header_match_stage2 action_set_action_id 1 1 0x080000000000000000000006000000000000000000000000000000000000000000000000000000000000&&&0xFFFF000000000000000000FF000000000000000000000000000000000000000000000000000000000000 => 0x2000000000 0 4 3 1 1 9 | table_add table_header_match_stage2 action_end 1 1 0&&&0 => 0xFF 3 10 | table_add table_header_match_stage3 action_set_action_id 1 2 0x0800000000000000000000110000000000000a0000010000005000000000000000000000000000000000&&&0x000000000000000000000000000000000000FFFFFFFF0000FFFF00000000000000000000000000000000 => 0x1000000000 0x0000002000000000 0 0 0xFF 1 11 | table_add table_mod_std_meta_stage3 action_drop 0x1000000000 => 12 | table_add table_header_match_stage4 action_set_action_id 1 3 0x0800000000000000000000060000000000000a0000021f90000000000000000000000000000000000000&&&0x000000000000000000000000000000000000FFFFFFFFFFFF000000000000000000000000000000000000 => 0x1000000000 0x0000002000000000 0 0 0xFF 1 13 | table_add table_mod_std_meta_stage4 action_drop 0x1000000000 => 14 | table_set_default dh_deparse action_dh_deparse -------------------------------------------------------------------------------- /tests/hyperv/l2_switch/commands: -------------------------------------------------------------------------------- 1 | table_add table_config_at_initial action_set_initial_config 1 0 0 => 1 0 4 2 | table_add table_header_match_stage1 action_set_action_id 1 0 0x00020000000000000000&&&0xFFFF0000000000000000 => 0x200000000 0x2000000000 0 0 0xFF 1 3 | table_add table_mod_std_meta_stage1 action_forward 0x200000000 => 2 4 | table_add table_header_match_stage1 action_set_action_id 1 0 0x00010000000000000000&&&0xFFFF0000000000000000 => 0x100000000 0x2000000000 0 0 0xFF 1 5 | table_add table_mod_std_meta_stage1 action_forward 0x100000000 => 1 6 | table_set_default dh_deparse action_dh_deparse -------------------------------------------------------------------------------- /tests/hyperv/l2_with_fw/commands: -------------------------------------------------------------------------------- 1 | table_add table_config_at_initial action_set_initial_config 1 0 0 => 1 0 4 2 | table_add table_header_match_stage1 action_set_action_id 1 0 0x0002803600010001080045000054dfe84000400146be0a0000010a0000020800a2440c010002d6a97458000000003ee30100&&&0xFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 => 0x200000000 0x2000000000 1 0 2 1 3 | table_add table_mod_std_meta_stage1 action_forward 0x200000000 => 2 4 | table_add table_header_match_stage1 action_set_action_id 1 0 0x0001000000000000000008000000000000000000001100000000000000000000000000000000000000000000000000000000&&&0xFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 => 0x100000000 0x2000000000 1 0 2 1 5 | table_add table_mod_std_meta_stage1 action_forward 0x100000000 => 1 6 | table_add table_config_at_end action_resubmit 1 2 0 => 2 7 | table_add table_std_meta_match_stage1 action_set_action_id 2 0 1&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 1 0x0000002000000000 4 1 2 1 8 | table_add table_std_meta_match_stage1 action_set_action_id 2 0 2&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 2 0x0000002000000000 4 1 2 1 9 | table_add table_mod_std_meta_stage1 action_forward 1 => 2 10 | table_add table_mod_std_meta_stage1 action_forward 2 => 1 11 | table_add table_header_match_stage2 action_set_action_id 2 1 0x080000000000000000000011000000000000000000000000000000000000000000000000000000000000&&&0xFFFF000000000000000000FF000000000000000000000000000000000000000000000000000000000000 => 0x1000000000 0 4 2 2 1 12 | table_add table_header_match_stage2 action_set_action_id 2 1 0x080000000000000000000006000000000000000000000000000000000000000000000000000000000000&&&0xFFFF000000000000000000FF000000000000000000000000000000000000000000000000000000000000 => 0x2000000000 0 4 3 2 1 13 | table_add table_header_match_stage2 action_end 2 1 0&&&0 => 0xFF 3 14 | table_add table_header_match_stage3 action_set_action_id 2 2 0x0800000000000000000000110000000000000a0000010000005000000000000000000000000000000000&&&0x000000000000000000000000000000000000FFFFFFFF0000FFFF00000000000000000000000000000000 => 0x1000000000 0x0000002000000000 0 0 0xFF 1 15 | table_add table_mod_std_meta_stage3 action_drop 0x1000000000 => 16 | table_add table_header_match_stage4 action_set_action_id 2 3 0x0800000000000000000000060000000000000a0000021f90000000000000000000000000000000000000&&&0x000000000000000000000000000000000000FFFFFFFFFFFF000000000000000000000000000000000000 => 0x1000000000 0x0000002000000000 0 0 0xFF 1 17 | table_add table_mod_std_meta_stage4 action_drop 0x1000000000 => 18 | table_set_default dh_deparse action_dh_deparse -------------------------------------------------------------------------------- /tests/hyperv/napt/commands: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HyperVDP/HyperV/5a533013e33cbd53b4d9031dd710c77d8a9909d5/tests/hyperv/napt/commands -------------------------------------------------------------------------------- /tests/hyperv/nat/commands: -------------------------------------------------------------------------------- 1 | table_add table_config_at_initial action_set_initial_config 1 0 0 => 1 0 4 2 | table_add table_header_match_stage1 action_set_action_id 1 0 0x0800000000000000000000000000000000000000000&&&0xFFFF000000000000000000000000000000000000000 => 0 0 4 1 1 1 3 | table_add table_header_match_stage2 action_set_action_id 1 1 0x0a00000000000000&&&0xFFFFFF0000000000 => 0x1000000000 0x0000000800000000 4 3 1 1 4 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x1000000000 => 0x0a00010000000000 0xFFFFFF0000000000 5 | table_add table_header_match_stage2 action_set_action_id 1 1 0x0a000100&&&0xFFFFFF00=> 0x2000000000 0x0000000800000000 4 3 1 1 6 | table_add table_mod_header_with_const_stage2 action_mod_header_with_const 0x1000000000 => 0x0a000000 0xFFFFFF00 7 | table_add table_header_match_stage3 action_set_action_id 1 2 0x0a000002&&&0xFFFFFFFF=> 0x1000000000 0x0000002800000000 4 3 1 1 8 | table_add table_header_match_stage3 action_set_action_id 1 2 0x0a000002&&&0xFFFFFFFF=> 0x2000000000 0x0000002800000000 4 3 1 1 9 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x1000000000 => 0x00110000000000000800000000000000000000000000000000000000000 0xFFFF0000000000000000000000000000000000000000000000000000000 10 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x2000000000 => 0x00020000000000000800000000000000000000000000000000000000000 0xFFFF0000000000000000000000000000000000000000000000000000000 11 | table_add table_mod_std_meta_stage3 action_forward 0x100000000 => 1 12 | table_add table_mod_std_meta_stage3 action_forward 0x200000000 => 2 13 | table_add table_header_match_stage3 action_set_action_id 1 3 0x0a00010200000000&&&0xFFFFFFFF00000000 => 0x1000000000 0x0000000800000000 0 0 0xFF 1 14 | table_add table_header_match_stage3 action_set_action_id 1 3 0x0a00010300000000&&&0xFFFFFFFF00000000 => 0x2000000000 0x0000000800000000 0 0 0xFF 1 15 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x1000000000 => 0x0822000100010000000000000000000000000000000000000000000 0xFFFFFFFFFFFF0000000000000000000000000000000000000000000 16 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x2000000000 => 0x0822000100120000000000000000000000000000000000000000000 0xFFFFFFFFFFFF0000000000000000000000000000000000000000000 17 | table_set_default dh_deparse action_dh_deparse -------------------------------------------------------------------------------- /tests/hyperv/router/commands: -------------------------------------------------------------------------------- 1 | table_add table_config_at_initial action_set_initial_config 1 0 0 => 1 0 4 2 | table_add table_header_match_stage1 action_set_action_id 1 0 0x0800000000000000000000000000000000000000000&&&0xFFFF000000000000000000000000000000000000000 => 0 0 4 1 1 1 3 | table_add table_header_match_stage1 action_end 1 0 0x0&&&0x0 => 0xFF 4 | table_add table_get_expression_stage2 action_set_expr__header_op_const 1 5 => 88 0xFF 0 0 5 | table_add table_branch1_stage2 action_end 1 5 0 => 0xFF 6 | table_add table_branch2_stage2 action_set_action_id 1 5 0 => 0 0 4 1 1 1 7 | table_add table_branch3_stage2 action_end 1 5 0 => 0xFF 8 | 9 | 10 | table_add table_header_match_stage2 action_set_action_id 1 1 0x0a000000&&&0xFFFFFF00 => 0x1000000000 0x100000080 2 2 1 1 11 | table_add table_mod_meta_with_const_stage2 action_mod_meta_with_const 0x1000000000 => 0x0a000002 0xFFFFFFFF 12 | table_add table_substract_stage2 action_subtract_const_from_header 0x1000000000 => 0x010000000000000000000000 0xFF0000000000000000000000 13 | 14 | table_add table_header_match_stage2 action_set_action_id 1 1 0x0a000100&&&0xFFFFFF00 => 0x2000000000 0x100000080 2 2 1 1 15 | table_add table_mod_meta_with_const_stage2 action_mod_meta_with_const 0x2000000000 => 0x0a000102 0xFFFFFFFF 16 | table_add table_substract_stage2 action_subtract_const_from_header 0x2000000000 => 0x010000000000000000000000 0xFF0000000000000000000000 17 | 18 | 19 | 20 | table_add table_header_match_stage3 action_set_action_id 1 2 0x0a000002&&&0xFFFFFFFF => 0x10000 0x280000000 1 3 1 1 21 | table_add table_mod_std_meta_stage3 action_forward 0x10000 => 1 22 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x10000 => 0x082200010001000000000000000000000000000000000000000000000000000000 0xFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000 23 | 24 | 25 | table_add table_header_match_stage3 action_set_action_id 1 2 0x0a000102&&&0xFFFFFFFF => 0x20000 0x280000000 1 3 1 1 26 | table_add table_mod_std_meta_stage3 action_forward 0x20000 => 2 27 | table_add table_mod_header_with_const_stage3 action_mod_header_with_const 0x20000 => 0x082200010002000000000000000000000000000000000000000000000000000000 0xFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000 28 | 29 | 30 | table_add table_std_meta_match_stage4 action_set_action_id 1 3 1&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 1 0x0000002000000000 0 0 0xFF 1 31 | table_add table_std_meta_match_stage4 action_set_action_id 1 3 2&&&0xFF 0&&&0 0&&&0 0&&&0 0&&&0 0&&&0 => 2 0x0000002000000000 0 0 0xFF 1 32 | 33 | table_add table_mod_header_with_const_stage4 action_mod_header_with_const 1 => 0x082200010001000000000000000000000000000000000000000000 0xFFFFFFFFFFFF000000000000000000000000000000000000000000 34 | 35 | table_add table_mod_header_with_const_stage4 action_mod_header_with_const 2 => 0x082200010002000000000000000000000000000000000000000000 0xFFFFFFFFFFFF000000000000000000000000000000000000000000 36 | 37 | 38 | 39 | table_add table_checksum action_ipv4_checksum 1 => 0 40 | table_set_default dh_deparse action_dh_deparse -------------------------------------------------------------------------------- /tests/p4/arp_proxy/arp_proxy.p4: -------------------------------------------------------------------------------- 1 | header_type ethernet_t { 2 | fields { 3 | dest : 48; 4 | src : 48; 5 | etherType : 16; 6 | } 7 | } 8 | 9 | header_type arp_t { 10 | fields { 11 | hw_type : 16; 12 | prot_type : 16; 13 | hw_size : 8; 14 | prot_size : 8; 15 | opcode : 16; 16 | sender_MAC : 48; 17 | sender_IP : 32; 18 | target_MAC : 48; 19 | target_IP : 32; 20 | } 21 | } 22 | 23 | header ethernet_t ethernet; 24 | header arp_t arp; 25 | 26 | parser start { 27 | extract(ethernet); 28 | return select(ethernet.etherType) { 29 | 0x0806 : parse_arp; 30 | default : ingress; 31 | } 32 | } 33 | 34 | parser parse_arp { 35 | extract(arp); 36 | return ingress; 37 | } 38 | 39 | action a_init_meta_egress(port) { 40 | modify_field(standard_metadata.egress_spec, port); 41 | } 42 | 43 | table init_meta_egress { 44 | reads { 45 | standard_metadata.ingress_port : exact; 46 | } 47 | actions { 48 | a_init_meta_egress; 49 | } 50 | } 51 | 52 | action arp_present() { 53 | } 54 | 55 | table check_arp { 56 | reads { 57 | arp : valid; 58 | } 59 | actions { 60 | arp_present; 61 | send_packet; 62 | } 63 | } 64 | 65 | action arp_request() { 66 | } 67 | 68 | table check_opcode { 69 | reads { 70 | arp.opcode : exact; 71 | } 72 | actions { 73 | arp_request; 74 | send_packet; 75 | } 76 | } 77 | 78 | action arp_reply(IP, MAC) { 79 | modify_field(standard_metadata.egress_spec, standard_metadata.ingress_port); 80 | 81 | modify_field(arp.targest_MAC, arp.sender_MAC); 82 | modify_field(arp.target_IP, arp.send_ip); 83 | modify_field(ethernet.dest, ethernet.src); 84 | 85 | modify_field(arp.sender_MAC, MAC); 86 | modify_field(arp.sender_IP, IP); 87 | modify_field(ethernet.src, MAC); 88 | modify_field(arp.opcode, 2); 89 | } 90 | 91 | table handle_arp_request { 92 | reads { 93 | arp.target_IP : exact; 94 | } 95 | actions { 96 | arp_reply; 97 | send_packet; 98 | } 99 | } 100 | 101 | // action_ID: 5 102 | action send_packet() { 103 | 104 | } 105 | 106 | 107 | control ingress { 108 | apply(init_meta_egress); 109 | apply(check_arp) { 110 | arp_present { 111 | apply(check_opcode) { 112 | arp_request { 113 | apply(handle_arp_request); 114 | } 115 | } 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /tests/p4/arp_proxy/commands: -------------------------------------------------------------------------------- 1 | table_add init_meta_egress a_init_meta_egress 1 => 2 2 | table_add init_meta_egress a_init_meta_egress 2 => 1 3 | table_add check_arp arp_present 1 => 4 | table_add check_opcode arp_request 1=> 5 | table_add handle_arp_packet arp_reply 0x0a000001 => 0x0a000001 0x082a00010001 6 | table_add handle_arp_packet arp_reply 0x0a000002 => 0x0a000001 0x082a00010002 7 | table_set_default check_arp send_packet 8 | table_set_default check_opcode send_packet 9 | table_set_default handle_arp_packet send_packet 10 | -------------------------------------------------------------------------------- /tests/p4/firewall/commands: -------------------------------------------------------------------------------- 1 | table_add forward_table forward 1 => 2 2 | table_add forward_table forward 2 => 1 3 | table_add firewall_with_tcp block 0&&&0 0x0a000001&&&0xFFFFFFFF 0&&&0 80&&&0xFFFF => 1 4 | table_add firewall_with_udp block 0&&&0 0x0a000002&&&0xFFFFFFFF 8080&&&0xFFFF 0&&&0 => 1 5 | table_set_default firewall_with_tcp noop 6 | table_set_default firewall_with_udp noop -------------------------------------------------------------------------------- /tests/p4/firewall/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "__meta__": { 3 | "version": [ 4 | 2, 5 | 0 6 | ] 7 | }, 8 | "header_types": [ 9 | { 10 | "name": "standard_metadata_t", 11 | "id": 0, 12 | "fields": [ 13 | [ 14 | "ingress_port", 15 | 9 16 | ], 17 | [ 18 | "packet_length", 19 | 32 20 | ], 21 | [ 22 | "egress_spec", 23 | 9 24 | ], 25 | [ 26 | "egress_port", 27 | 9 28 | ], 29 | [ 30 | "egress_instance", 31 | 32 32 | ], 33 | [ 34 | "instance_type", 35 | 32 36 | ], 37 | [ 38 | "clone_spec", 39 | 32 40 | ], 41 | [ 42 | "_padding", 43 | 5 44 | ] 45 | ], 46 | "length_exp": null, 47 | "max_length": null 48 | }, 49 | { 50 | "name": "ethernet_t", 51 | "id": 1, 52 | "fields": [ 53 | [ 54 | "dstAddr", 55 | 48 56 | ], 57 | [ 58 | "srcAddr", 59 | 48 60 | ], 61 | [ 62 | "etherType", 63 | 16 64 | ] 65 | ], 66 | "length_exp": null, 67 | "max_length": null 68 | }, 69 | { 70 | "name": "ipv4_t", 71 | "id": 2, 72 | "fields": [ 73 | [ 74 | "version", 75 | 4 76 | ], 77 | [ 78 | "ihl", 79 | 4 80 | ], 81 | [ 82 | "diffserv", 83 | 8 84 | ], 85 | [ 86 | "totalLen", 87 | 16 88 | ], 89 | [ 90 | "identification", 91 | 16 92 | ], 93 | [ 94 | "flags", 95 | 3 96 | ], 97 | [ 98 | "fragOffset", 99 | 13 100 | ], 101 | [ 102 | "ttl", 103 | 8 104 | ], 105 | [ 106 | "protocol", 107 | 8 108 | ], 109 | [ 110 | "hdrChecksum", 111 | 16 112 | ], 113 | [ 114 | "srcAddr", 115 | 32 116 | ], 117 | [ 118 | "dstAddr", 119 | 32 120 | ] 121 | ], 122 | "length_exp": null, 123 | "max_length": null 124 | }, 125 | { 126 | "name": "tcp_t", 127 | "id": 3, 128 | "fields": [ 129 | [ 130 | "srcPort", 131 | 16 132 | ], 133 | [ 134 | "dstPort", 135 | 16 136 | ], 137 | [ 138 | "seqNo", 139 | 32 140 | ], 141 | [ 142 | "ackNo", 143 | 32 144 | ], 145 | [ 146 | "dataOffset", 147 | 4 148 | ], 149 | [ 150 | "res", 151 | 3 152 | ], 153 | [ 154 | "ecn", 155 | 3 156 | ], 157 | [ 158 | "ctrl", 159 | 6 160 | ], 161 | [ 162 | "window", 163 | 16 164 | ], 165 | [ 166 | "checksum", 167 | 16 168 | ], 169 | [ 170 | "urgentPtr", 171 | 16 172 | ] 173 | ], 174 | "length_exp": null, 175 | "max_length": null 176 | }, 177 | { 178 | "name": "udp_t", 179 | "id": 4, 180 | "fields": [ 181 | [ 182 | "srcPort", 183 | 16 184 | ], 185 | [ 186 | "dstPort", 187 | 16 188 | ], 189 | [ 190 | "len", 191 | 16 192 | ], 193 | [ 194 | "checksum", 195 | 16 196 | ] 197 | ], 198 | "length_exp": null, 199 | "max_length": null 200 | } 201 | ], 202 | "headers": [ 203 | { 204 | "name": "standard_metadata", 205 | "id": 0, 206 | "header_type": "standard_metadata_t", 207 | "metadata": true 208 | }, 209 | { 210 | "name": "ethernet", 211 | "id": 1, 212 | "header_type": "ethernet_t", 213 | "metadata": false 214 | }, 215 | { 216 | "name": "ipv4", 217 | "id": 2, 218 | "header_type": "ipv4_t", 219 | "metadata": false 220 | }, 221 | { 222 | "name": "tcp", 223 | "id": 3, 224 | "header_type": "tcp_t", 225 | "metadata": false 226 | }, 227 | { 228 | "name": "udp", 229 | "id": 4, 230 | "header_type": "udp_t", 231 | "metadata": false 232 | } 233 | ], 234 | "header_stacks": [], 235 | "parsers": [ 236 | { 237 | "name": "parser", 238 | "id": 0, 239 | "init_state": "start", 240 | "parse_states": [ 241 | { 242 | "name": "start", 243 | "id": 0, 244 | "parser_ops": [ 245 | { 246 | "op": "extract", 247 | "parameters": [ 248 | { 249 | "type": "regular", 250 | "value": "ethernet" 251 | } 252 | ] 253 | } 254 | ], 255 | "transition_key": [ 256 | { 257 | "type": "field", 258 | "value": [ 259 | "ethernet", 260 | "etherType" 261 | ] 262 | } 263 | ], 264 | "transitions": [ 265 | { 266 | "type": "hexstr", 267 | "value": "0x0806", 268 | "mask": null, 269 | "next_state": "ipv4_parser" 270 | }, 271 | { 272 | "type": "default", 273 | "value": null, 274 | "mask": null, 275 | "next_state": null 276 | } 277 | ] 278 | }, 279 | { 280 | "name": "udp_parser", 281 | "id": 1, 282 | "parser_ops": [ 283 | { 284 | "op": "extract", 285 | "parameters": [ 286 | { 287 | "type": "regular", 288 | "value": "udp" 289 | } 290 | ] 291 | } 292 | ], 293 | "transition_key": [], 294 | "transitions": [ 295 | { 296 | "type": "default", 297 | "value": null, 298 | "mask": null, 299 | "next_state": null 300 | } 301 | ] 302 | }, 303 | { 304 | "name": "tcp_parser", 305 | "id": 2, 306 | "parser_ops": [ 307 | { 308 | "op": "extract", 309 | "parameters": [ 310 | { 311 | "type": "regular", 312 | "value": "tcp" 313 | } 314 | ] 315 | } 316 | ], 317 | "transition_key": [], 318 | "transitions": [ 319 | { 320 | "type": "default", 321 | "value": null, 322 | "mask": null, 323 | "next_state": null 324 | } 325 | ] 326 | }, 327 | { 328 | "name": "ipv4_parser", 329 | "id": 3, 330 | "parser_ops": [ 331 | { 332 | "op": "extract", 333 | "parameters": [ 334 | { 335 | "type": "regular", 336 | "value": "ipv4" 337 | } 338 | ] 339 | } 340 | ], 341 | "transition_key": [ 342 | { 343 | "type": "field", 344 | "value": [ 345 | "ipv4", 346 | "protocol" 347 | ] 348 | } 349 | ], 350 | "transitions": [ 351 | { 352 | "type": "hexstr", 353 | "value": "0x06", 354 | "mask": null, 355 | "next_state": "tcp_parser" 356 | }, 357 | { 358 | "type": "hexstr", 359 | "value": "0x11", 360 | "mask": null, 361 | "next_state": "udp_parser" 362 | }, 363 | { 364 | "type": "default", 365 | "value": null, 366 | "mask": null, 367 | "next_state": null 368 | } 369 | ] 370 | } 371 | ] 372 | } 373 | ], 374 | "parse_vsets": [], 375 | "deparsers": [ 376 | { 377 | "name": "deparser", 378 | "id": 0, 379 | "order": [ 380 | "ethernet", 381 | "ipv4", 382 | "tcp", 383 | "udp" 384 | ] 385 | } 386 | ], 387 | "meter_arrays": [], 388 | "actions": [ 389 | { 390 | "name": "block", 391 | "id": 0, 392 | "runtime_data": [], 393 | "primitives": [ 394 | { 395 | "op": "drop", 396 | "parameters": [] 397 | } 398 | ] 399 | }, 400 | { 401 | "name": "noop", 402 | "id": 1, 403 | "runtime_data": [], 404 | "primitives": [ 405 | { 406 | "op": "no_op", 407 | "parameters": [] 408 | } 409 | ] 410 | }, 411 | { 412 | "name": "forward", 413 | "id": 2, 414 | "runtime_data": [ 415 | { 416 | "name": "port", 417 | "bitwidth": 9 418 | } 419 | ], 420 | "primitives": [ 421 | { 422 | "op": "modify_field", 423 | "parameters": [ 424 | { 425 | "type": "field", 426 | "value": [ 427 | "standard_metadata", 428 | "egress_spec" 429 | ] 430 | }, 431 | { 432 | "type": "runtime_data", 433 | "value": 0 434 | } 435 | ] 436 | } 437 | ] 438 | } 439 | ], 440 | "pipelines": [ 441 | { 442 | "name": "ingress", 443 | "id": 0, 444 | "init_table": "forward_table", 445 | "tables": [ 446 | { 447 | "name": "firewall_with_tcp", 448 | "id": 0, 449 | "match_type": "ternary", 450 | "type": "simple", 451 | "max_size": 16384, 452 | "with_counters": false, 453 | "direct_meters": null, 454 | "support_timeout": false, 455 | "key": [ 456 | { 457 | "match_type": "ternary", 458 | "target": [ 459 | "ipv4", 460 | "srcAddr" 461 | ], 462 | "mask": null 463 | }, 464 | { 465 | "match_type": "ternary", 466 | "target": [ 467 | "ipv4", 468 | "dstAddr" 469 | ], 470 | "mask": null 471 | }, 472 | { 473 | "match_type": "ternary", 474 | "target": [ 475 | "tcp", 476 | "srcPort" 477 | ], 478 | "mask": null 479 | }, 480 | { 481 | "match_type": "ternary", 482 | "target": [ 483 | "tcp", 484 | "dstPort" 485 | ], 486 | "mask": null 487 | } 488 | ], 489 | "actions": [ 490 | "block", 491 | "noop" 492 | ], 493 | "next_tables": { 494 | "block": null, 495 | "noop": null 496 | }, 497 | "base_default_next": null 498 | }, 499 | { 500 | "name": "firewall_with_udp", 501 | "id": 1, 502 | "match_type": "ternary", 503 | "type": "simple", 504 | "max_size": 16384, 505 | "with_counters": false, 506 | "direct_meters": null, 507 | "support_timeout": false, 508 | "key": [ 509 | { 510 | "match_type": "ternary", 511 | "target": [ 512 | "ipv4", 513 | "srcAddr" 514 | ], 515 | "mask": null 516 | }, 517 | { 518 | "match_type": "ternary", 519 | "target": [ 520 | "ipv4", 521 | "dstAddr" 522 | ], 523 | "mask": null 524 | }, 525 | { 526 | "match_type": "ternary", 527 | "target": [ 528 | "udp", 529 | "srcPort" 530 | ], 531 | "mask": null 532 | }, 533 | { 534 | "match_type": "ternary", 535 | "target": [ 536 | "udp", 537 | "dstPort" 538 | ], 539 | "mask": null 540 | } 541 | ], 542 | "actions": [ 543 | "block", 544 | "noop" 545 | ], 546 | "next_tables": { 547 | "block": null, 548 | "noop": null 549 | }, 550 | "base_default_next": null 551 | }, 552 | { 553 | "name": "forward_table", 554 | "id": 2, 555 | "match_type": "exact", 556 | "type": "simple", 557 | "max_size": 16384, 558 | "with_counters": false, 559 | "direct_meters": null, 560 | "support_timeout": false, 561 | "key": [ 562 | { 563 | "match_type": "exact", 564 | "target": [ 565 | "standard_metadata", 566 | "ingress_port" 567 | ], 568 | "mask": null 569 | } 570 | ], 571 | "actions": [ 572 | "forward" 573 | ], 574 | "next_tables": { 575 | "forward": "_condition_0" 576 | }, 577 | "base_default_next": "_condition_0" 578 | } 579 | ], 580 | "action_profiles": [], 581 | "conditionals": [ 582 | { 583 | "name": "_condition_0", 584 | "id": 0, 585 | "expression": { 586 | "type": "expression", 587 | "value": { 588 | "op": "valid", 589 | "left": null, 590 | "right": { 591 | "type": "header", 592 | "value": "ipv4" 593 | } 594 | } 595 | }, 596 | "true_next": "_condition_1", 597 | "false_next": null 598 | }, 599 | { 600 | "name": "_condition_1", 601 | "id": 1, 602 | "expression": { 603 | "type": "expression", 604 | "value": { 605 | "op": "valid", 606 | "left": null, 607 | "right": { 608 | "type": "header", 609 | "value": "udp" 610 | } 611 | } 612 | }, 613 | "true_next": "firewall_with_udp", 614 | "false_next": "_condition_2" 615 | }, 616 | { 617 | "name": "_condition_2", 618 | "id": 2, 619 | "expression": { 620 | "type": "expression", 621 | "value": { 622 | "op": "valid", 623 | "left": null, 624 | "right": { 625 | "type": "header", 626 | "value": "tcp" 627 | } 628 | } 629 | }, 630 | "true_next": "firewall_with_tcp", 631 | "false_next": null 632 | } 633 | ] 634 | }, 635 | { 636 | "name": "egress", 637 | "id": 1, 638 | "init_table": null, 639 | "tables": [], 640 | "action_profiles": [], 641 | "conditionals": [] 642 | } 643 | ], 644 | "calculations": [], 645 | "checksums": [], 646 | "learn_lists": [], 647 | "field_lists": [], 648 | "counter_arrays": [], 649 | "register_arrays": [], 650 | "force_arith": [ 651 | [ 652 | "standard_metadata", 653 | "ingress_port" 654 | ], 655 | [ 656 | "standard_metadata", 657 | "packet_length" 658 | ], 659 | [ 660 | "standard_metadata", 661 | "egress_spec" 662 | ], 663 | [ 664 | "standard_metadata", 665 | "egress_port" 666 | ], 667 | [ 668 | "standard_metadata", 669 | "egress_instance" 670 | ], 671 | [ 672 | "standard_metadata", 673 | "instance_type" 674 | ], 675 | [ 676 | "standard_metadata", 677 | "clone_spec" 678 | ], 679 | [ 680 | "standard_metadata", 681 | "_padding" 682 | ] 683 | ] 684 | } -------------------------------------------------------------------------------- /tests/p4/firewall/firewall.p4: -------------------------------------------------------------------------------- 1 | header_type ethernet_t { 2 | fields { 3 | dstAddr : 48; 4 | srcAddr : 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 tcp_t { 27 | fields { 28 | srcPort : 16; 29 | dstPort : 16; 30 | seqNo : 32; 31 | ackNo : 32; 32 | dataOffset : 4; 33 | res : 3; 34 | ecn : 3; 35 | ctrl : 6; 36 | window : 16; 37 | checksum : 16; 38 | urgentPtr : 16; 39 | } 40 | } 41 | 42 | header_type udp_t { 43 | fields { 44 | srcPort : 16; 45 | dstPort : 16; 46 | len : 16; 47 | checksum: 16; 48 | } 49 | } 50 | 51 | header ethernet_t ethernet; 52 | header ipv4_t ipv4; 53 | header tcp_t tcp; 54 | header udp_t udp; 55 | 56 | #define ETHERTYPE_IPv4 0x0806 57 | #define IPPROTCOL_UDP 17 58 | #define IPPROTCOL_TCP 6 59 | parser start { 60 | extract(ethernet); 61 | return select(ethernet.etherType) { 62 | ETHERTYPE_IPv4 : ipv4_parser; 63 | default : ingress; 64 | } 65 | } 66 | 67 | parser ipv4_parser { 68 | extract(ipv4); 69 | return select(ipv4.protocol) { 70 | IPPROTCOL_TCP : tcp_parser; 71 | IPPROTCOL_UDP : udp_parser; 72 | default : ingress; 73 | } 74 | } 75 | 76 | parser tcp_parser { 77 | extract(tcp); 78 | return ingress; 79 | } 80 | 81 | parser udp_parser { 82 | extract(udp); 83 | return ingress; 84 | } 85 | 86 | action block() { 87 | drop(); 88 | } 89 | 90 | action noop() { 91 | no_op(); 92 | } 93 | action forward(port) { 94 | modify_field(standard_metadata.egress_spec, port); 95 | } 96 | 97 | table firewall_with_tcp { 98 | reads { 99 | ipv4.srcAddr : ternary; 100 | ipv4.dstAddr : ternary; 101 | tcp.srcPort : ternary; 102 | tcp.dstPort : ternary; 103 | } 104 | actions { 105 | block; 106 | noop; 107 | } 108 | } 109 | 110 | table firewall_with_udp { 111 | reads { 112 | ipv4.srcAddr : ternary; 113 | ipv4.dstAddr : ternary; 114 | udp.srcPort : ternary; 115 | udp.dstPort : ternary; 116 | } 117 | actions { 118 | block; 119 | noop; 120 | } 121 | } 122 | 123 | table forward_table { 124 | reads { 125 | standard_metadata.ingress_port : exact; 126 | } 127 | actions { 128 | forward; 129 | } 130 | } 131 | control ingress { 132 | apply(forward_table); 133 | if (valid(ipv4)) { 134 | if(valid(udp)) { 135 | apply(firewall_with_udp); 136 | } 137 | else if(valid(tcp)) { 138 | apply(firewall_with_tcp); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /tests/p4/l2_switch/commands: -------------------------------------------------------------------------------- 1 | table_add dmac forward 0x800e00010002 => 2 2 | table_add dmac forward 0x800e00010001 => 1 3 | -------------------------------------------------------------------------------- /tests/p4/l2_switch/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "__meta__": { 3 | "version": [ 4 | 2, 5 | 0 6 | ] 7 | }, 8 | "header_types": [ 9 | { 10 | "name": "standard_metadata_t", 11 | "id": 0, 12 | "fields": [ 13 | [ 14 | "ingress_port", 15 | 9 16 | ], 17 | [ 18 | "packet_length", 19 | 32 20 | ], 21 | [ 22 | "egress_spec", 23 | 9 24 | ], 25 | [ 26 | "egress_port", 27 | 9 28 | ], 29 | [ 30 | "egress_instance", 31 | 32 32 | ], 33 | [ 34 | "instance_type", 35 | 32 36 | ], 37 | [ 38 | "clone_spec", 39 | 32 40 | ], 41 | [ 42 | "_padding", 43 | 5 44 | ] 45 | ], 46 | "length_exp": null, 47 | "max_length": null 48 | }, 49 | { 50 | "name": "ethernet_t", 51 | "id": 1, 52 | "fields": [ 53 | [ 54 | "dstAddr", 55 | 48 56 | ], 57 | [ 58 | "srcAddr", 59 | 48 60 | ], 61 | [ 62 | "etherType", 63 | 16 64 | ] 65 | ], 66 | "length_exp": null, 67 | "max_length": null 68 | } 69 | ], 70 | "headers": [ 71 | { 72 | "name": "standard_metadata", 73 | "id": 0, 74 | "header_type": "standard_metadata_t", 75 | "metadata": true 76 | }, 77 | { 78 | "name": "ethernet", 79 | "id": 1, 80 | "header_type": "ethernet_t", 81 | "metadata": false 82 | } 83 | ], 84 | "header_stacks": [], 85 | "parsers": [ 86 | { 87 | "name": "parser", 88 | "id": 0, 89 | "init_state": "start", 90 | "parse_states": [ 91 | { 92 | "name": "parse_ethernet", 93 | "id": 0, 94 | "parser_ops": [ 95 | { 96 | "op": "extract", 97 | "parameters": [ 98 | { 99 | "type": "regular", 100 | "value": "ethernet" 101 | } 102 | ] 103 | } 104 | ], 105 | "transition_key": [], 106 | "transitions": [ 107 | { 108 | "type": "default", 109 | "value": null, 110 | "mask": null, 111 | "next_state": null 112 | } 113 | ] 114 | }, 115 | { 116 | "name": "start", 117 | "id": 1, 118 | "parser_ops": [], 119 | "transition_key": [], 120 | "transitions": [ 121 | { 122 | "type": "default", 123 | "value": null, 124 | "mask": null, 125 | "next_state": "parse_ethernet" 126 | } 127 | ] 128 | } 129 | ] 130 | } 131 | ], 132 | "parse_vsets": [], 133 | "deparsers": [ 134 | { 135 | "name": "deparser", 136 | "id": 0, 137 | "order": [ 138 | "ethernet" 139 | ] 140 | } 141 | ], 142 | "meter_arrays": [], 143 | "actions": [ 144 | { 145 | "name": "forward", 146 | "id": 0, 147 | "runtime_data": [ 148 | { 149 | "name": "port", 150 | "bitwidth": 9 151 | } 152 | ], 153 | "primitives": [ 154 | { 155 | "op": "modify_field", 156 | "parameters": [ 157 | { 158 | "type": "field", 159 | "value": [ 160 | "standard_metadata", 161 | "egress_spec" 162 | ] 163 | }, 164 | { 165 | "type": "runtime_data", 166 | "value": 0 167 | } 168 | ] 169 | } 170 | ] 171 | } 172 | ], 173 | "pipelines": [ 174 | { 175 | "name": "ingress", 176 | "id": 0, 177 | "init_table": "dmac", 178 | "tables": [ 179 | { 180 | "name": "dmac", 181 | "id": 0, 182 | "match_type": "exact", 183 | "type": "simple", 184 | "max_size": 512, 185 | "with_counters": false, 186 | "direct_meters": null, 187 | "support_timeout": false, 188 | "key": [ 189 | { 190 | "match_type": "exact", 191 | "target": [ 192 | "ethernet", 193 | "dstAddr" 194 | ], 195 | "mask": null 196 | } 197 | ], 198 | "actions": [ 199 | "forward" 200 | ], 201 | "next_tables": { 202 | "forward": null 203 | }, 204 | "base_default_next": null 205 | } 206 | ], 207 | "action_profiles": [], 208 | "conditionals": [] 209 | }, 210 | { 211 | "name": "egress", 212 | "id": 1, 213 | "init_table": null, 214 | "tables": [], 215 | "action_profiles": [], 216 | "conditionals": [] 217 | } 218 | ], 219 | "calculations": [], 220 | "checksums": [], 221 | "learn_lists": [], 222 | "field_lists": [], 223 | "counter_arrays": [], 224 | "register_arrays": [], 225 | "force_arith": [ 226 | [ 227 | "standard_metadata", 228 | "ingress_port" 229 | ], 230 | [ 231 | "standard_metadata", 232 | "packet_length" 233 | ], 234 | [ 235 | "standard_metadata", 236 | "egress_spec" 237 | ], 238 | [ 239 | "standard_metadata", 240 | "egress_port" 241 | ], 242 | [ 243 | "standard_metadata", 244 | "egress_instance" 245 | ], 246 | [ 247 | "standard_metadata", 248 | "instance_type" 249 | ], 250 | [ 251 | "standard_metadata", 252 | "clone_spec" 253 | ], 254 | [ 255 | "standard_metadata", 256 | "_padding" 257 | ] 258 | ] 259 | } -------------------------------------------------------------------------------- /tests/p4/l2_switch/l2_switch.p4: -------------------------------------------------------------------------------- 1 | header_type ethernet_t { 2 | fields { 3 | dstAddr : 48; 4 | srcAddr : 48; 5 | etherType : 16; 6 | } 7 | } 8 | 9 | parser start { 10 | return parse_ethernet; 11 | } 12 | 13 | header ethernet_t ethernet; 14 | 15 | parser parse_ethernet { 16 | extract(ethernet); 17 | return ingress; 18 | } 19 | 20 | action forward(port) { 21 | modify_field(standard_metadata.egress_spec, port); 22 | } 23 | 24 | table dmac { 25 | reads { 26 | ethernet.dstAddr : exact; 27 | } 28 | actions {forward;} 29 | size : 512; 30 | } 31 | 32 | control ingress{ 33 | apply(dmac); 34 | } 35 | -------------------------------------------------------------------------------- /tests/p4/l2_with_fw/commands: -------------------------------------------------------------------------------- 1 | table_add dmac forward 0x803600010002 => 2 2 | table_add dmac forward 0x803600010001 => 1 3 | table_add forward_table forward 1 => 2 4 | table_add forward_table forward 2 => 1 5 | table_add firewall_with_tcp block 0&&&0 0x0a000001&&&0xFFFFFFFF 0&&&0 80&&&0xFFFF => 1 6 | table_add firewall_with_udp block 0&&&0 0x0a000002&&&0xFFFFFFFF 8080&&&0xFFFF 0&&&0 => 1 7 | table_set_default firewall_with_tcp noop 8 | table_set_default firewall_with_udp noop -------------------------------------------------------------------------------- /tests/p4/l2_with_fw/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "__meta__": { 3 | "version": [ 4 | 2, 5 | 0 6 | ] 7 | }, 8 | "header_types": [ 9 | { 10 | "name": "standard_metadata_t", 11 | "id": 0, 12 | "fields": [ 13 | [ 14 | "ingress_port", 15 | 9 16 | ], 17 | [ 18 | "packet_length", 19 | 32 20 | ], 21 | [ 22 | "egress_spec", 23 | 9 24 | ], 25 | [ 26 | "egress_port", 27 | 9 28 | ], 29 | [ 30 | "egress_instance", 31 | 32 32 | ], 33 | [ 34 | "instance_type", 35 | 32 36 | ], 37 | [ 38 | "clone_spec", 39 | 32 40 | ], 41 | [ 42 | "_padding", 43 | 5 44 | ] 45 | ], 46 | "length_exp": null, 47 | "max_length": null 48 | }, 49 | { 50 | "name": "ipv4_t", 51 | "id": 1, 52 | "fields": [ 53 | [ 54 | "version", 55 | 4 56 | ], 57 | [ 58 | "ihl", 59 | 4 60 | ], 61 | [ 62 | "diffserv", 63 | 8 64 | ], 65 | [ 66 | "totalLen", 67 | 16 68 | ], 69 | [ 70 | "identification", 71 | 16 72 | ], 73 | [ 74 | "flags", 75 | 3 76 | ], 77 | [ 78 | "fragOffset", 79 | 13 80 | ], 81 | [ 82 | "ttl", 83 | 8 84 | ], 85 | [ 86 | "protocol", 87 | 8 88 | ], 89 | [ 90 | "hdrChecksum", 91 | 16 92 | ], 93 | [ 94 | "srcAddr", 95 | 32 96 | ], 97 | [ 98 | "dstAddr", 99 | 32 100 | ] 101 | ], 102 | "length_exp": null, 103 | "max_length": null 104 | }, 105 | { 106 | "name": "tcp_t", 107 | "id": 2, 108 | "fields": [ 109 | [ 110 | "srcPort", 111 | 16 112 | ], 113 | [ 114 | "dstPort", 115 | 16 116 | ], 117 | [ 118 | "seqNo", 119 | 32 120 | ], 121 | [ 122 | "ackNo", 123 | 32 124 | ], 125 | [ 126 | "dataOffset", 127 | 4 128 | ], 129 | [ 130 | "res", 131 | 3 132 | ], 133 | [ 134 | "ecn", 135 | 3 136 | ], 137 | [ 138 | "ctrl", 139 | 6 140 | ], 141 | [ 142 | "window", 143 | 16 144 | ], 145 | [ 146 | "checksum", 147 | 16 148 | ], 149 | [ 150 | "urgentPtr", 151 | 16 152 | ] 153 | ], 154 | "length_exp": null, 155 | "max_length": null 156 | }, 157 | { 158 | "name": "udp_t", 159 | "id": 3, 160 | "fields": [ 161 | [ 162 | "srcPort", 163 | 16 164 | ], 165 | [ 166 | "dstPort", 167 | 16 168 | ], 169 | [ 170 | "len", 171 | 16 172 | ], 173 | [ 174 | "checksum", 175 | 16 176 | ] 177 | ], 178 | "length_exp": null, 179 | "max_length": null 180 | }, 181 | { 182 | "name": "ethernet_t", 183 | "id": 4, 184 | "fields": [ 185 | [ 186 | "dstAddr", 187 | 48 188 | ], 189 | [ 190 | "srcAddr", 191 | 48 192 | ], 193 | [ 194 | "etherType", 195 | 16 196 | ] 197 | ], 198 | "length_exp": null, 199 | "max_length": null 200 | } 201 | ], 202 | "headers": [ 203 | { 204 | "name": "standard_metadata", 205 | "id": 0, 206 | "header_type": "standard_metadata_t", 207 | "metadata": true 208 | }, 209 | { 210 | "name": "ethernet", 211 | "id": 1, 212 | "header_type": "ethernet_t", 213 | "metadata": false 214 | }, 215 | { 216 | "name": "ipv4", 217 | "id": 2, 218 | "header_type": "ipv4_t", 219 | "metadata": false 220 | }, 221 | { 222 | "name": "tcp", 223 | "id": 3, 224 | "header_type": "tcp_t", 225 | "metadata": false 226 | }, 227 | { 228 | "name": "udp", 229 | "id": 4, 230 | "header_type": "udp_t", 231 | "metadata": false 232 | } 233 | ], 234 | "header_stacks": [], 235 | "parsers": [ 236 | { 237 | "name": "parser", 238 | "id": 0, 239 | "init_state": "start", 240 | "parse_states": [ 241 | { 242 | "name": "tcp_parser", 243 | "id": 0, 244 | "parser_ops": [ 245 | { 246 | "op": "extract", 247 | "parameters": [ 248 | { 249 | "type": "regular", 250 | "value": "tcp" 251 | } 252 | ] 253 | } 254 | ], 255 | "transition_key": [], 256 | "transitions": [ 257 | { 258 | "type": "default", 259 | "value": null, 260 | "mask": null, 261 | "next_state": null 262 | } 263 | ] 264 | }, 265 | { 266 | "name": "start", 267 | "id": 1, 268 | "parser_ops": [ 269 | { 270 | "op": "extract", 271 | "parameters": [ 272 | { 273 | "type": "regular", 274 | "value": "ethernet" 275 | } 276 | ] 277 | } 278 | ], 279 | "transition_key": [ 280 | { 281 | "type": "field", 282 | "value": [ 283 | "ethernet", 284 | "etherType" 285 | ] 286 | } 287 | ], 288 | "transitions": [ 289 | { 290 | "type": "hexstr", 291 | "value": "0x0806", 292 | "mask": null, 293 | "next_state": "ipv4_parser" 294 | }, 295 | { 296 | "type": "default", 297 | "value": null, 298 | "mask": null, 299 | "next_state": null 300 | } 301 | ] 302 | }, 303 | { 304 | "name": "udp_parser", 305 | "id": 2, 306 | "parser_ops": [ 307 | { 308 | "op": "extract", 309 | "parameters": [ 310 | { 311 | "type": "regular", 312 | "value": "udp" 313 | } 314 | ] 315 | } 316 | ], 317 | "transition_key": [], 318 | "transitions": [ 319 | { 320 | "type": "default", 321 | "value": null, 322 | "mask": null, 323 | "next_state": null 324 | } 325 | ] 326 | }, 327 | { 328 | "name": "ipv4_parser", 329 | "id": 3, 330 | "parser_ops": [ 331 | { 332 | "op": "extract", 333 | "parameters": [ 334 | { 335 | "type": "regular", 336 | "value": "ipv4" 337 | } 338 | ] 339 | } 340 | ], 341 | "transition_key": [ 342 | { 343 | "type": "field", 344 | "value": [ 345 | "ipv4", 346 | "protocol" 347 | ] 348 | } 349 | ], 350 | "transitions": [ 351 | { 352 | "type": "hexstr", 353 | "value": "0x06", 354 | "mask": null, 355 | "next_state": "tcp_parser" 356 | }, 357 | { 358 | "type": "hexstr", 359 | "value": "0x11", 360 | "mask": null, 361 | "next_state": "udp_parser" 362 | }, 363 | { 364 | "type": "default", 365 | "value": null, 366 | "mask": null, 367 | "next_state": null 368 | } 369 | ] 370 | } 371 | ] 372 | } 373 | ], 374 | "parse_vsets": [], 375 | "deparsers": [ 376 | { 377 | "name": "deparser", 378 | "id": 0, 379 | "order": [ 380 | "ethernet", 381 | "ipv4", 382 | "tcp", 383 | "udp" 384 | ] 385 | } 386 | ], 387 | "meter_arrays": [], 388 | "actions": [ 389 | { 390 | "name": "block", 391 | "id": 0, 392 | "runtime_data": [], 393 | "primitives": [ 394 | { 395 | "op": "drop", 396 | "parameters": [] 397 | } 398 | ] 399 | }, 400 | { 401 | "name": "noop", 402 | "id": 1, 403 | "runtime_data": [], 404 | "primitives": [ 405 | { 406 | "op": "no_op", 407 | "parameters": [] 408 | } 409 | ] 410 | }, 411 | { 412 | "name": "forward", 413 | "id": 2, 414 | "runtime_data": [ 415 | { 416 | "name": "port", 417 | "bitwidth": 9 418 | } 419 | ], 420 | "primitives": [ 421 | { 422 | "op": "modify_field", 423 | "parameters": [ 424 | { 425 | "type": "field", 426 | "value": [ 427 | "standard_metadata", 428 | "egress_spec" 429 | ] 430 | }, 431 | { 432 | "type": "runtime_data", 433 | "value": 0 434 | } 435 | ] 436 | } 437 | ] 438 | } 439 | ], 440 | "pipelines": [ 441 | { 442 | "name": "ingress", 443 | "id": 0, 444 | "init_table": "dmac", 445 | "tables": [ 446 | { 447 | "name": "firewall_with_tcp", 448 | "id": 0, 449 | "match_type": "ternary", 450 | "type": "simple", 451 | "max_size": 16384, 452 | "with_counters": false, 453 | "direct_meters": null, 454 | "support_timeout": false, 455 | "key": [ 456 | { 457 | "match_type": "ternary", 458 | "target": [ 459 | "ipv4", 460 | "srcAddr" 461 | ], 462 | "mask": null 463 | }, 464 | { 465 | "match_type": "ternary", 466 | "target": [ 467 | "ipv4", 468 | "dstAddr" 469 | ], 470 | "mask": null 471 | }, 472 | { 473 | "match_type": "ternary", 474 | "target": [ 475 | "tcp", 476 | "srcPort" 477 | ], 478 | "mask": null 479 | }, 480 | { 481 | "match_type": "ternary", 482 | "target": [ 483 | "tcp", 484 | "dstPort" 485 | ], 486 | "mask": null 487 | } 488 | ], 489 | "actions": [ 490 | "block", 491 | "noop" 492 | ], 493 | "next_tables": { 494 | "block": null, 495 | "noop": null 496 | }, 497 | "base_default_next": null 498 | }, 499 | { 500 | "name": "firewall_with_udp", 501 | "id": 1, 502 | "match_type": "ternary", 503 | "type": "simple", 504 | "max_size": 16384, 505 | "with_counters": false, 506 | "direct_meters": null, 507 | "support_timeout": false, 508 | "key": [ 509 | { 510 | "match_type": "ternary", 511 | "target": [ 512 | "ipv4", 513 | "srcAddr" 514 | ], 515 | "mask": null 516 | }, 517 | { 518 | "match_type": "ternary", 519 | "target": [ 520 | "ipv4", 521 | "dstAddr" 522 | ], 523 | "mask": null 524 | }, 525 | { 526 | "match_type": "ternary", 527 | "target": [ 528 | "udp", 529 | "srcPort" 530 | ], 531 | "mask": null 532 | }, 533 | { 534 | "match_type": "ternary", 535 | "target": [ 536 | "udp", 537 | "dstPort" 538 | ], 539 | "mask": null 540 | } 541 | ], 542 | "actions": [ 543 | "block", 544 | "noop" 545 | ], 546 | "next_tables": { 547 | "block": null, 548 | "noop": null 549 | }, 550 | "base_default_next": null 551 | }, 552 | { 553 | "name": "forward_table", 554 | "id": 2, 555 | "match_type": "exact", 556 | "type": "simple", 557 | "max_size": 16384, 558 | "with_counters": false, 559 | "direct_meters": null, 560 | "support_timeout": false, 561 | "key": [ 562 | { 563 | "match_type": "exact", 564 | "target": [ 565 | "standard_metadata", 566 | "ingress_port" 567 | ], 568 | "mask": null 569 | } 570 | ], 571 | "actions": [ 572 | "forward" 573 | ], 574 | "next_tables": { 575 | "forward": "_condition_0" 576 | }, 577 | "base_default_next": "_condition_0" 578 | }, 579 | { 580 | "name": "dmac", 581 | "id": 3, 582 | "match_type": "exact", 583 | "type": "simple", 584 | "max_size": 512, 585 | "with_counters": false, 586 | "direct_meters": null, 587 | "support_timeout": false, 588 | "key": [ 589 | { 590 | "match_type": "exact", 591 | "target": [ 592 | "ethernet", 593 | "dstAddr" 594 | ], 595 | "mask": null 596 | } 597 | ], 598 | "actions": [ 599 | "forward" 600 | ], 601 | "next_tables": { 602 | "forward": "forward_table" 603 | }, 604 | "base_default_next": "forward_table" 605 | } 606 | ], 607 | "action_profiles": [], 608 | "conditionals": [ 609 | { 610 | "name": "_condition_0", 611 | "id": 0, 612 | "expression": { 613 | "type": "expression", 614 | "value": { 615 | "op": "valid", 616 | "left": null, 617 | "right": { 618 | "type": "header", 619 | "value": "ipv4" 620 | } 621 | } 622 | }, 623 | "true_next": "_condition_1", 624 | "false_next": null 625 | }, 626 | { 627 | "name": "_condition_1", 628 | "id": 1, 629 | "expression": { 630 | "type": "expression", 631 | "value": { 632 | "op": "valid", 633 | "left": null, 634 | "right": { 635 | "type": "header", 636 | "value": "udp" 637 | } 638 | } 639 | }, 640 | "true_next": "firewall_with_udp", 641 | "false_next": "_condition_2" 642 | }, 643 | { 644 | "name": "_condition_2", 645 | "id": 2, 646 | "expression": { 647 | "type": "expression", 648 | "value": { 649 | "op": "valid", 650 | "left": null, 651 | "right": { 652 | "type": "header", 653 | "value": "tcp" 654 | } 655 | } 656 | }, 657 | "true_next": "firewall_with_tcp", 658 | "false_next": null 659 | } 660 | ] 661 | }, 662 | { 663 | "name": "egress", 664 | "id": 1, 665 | "init_table": null, 666 | "tables": [], 667 | "action_profiles": [], 668 | "conditionals": [] 669 | } 670 | ], 671 | "calculations": [], 672 | "checksums": [], 673 | "learn_lists": [], 674 | "field_lists": [], 675 | "counter_arrays": [], 676 | "register_arrays": [], 677 | "force_arith": [ 678 | [ 679 | "standard_metadata", 680 | "ingress_port" 681 | ], 682 | [ 683 | "standard_metadata", 684 | "packet_length" 685 | ], 686 | [ 687 | "standard_metadata", 688 | "egress_spec" 689 | ], 690 | [ 691 | "standard_metadata", 692 | "egress_port" 693 | ], 694 | [ 695 | "standard_metadata", 696 | "egress_instance" 697 | ], 698 | [ 699 | "standard_metadata", 700 | "instance_type" 701 | ], 702 | [ 703 | "standard_metadata", 704 | "clone_spec" 705 | ], 706 | [ 707 | "standard_metadata", 708 | "_padding" 709 | ] 710 | ] 711 | } -------------------------------------------------------------------------------- /tests/p4/l2_with_fw/l2_with_fw.p4: -------------------------------------------------------------------------------- 1 | header_type ipv4_t { 2 | fields { 3 | version : 4; 4 | ihl : 4; 5 | diffserv : 8; 6 | totalLen : 16; 7 | identification : 16; 8 | flags : 3; 9 | fragOffset : 13; 10 | ttl : 8; 11 | protocol : 8; 12 | hdrChecksum : 16; 13 | srcAddr : 32; 14 | dstAddr: 32; 15 | } 16 | } 17 | 18 | header_type tcp_t { 19 | fields { 20 | srcPort : 16; 21 | dstPort : 16; 22 | seqNo : 32; 23 | ackNo : 32; 24 | dataOffset : 4; 25 | res : 3; 26 | ecn : 3; 27 | ctrl : 6; 28 | window : 16; 29 | checksum : 16; 30 | urgentPtr : 16; 31 | } 32 | } 33 | 34 | header_type udp_t { 35 | fields { 36 | srcPort : 16; 37 | dstPort : 16; 38 | len : 16; 39 | checksum: 16; 40 | } 41 | } 42 | 43 | header ethernet_t ethernet; 44 | header ipv4_t ipv4; 45 | header tcp_t tcp; 46 | header udp_t udp; 47 | 48 | #define ETHERTYPE_IPv4 0x0806 49 | #define IPPROTCOL_UDP 17 50 | #define IPPROTCOL_TCP 6 51 | 52 | parser start { 53 | extract(ethernet); 54 | return select(ethernet.etherType) { 55 | ETHERTYPE_IPv4 : ipv4_parser; 56 | default : ingress; 57 | } 58 | } 59 | 60 | parser ipv4_parser { 61 | extract(ipv4); 62 | return select(ipv4.protocol) { 63 | IPPROTCOL_TCP : tcp_parser; 64 | IPPROTCOL_UDP : udp_parser; 65 | default : ingress; 66 | } 67 | } 68 | 69 | parser tcp_parser { 70 | extract(tcp); 71 | return ingress; 72 | } 73 | 74 | parser udp_parser { 75 | extract(udp); 76 | return ingress; 77 | } 78 | 79 | action block() { 80 | drop(); 81 | } 82 | 83 | action noop() { 84 | no_op(); 85 | } 86 | action forward(port) { 87 | modify_field(standard_metadata.egress_spec, port); 88 | } 89 | 90 | table firewall_with_tcp { 91 | reads { 92 | ipv4.srcAddr : ternary; 93 | ipv4.dstAddr : ternary; 94 | tcp.srcPort : ternary; 95 | tcp.dstPort : ternary; 96 | } 97 | actions { 98 | block; 99 | noop; 100 | } 101 | } 102 | 103 | table firewall_with_udp { 104 | reads { 105 | ipv4.srcAddr : ternary; 106 | ipv4.dstAddr : ternary; 107 | udp.srcPort : ternary; 108 | udp.dstPort : ternary; 109 | } 110 | actions { 111 | block; 112 | noop; 113 | } 114 | } 115 | 116 | table forward_table { 117 | reads { 118 | standard_metadata.ingress_port : exact; 119 | } 120 | actions { 121 | forward; 122 | } 123 | } 124 | 125 | table dmac { 126 | reads { 127 | ethernet.dstAddr : exact; 128 | } 129 | actions {forward;} 130 | size : 512; 131 | } 132 | 133 | 134 | header_type ethernet_t { 135 | fields { 136 | dstAddr : 48; 137 | srcAddr : 48; 138 | etherType : 16; 139 | } 140 | } 141 | 142 | control l2_switch { 143 | apply(dmac); 144 | } 145 | 146 | control fw { 147 | apply(forward_table); 148 | if (valid(ipv4)) { 149 | if(valid(udp)) { 150 | apply(firewall_with_udp); 151 | } 152 | else if(valid(tcp)) { 153 | apply(firewall_with_tcp); 154 | } 155 | } 156 | } 157 | 158 | control ingress { 159 | l2_switch(); 160 | fw(); 161 | } -------------------------------------------------------------------------------- /tests/p4/napt/commands: -------------------------------------------------------------------------------- 1 | // TODO 2 | -------------------------------------------------------------------------------- /tests/p4/napt/napt.p4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HyperVDP/HyperV/5a533013e33cbd53b4d9031dd710c77d8a9909d5/tests/p4/napt/napt.p4 -------------------------------------------------------------------------------- /tests/p4/nat/commands: -------------------------------------------------------------------------------- 1 | table_add nat nat_output 0x0a000002&&&0xFFFFFF00 0&&&0 => 0x0a000001 0xFFFFFF00 1 2 | table_add nat nat_input 0&&&0 0x0a000002&0xFFFFFF00 => 0x0a000000 0xFFFFFF00 1 3 | table_add forward set_dmac 0x0a000002 => 0x082200010011 1 4 | table_add forward set_dmac 0x0a000103 => 0x082200010002 2 5 | table_add send_frame set_smac 0x0a000102 => 0x082200010001 6 | table_add send_frame set_smac 0x0a000103 => 0x082200010012 7 | table_set_default forward _drop 8 | table_set_default send_frame _drop -------------------------------------------------------------------------------- /tests/p4/nat/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "__meta__": { 3 | "version": [ 4 | 2, 5 | 0 6 | ] 7 | }, 8 | "header_types": [ 9 | { 10 | "name": "standard_metadata_t", 11 | "id": 0, 12 | "fields": [ 13 | [ 14 | "ingress_port", 15 | 9 16 | ], 17 | [ 18 | "packet_length", 19 | 32 20 | ], 21 | [ 22 | "egress_spec", 23 | 9 24 | ], 25 | [ 26 | "egress_port", 27 | 9 28 | ], 29 | [ 30 | "egress_instance", 31 | 32 32 | ], 33 | [ 34 | "instance_type", 35 | 32 36 | ], 37 | [ 38 | "clone_spec", 39 | 32 40 | ], 41 | [ 42 | "_padding", 43 | 5 44 | ] 45 | ], 46 | "length_exp": null, 47 | "max_length": null 48 | }, 49 | { 50 | "name": "ethernet_t", 51 | "id": 1, 52 | "fields": [ 53 | [ 54 | "dstAddr", 55 | 48 56 | ], 57 | [ 58 | "srcAddr", 59 | 48 60 | ], 61 | [ 62 | "etherType", 63 | 16 64 | ] 65 | ], 66 | "length_exp": null, 67 | "max_length": null 68 | }, 69 | { 70 | "name": "ipv4_t", 71 | "id": 2, 72 | "fields": [ 73 | [ 74 | "version", 75 | 4 76 | ], 77 | [ 78 | "ihl", 79 | 4 80 | ], 81 | [ 82 | "diffserv", 83 | 8 84 | ], 85 | [ 86 | "totalLen", 87 | 16 88 | ], 89 | [ 90 | "identification", 91 | 16 92 | ], 93 | [ 94 | "flags", 95 | 3 96 | ], 97 | [ 98 | "fragOffset", 99 | 13 100 | ], 101 | [ 102 | "ttl", 103 | 8 104 | ], 105 | [ 106 | "protocol", 107 | 8 108 | ], 109 | [ 110 | "hdrChecksum", 111 | 16 112 | ], 113 | [ 114 | "srcAddr", 115 | 32 116 | ], 117 | [ 118 | "dstAddr", 119 | 32 120 | ] 121 | ], 122 | "length_exp": null, 123 | "max_length": null 124 | }, 125 | { 126 | "name": "meta_t", 127 | "id": 3, 128 | "fields": [ 129 | [ 130 | "nhop_ipv4", 131 | 32 132 | ] 133 | ], 134 | "length_exp": null, 135 | "max_length": null 136 | } 137 | ], 138 | "headers": [ 139 | { 140 | "name": "standard_metadata", 141 | "id": 0, 142 | "header_type": "standard_metadata_t", 143 | "metadata": true 144 | }, 145 | { 146 | "name": "ethernet", 147 | "id": 1, 148 | "header_type": "ethernet_t", 149 | "metadata": false 150 | }, 151 | { 152 | "name": "ipv4", 153 | "id": 2, 154 | "header_type": "ipv4_t", 155 | "metadata": false 156 | }, 157 | { 158 | "name": "meta", 159 | "id": 3, 160 | "header_type": "meta_t", 161 | "metadata": true 162 | } 163 | ], 164 | "header_stacks": [], 165 | "parsers": [ 166 | { 167 | "name": "parser", 168 | "id": 0, 169 | "init_state": "start", 170 | "parse_states": [ 171 | { 172 | "name": "start", 173 | "id": 0, 174 | "parser_ops": [ 175 | { 176 | "op": "extract", 177 | "parameters": [ 178 | { 179 | "type": "regular", 180 | "value": "ethernet" 181 | } 182 | ] 183 | } 184 | ], 185 | "transition_key": [ 186 | { 187 | "type": "field", 188 | "value": [ 189 | "ethernet", 190 | "etherType" 191 | ] 192 | } 193 | ], 194 | "transitions": [ 195 | { 196 | "type": "hexstr", 197 | "value": "0x0800", 198 | "mask": null, 199 | "next_state": "parse_ipv4" 200 | }, 201 | { 202 | "type": "default", 203 | "value": null, 204 | "mask": null, 205 | "next_state": null 206 | } 207 | ] 208 | }, 209 | { 210 | "name": "parse_ipv4", 211 | "id": 1, 212 | "parser_ops": [ 213 | { 214 | "op": "extract", 215 | "parameters": [ 216 | { 217 | "type": "regular", 218 | "value": "ipv4" 219 | } 220 | ] 221 | } 222 | ], 223 | "transition_key": [], 224 | "transitions": [ 225 | { 226 | "type": "default", 227 | "value": null, 228 | "mask": null, 229 | "next_state": null 230 | } 231 | ] 232 | } 233 | ] 234 | } 235 | ], 236 | "parse_vsets": [], 237 | "deparsers": [ 238 | { 239 | "name": "deparser", 240 | "id": 0, 241 | "order": [ 242 | "ethernet", 243 | "ipv4" 244 | ] 245 | } 246 | ], 247 | "meter_arrays": [], 248 | "actions": [ 249 | { 250 | "name": "rewrite_mac", 251 | "id": 0, 252 | "runtime_data": [ 253 | { 254 | "name": "smac", 255 | "bitwidth": 48 256 | } 257 | ], 258 | "primitives": [ 259 | { 260 | "op": "modify_field", 261 | "parameters": [ 262 | { 263 | "type": "field", 264 | "value": [ 265 | "ethernet", 266 | "srcAddr" 267 | ] 268 | }, 269 | { 270 | "type": "runtime_data", 271 | "value": 0 272 | } 273 | ] 274 | } 275 | ] 276 | }, 277 | { 278 | "name": "nat_output", 279 | "id": 1, 280 | "runtime_data": [ 281 | { 282 | "name": "srcAddr", 283 | "bitwidth": 32 284 | } 285 | ], 286 | "primitives": [ 287 | { 288 | "op": "modify_field", 289 | "parameters": [ 290 | { 291 | "type": "field", 292 | "value": [ 293 | "ipv4", 294 | "srcAddr" 295 | ] 296 | }, 297 | { 298 | "type": "runtime_data", 299 | "value": 0 300 | } 301 | ] 302 | } 303 | ] 304 | }, 305 | { 306 | "name": "nat_input", 307 | "id": 2, 308 | "runtime_data": [ 309 | { 310 | "name": "dstAddr", 311 | "bitwidth": 32 312 | } 313 | ], 314 | "primitives": [ 315 | { 316 | "op": "modify_field", 317 | "parameters": [ 318 | { 319 | "type": "field", 320 | "value": [ 321 | "ipv4", 322 | "dstAddr" 323 | ] 324 | }, 325 | { 326 | "type": "runtime_data", 327 | "value": 0 328 | } 329 | ] 330 | } 331 | ] 332 | }, 333 | { 334 | "name": "set_nhop", 335 | "id": 3, 336 | "runtime_data": [ 337 | { 338 | "name": "nhop_ipv4", 339 | "bitwidth": 32 340 | }, 341 | { 342 | "name": "port", 343 | "bitwidth": 9 344 | } 345 | ], 346 | "primitives": [ 347 | { 348 | "op": "modify_field", 349 | "parameters": [ 350 | { 351 | "type": "field", 352 | "value": [ 353 | "meta", 354 | "nhop_ipv4" 355 | ] 356 | }, 357 | { 358 | "type": "runtime_data", 359 | "value": 0 360 | } 361 | ] 362 | }, 363 | { 364 | "op": "modify_field", 365 | "parameters": [ 366 | { 367 | "type": "field", 368 | "value": [ 369 | "standard_metadata", 370 | "egress_spec" 371 | ] 372 | }, 373 | { 374 | "type": "runtime_data", 375 | "value": 1 376 | } 377 | ] 378 | } 379 | ] 380 | }, 381 | { 382 | "name": "set_dmac", 383 | "id": 4, 384 | "runtime_data": [ 385 | { 386 | "name": "dmac", 387 | "bitwidth": 48 388 | } 389 | ], 390 | "primitives": [ 391 | { 392 | "op": "modify_field", 393 | "parameters": [ 394 | { 395 | "type": "field", 396 | "value": [ 397 | "ethernet", 398 | "dstAddr" 399 | ] 400 | }, 401 | { 402 | "type": "runtime_data", 403 | "value": 0 404 | } 405 | ] 406 | } 407 | ] 408 | }, 409 | { 410 | "name": "_drop", 411 | "id": 5, 412 | "runtime_data": [], 413 | "primitives": [ 414 | { 415 | "op": "drop", 416 | "parameters": [] 417 | } 418 | ] 419 | } 420 | ], 421 | "pipelines": [ 422 | { 423 | "name": "ingress", 424 | "id": 0, 425 | "init_table": "_condition_0", 426 | "tables": [ 427 | { 428 | "name": "nat", 429 | "id": 0, 430 | "match_type": "exact", 431 | "type": "simple", 432 | "max_size": 16384, 433 | "with_counters": false, 434 | "direct_meters": null, 435 | "support_timeout": false, 436 | "key": [ 437 | { 438 | "match_type": "exact", 439 | "target": [ 440 | "ipv4", 441 | "srcAddr" 442 | ], 443 | "mask": null 444 | }, 445 | { 446 | "match_type": "exact", 447 | "target": [ 448 | "ipv4", 449 | "dstAddr" 450 | ], 451 | "mask": null 452 | } 453 | ], 454 | "actions": [ 455 | "_drop", 456 | "nat_input", 457 | "nat_output" 458 | ], 459 | "next_tables": { 460 | "_drop": "forward", 461 | "nat_input": "forward", 462 | "nat_output": "forward" 463 | }, 464 | "base_default_next": "forward" 465 | }, 466 | { 467 | "name": "ipv4_nhop", 468 | "id": 1, 469 | "match_type": "exact", 470 | "type": "simple", 471 | "max_size": 16384, 472 | "with_counters": false, 473 | "direct_meters": null, 474 | "support_timeout": false, 475 | "key": [ 476 | { 477 | "match_type": "exact", 478 | "target": [ 479 | "ipv4", 480 | "dstAddr" 481 | ], 482 | "mask": null 483 | } 484 | ], 485 | "actions": [ 486 | "set_nhop" 487 | ], 488 | "next_tables": { 489 | "set_nhop": "nat" 490 | }, 491 | "base_default_next": "nat" 492 | }, 493 | { 494 | "name": "forward", 495 | "id": 2, 496 | "match_type": "exact", 497 | "type": "simple", 498 | "max_size": 16384, 499 | "with_counters": false, 500 | "direct_meters": null, 501 | "support_timeout": false, 502 | "key": [ 503 | { 504 | "match_type": "exact", 505 | "target": [ 506 | "meta", 507 | "nhop_ipv4" 508 | ], 509 | "mask": null 510 | } 511 | ], 512 | "actions": [ 513 | "set_dmac", 514 | "_drop" 515 | ], 516 | "next_tables": { 517 | "set_dmac": "send_frame", 518 | "_drop": "send_frame" 519 | }, 520 | "base_default_next": "send_frame" 521 | }, 522 | { 523 | "name": "send_frame", 524 | "id": 3, 525 | "match_type": "exact", 526 | "type": "simple", 527 | "max_size": 256, 528 | "with_counters": false, 529 | "direct_meters": null, 530 | "support_timeout": false, 531 | "key": [ 532 | { 533 | "match_type": "exact", 534 | "target": [ 535 | "standard_metadata", 536 | "egress_port" 537 | ], 538 | "mask": null 539 | } 540 | ], 541 | "actions": [ 542 | "rewrite_mac", 543 | "_drop" 544 | ], 545 | "next_tables": { 546 | "rewrite_mac": null, 547 | "_drop": null 548 | }, 549 | "base_default_next": null 550 | } 551 | ], 552 | "action_profiles": [], 553 | "conditionals": [ 554 | { 555 | "name": "_condition_0", 556 | "id": 0, 557 | "expression": { 558 | "type": "expression", 559 | "value": { 560 | "op": "valid", 561 | "left": null, 562 | "right": { 563 | "type": "header", 564 | "value": "ipv4" 565 | } 566 | } 567 | }, 568 | "true_next": "ipv4_nhop", 569 | "false_next": "send_frame" 570 | } 571 | ] 572 | }, 573 | { 574 | "name": "egress", 575 | "id": 1, 576 | "init_table": null, 577 | "tables": [], 578 | "action_profiles": [], 579 | "conditionals": [] 580 | } 581 | ], 582 | "calculations": [ 583 | { 584 | "name": "ipv4_checksum", 585 | "id": 0, 586 | "input": [ 587 | { 588 | "type": "field", 589 | "value": [ 590 | "ipv4", 591 | "version" 592 | ] 593 | }, 594 | { 595 | "type": "field", 596 | "value": [ 597 | "ipv4", 598 | "ihl" 599 | ] 600 | }, 601 | { 602 | "type": "field", 603 | "value": [ 604 | "ipv4", 605 | "diffserv" 606 | ] 607 | }, 608 | { 609 | "type": "field", 610 | "value": [ 611 | "ipv4", 612 | "totalLen" 613 | ] 614 | }, 615 | { 616 | "type": "field", 617 | "value": [ 618 | "ipv4", 619 | "identification" 620 | ] 621 | }, 622 | { 623 | "type": "field", 624 | "value": [ 625 | "ipv4", 626 | "flags" 627 | ] 628 | }, 629 | { 630 | "type": "field", 631 | "value": [ 632 | "ipv4", 633 | "fragOffset" 634 | ] 635 | }, 636 | { 637 | "type": "field", 638 | "value": [ 639 | "ipv4", 640 | "ttl" 641 | ] 642 | }, 643 | { 644 | "type": "field", 645 | "value": [ 646 | "ipv4", 647 | "protocol" 648 | ] 649 | }, 650 | { 651 | "type": "field", 652 | "value": [ 653 | "ipv4", 654 | "srcAddr" 655 | ] 656 | }, 657 | { 658 | "type": "field", 659 | "value": [ 660 | "ipv4", 661 | "dstAddr" 662 | ] 663 | } 664 | ], 665 | "algo": "csum16" 666 | } 667 | ], 668 | "checksums": [ 669 | { 670 | "name": "ipv4.hdrChecksum|ipv4_checksum", 671 | "id": 0, 672 | "target": [ 673 | "ipv4", 674 | "hdrChecksum" 675 | ], 676 | "type": "generic", 677 | "calculation": "ipv4_checksum", 678 | "if_cond": null 679 | } 680 | ], 681 | "learn_lists": [], 682 | "field_lists": [], 683 | "counter_arrays": [], 684 | "register_arrays": [], 685 | "force_arith": [ 686 | [ 687 | "standard_metadata", 688 | "ingress_port" 689 | ], 690 | [ 691 | "standard_metadata", 692 | "packet_length" 693 | ], 694 | [ 695 | "standard_metadata", 696 | "egress_spec" 697 | ], 698 | [ 699 | "standard_metadata", 700 | "egress_port" 701 | ], 702 | [ 703 | "standard_metadata", 704 | "egress_instance" 705 | ], 706 | [ 707 | "standard_metadata", 708 | "instance_type" 709 | ], 710 | [ 711 | "standard_metadata", 712 | "clone_spec" 713 | ], 714 | [ 715 | "standard_metadata", 716 | "_padding" 717 | ] 718 | ] 719 | } -------------------------------------------------------------------------------- /tests/p4/nat/nat.p4: -------------------------------------------------------------------------------- 1 | #define ETHERTYPE_IPV4 0x0800 2 | 3 | header_type ethernet_t { 4 | fields { 5 | dstAddr : 48; 6 | srcAddr : 48; 7 | etherType : 16; 8 | } 9 | } 10 | 11 | header_type ipv4_t { 12 | fields { 13 | version : 4; 14 | ihl : 4; 15 | diffserv : 8; 16 | totalLen : 16; 17 | identification : 16; 18 | flags : 3; 19 | fragOffset : 13; 20 | ttl : 8; 21 | protocol : 8; 22 | hdrChecksum : 16; 23 | srcAddr : 32; 24 | dstAddr: 32; 25 | } 26 | } 27 | 28 | parser start { 29 | extract(ethernet); 30 | return select(ethernet.etherType) { 31 | ETHERTYPE_IPV4 : parse_ipv4; 32 | default : ingress; 33 | } 34 | } 35 | 36 | 37 | header ethernet_t ethernet; 38 | header ipv4_t ipv4; 39 | 40 | field_list ipv4_checksum_list { 41 | ipv4.version; 42 | ipv4.ihl; 43 | ipv4.diffserv; 44 | ipv4.totalLen; 45 | ipv4.identification; 46 | ipv4.flags; 47 | ipv4.fragOffset; 48 | ipv4.ttl; 49 | ipv4.protocol; 50 | ipv4.srcAddr; 51 | ipv4.dstAddr; 52 | } 53 | 54 | field_list_calculation ipv4_checksum { 55 | input { 56 | ipv4_checksum_list; 57 | } 58 | algorithm : csum16; 59 | output_width : 16; 60 | } 61 | 62 | calculated_field ipv4.hdrChecksum { 63 | verify ipv4_checksum; 64 | update ipv4_checksum; 65 | } 66 | 67 | parser parse_ipv4 { 68 | extract(ipv4); 69 | return ingress; 70 | } 71 | 72 | action _drop() { 73 | drop(); 74 | } 75 | 76 | header_type meta_t { 77 | fields { 78 | nhop_ipv4 : 32; 79 | } 80 | } 81 | 82 | metadata meta_t meta; 83 | 84 | action nat_output(srcAddr, mask1) { 85 | bit_or(ipv4.srcAddr, ipv4.srcAddr & (~mask1) ,srcAddr & mask1); 86 | } 87 | 88 | action nat_input(dstAddr, mask1) { 89 | bit_or(ipv4.dstAddr, ipv4.dstAddr & (~mask1) ,dstAddr & mask1); 90 | } 91 | 92 | table nat { 93 | reads { 94 | ipv4.srcAddr : ternary; 95 | ipv4.dstAddr : ternary; 96 | } 97 | actions { 98 | nat_input; 99 | nat_output; 100 | } 101 | } 102 | 103 | action set_dmac(dmac, port) { 104 | modify_field(ethernet.dstAddr, dmac); 105 | modify_field(standard_metadata.egress_spec, port); 106 | } 107 | 108 | table forward { 109 | reads { 110 | ipv4.dstAddr : exact; 111 | } 112 | actions { 113 | set_dmac; 114 | _drop; 115 | } 116 | } 117 | action set_smac(smac) { 118 | modify_field(ethernet.srcAddr, smac); 119 | } 120 | table send_frame { 121 | reads { 122 | standard_metadata.egress_port: exact; 123 | } 124 | actions { 125 | set_smac; 126 | _drop; 127 | } 128 | size: 256; 129 | } 130 | 131 | control ingress { 132 | if (valid(ipv4)) { 133 | apply(nat) { 134 | hit { 135 | apply(forward); 136 | apply(send_frame); 137 | } 138 | } 139 | 140 | } 141 | } -------------------------------------------------------------------------------- /tests/p4/router/commands: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HyperVDP/HyperV/5a533013e33cbd53b4d9031dd710c77d8a9909d5/tests/p4/router/commands -------------------------------------------------------------------------------- /tests/p4/router/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "__meta__": { 3 | "version": [ 4 | 2, 5 | 0 6 | ] 7 | }, 8 | "header_types": [ 9 | { 10 | "name": "standard_metadata_t", 11 | "id": 0, 12 | "fields": [ 13 | [ 14 | "ingress_port", 15 | 9 16 | ], 17 | [ 18 | "packet_length", 19 | 32 20 | ], 21 | [ 22 | "egress_spec", 23 | 9 24 | ], 25 | [ 26 | "egress_port", 27 | 9 28 | ], 29 | [ 30 | "egress_instance", 31 | 32 32 | ], 33 | [ 34 | "instance_type", 35 | 32 36 | ], 37 | [ 38 | "clone_spec", 39 | 32 40 | ], 41 | [ 42 | "_padding", 43 | 5 44 | ] 45 | ], 46 | "length_exp": null, 47 | "max_length": null 48 | }, 49 | { 50 | "name": "ethernet_t", 51 | "id": 1, 52 | "fields": [ 53 | [ 54 | "dstAddr", 55 | 48 56 | ], 57 | [ 58 | "srcAddr", 59 | 48 60 | ], 61 | [ 62 | "etherType", 63 | 16 64 | ] 65 | ], 66 | "length_exp": null, 67 | "max_length": null 68 | }, 69 | { 70 | "name": "ipv4_t", 71 | "id": 2, 72 | "fields": [ 73 | [ 74 | "version", 75 | 4 76 | ], 77 | [ 78 | "ihl", 79 | 4 80 | ], 81 | [ 82 | "diffserv", 83 | 8 84 | ], 85 | [ 86 | "totalLen", 87 | 16 88 | ], 89 | [ 90 | "identification", 91 | 16 92 | ], 93 | [ 94 | "flags", 95 | 3 96 | ], 97 | [ 98 | "fragOffset", 99 | 13 100 | ], 101 | [ 102 | "ttl", 103 | 8 104 | ], 105 | [ 106 | "protocol", 107 | 8 108 | ], 109 | [ 110 | "hdrChecksum", 111 | 16 112 | ], 113 | [ 114 | "srcAddr", 115 | 32 116 | ], 117 | [ 118 | "dstAddr", 119 | 32 120 | ] 121 | ], 122 | "length_exp": null, 123 | "max_length": null 124 | }, 125 | { 126 | "name": "routing_metadata_t", 127 | "id": 3, 128 | "fields": [ 129 | [ 130 | "nhop_ipv4", 131 | 32 132 | ] 133 | ], 134 | "length_exp": null, 135 | "max_length": null 136 | } 137 | ], 138 | "headers": [ 139 | { 140 | "name": "standard_metadata", 141 | "id": 0, 142 | "header_type": "standard_metadata_t", 143 | "metadata": true 144 | }, 145 | { 146 | "name": "ethernet", 147 | "id": 1, 148 | "header_type": "ethernet_t", 149 | "metadata": false 150 | }, 151 | { 152 | "name": "ipv4", 153 | "id": 2, 154 | "header_type": "ipv4_t", 155 | "metadata": false 156 | }, 157 | { 158 | "name": "routing_metadata", 159 | "id": 3, 160 | "header_type": "routing_metadata_t", 161 | "metadata": true 162 | } 163 | ], 164 | "header_stacks": [], 165 | "parsers": [ 166 | { 167 | "name": "parser", 168 | "id": 0, 169 | "init_state": "start", 170 | "parse_states": [ 171 | { 172 | "name": "parse_ethernet", 173 | "id": 0, 174 | "parser_ops": [ 175 | { 176 | "op": "extract", 177 | "parameters": [ 178 | { 179 | "type": "regular", 180 | "value": "ethernet" 181 | } 182 | ] 183 | } 184 | ], 185 | "transition_key": [ 186 | { 187 | "type": "field", 188 | "value": [ 189 | "ethernet", 190 | "etherType" 191 | ] 192 | } 193 | ], 194 | "transitions": [ 195 | { 196 | "type": "hexstr", 197 | "value": "0x0800", 198 | "mask": null, 199 | "next_state": "parse_ipv4" 200 | }, 201 | { 202 | "type": "default", 203 | "value": null, 204 | "mask": null, 205 | "next_state": null 206 | } 207 | ] 208 | }, 209 | { 210 | "name": "start", 211 | "id": 1, 212 | "parser_ops": [], 213 | "transition_key": [], 214 | "transitions": [ 215 | { 216 | "type": "default", 217 | "value": null, 218 | "mask": null, 219 | "next_state": "parse_ethernet" 220 | } 221 | ] 222 | }, 223 | { 224 | "name": "parse_ipv4", 225 | "id": 2, 226 | "parser_ops": [ 227 | { 228 | "op": "extract", 229 | "parameters": [ 230 | { 231 | "type": "regular", 232 | "value": "ipv4" 233 | } 234 | ] 235 | } 236 | ], 237 | "transition_key": [], 238 | "transitions": [ 239 | { 240 | "type": "default", 241 | "value": null, 242 | "mask": null, 243 | "next_state": null 244 | } 245 | ] 246 | } 247 | ] 248 | } 249 | ], 250 | "parse_vsets": [], 251 | "deparsers": [ 252 | { 253 | "name": "deparser", 254 | "id": 0, 255 | "order": [ 256 | "ethernet", 257 | "ipv4" 258 | ] 259 | } 260 | ], 261 | "meter_arrays": [], 262 | "actions": [ 263 | { 264 | "name": "rewrite_mac", 265 | "id": 0, 266 | "runtime_data": [ 267 | { 268 | "name": "smac", 269 | "bitwidth": 48 270 | } 271 | ], 272 | "primitives": [ 273 | { 274 | "op": "modify_field", 275 | "parameters": [ 276 | { 277 | "type": "field", 278 | "value": [ 279 | "ethernet", 280 | "srcAddr" 281 | ] 282 | }, 283 | { 284 | "type": "runtime_data", 285 | "value": 0 286 | } 287 | ] 288 | } 289 | ] 290 | }, 291 | { 292 | "name": "set_nhop", 293 | "id": 1, 294 | "runtime_data": [ 295 | { 296 | "name": "nhop_ipv4", 297 | "bitwidth": 32 298 | }, 299 | { 300 | "name": "port", 301 | "bitwidth": 9 302 | } 303 | ], 304 | "primitives": [ 305 | { 306 | "op": "modify_field", 307 | "parameters": [ 308 | { 309 | "type": "field", 310 | "value": [ 311 | "routing_metadata", 312 | "nhop_ipv4" 313 | ] 314 | }, 315 | { 316 | "type": "runtime_data", 317 | "value": 0 318 | } 319 | ] 320 | }, 321 | { 322 | "op": "modify_field", 323 | "parameters": [ 324 | { 325 | "type": "field", 326 | "value": [ 327 | "standard_metadata", 328 | "egress_port" 329 | ] 330 | }, 331 | { 332 | "type": "runtime_data", 333 | "value": 1 334 | } 335 | ] 336 | }, 337 | { 338 | "op": "add_to_field", 339 | "parameters": [ 340 | { 341 | "type": "field", 342 | "value": [ 343 | "ipv4", 344 | "ttl" 345 | ] 346 | }, 347 | { 348 | "type": "hexstr", 349 | "value": "-0x1" 350 | } 351 | ] 352 | } 353 | ] 354 | }, 355 | { 356 | "name": "_drop", 357 | "id": 2, 358 | "runtime_data": [], 359 | "primitives": [ 360 | { 361 | "op": "drop", 362 | "parameters": [] 363 | } 364 | ] 365 | }, 366 | { 367 | "name": "set_dmac", 368 | "id": 3, 369 | "runtime_data": [ 370 | { 371 | "name": "dmac", 372 | "bitwidth": 48 373 | } 374 | ], 375 | "primitives": [ 376 | { 377 | "op": "modify_field", 378 | "parameters": [ 379 | { 380 | "type": "field", 381 | "value": [ 382 | "ethernet", 383 | "dstAddr" 384 | ] 385 | }, 386 | { 387 | "type": "runtime_data", 388 | "value": 0 389 | } 390 | ] 391 | } 392 | ] 393 | } 394 | ], 395 | "pipelines": [ 396 | { 397 | "name": "ingress", 398 | "id": 0, 399 | "init_table": "_condition_0", 400 | "tables": [ 401 | { 402 | "name": "ipv4_nhop", 403 | "id": 0, 404 | "match_type": "exact", 405 | "type": "simple", 406 | "max_size": 1024, 407 | "with_counters": false, 408 | "direct_meters": null, 409 | "support_timeout": false, 410 | "key": [ 411 | { 412 | "match_type": "exact", 413 | "target": [ 414 | "ipv4", 415 | "dstAddr" 416 | ], 417 | "mask": null 418 | } 419 | ], 420 | "actions": [ 421 | "set_nhop", 422 | "_drop" 423 | ], 424 | "next_tables": { 425 | "set_nhop": "forward", 426 | "_drop": "forward" 427 | }, 428 | "base_default_next": "forward" 429 | }, 430 | { 431 | "name": "forward", 432 | "id": 1, 433 | "match_type": "exact", 434 | "type": "simple", 435 | "max_size": 512, 436 | "with_counters": false, 437 | "direct_meters": null, 438 | "support_timeout": false, 439 | "key": [ 440 | { 441 | "match_type": "exact", 442 | "target": [ 443 | "routing_metadata", 444 | "nhop_ipv4" 445 | ], 446 | "mask": null 447 | } 448 | ], 449 | "actions": [ 450 | "set_dmac", 451 | "_drop" 452 | ], 453 | "next_tables": { 454 | "set_dmac": "send_frame", 455 | "_drop": "send_frame" 456 | }, 457 | "base_default_next": "send_frame" 458 | }, 459 | { 460 | "name": "send_frame", 461 | "id": 2, 462 | "match_type": "exact", 463 | "type": "simple", 464 | "max_size": 256, 465 | "with_counters": false, 466 | "direct_meters": null, 467 | "support_timeout": false, 468 | "key": [ 469 | { 470 | "match_type": "exact", 471 | "target": [ 472 | "standard_metadata", 473 | "egress_port" 474 | ], 475 | "mask": null 476 | } 477 | ], 478 | "actions": [ 479 | "rewrite_mac", 480 | "_drop" 481 | ], 482 | "next_tables": { 483 | "rewrite_mac": null, 484 | "_drop": null 485 | }, 486 | "base_default_next": null 487 | } 488 | ], 489 | "action_profiles": [], 490 | "conditionals": [ 491 | { 492 | "name": "_condition_0", 493 | "id": 0, 494 | "expression": { 495 | "type": "expression", 496 | "value": { 497 | "op": "and", 498 | "left": { 499 | "type": "expression", 500 | "value": { 501 | "op": "valid", 502 | "left": null, 503 | "right": { 504 | "type": "header", 505 | "value": "ipv4" 506 | } 507 | } 508 | }, 509 | "right": { 510 | "type": "expression", 511 | "value": { 512 | "op": ">", 513 | "left": { 514 | "type": "field", 515 | "value": [ 516 | "ipv4", 517 | "ttl" 518 | ] 519 | }, 520 | "right": { 521 | "type": "hexstr", 522 | "value": "0x0" 523 | } 524 | } 525 | } 526 | } 527 | }, 528 | "true_next": "ipv4_nhop", 529 | "false_next": "send_frame" 530 | } 531 | ] 532 | }, 533 | { 534 | "name": "egress", 535 | "id": 1, 536 | "init_table": null, 537 | "tables": [], 538 | "action_profiles": [], 539 | "conditionals": [] 540 | } 541 | ], 542 | "calculations": [ 543 | { 544 | "name": "ipv4_checksum", 545 | "id": 0, 546 | "input": [ 547 | { 548 | "type": "field", 549 | "value": [ 550 | "ipv4", 551 | "version" 552 | ] 553 | }, 554 | { 555 | "type": "field", 556 | "value": [ 557 | "ipv4", 558 | "ihl" 559 | ] 560 | }, 561 | { 562 | "type": "field", 563 | "value": [ 564 | "ipv4", 565 | "diffserv" 566 | ] 567 | }, 568 | { 569 | "type": "field", 570 | "value": [ 571 | "ipv4", 572 | "totalLen" 573 | ] 574 | }, 575 | { 576 | "type": "field", 577 | "value": [ 578 | "ipv4", 579 | "identification" 580 | ] 581 | }, 582 | { 583 | "type": "field", 584 | "value": [ 585 | "ipv4", 586 | "flags" 587 | ] 588 | }, 589 | { 590 | "type": "field", 591 | "value": [ 592 | "ipv4", 593 | "fragOffset" 594 | ] 595 | }, 596 | { 597 | "type": "field", 598 | "value": [ 599 | "ipv4", 600 | "ttl" 601 | ] 602 | }, 603 | { 604 | "type": "field", 605 | "value": [ 606 | "ipv4", 607 | "protocol" 608 | ] 609 | }, 610 | { 611 | "type": "field", 612 | "value": [ 613 | "ipv4", 614 | "srcAddr" 615 | ] 616 | }, 617 | { 618 | "type": "field", 619 | "value": [ 620 | "ipv4", 621 | "dstAddr" 622 | ] 623 | } 624 | ], 625 | "algo": "csum16" 626 | } 627 | ], 628 | "checksums": [ 629 | { 630 | "name": "ipv4.hdrChecksum|ipv4_checksum", 631 | "id": 0, 632 | "target": [ 633 | "ipv4", 634 | "hdrChecksum" 635 | ], 636 | "type": "generic", 637 | "calculation": "ipv4_checksum", 638 | "if_cond": null 639 | } 640 | ], 641 | "learn_lists": [], 642 | "field_lists": [], 643 | "counter_arrays": [], 644 | "register_arrays": [], 645 | "force_arith": [ 646 | [ 647 | "standard_metadata", 648 | "ingress_port" 649 | ], 650 | [ 651 | "standard_metadata", 652 | "packet_length" 653 | ], 654 | [ 655 | "standard_metadata", 656 | "egress_spec" 657 | ], 658 | [ 659 | "standard_metadata", 660 | "egress_port" 661 | ], 662 | [ 663 | "standard_metadata", 664 | "egress_instance" 665 | ], 666 | [ 667 | "standard_metadata", 668 | "instance_type" 669 | ], 670 | [ 671 | "standard_metadata", 672 | "clone_spec" 673 | ], 674 | [ 675 | "standard_metadata", 676 | "_padding" 677 | ] 678 | ] 679 | } -------------------------------------------------------------------------------- /tests/p4/router/router.p4: -------------------------------------------------------------------------------- 1 | header_type ethernet_t { 2 | fields { 3 | dstAddr : 48; 4 | srcAddr : 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 | parser start { 27 | return parse_ethernet; 28 | } 29 | 30 | #define ETHERTYPE_IPV4 0x0800 31 | 32 | header ethernet_t ethernet; 33 | 34 | parser parse_ethernet { 35 | extract(ethernet); 36 | return select(latest.etherType) { 37 | ETHERTYPE_IPV4 : parse_ipv4; 38 | default: ingress; 39 | } 40 | } 41 | 42 | header ipv4_t ipv4; 43 | 44 | field_list ipv4_checksum_list { 45 | ipv4.version; 46 | ipv4.ihl; 47 | ipv4.diffserv; 48 | ipv4.totalLen; 49 | ipv4.identification; 50 | ipv4.flags; 51 | ipv4.fragOffset; 52 | ipv4.ttl; 53 | ipv4.protocol; 54 | ipv4.srcAddr; 55 | ipv4.dstAddr; 56 | } 57 | 58 | field_list_calculation ipv4_checksum { 59 | input { 60 | ipv4_checksum_list; 61 | } 62 | algorithm : csum16; 63 | output_width : 16; 64 | } 65 | 66 | calculated_field ipv4.hdrChecksum { 67 | verify ipv4_checksum; 68 | update ipv4_checksum; 69 | } 70 | 71 | parser parse_ipv4 { 72 | extract(ipv4); 73 | return ingress; 74 | } 75 | 76 | 77 | action _drop() { 78 | drop(); 79 | } 80 | 81 | header_type routing_metadata_t { 82 | fields { 83 | nhop_ipv4 : 32; 84 | } 85 | } 86 | 87 | metadata routing_metadata_t routing_metadata; 88 | 89 | action set_nhop(nhop_ipv4) { 90 | modify_field(routing_metadata.nhop_ipv4, nhop_ipv4); 91 | add_to_field(ipv4.ttl, -1); 92 | } 93 | 94 | table ipv4_nhop { 95 | reads { 96 | ipv4.dstAddr : exact; 97 | } 98 | actions { 99 | set_nhop; 100 | _drop; 101 | } 102 | size: 1024; 103 | } 104 | 105 | action set_dmac(dmac, port) { 106 | modify_field(ethernet.dstAddr, dmac); 107 | modify_field(standard_metadata.egress_port, port); 108 | } 109 | 110 | table forward_table { 111 | reads { 112 | routing_metadata.nhop_ipv4 : exact; 113 | } 114 | actions { 115 | set_dmac; 116 | _drop; 117 | } 118 | size: 512; 119 | } 120 | 121 | action set_smac(smac) { 122 | modify_field(ethernet.srcAddr, smac); 123 | } 124 | 125 | table send_frame { 126 | reads { 127 | standard_metadata.egress_port: exact; 128 | } 129 | actions { 130 | set_smac; 131 | _drop; 132 | } 133 | size: 256; 134 | } 135 | 136 | control ingress { 137 | if(valid(ipv4) and ipv4.ttl > 0) { 138 | apply(ipv4_nhop); 139 | apply(forward_table); 140 | apply(send_frame); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /tests/p4/stateful_tcp_firewall/commands: -------------------------------------------------------------------------------- 1 | table_add forward_table forward 1 => 2 2 | table_add forward_table forward 2 => 1 3 | table_add state_table get_state_with_tcp_flag 0x0a000002 0x0a000003 8080 8080 => 0 4 | table_add state_table get_state_with_tcp_flag 0x0a000003 0x0a000002 8080 8080 => 0 5 | table_add state_table state_transfer_table 0 0b10 => 1 0 6 | table_add state_table state_transfer_table 1 0b10010 => 2 0 7 | table_add state_table state_transfer_table 2 0b10000 => 2 0 8 | table_add state_table state_transfer_table 2 0b1 => 3 0 9 | table_add state_table state_transfer_table 4 0b10001 => 4 0 10 | table_add state_table state_transfer_table 4 0b10000 => 4 0 11 | table_add state_table state_transfer_table 4 0b1 => 5 0 12 | table_add state_table state_transfer_table 5 0b10001 => 0 0 13 | table_add action_table alert 0 => 14 | table_set_default action_table noop -------------------------------------------------------------------------------- /tests/p4/stateful_tcp_firewall/stateful_tcp_firewall.p4: -------------------------------------------------------------------------------- 1 | header_type ethernet_t { 2 | fields { 3 | dstAddr : 48; 4 | srcAddr : 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 tcp_t { 27 | fields { 28 | srcPort : 16; 29 | dstPort : 16; 30 | seqNo : 32; 31 | ackNo : 32; 32 | dataOffset : 4; 33 | res : 3; 34 | ecn : 3; 35 | ctrl : 6; 36 | window : 16; 37 | checksum : 16; 38 | urgentPtr : 16; 39 | } 40 | } 41 | 42 | #define ETHERTYPE_IPV4 0x0800 43 | 44 | #define IP_PROTOCOLS_TCP 0x06 45 | 46 | header ethernet_t ethernet; 47 | header ipv4_t ipv4; 48 | header tcp_t tcp; 49 | metadata state_metadata_t state_metadata; 50 | 51 | parser start { 52 | return parse_ethernet; 53 | } 54 | 55 | parser parse_ethernet { 56 | extract(ethernet); 57 | return select(latest.etherType) { 58 | ETHERTYPE_IPV4 : parse_ipv4; 59 | default: ingress; 60 | } 61 | } 62 | 63 | parser parse_ipv4 { 64 | extract(ipv4); 65 | return select(latest.protocol) { 66 | IP_PROTOCOLS_TCP : parse_tcp; 67 | default: ingress; 68 | } 69 | } 70 | 71 | parser parse_tcp { 72 | extract(tcp); 73 | return ingress; 74 | } 75 | 76 | header_type state_metadata_t { 77 | fields { 78 | cur_state : 8; 79 | next_state : 8; 80 | trigger : 16; 81 | } 82 | } 83 | 84 | register state_register { 85 | width : 8; 86 | instance_count : 1024; 87 | } 88 | 89 | action alert() { 90 | drop(); 91 | } 92 | 93 | action forward(port) { 94 | modify_field(standard_metadata.egress_spec, port); 95 | } 96 | 97 | action get_state_with_tcp_flag(register_id) { 98 | register_read(state_metadata.cur_state, state_register, register_id); 99 | modify_field(state_metadata.trigger, tcp.ctrl); 100 | } 101 | 102 | action state_transfer(next_state, register_id) { 103 | register_write(state_register, register_id, next_state); 104 | modify_field(state_metadata.next_state, next_state); 105 | } 106 | 107 | table forward_table { 108 | reads { 109 | standard_metadata.ingress_port : exact; 110 | } 111 | actions { 112 | forward; 113 | } 114 | } 115 | 116 | table state_table { 117 | reads { 118 | ipv4.dstAddr : exact; 119 | ipv4.srcAddr : exact; 120 | tcp.srcPort : exact; 121 | tcp.dstPort : exact; 122 | } 123 | actions { 124 | get_state_with_tcp_flag; 125 | } 126 | } 127 | 128 | table state_transfer_table { 129 | reads { 130 | state_metadata.cur_state : exact; 131 | state_metadata.trigger : exact; 132 | } 133 | actions { 134 | state_transfer; 135 | } 136 | } 137 | 138 | action noop() { 139 | 140 | } 141 | 142 | table action_table { 143 | reads { 144 | state_metadata.next_state : exact; 145 | } 146 | actions { 147 | noop; 148 | alert; 149 | } 150 | } 151 | 152 | control ingress { 153 | apply(forward_table); 154 | if (valid(tcp)) { 155 | apply(state_table) { 156 | hit { 157 | apply(state_transfer_table); 158 | } 159 | } 160 | apply(action_table); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /tools/clear: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | ip netns delete h1 4 | ip netns delete h2 5 | -------------------------------------------------------------------------------- /tools/populate: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | export TEST_ROOT='/home/netarchlab/vp4-test' 4 | export SWITCH_ROOT='/home/netarchlab/vp4-bmv2/targets/simple_switch' 5 | export SWITCH_EXE='/home/netarchlab/vp4-bmv2/targets/simple_switch/simple_switch' 6 | 7 | COMMANDS=${TEST_ROOT}/${1}/commands 8 | 9 | cd ${SWITCH_ROOT} 10 | ./runtime_CLI <$COMMANDS 11 | -------------------------------------------------------------------------------- /tools/setup: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | 4 | ip link add p4p1 type veth peer name veth3 5 | ip link add p4p2 type veth peer name veth4 6 | 7 | ip netns add h1 8 | ip netns add h2 9 | 10 | ip link set veth3 netns h1 11 | ip link set veth4 netns h2 12 | 13 | ip netns exec h1 ifconfig lo up 14 | ip netns exec h2 ifconfig lo up 15 | 16 | ip netns exec h1 ifconfig veth3 hw ether 802200010001 17 | ip netns exec h2 ifconfig veth4 hw ether 802200010002 18 | 19 | ip netns exec h1 ifconfig veth3 10.0.0.1 up 20 | ip netns exec h2 ifconfig veth4 10.0.0.2 up 21 | 22 | ip netns exec h1 arp -s 10.0.0.2 80:22:00:01:00:02 23 | ip netns exec h2 arp -s 10.0.0.1 80:22:00:01:00:01 24 | 25 | sudo ifconfig p4p1 up 26 | sudo ifconfig p4p2 up 27 | 28 | 29 | 30 | --------------------------------------------------------------------------------