├── INDDoS.p4app ├── README.md ├── cleanup ├── commands1.txt ├── commands2.txt ├── commands3.txt ├── debug_switch1.sh ├── debug_switch2.sh ├── debug_switch3.sh ├── p4app.json ├── p4src │ ├── INDDoS.p4 │ └── includes │ │ ├── headers.p4 │ │ └── parser.p4 ├── read_registers1.sh ├── read_registers2.sh ├── read_registers3.sh ├── receive.py ├── send.py ├── topo.py ├── topo.txt ├── xterm_h1.sh ├── xterm_h2.sh └── xterm_h3.sh ├── INDDoS_TNA ├── add_rule_ddos_mitigation.py ├── digest.py └── myDDoS3.p4 ├── README.md └── p4app /INDDoS.p4app/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DINGDAMU/INDDoS/448207372c6c7d39c0bc0b36ad85547d3da808e6/INDDoS.p4app/README.md -------------------------------------------------------------------------------- /INDDoS.p4app/cleanup: -------------------------------------------------------------------------------- 1 | sudo mn -c 2 | sudo killall lt-simple_switch 3 | sudo rm -f *.pcap 4 | sudo rm -f *.json 5 | -------------------------------------------------------------------------------- /INDDoS.p4app/commands1.txt: -------------------------------------------------------------------------------- 1 | table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:00:01:01 1 2 | table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:00:02:02 3 3 | table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:00:03:03 2 4 | 5 | -------------------------------------------------------------------------------- /INDDoS.p4app/commands2.txt: -------------------------------------------------------------------------------- 1 | table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:00:01:01 2 2 | table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:00:02:02 1 3 | table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:00:03:03 3 4 | -------------------------------------------------------------------------------- /INDDoS.p4app/commands3.txt: -------------------------------------------------------------------------------- 1 | table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:00:01:01 2 2 | table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:00:02:02 3 3 | table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:00:03:03 1 4 | -------------------------------------------------------------------------------- /INDDoS.p4app/debug_switch1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.1.1" 24 | 25 | 26 | echo "displaying switch1 debug mode" 27 | docker exec -i -t hh bm_p4dbg --thrift-port 22222 28 | echo 29 | 30 | 31 | -------------------------------------------------------------------------------- /INDDoS.p4app/debug_switch2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.2.2" 24 | 25 | echo "displaying switch1 debug mode" 26 | docker exec -i -t hh bm_p4dbg --thrift-port 22223 27 | echo 28 | 29 | 30 | -------------------------------------------------------------------------------- /INDDoS.p4app/debug_switch3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.3.3" 24 | 25 | 26 | echo "displaying switch1 debug mode" 27 | docker exec -i -t hh bm_p4dbg --thrift-port 22224 28 | echo 29 | 30 | 31 | -------------------------------------------------------------------------------- /INDDoS.p4app/p4app.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "p4src/INDDoS.p4", 3 | "language": "p4-16", 4 | "targets": { 5 | "custom": { 6 | "program": "topo.py" 7 | }, 8 | "after": { 9 | "cmd": [ 10 | "sudo mn -c", 11 | " killall lt-simple_switch" 12 | ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /INDDoS.p4app/p4src/INDDoS.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_DDoS_SIZE 131072 5 | #define DDoS_threshold 200 6 | 7 | header ethernet_t { 8 | bit<48> dstAddr; 9 | bit<48> srcAddr; 10 | bit<16> etherType; 11 | } 12 | 13 | header ipv4_t { 14 | bit<4> version; 15 | bit<4> ihl; 16 | bit<8> diffserv; 17 | bit<16> totalLen; 18 | bit<16> identification; 19 | bit<3> flags; 20 | bit<13> fragOffset; 21 | bit<8> ttl; 22 | bit<8> protocol; 23 | bit<16> hdrChecksum; 24 | bit<32> srcAddr; 25 | bit<32> dstAddr; 26 | } 27 | 28 | header tcp_t { 29 | bit<16> srcPort; 30 | bit<16> dstPort; 31 | bit<32> seqNo; 32 | bit<32> ackNo; 33 | bit<4> dataOffset; 34 | bit<3> res; 35 | bit<3> ecn; 36 | bit<6> ctrl; 37 | bit<16> window; 38 | bit<16> checksum; 39 | bit<16> urgentPtr; 40 | } 41 | 42 | header udp_t { 43 | bit<16> srcPort; 44 | bit<16> dstPort; 45 | bit<16> udplen; 46 | bit<16> udpchk; 47 | } 48 | 49 | struct metadata { 50 | bit<32> count_min; 51 | } 52 | 53 | struct headers { 54 | @name(".ethernet") 55 | ethernet_t ethernet; 56 | @name(".ipv4") 57 | ipv4_t ipv4; 58 | @name(".tcp") 59 | tcp_t tcp; 60 | @name(".udp") 61 | udp_t udp; 62 | } 63 | 64 | parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 65 | @name(".parse_ethernet") state parse_ethernet { 66 | packet.extract(hdr.ethernet); 67 | transition select(hdr.ethernet.etherType) { 68 | 16w0x800: parse_ipv4; 69 | default: accept; 70 | } 71 | } 72 | @name(".parse_ipv4") state parse_ipv4 { 73 | packet.extract(hdr.ipv4); 74 | transition select(hdr.ipv4.protocol) { 75 | 8w0x6: parse_tcp; 76 | 8w0x11: parse_udp; 77 | default: accept; 78 | } 79 | } 80 | @name(".parse_tcp") state parse_tcp { 81 | packet.extract(hdr.tcp); 82 | transition accept; 83 | } 84 | @name(".parse_udp") state parse_udp { 85 | packet.extract(hdr.udp); 86 | transition accept; 87 | } 88 | @name(".start") state start { 89 | transition parse_ethernet; 90 | } 91 | } 92 | 93 | control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 94 | @name(".rewrite_mac") action rewrite_mac(bit<48> smac) { 95 | hdr.ethernet.srcAddr = smac; 96 | } 97 | @name("._drop") action _drop() { 98 | mark_to_drop(); 99 | } 100 | @name(".send_frame") table send_frame { 101 | actions = { 102 | rewrite_mac; 103 | _drop; 104 | } 105 | key = { 106 | standard_metadata.egress_port: exact; 107 | } 108 | size = 256; 109 | } 110 | apply { 111 | send_frame.apply(); 112 | } 113 | } 114 | 115 | register>(1024) occSlots1; 116 | register>(1024) occSlots2; 117 | register>(1024) occSlots3; 118 | 119 | register>(MAX_DDoS_SIZE) cms1_0; 120 | register>(MAX_DDoS_SIZE) cms1_1; 121 | register>(MAX_DDoS_SIZE) cms1_2; 122 | register>(MAX_DDoS_SIZE) cms1_3; 123 | register>(MAX_DDoS_SIZE) cms1_4; 124 | register>(MAX_DDoS_SIZE) cms1_5; 125 | register>(MAX_DDoS_SIZE) cms1_6; 126 | register>(MAX_DDoS_SIZE) cms1_7; 127 | 128 | register>(MAX_DDoS_SIZE) cms2_0; 129 | register>(MAX_DDoS_SIZE) cms2_1; 130 | register>(MAX_DDoS_SIZE) cms2_2; 131 | register>(MAX_DDoS_SIZE) cms2_3; 132 | register>(MAX_DDoS_SIZE) cms2_4; 133 | register>(MAX_DDoS_SIZE) cms2_5; 134 | register>(MAX_DDoS_SIZE) cms2_6; 135 | register>(MAX_DDoS_SIZE) cms2_7; 136 | 137 | register>(MAX_DDoS_SIZE) cms3_0; 138 | register>(MAX_DDoS_SIZE) cms3_1; 139 | register>(MAX_DDoS_SIZE) cms3_2; 140 | register>(MAX_DDoS_SIZE) cms3_3; 141 | register>(MAX_DDoS_SIZE) cms3_4; 142 | register>(MAX_DDoS_SIZE) cms3_5; 143 | register>(MAX_DDoS_SIZE) cms3_6; 144 | register>(MAX_DDoS_SIZE) cms3_7; 145 | control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { 146 | action ipv4_forward(bit<48> dstAddr, bit<9> port) { 147 | standard_metadata.egress_spec = port; 148 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 149 | hdr.ethernet.dstAddr = dstAddr; 150 | hdr.ipv4.ttl = hdr.ipv4.ttl - 8w1; 151 | } 152 | action _drop() { 153 | mark_to_drop(); 154 | } 155 | 156 | table ipv4_lpm { 157 | actions = { 158 | ipv4_forward; 159 | _drop; 160 | } 161 | key = { 162 | hdr.ipv4.dstAddr: lpm; 163 | } 164 | size = 1024; 165 | } 166 | apply { 167 | // Index in Count-min sketch (Size 1024) 168 | bit<10> hash_32_1; 169 | bit<10> hash_32_2; 170 | bit<10> hash_32_3; 171 | // Index in Bitmap (Size 1024) 172 | bit<10> bm_hash; 173 | // Index in BACON Sketch (Size 1024 * 1024) 174 | bit<32> index1 = 32w0; 175 | bit<32> index2 = 32w0; 176 | bit<32> index3 = 32w0; 177 | // Values in BACON Sketch (0 or 1) 178 | bit<1> res1 = 1w0; 179 | bit<1> res2 = 1w0; 180 | bit<1> res3 = 1w0; 181 | // Number of 1s in BACON Sketch 182 | bit<32> value_1 = 32w0; 183 | bit<32> value_2 = 32w0; 184 | bit<32> value_3 =32w0; 185 | 186 | // Difference between values 187 | bit<32> d12; 188 | bit<32> d13; 189 | bit<32> d23; 190 | 191 | // Digest 192 | // 0: No report 193 | // 1: Report hdr.ipv4.dstAddr to controller 194 | bit<1> digest_type; 195 | 196 | /* Stage 0 */ 197 | ipv4_lpm.apply(); 198 | 199 | 200 | /* Stage 1 */ 201 | //crc32_custom: 202 | // Please refer to the paper how to customize CRC32 203 | hash(hash_32_1, HashAlgorithm.crc32, 1w0, {hdr.ipv4.dstAddr}, 10w1023); 204 | hash(hash_32_2, HashAlgorithm.crc32_custom, 1w0, {hdr.ipv4.dstAddr}, 10w1023); 205 | 206 | /* Stage 2 */ 207 | hash(hash_32_3, HashAlgorithm.crc32_custom, 1w0, {hdr.ipv4.dstAddr}, 10w1023); 208 | hash(bm_hash, HashAlgorithm.crc32, 1w0, {hdr.ipv4.srcAddr}, 10w1023); 209 | 210 | /* Stage 3 */ 211 | index1[9:0] = bm_hash; 212 | index2[9:0] = bm_hash; 213 | index2[9:0] = bm_hash; 214 | 215 | index1[16:10] = hash_32_1[6:0]; 216 | index2[16:10] = hash_32_2[6:0]; 217 | index3[16:10] = hash_32_3[6:0]; 218 | 219 | 220 | /* Stage 4 */ 221 | if(hash_32_1[9:7] == 0){ 222 | cms1_0.read(res1, index1); 223 | if(res1==0){ 224 | cms1_0.write(index1, 1); 225 | } 226 | }else if(hash_32_1[9:7] == 1){ 227 | cms1_1.read(res1, index1); 228 | if(res1==0){ 229 | cms1_1.write(index1, 1); 230 | } 231 | }else if(hash_32_1[9:7] == 2){ 232 | cms1_2.read(res1, index1); 233 | if(res1==0){ 234 | cms1_2.write(index1, 1); 235 | } 236 | }else if(hash_32_1[9:7] == 3){ 237 | cms1_3.read(res1, index1); 238 | if(res1==0){ 239 | cms1_3.write(index1, 1); 240 | } 241 | } 242 | /* Stage 5 */ 243 | else if(hash_32_1[9:7] == 4){ 244 | cms1_4.read(res1, index1); 245 | if(res1==0){ 246 | cms1_4.write(index1, 1); 247 | } 248 | }else if(hash_32_1[9:7] == 5){ 249 | cms1_5.read(res1, index1); 250 | if(res1==0){ 251 | cms1_5.write(index1, 1); 252 | } 253 | }else if(hash_32_1[9:7] == 6){ 254 | cms1_6.read(res1, index1); 255 | if(res1==0){ 256 | cms1_6.write(index1, 1); 257 | } 258 | }else if(hash_32_1[9:7] == 7){ 259 | cms1_7.read(res1, index1); 260 | if(res1==0){ 261 | cms1_7.write(index1, 1); 262 | } 263 | } 264 | 265 | /* Stage 6 */ 266 | if(hash_32_2[9:7] == 0){ 267 | cms2_0.read(res2, index2); 268 | if(res2==0){ 269 | cms2_0.write(index2, 1); 270 | } 271 | }else if(hash_32_2[9:7] == 1){ 272 | cms2_1.read(res2, index2); 273 | if(res2==0){ 274 | cms2_1.write(index2, 1); 275 | } 276 | }else if(hash_32_2[9:7] == 2){ 277 | cms2_2.read(res2, index2); 278 | if(res2==0){ 279 | cms2_2.write(index2, 1); 280 | } 281 | }else if(hash_32_2[9:7] == 3){ 282 | cms2_3.read(res2, index2); 283 | if(res2==0){ 284 | cms2_3.write(index2, 1); 285 | } 286 | } 287 | /* Stage 7 */ 288 | else if(hash_32_2[9:7] == 4){ 289 | cms2_4.read(res2, index2); 290 | if(res2==0){ 291 | cms2_4.write(index2, 1); 292 | } 293 | }else if(hash_32_2[9:7] == 5){ 294 | cms2_5.read(res2, index2); 295 | if(res2==0){ 296 | cms2_5.write(index2, 1); 297 | } 298 | }else if(hash_32_2[9:7] == 6){ 299 | cms2_6.read(res2, index2); 300 | if(res2==0){ 301 | cms2_6.write(index2, 1); 302 | } 303 | }else if(hash_32_2[9:7] == 7){ 304 | cms2_7.read(res2, index2); 305 | if(res2==0){ 306 | cms2_7.write(index2, 1); 307 | } 308 | } 309 | 310 | 311 | /* Stage 8 */ 312 | if(hash_32_3[9:7] == 0){ 313 | cms3_0.read(res3, index3); 314 | if(res3==0){ 315 | cms3_0.write(index3, 1); 316 | } 317 | }else if(hash_32_3[9:7] == 1){ 318 | cms3_1.read(res3, index3); 319 | if(res3==0){ 320 | cms3_1.write(index3, 1); 321 | } 322 | }else if(hash_32_3[9:7] == 2){ 323 | cms3_2.read(res3, index3); 324 | if(res3==0){ 325 | cms3_2.write(index3, 1); 326 | } 327 | }else if(hash_32_3[9:7] == 3){ 328 | cms3_3.read(res3, index3); 329 | if(res3==0){ 330 | cms3_3.write(index3, 1); 331 | } 332 | } 333 | /* Stage 9 */ 334 | else if(hash_32_3[9:7] == 4){ 335 | cms3_4.read(res3, index3); 336 | if(res3==0){ 337 | cms3_4.write(index3, 1); 338 | } 339 | }else if(hash_32_3[9:7] == 5){ 340 | cms3_5.read(res3, index3); 341 | if(res3==0){ 342 | cms3_5.write(index3, 1); 343 | } 344 | }else if(hash_32_3[9:7] == 6){ 345 | cms3_6.read(res3, index3); 346 | if(res3==0){ 347 | cms3_6.write(index3, 1); 348 | } 349 | }else if(hash_32_3[9:7] == 7){ 350 | cms3_7.read(res3, index3); 351 | if(res3==0){ 352 | cms3_7.write(index3, 1); 353 | } 354 | } 355 | /* Stage 10*/ 356 | occSlots1.read(value_1, (bit<32>)hash_32_1); 357 | if(res1 == 0){ 358 | value_1 = value_1 + 1; 359 | occSlots1.write((bit<32>)hash_32_1, value_1); 360 | } 361 | 362 | occSlots2.read(value_2, (bit<32>)hash_32_2); 363 | if(res2 == 0){ 364 | value_2 = value_2 + 1; 365 | occSlots2.write((bit<32>)hash_32_2, value_2); 366 | } 367 | 368 | occSlots3.read(value_3, (bit<32>)hash_32_3); 369 | if(res3 == 0){ 370 | value_3 = value_3 + 1; 371 | occSlots3.write((bit<32>)hash_32_3, value_3); 372 | } 373 | 374 | 375 | /* Stage 11 */ 376 | d12 = value_1 - value_2; 377 | d13 = value_1 - value_3; 378 | d23 = value_2 - value_3; 379 | if (d12 < 0 && d13 < 0){ 380 | meta.count_min = value_1; 381 | }else if (d12 > 0 && d23 <0){ 382 | meta.count_min = value_2; 383 | }else{ 384 | meta.count_min = value_3; 385 | } 386 | 387 | if (meta.count_min == DDoS_threshold + 1){ 388 | digest_type = 1; 389 | } 390 | 391 | } 392 | } 393 | 394 | control DeparserImpl(packet_out packet, in headers hdr) { 395 | apply { 396 | packet.emit(hdr.ethernet); 397 | packet.emit(hdr.ipv4); 398 | packet.emit(hdr.udp); 399 | packet.emit(hdr.tcp); 400 | } 401 | } 402 | 403 | control verifyChecksum(inout headers hdr, inout metadata meta) { 404 | apply { 405 | verify_checksum(true, { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffserv, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }, hdr.ipv4.hdrChecksum, HashAlgorithm.csum16); 406 | } 407 | } 408 | 409 | control computeChecksum(inout headers hdr, inout metadata meta) { 410 | apply { 411 | update_checksum(true, { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffserv, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }, hdr.ipv4.hdrChecksum, HashAlgorithm.csum16); 412 | } 413 | } 414 | 415 | V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; 416 | 417 | -------------------------------------------------------------------------------- /INDDoS.p4app/p4src/includes/headers.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-present Barefoot Networks, Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | header_type ethernet_t { 17 | fields { 18 | dstAddr : 48; 19 | srcAddr : 48; 20 | etherType : 16; 21 | } 22 | } 23 | 24 | header_type ipv4_t { 25 | fields { 26 | version : 4; 27 | ihl : 4; 28 | diffserv : 8; 29 | totalLen : 16; 30 | identification : 16; 31 | flags : 3; 32 | fragOffset : 13; 33 | ttl : 8; 34 | protocol : 8; 35 | hdrChecksum : 16; 36 | srcAddr : 32; 37 | dstAddr: 32; 38 | } 39 | } 40 | 41 | header_type tcp_t { 42 | fields { 43 | srcPort : 16; 44 | dstPort : 16; 45 | seqNo : 32; 46 | ackNo : 32; 47 | dataOffset : 4; 48 | res : 3; 49 | ecn : 3; 50 | ctrl : 6; 51 | window : 16; 52 | checksum : 16; 53 | urgentPtr : 16; 54 | } 55 | } 56 | 57 | //========================================================================================================== 58 | header_type udp_t { 59 | fields { 60 | srcPort : 16; 61 | dstPort : 16; 62 | udplen : 16; 63 | udpchk : 16; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /INDDoS.p4app/p4src/includes/parser.p4: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-present Barefoot Networks, Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | parser start { 17 | return parse_ethernet; 18 | } 19 | 20 | #define ETHERTYPE_IPV4 0x0800 21 | 22 | header ethernet_t ethernet; 23 | 24 | parser parse_ethernet { 25 | extract(ethernet); 26 | return select(latest.etherType) { 27 | ETHERTYPE_IPV4 : parse_ipv4; 28 | default: ingress; 29 | } 30 | } 31 | 32 | header ipv4_t ipv4; 33 | 34 | #define TCP_PROTO 0x06 35 | #define UDP_PROTO 0x11 36 | 37 | parser parse_ipv4 { 38 | extract(ipv4); 39 | return select(latest.protocol) { 40 | TCP_PROTO : parse_tcp; 41 | UDP_PROTO : parse_udp; 42 | default: ingress; 43 | } 44 | } 45 | 46 | header tcp_t tcp; 47 | 48 | parser parse_tcp { 49 | extract(tcp); 50 | return ingress; 51 | } 52 | header udp_t udp; 53 | 54 | parser parse_udp { 55 | extract(udp); 56 | return ingress; 57 | } 58 | -------------------------------------------------------------------------------- /INDDoS.p4app/read_registers1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.1.1" 24 | #echo "table_add set_heavy_hitter_count_table set_heavy_hitter_count 10.0.0.1/32 => " | $CLI_PATH heavy_hitter.json 22222 25 | 26 | 27 | echo "displaying occSlots1" 28 | echo "register_read occSlots1" | docker exec -i hh simple_switch_CLI --thrift-port 22222 29 | echo 30 | echo "displaying occSlots2" 31 | echo "register_read occSlots2" | docker exec -i hh simple_switch_CLI --thrift-port 22222 32 | echo 33 | echo "displaying occSlots3" 34 | echo "register_read occSlots3" | docker exec -i hh simple_switch_CLI --thrift-port 22222 35 | echo 36 | 37 | 38 | -------------------------------------------------------------------------------- /INDDoS.p4app/read_registers2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.2.2" 24 | 25 | 26 | echo "displaying occSlots1" 27 | echo "register_read occSlots1" | docker exec -i hh simple_switch_CLI --thrift-port 22223 28 | echo 29 | echo "displaying occSlots2" 30 | echo "register_read occSlots2" | docker exec -i hh simple_switch_CLI --thrift-port 22223 31 | echo 32 | echo "displaying occSlots3" 33 | echo "register_read occSlots3" | docker exec -i hh simple_switch_CLI --thrift-port 22223 34 | echo 35 | 36 | 37 | -------------------------------------------------------------------------------- /INDDoS.p4app/read_registers3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.3.3" 24 | 25 | 26 | echo "displaying occSlots1" 27 | echo "register_read occSlots1" | docker exec -i hh simple_switch_CLI --thrift-port 22224 28 | echo 29 | echo "displaying occSlots2" 30 | echo "register_read occSlots2" | docker exec -i hh simple_switch_CLI --thrift-port 22224 31 | echo 32 | echo "displaying occSlots3" 33 | echo "register_read occSlots3" | docker exec -i hh simple_switch_CLI --thrift-port 22224 34 | echo 35 | 36 | 37 | -------------------------------------------------------------------------------- /INDDoS.p4app/receive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | from scapy.all import sniff 18 | from scapy.all import IP, TCP, UDP 19 | 20 | VALID_IPS = ("10.0.1.1", "10.0.2.2", "10.0.3.3") 21 | totals = {} 22 | 23 | def handle_pkt(pkt): 24 | if IP in pkt and UDP in pkt: 25 | # if IP in pkt and TCP in pkt: 26 | src_ip = pkt[IP].src 27 | dst_ip = pkt[IP].dst 28 | id_tup = (src_ip, dst_ip) 29 | print id_tup 30 | if src_ip in VALID_IPS: 31 | if id_tup not in totals: 32 | totals[id_tup] = 0 33 | totals[id_tup] += 1 34 | print ("Received from %s total: %s" % 35 | (id_tup, totals[id_tup])) 36 | 37 | def main(): 38 | sniff(iface = "eth0", 39 | prn = lambda x: handle_pkt(x)) 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /INDDoS.p4app/send.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | from scapy.all import Ether, IP, sendp, get_if_hwaddr, get_if_list, TCP, Raw, UDP 18 | import sys 19 | import random, string 20 | 21 | def randomword(max_length): 22 | length = random.randint(1, max_length) 23 | return ''.join(random.choice(string.lowercase) for i in range(length)) 24 | 25 | def read_topo(): 26 | nb_hosts = 0 27 | nb_switches = 0 28 | links = [] 29 | with open("topo.txt", "r") as f: 30 | line = f.readline()[:-1] 31 | w, nb_switches = line.split() 32 | assert(w == "switches") 33 | line = f.readline()[:-1] 34 | w, nb_hosts = line.split() 35 | assert(w == "hosts") 36 | for line in f: 37 | if not f: break 38 | a, b = line.split() 39 | links.append( (a, b) ) 40 | return int(nb_hosts), int(nb_switches), links 41 | 42 | def send_random_traffic(dst, num_packets): 43 | dst_mac = None 44 | dst_ip = None 45 | src_mac = [get_if_hwaddr(i) for i in get_if_list() if i == 'eth0'] 46 | if len(src_mac) < 1: 47 | print ("No interface for output") 48 | sys.exit(1) 49 | src_mac = src_mac[0] 50 | src_ip = None 51 | if src_mac =="00:00:00:00:01:01": 52 | src_ip = "10.0.1.1" 53 | elif src_mac =="00:00:00:00:02:02": 54 | src_ip = "10.0.2.2" 55 | elif src_mac =="00:00:00:00:03:03": 56 | src_ip = "10.0.3.3" 57 | else: 58 | print ("Invalid source host") 59 | sys.exit(1) 60 | 61 | if dst == 'h1': 62 | dst_mac = "00:00:00:00:01:01" 63 | dst_ip = "10.0.1.1" 64 | elif dst == 'h2': 65 | dst_mac = "00:00:00:00:02:02" 66 | dst_ip = "10.0.2.2" 67 | elif dst == 'h3': 68 | dst_mac = "00:00:00:00:03:03" 69 | dst_ip = "10.0.3.3" 70 | else: 71 | print ("Invalid host to send to") 72 | sys.exit(1) 73 | 74 | total_pkts = 0 75 | # random_ports = random.sample(xrange(1024, 65535), 10000) 76 | # for port in random_ports: 77 | # num_packets = random.randint(50, 250) 78 | # num_packets = 1 79 | port = 1024 80 | for i in range(num_packets): 81 | # data = randomword(100) 82 | data = 'a' 83 | p = Ether(dst=dst_mac,src=src_mac)/IP(dst=dst_ip,src=src_ip) 84 | p = p/UDP(dport=port)/Raw(load=data) 85 | # p = p/TCP(dport=port)/Raw(load=data) 86 | print p.show() 87 | sendp(p, iface = "eth0", inter = 0.01) 88 | total_pkts += 1 89 | print "Sent %s packets in total" % total_pkts 90 | 91 | if __name__ == '__main__': 92 | if len(sys.argv) < 3: 93 | print("Usage: python send.py dst_host_name packet_num") 94 | sys.exit(1) 95 | else: 96 | dst_name = sys.argv[1] 97 | num_packets = sys.argv[2] 98 | send_random_traffic(dst_name, int(num_packets)) 99 | -------------------------------------------------------------------------------- /INDDoS.p4app/topo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | from mininet.net import Mininet 18 | from mininet.topo import Topo 19 | from mininet.log import setLogLevel 20 | from mininet.cli import CLI 21 | 22 | from p4_mininet import P4Switch, P4Host 23 | 24 | import argparse 25 | from time import sleep 26 | import os 27 | import subprocess 28 | 29 | _THIS_DIR = os.path.dirname(os.path.realpath(__file__)) 30 | _THRIFT_BASE_PORT = 22222 31 | 32 | parser = argparse.ArgumentParser(description='Mininet demo') 33 | parser.add_argument('--behavioral-exe', help='Path to behavioral executable', 34 | type=str, action="store", required=True) 35 | parser.add_argument('--json', help='Path to JSON config file', 36 | type=str, action="store", required=True) 37 | parser.add_argument('--cli', help='Path to BM CLI', 38 | type=str, action="store", required=True) 39 | args = parser.parse_args() 40 | 41 | class MyTopo(Topo): 42 | def __init__(self, sw_path, json_path, nb_hosts, nb_switches, links, **opts): 43 | # Initialize topology and default options 44 | Topo.__init__(self, **opts) 45 | for i in xrange(nb_switches): 46 | self.addSwitch('s%d' % (i + 1), 47 | sw_path = sw_path, 48 | json_path = json_path, 49 | thrift_port = _THRIFT_BASE_PORT + i, 50 | pcap_dump = True, 51 | device_id = i, 52 | enable_debugger = True) 53 | 54 | for h in xrange(nb_hosts): 55 | self.addHost('h%d' % (h + 1), ip="10.0.%d.%d" % ((h + 1) , (h + 1)), 56 | mac="00:00:00:00:0%d:0%d" % ((h+1), (h+1))) 57 | 58 | for a, b in links: 59 | self.addLink(a, b) 60 | 61 | def read_topo(): 62 | nb_hosts = 0 63 | nb_switches = 0 64 | links = [] 65 | with open("topo.txt", "r") as f: 66 | line = f.readline()[:-1] 67 | w, nb_switches = line.split() 68 | assert(w == "switches") 69 | line = f.readline()[:-1] 70 | w, nb_hosts = line.split() 71 | assert(w == "hosts") 72 | for line in f: 73 | if not f: break 74 | a, b = line.split() 75 | links.append( (a, b) ) 76 | return int(nb_hosts), int(nb_switches), links 77 | 78 | 79 | def main(): 80 | nb_hosts, nb_switches, links = read_topo() 81 | topo = MyTopo(args.behavioral_exe, 82 | args.json, 83 | nb_hosts, nb_switches, links) 84 | 85 | net = Mininet(topo = topo, 86 | host = P4Host, 87 | switch = P4Switch, 88 | controller = None, 89 | autoStaticArp=True) 90 | net.start() 91 | 92 | for n in xrange(nb_hosts): 93 | h = net.get('h%d' % (n + 1)) 94 | for off in ["rx", "tx", "sg"]: 95 | cmd = "/sbin/ethtool --offload eth0 %s off" % off 96 | print cmd 97 | h.cmd(cmd) 98 | print "disable ipv6" 99 | h.cmd("sysctl -w net.ipv6.conf.all.disable_ipv6=1") 100 | h.cmd("sysctl -w net.ipv6.conf.default.disable_ipv6=1") 101 | h.cmd("sysctl -w net.ipv6.conf.lo.disable_ipv6=1") 102 | h.cmd("sysctl -w net.ipv4.tcp_congestion_control=reno") 103 | h.cmd("iptables -I OUTPUT -p icmp --icmp-type destination-unreachable -j DROP") 104 | 105 | sleep(1) 106 | 107 | for i in xrange(nb_switches): 108 | cmd = [args.cli, "--json", args.json, 109 | "--thrift-port", str(_THRIFT_BASE_PORT + i) 110 | ] 111 | with open("commands"+str((i+1))+".txt", "r") as f: 112 | print " ".join(cmd) 113 | try: 114 | output = subprocess.check_output(cmd, stdin = f) 115 | print output 116 | except subprocess.CalledProcessError as e: 117 | print e 118 | print e.output 119 | 120 | s = net.get('s%d' % (n + 1)) 121 | s.cmd("sysctl -w net.ipv6.conf.all.disable_ipv6=1") 122 | s.cmd("sysctl -w net.ipv6.conf.default.disable_ipv6=1") 123 | s.cmd("sysctl -w net.ipv6.conf.lo.disable_ipv6=1") 124 | s.cmd("sysctl -w net.ipv4.tcp_congestion_control=reno") 125 | s.cmd("iptables -I OUTPUT -p icmp --icmp-type destination-unreachable -j DROP") 126 | 127 | sleep(1) 128 | 129 | print "Ready !" 130 | 131 | CLI( net ) 132 | net.stop() 133 | 134 | if __name__ == '__main__': 135 | setLogLevel( 'info' ) 136 | main() 137 | -------------------------------------------------------------------------------- /INDDoS.p4app/topo.txt: -------------------------------------------------------------------------------- 1 | switches 3 2 | hosts 3 3 | h1 s1 4 | h2 s2 5 | h3 s3 6 | s1 s3 7 | s1 s2 8 | s2 s3 9 | -------------------------------------------------------------------------------- /INDDoS.p4app/xterm_h1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.1.1" 24 | 25 | 26 | echo "Entering host xterm h1" 27 | p4app exec m h1 bash 28 | echo 29 | 30 | -------------------------------------------------------------------------------- /INDDoS.p4app/xterm_h2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.2.2" 24 | 25 | 26 | echo "Entering host xterm h2" 27 | p4app exec m h2 bash 28 | echo 29 | 30 | -------------------------------------------------------------------------------- /INDDoS.p4app/xterm_h3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013-present Barefoot Networks, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 18 | 19 | #source $THIS_DIR/../../env.sh 20 | 21 | #CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI 22 | 23 | echo "Switch 10.0.3.3" 24 | 25 | 26 | echo "Entering host xterm h3" 27 | p4app exec m h3 bash 28 | echo 29 | 30 | -------------------------------------------------------------------------------- /INDDoS_TNA/add_rule_ddos_mitigation.py: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY 3 | # 4 | # Copyright (c) 2019-present Barefoot Networks, Inc. 5 | # 6 | # All Rights Reserved. 7 | # 8 | # NOTICE: All information contained herein is, and remains the property of 9 | # Barefoot Networks, Inc. and its suppliers, if any. The intellectual and 10 | # technical concepts contained herein are proprietary to Barefoot Networks, Inc. 11 | # and its suppliers and may be covered by U.S. and Foreign Patents, patents in 12 | # process, and are protected by trade secret or copyright law. Dissemination of 13 | # this information or reproduction of this material is strictly forbidden unless 14 | # prior written permission is obtained from Barefoot Networks, Inc. 15 | # 16 | # No warranty, explicit or implicit is provided, unless granted under a written 17 | # agreement with Barefoot Networks, Inc. 18 | # 19 | ################################################################################ 20 | 21 | 22 | from scapy.all import Ether, IP, sendp, TCP, Raw, UDP 23 | 24 | 25 | 26 | p4 = bfrt.myDDoS_mitigation.pipe.Egress.acl 27 | p4learn = bfrt.myDDoS_mitigation.learn.pipe.IngressDeparser 28 | def my_learning_cb(dev_id, pipe_id, direction, pasrser_id, session, msg): 29 | global p4 30 | print(msg) 31 | for digest in msg: 32 | print(digest) 33 | dstIP = digest["dst_addr"] 34 | print(dstIP) 35 | p4.add_with_drop(dst_addr=dstIP) 36 | p4.dump() 37 | return 0 38 | 39 | try: 40 | p4learn.digest.callback_deregister() 41 | except: 42 | pass 43 | finally: 44 | print("Deregistering old learning callback (if any)") 45 | p4learn.digest.callback_register(my_learning_cb) 46 | print("callback register is running") 47 | 48 | -------------------------------------------------------------------------------- /INDDoS_TNA/digest.py: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY 3 | # 4 | # Copyright (c) 2019-present Barefoot Networks, Inc. 5 | # 6 | # All Rights Reserved. 7 | # 8 | # NOTICE: All information contained herein is, and remains the property of 9 | # Barefoot Networks, Inc. and its suppliers, if any. The intellectual and 10 | # technical concepts contained herein are proprietary to Barefoot Networks, Inc. 11 | # and its suppliers and may be covered by U.S. and Foreign Patents, patents in 12 | # process, and are protected by trade secret or copyright law. Dissemination of 13 | # this information or reproduction of this material is strictly forbidden unless 14 | # prior written permission is obtained from Barefoot Networks, Inc. 15 | # 16 | # No warranty, explicit or implicit is provided, unless granted under a written 17 | # agreement with Barefoot Networks, Inc. 18 | # 19 | ################################################################################ 20 | 21 | 22 | from scapy.all import Ether, IP, sendp, TCP, Raw, UDP 23 | 24 | 25 | 26 | p4 = bfrt.myDDoS3.pipe 27 | p4learn = bfrt.myDDoS3.learn.pipe.IngressDeparser 28 | def my_learning_cb(dev_id, pipe_id, direction, pasrser_id, session, msg): 29 | global p4 30 | print(msg) 31 | for digest in msg: 32 | print(digest) 33 | dstIP = digest["dst_addr"] 34 | print(dstIP) 35 | return 0 36 | 37 | try: 38 | p4learn.digest.callback_deregister() 39 | except: 40 | pass 41 | finally: 42 | print("Deregistering old learning callback (if any)") 43 | p4learn.digest.callback_register(my_learning_cb) 44 | print("callback register is running") 45 | 46 | -------------------------------------------------------------------------------- /INDDoS_TNA/myDDoS3.p4: -------------------------------------------------------------------------------- 1 | /* -*- P4_16 -*- */ 2 | 3 | #include 4 | #include 5 | 6 | /************************************************************************* 7 | ************* C O N S T A N T S A N D T Y P E S ******************* 8 | **************************************************************************/ 9 | const bit<16> ETHERTYPE_TPID = 0x8100; 10 | const bit<16> ETHERTYPE_IPV4 = 0x0800; 11 | 12 | /* Table Sizes */ 13 | const int<32> IPV4_HOST_SIZE = 65536; 14 | const int IPV4_LPM_SIZE = 12288; 15 | const bit<32> MAX_SIZE = 1024; // Bitmap size 16 | const bit<32> MAX_BH = 9;// MAX_BH = log2(MAX_SIZE)-1 17 | const bit<32> MAX_BH_begin = 10;// MAX_BH_begin = MAX_BH + 1 18 | const bit<32> MAX_CMS_SIZE = 1024; //CMS_SIZE 19 | const bit<32> MAX_DDoS_SIZE = 131072; // The max size of register is 131072 20 | const bit<32> MAX_H = 9;// MAX_H = log2(MAX_CMS_SIZE)-1 21 | const bit<32> MAX_H_min = 7;// MAX_H = MAX_H - 2 (log2(1024*1024) - log2(131072)) Fixed 22 | const bit<32> MAX_H_begin = 10;// MAX_H = log2(MAX_CMS_SIZE) 23 | const bit<32> MAX_end = 19;// log2(MAX_DDoS_SIZE) - 1 24 | const bit<32> UP = 16; // MAX_BH_begin + 6 25 | const bit<32> DDoS_threshold = 239; // Define the threshold here 26 | 27 | /* Typedef*/ 28 | typedef bit<32> data_t; 29 | typedef bit<1> bit_t; 30 | typedef bit<(MAX_H_begin)> hash_t; 31 | 32 | /************************************************************************* 33 | *********************** H E A D E R S ********************************* 34 | *************************************************************************/ 35 | 36 | /* Define all the headers the program will recognize */ 37 | /* The actual sets of headers processed by each gress can differ */ 38 | 39 | /* Standard ethernet header */ 40 | header ethernet_h { 41 | bit<48> dst_addr; 42 | bit<48> src_addr; 43 | bit<16> ether_type; 44 | } 45 | 46 | header vlan_tag_h { 47 | bit<3> pcp; 48 | bit<1> cfi; 49 | bit<12> vid; 50 | bit<16> ether_type; 51 | } 52 | 53 | header ipv4_h { 54 | bit<4> version; 55 | bit<4> ihl; 56 | bit<8> diffserv; 57 | bit<16> total_len; 58 | bit<16> identification; 59 | bit<3> flags; 60 | bit<13> frag_offset; 61 | bit<8> ttl; 62 | bit<8> protocol; 63 | bit<16> hdr_checksum; 64 | bit<32> src_addr; 65 | bit<32> dst_addr; 66 | } 67 | 68 | 69 | 70 | /************************************************************************* 71 | ************** I N G R E S S P R O C E S S I N G ******************* 72 | *************************************************************************/ 73 | /*********************** H E A D E R S ************************/ 74 | 75 | struct my_ingress_headers_t { 76 | ethernet_h ethernet; 77 | vlan_tag_h vlan_tag; 78 | ipv4_h ipv4; 79 | } 80 | 81 | /****** G L O B A L I N G R E S S M E T A D A T A *********/ 82 | 83 | struct my_ingress_metadata_t { 84 | bit<1> res_1; 85 | bit<1> res_2; 86 | bit<1> res_3; 87 | bit<32> count_min; 88 | } 89 | 90 | 91 | /****** DIGEST *********/ 92 | 93 | struct digest_t{ 94 | data_t dst_addr; 95 | } 96 | /*********************** P A R S E R **************************/ 97 | parser IngressParser(packet_in pkt, 98 | /* User */ 99 | out my_ingress_headers_t hdr, 100 | out my_ingress_metadata_t meta, 101 | /* Intrinsic */ 102 | out ingress_intrinsic_metadata_t ig_intr_md) 103 | { 104 | /* This is a mandatory state, required by Tofino Architecture */ 105 | state start { 106 | pkt.extract(ig_intr_md); 107 | pkt.advance(PORT_METADATA_SIZE); 108 | transition parse_ethernet; 109 | } 110 | //Remove since CAIDA trace does not have Ethernet header 111 | state parse_ethernet { 112 | pkt.extract(hdr.ethernet); 113 | transition select(hdr.ethernet.ether_type) { 114 | ETHERTYPE_TPID: parse_vlan_tag; 115 | ETHERTYPE_IPV4: parse_ipv4; 116 | default: accept; 117 | } 118 | } 119 | 120 | state parse_vlan_tag { 121 | pkt.extract(hdr.vlan_tag); 122 | transition select(hdr.vlan_tag.ether_type) { 123 | ETHERTYPE_IPV4: parse_ipv4; 124 | default: accept; 125 | } 126 | } 127 | 128 | state parse_ipv4 { 129 | pkt.extract(hdr.ipv4); 130 | transition accept; 131 | } 132 | 133 | } 134 | 135 | /***************** M A T C H - A C T I O N *********************/ 136 | control cal_ipv4_hash(in my_ingress_headers_t hdr, out hash_t hash)(bit<32> coeff) 137 | { 138 | 139 | CRCPolynomial>( 140 | coeff, 141 | true, 142 | false, 143 | false, 144 | 0xFFFFFFFF, 145 | 0xFFFFFFFF) poly; 146 | 147 | 148 | Hash>(HashAlgorithm_t.CUSTOM, poly) hash_algo; 149 | 150 | 151 | action do_hash(){ 152 | hash = (hash_algo.get({ 153 | hdr.ipv4.dst_addr 154 | })[MAX_H:0]); 155 | } 156 | apply{ 157 | do_hash(); 158 | } 159 | } 160 | control Ingress( 161 | /* User */ 162 | inout my_ingress_headers_t hdr, 163 | inout my_ingress_metadata_t meta, 164 | /* Intrinsic */ 165 | in ingress_intrinsic_metadata_t ig_intr_md, 166 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 167 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 168 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 169 | { 170 | Register(MAX_DDoS_SIZE) cms1_0; 171 | RegisterAction(cms1_0) 172 | update_cms1_0 = { 173 | void apply(inout bit_t value, out bit_t result) { 174 | result = ~value; 175 | value = 1; 176 | } 177 | }; 178 | 179 | Register(MAX_DDoS_SIZE) cms1_1; 180 | RegisterAction(cms1_1) 181 | update_cms1_1 = { 182 | void apply(inout bit_t value, out bit_t result) { 183 | result = ~value; 184 | value = 1; 185 | } 186 | }; 187 | 188 | Register(MAX_DDoS_SIZE) cms1_2; 189 | RegisterAction(cms1_2) 190 | update_cms1_2 = { 191 | void apply(inout bit_t value, out bit_t result) { 192 | result = ~value; 193 | value = 1; 194 | } 195 | }; 196 | 197 | Register(MAX_DDoS_SIZE) cms1_3; 198 | RegisterAction(cms1_3) 199 | update_cms1_3 = { 200 | void apply(inout bit_t value, out bit_t result) { 201 | result = ~value; 202 | value = 1; 203 | } 204 | }; 205 | 206 | Register(MAX_DDoS_SIZE) cms1_4; 207 | RegisterAction(cms1_4) 208 | update_cms1_4 = { 209 | void apply(inout bit_t value, out bit_t result) { 210 | result = ~value; 211 | value = 1; 212 | } 213 | }; 214 | 215 | Register(MAX_DDoS_SIZE) cms1_5; 216 | RegisterAction(cms1_5) 217 | update_cms1_5 = { 218 | void apply(inout bit_t value, out bit_t result) { 219 | result = ~value; 220 | value = 1; 221 | } 222 | }; 223 | 224 | Register(MAX_DDoS_SIZE) cms1_6; 225 | RegisterAction(cms1_6) 226 | update_cms1_6 = { 227 | void apply(inout bit_t value, out bit_t result) { 228 | result = ~value; 229 | value = 1; 230 | } 231 | }; 232 | 233 | Register(MAX_DDoS_SIZE) cms1_7; 234 | RegisterAction(cms1_7) 235 | update_cms1_7 = { 236 | void apply(inout bit_t value, out bit_t result) { 237 | result = ~value; 238 | value = 1; 239 | } 240 | }; 241 | 242 | Register(MAX_DDoS_SIZE) cms2_0; 243 | RegisterAction(cms2_0) 244 | update_cms2_0 = { 245 | void apply(inout bit_t value, out bit_t result) { 246 | result = ~value; 247 | value = 1; 248 | } 249 | }; 250 | 251 | Register(MAX_DDoS_SIZE) cms2_1; 252 | RegisterAction(cms2_1) 253 | update_cms2_1 = { 254 | void apply(inout bit_t value, out bit_t result) { 255 | result = ~value; 256 | value = 1; 257 | } 258 | }; 259 | 260 | Register(MAX_DDoS_SIZE) cms2_2; 261 | RegisterAction(cms2_2) 262 | update_cms2_2 = { 263 | void apply(inout bit_t value, out bit_t result) { 264 | result = ~value; 265 | value = 1; 266 | } 267 | }; 268 | 269 | Register(MAX_DDoS_SIZE) cms2_3; 270 | RegisterAction(cms2_3) 271 | update_cms2_3 = { 272 | void apply(inout bit_t value, out bit_t result) { 273 | result = ~value; 274 | value = 1; 275 | } 276 | }; 277 | 278 | Register(MAX_DDoS_SIZE) cms2_4; 279 | RegisterAction(cms2_4) 280 | update_cms2_4 = { 281 | void apply(inout bit_t value, out bit_t result) { 282 | result = ~value; 283 | value = 1; 284 | } 285 | }; 286 | 287 | Register(MAX_DDoS_SIZE) cms2_5; 288 | RegisterAction(cms2_5) 289 | update_cms2_5 = { 290 | void apply(inout bit_t value, out bit_t result) { 291 | result = ~value; 292 | value = 1; 293 | } 294 | }; 295 | 296 | Register(MAX_DDoS_SIZE) cms2_6; 297 | RegisterAction(cms2_6) 298 | update_cms2_6 = { 299 | void apply(inout bit_t value, out bit_t result) { 300 | result = ~value; 301 | value = 1; 302 | } 303 | }; 304 | 305 | Register(MAX_DDoS_SIZE) cms2_7; 306 | RegisterAction(cms2_7) 307 | update_cms2_7 = { 308 | void apply(inout bit_t value, out bit_t result) { 309 | result = ~value; 310 | value = 1; 311 | } 312 | }; 313 | 314 | 315 | 316 | Register(MAX_DDoS_SIZE) cms3_0; 317 | RegisterAction(cms3_0) 318 | update_cms3_0 = { 319 | void apply(inout bit_t value, out bit_t result) { 320 | result = ~value; 321 | value = 1; 322 | } 323 | }; 324 | 325 | Register(MAX_DDoS_SIZE) cms3_1; 326 | RegisterAction(cms3_1) 327 | update_cms3_1 = { 328 | void apply(inout bit_t value, out bit_t result) { 329 | result = ~value; 330 | value = 1; 331 | } 332 | }; 333 | 334 | Register(MAX_DDoS_SIZE) cms3_2; 335 | RegisterAction(cms3_2) 336 | update_cms3_2 = { 337 | void apply(inout bit_t value, out bit_t result) { 338 | result = ~value; 339 | value = 1; 340 | } 341 | }; 342 | 343 | Register(MAX_DDoS_SIZE) cms3_3; 344 | RegisterAction(cms3_3) 345 | update_cms3_3 = { 346 | void apply(inout bit_t value, out bit_t result) { 347 | result = ~value; 348 | value = 1; 349 | } 350 | }; 351 | 352 | Register(MAX_DDoS_SIZE) cms3_4; 353 | RegisterAction(cms3_4) 354 | update_cms3_4 = { 355 | void apply(inout bit_t value, out bit_t result) { 356 | result = ~value; 357 | value = 1; 358 | } 359 | }; 360 | 361 | Register(MAX_DDoS_SIZE) cms3_5; 362 | RegisterAction(cms3_5) 363 | update_cms3_5 = { 364 | void apply(inout bit_t value, out bit_t result) { 365 | result = ~value; 366 | value = 1; 367 | } 368 | }; 369 | 370 | Register(MAX_DDoS_SIZE) cms3_6; 371 | RegisterAction(cms3_6) 372 | update_cms3_6 = { 373 | void apply(inout bit_t value, out bit_t result) { 374 | result = ~value; 375 | value = 1; 376 | } 377 | }; 378 | 379 | Register(MAX_DDoS_SIZE) cms3_7; 380 | RegisterAction(cms3_7) 381 | update_cms3_7 = { 382 | void apply(inout bit_t value, out bit_t result) { 383 | result = ~value; 384 | value = 1; 385 | } 386 | }; 387 | 388 | 389 | 390 | Register(MAX_CMS_SIZE) occSlots1; 391 | RegisterAction(occSlots1) 392 | update_occ1 = { 393 | void apply(inout data_t value, out data_t result) { 394 | if (meta.res_1 == 1){ 395 | value = value + 1; 396 | } 397 | result = value; 398 | } 399 | }; 400 | 401 | Register(MAX_CMS_SIZE) occSlots2; 402 | RegisterAction(occSlots2) 403 | update_occ2 = { 404 | void apply(inout data_t value, out data_t result) { 405 | if (meta.res_2 == 1){ 406 | value = value + 1; 407 | } 408 | 409 | result = value; 410 | } 411 | }; 412 | 413 | Register(MAX_CMS_SIZE) occSlots3; 414 | RegisterAction(occSlots3) 415 | update_occ3 = { 416 | void apply(inout data_t value, out data_t result) { 417 | if (meta.res_3 == 1){ 418 | value = value + 1; 419 | } 420 | result = value; 421 | } 422 | }; 423 | 424 | 425 | Register(1) intimeReg; 426 | RegisterAction(intimeReg) 427 | update_intimeReg = { 428 | void apply(inout data_t value) { 429 | value = (bit<32>)ig_prsr_md.global_tstamp; 430 | } 431 | }; 432 | 433 | /*Hash functions for CMS*/ 434 | cal_ipv4_hash(coeff=0x04C11DB7) hash1; 435 | cal_ipv4_hash(coeff=0x1EDC6F41) hash2; 436 | cal_ipv4_hash(coeff=0xA833982B) hash3; 437 | /*Hash function for BitMap*/ 438 | Hash>(HashAlgorithm_t.CRC32) hash; 439 | 440 | action send(PortId_t port) { 441 | ig_tm_md.ucast_egress_port = port; 442 | } 443 | 444 | action drop() { 445 | ig_dprsr_md.drop_ctl = 1; 446 | } 447 | 448 | table ipv4_host { 449 | key = { hdr.ipv4.dst_addr : exact; } 450 | actions = { 451 | send; drop; 452 | } 453 | 454 | size = IPV4_HOST_SIZE; 455 | } 456 | 457 | table ipv4_lpm { 458 | key = { hdr.ipv4.dst_addr : lpm; } 459 | actions = { send; drop; } 460 | size = IPV4_LPM_SIZE; 461 | } 462 | 463 | apply { 464 | if (hdr.ipv4.isValid()) { 465 | if (!ipv4_host.apply().hit) { 466 | ipv4_lpm.apply(); 467 | } 468 | update_intimeReg.execute(0); 469 | } 470 | 471 | bit<(MAX_BH_begin)> bm_hash; 472 | hash_t hash_32_1; 473 | hash_t hash_32_2; 474 | hash_t hash_32_3; 475 | data_t index1; 476 | data_t index2; 477 | data_t index3; 478 | bit<32> value_1; 479 | bit<32> value_2; 480 | bit<32> value_3; 481 | 482 | 483 | 484 | hash1.apply(hdr, hash_32_1); 485 | hash2.apply(hdr, hash_32_2); 486 | hash3.apply(hdr, hash_32_3); 487 | 488 | 489 | bm_hash = (hash.get({ 490 | hdr.ipv4.src_addr, 491 | hdr.ipv4.dst_addr 492 | })[MAX_BH:0]); 493 | 494 | 495 | index1[MAX_BH:0] = bm_hash; 496 | index2[MAX_BH:0] = bm_hash; 497 | index3[MAX_BH:0] = bm_hash; 498 | 499 | index1[UP:MAX_BH_begin] = hash_32_1[6:0]; 500 | index2[UP:MAX_BH_begin] = hash_32_2[6:0]; 501 | index3[UP:MAX_BH_begin] = hash_32_3[6:0]; 502 | 503 | if( hash_32_1[MAX_H:MAX_H_min] == 3w0){ 504 | meta.res_1 = update_cms1_0.execute(index1); 505 | }else if (hash_32_1[MAX_H:MAX_H_min] == 3w1){ 506 | meta.res_1 = update_cms1_1.execute(index1); 507 | }else if (hash_32_1[MAX_H:MAX_H_min] == 3w2){ 508 | meta.res_1 = update_cms1_2.execute(index1); 509 | }else if (hash_32_1[MAX_H:MAX_H_min] == 3w3){ 510 | meta.res_1 = update_cms1_3.execute(index1); 511 | }else if (hash_32_1[MAX_H:MAX_H_min] == 3w4){ 512 | meta.res_1 = update_cms1_4.execute(index1); 513 | }else if (hash_32_1[MAX_H:MAX_H_min] == 3w5){ 514 | meta.res_1 = update_cms1_5.execute(index1); 515 | }else if (hash_32_1[MAX_H:MAX_H_min] == 3w6){ 516 | meta.res_1 = update_cms1_6.execute(index1); 517 | }else if (hash_32_1[MAX_H:MAX_H_min] == 3w7){ 518 | meta.res_1 = update_cms1_7.execute(index1); 519 | } 520 | if( hash_32_2[MAX_H:MAX_H_min] == 3w0){ 521 | meta.res_2 = update_cms2_0.execute(index2); 522 | }else if (hash_32_2[MAX_H:MAX_H_min] == 3w1){ 523 | meta.res_2 = update_cms2_1.execute(index2); 524 | }else if (hash_32_2[MAX_H:MAX_H_min] == 3w2){ 525 | meta.res_2 = update_cms2_2.execute(index2); 526 | }else if (hash_32_2[MAX_H:MAX_H_min] == 3w3){ 527 | meta.res_2 = update_cms2_3.execute(index2); 528 | }else if (hash_32_2[MAX_H:MAX_H_min] == 3w4){ 529 | meta.res_2 = update_cms2_4.execute(index2); 530 | }else if (hash_32_2[MAX_H:MAX_H_min] == 3w5){ 531 | meta.res_2 = update_cms2_5.execute(index2); 532 | }else if (hash_32_2[MAX_H:MAX_H_min] == 3w6){ 533 | meta.res_2 = update_cms2_6.execute(index2); 534 | }else if (hash_32_2[MAX_H:MAX_H_min] == 3w7){ 535 | meta.res_2 = update_cms2_7.execute(index2); 536 | } 537 | if( hash_32_3[MAX_H:MAX_H_min] == 3w0){ 538 | meta.res_3 = update_cms3_0.execute(index3); 539 | }else if (hash_32_3[MAX_H:MAX_H_min] == 3w1){ 540 | meta.res_3 = update_cms3_1.execute(index3); 541 | }else if (hash_32_3[MAX_H:MAX_H_min] == 3w2){ 542 | meta.res_3 = update_cms3_2.execute(index3); 543 | }else if (hash_32_3[MAX_H:MAX_H_min] == 3w3){ 544 | meta.res_3 = update_cms3_3.execute(index3); 545 | }else if (hash_32_3[MAX_H:MAX_H_min] == 3w4){ 546 | meta.res_3 = update_cms3_4.execute(index3); 547 | }else if (hash_32_3[MAX_H:MAX_H_min] == 3w5){ 548 | meta.res_3 = update_cms3_5.execute(index3); 549 | }else if (hash_32_3[MAX_H:MAX_H_min] == 3w6){ 550 | meta.res_3 = update_cms3_6.execute(index3); 551 | }else if (hash_32_3[MAX_H:MAX_H_min] == 3w7){ 552 | meta.res_3 = update_cms3_7.execute(index3); 553 | } 554 | 555 | 556 | value_1 = update_occ1.execute((bit<32>)hash_32_1); 557 | value_2 = update_occ2.execute((bit<32>)hash_32_2); 558 | value_3 = update_occ3.execute((bit<32>)hash_32_3); 559 | 560 | bit<32> d12; 561 | bit<32> d13; 562 | bit<32> d23; 563 | /*bit_t dmin;*/ 564 | d12 = value_1 - value_2; 565 | d13 = value_1 - value_3; 566 | d23 = value_2 - value_3; 567 | if (d12 < 0 && d13 < 0){ 568 | meta.count_min = value_1; 569 | }else if (d12 > 0 && d23 <0){ 570 | meta.count_min = value_2; 571 | }else{ 572 | meta.count_min = value_3; 573 | } 574 | if (meta.count_min == DDoS_threshold + 1 ){ 575 | ig_dprsr_md.digest_type = 1; 576 | } 577 | 578 | } 579 | } 580 | 581 | /********************* D E P A R S E R ************************/ 582 | 583 | control IngressDeparser(packet_out pkt, 584 | /* User */ 585 | inout my_ingress_headers_t hdr, 586 | in my_ingress_metadata_t meta, 587 | /* Intrinsic */ 588 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) 589 | { 590 | Digest() digest; 591 | apply { 592 | if(ig_dprsr_md.digest_type == 1){ 593 | digest.pack({hdr.ipv4.dst_addr}); 594 | } 595 | pkt.emit(hdr); 596 | } 597 | } 598 | 599 | 600 | /************************************************************************* 601 | **************** E G R E S S P R O C E S S I N G ******************* 602 | *************************************************************************/ 603 | 604 | /*********************** H E A D E R S ************************/ 605 | 606 | struct my_egress_headers_t { 607 | } 608 | 609 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 610 | 611 | struct my_egress_metadata_t { 612 | } 613 | 614 | /*********************** P A R S E R **************************/ 615 | 616 | parser EgressParser(packet_in pkt, 617 | /* User */ 618 | out my_egress_headers_t hdr, 619 | out my_egress_metadata_t meta, 620 | /* Intrinsic */ 621 | out egress_intrinsic_metadata_t eg_intr_md) 622 | { 623 | /* This is a mandatory state, required by Tofino Architecture */ 624 | state start { 625 | pkt.extract(eg_intr_md); 626 | transition accept; 627 | } 628 | } 629 | 630 | /***************** M A T C H - A C T I O N *********************/ 631 | 632 | control Egress( 633 | /* User */ 634 | inout my_egress_headers_t hdr, 635 | inout my_egress_metadata_t meta, 636 | /* Intrinsic */ 637 | in egress_intrinsic_metadata_t eg_intr_md, 638 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 639 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 640 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) 641 | { 642 | Register(1) timeReg; 643 | RegisterAction(timeReg) 644 | update_timeReg = { 645 | void apply(inout data_t value) { 646 | value = (bit<32>)eg_prsr_md.global_tstamp; 647 | } 648 | }; 649 | 650 | apply { 651 | update_timeReg.execute(0); 652 | } 653 | } 654 | 655 | /********************* D E P A R S E R ************************/ 656 | 657 | control EgressDeparser(packet_out pkt, 658 | /* User */ 659 | inout my_egress_headers_t hdr, 660 | in my_egress_metadata_t meta, 661 | /* Intrinsic */ 662 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 663 | { 664 | apply { 665 | pkt.emit(hdr); 666 | } 667 | } 668 | 669 | 670 | /************ F I N A L P A C K A G E ******************************/ 671 | Pipeline( 672 | IngressParser(), 673 | Ingress(), 674 | IngressDeparser(), 675 | EgressParser(), 676 | Egress(), 677 | EgressDeparser() 678 | ) pipe; 679 | 680 | Switch(pipe) main; 681 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Citation 2 | -------- 3 | ``` 4 | @article{ding2021innetwork, 5 | title={In-Network Volumetric DDoS Victim Identification Using Programmable Commodity Switches}, 6 | author={Ding, Damu and Savi, Marco and Pederzolli, Federico and Mauro, Campanella and Siracusa, Domenico}, 7 | journal={IEEE Transactions on Network and Service Management}, 8 | year={2021}, 9 | publisher={IEEE} 10 | } 11 | ``` 12 | INDDoS has been implemented in two different testbeds: 13 | * Bmv2 (v1model, available in the folder INDDoS.p4app) 14 | * Tofino (TNA, available in the folder INDDoS\_TNA) 15 | 16 | # Bmv2 17 | 18 | Installation 19 | ------------ 20 | 21 | 1. Install [docker](https://docs.docker.com/engine/installation/) if you don't 22 | already have it. 23 | 24 | 2. Clone the repository to local 25 | 26 | ``` 27 | git clone https://github.com/DINGDAMU/INDDoS.git 28 | ``` 29 | 30 | 3. ``` 31 | cd INDDoS 32 | ``` 33 | 34 | 4. If you want, put the `p4app` script somewhere in your path. For example: 35 | 36 | ``` 37 | cp p4app /usr/local/bin 38 | ``` 39 | 40 | Execute the program 41 | -------------- 42 | 43 | 1. ``` 44 | ./p4app run INDDoS.p4app 45 | ``` 46 | After this step you'll see the terminal of **mininet** 47 | 2. Forwarding some packets in **mininet** 48 | 49 | ``` 50 | pingall 51 | pingall 52 | ``` 53 | or 54 | ``` 55 | h1 ping h2 -c 12 -i 0.1 56 | ``` 57 | 58 | It is also possible to test the code by using **scapy** 59 | 60 | An example can be found in INDDoS.p4app/send.py and INDDoS.p4app/receive.py 61 | 62 | 63 | 3. Enter INDDoS.p4app folder 64 | ``` 65 | cd INDDoS.p4app 66 | ``` 67 | 4. Check the result by reading the register 68 | ``` 69 | ./read_registers1.sh 70 | ./read_registers2.sh 71 | ./read_registers3.sh 72 | ``` 73 | 74 | In registers `occSlots 1-3` there are the resulsted number of 1s. 75 | 76 | # Tofino 77 | The P4 code has been installed and tested in Edgecore Wedge-100BF-32X switch equipped with Barefoot Tofino 3.3 Tbps ASIC using SDE 9.1.1. 78 | 79 | -------------------------------------------------------------------------------- /p4app: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2013-present Barefoot Networks, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | P4APP_IMAGE=${P4APP_IMAGE:-dingdamu/p4app-ddos:nwhhd} 17 | P4APP_CONTAINER_ARGS=${P4APP_CONTAINER_ARGS:-""} 18 | 19 | 20 | myrealpath() { 21 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 22 | } 23 | 24 | P4APP_LOGDIR=$(myrealpath "${P4APP_LOGDIR:-/tmp/p4app_logs}") 25 | 26 | 27 | function get_abs_filename() { 28 | # Convert a possibly-relative path to an absolute path. 29 | echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" 30 | } 31 | 32 | function normalize_path() { 33 | # Remove any trailing slash from the provided path. 34 | echo ${1%/} 35 | } 36 | 37 | function build-command { 38 | if [ -z $2 ]; then 39 | OUTPUT_FILE="out.json" 40 | else 41 | OUTPUT_FILE="$2" 42 | fi 43 | 44 | run-command $1 --build-only "${@:3}" 45 | rc=$? 46 | 47 | [ $rc -eq 0 ] && cp "$P4APP_LOGDIR/program.json" $OUTPUT_FILE 48 | 49 | exit $rc 50 | } 51 | 52 | function run-p4app { 53 | APP_TO_RUN=/tmp/app.tar.gz 54 | P4APP_NAME='hh' 55 | docker run --privileged --interactive -i --tty --rm \ 56 | --name "$P4APP_NAME" \ 57 | -v $1:$APP_TO_RUN \ 58 | -e DISPLAY=$DISPLAY \ 59 | -v "$P4APP_LOGDIR":/tmp/p4app_logs \ 60 | $P4APP_CONTAINER_ARGS \ 61 | $P4APP_IMAGE $APP_TO_RUN "${@:2}" 62 | } 63 | 64 | function run-command { 65 | # Run the .p4app package provided by the user. 66 | if [ -d "$1" ]; then 67 | # The user passed the package as a directory. Tar it up and pass it to the 68 | # container. 69 | PACKAGE_DIR=$(normalize_path "$1") 70 | APP_FILE=$(mktemp /tmp/p4app.tar.gz.XXXXXX) 71 | tar -czf "$APP_FILE" -C "$PACKAGE_DIR" . 72 | run-p4app "$APP_FILE" "${@:2}" 73 | rc=$? 74 | rm "$APP_FILE" 75 | elif [ -f "$1" ]; then 76 | # The user passed the package as a file. We'll assume it's already a .tar.gz 77 | # archive; just pass it to the container as-is. 78 | APP_FILE=$(get_abs_filename "$1") 79 | run-p4app "$APP_FILE" "${@:2}" 80 | rc=$? 81 | else 82 | echo "Couldn't read p4app package: $1" 83 | exit 1 84 | fi 85 | return $rc 86 | } 87 | 88 | function pack-command { 89 | # Compress the provided .p4app package. 90 | if [ -d "$1" ]; then 91 | # The user passed the package as a directory. Tar it up. 92 | PACKAGE_DIR=$(normalize_path "$1") 93 | APP_FILE=$(mktemp /tmp/p4app.tar.gz.XXXXXX) 94 | tar -czf "$APP_FILE" -C "$PACKAGE_DIR" . && 95 | rm -rf "$PACKAGE_DIR" 96 | mv "$APP_FILE" "$PACKAGE_DIR" 97 | elif [ -f "$1" ]; then 98 | # The user passed the package as a file. We'll assume it's already a .tar.gz 99 | # archive and leave it alone so that this command is idempotent. 100 | echo "Package is already packed: $1" 101 | else 102 | echo "Couldn't read p4app package: $1" 103 | exit 1 104 | fi 105 | } 106 | 107 | function unpack-command { 108 | # Decompress the provided .p4app package. 109 | if [ -d "$1" ]; then 110 | # The user passed the package as a directory. We'll leave it alone so that 111 | # this command is idempotent. 112 | echo "Package is already unpacked: $1" 113 | elif [ -f "$1" ]; then 114 | # The user passed the package as a file. Extract it. 115 | APP_FILE=$(mktemp /tmp/p4app.tar.gz.XXXXXX) 116 | mv "$1" "$APP_FILE" && 117 | mkdir -p "$1" && 118 | tar -xzf "$APP_FILE" -C "$1" && 119 | rm "$APP_FILE" 120 | else 121 | echo "Couldn't read p4app package: $1" 122 | exit 1 123 | fi 124 | } 125 | 126 | function update-command { 127 | docker pull $P4APP_IMAGE 128 | } 129 | 130 | function exec-command { 131 | #container_id=${P4APP_NAME:-$(docker ps | grep -m1 p4app | awk '{print $1}')} 132 | container_id='hh' 133 | if [ -z "$container_id" ]; then 134 | (>&2 echo "Couldn't find any p4app currently running.") 135 | exit 1 136 | fi 137 | 138 | if [ -t 1 ]; then 139 | # Called from a terminal, be interactive 140 | docker exec -it $container_id ${@:1} 141 | else 142 | # Inside a pipe, don't allocate a ptty 143 | docker exec $container_id ${@:1} 144 | fi 145 | } 146 | 147 | function usage-command { 148 | echo "Usage:" 149 | echo " p4app run " 150 | echo " Run a p4app." 151 | echo " p4app run " 152 | echo " Run a p4app, specifying a target." 153 | echo " p4app build " 154 | echo " Build a p4app, specifying the output JSON filename." 155 | echo " p4app pack " 156 | echo " Compress a p4app directory into a single file, in-place." 157 | echo " p4app unpack " 158 | echo " Expand a p4app file into a directory, in-place." 159 | echo " p4app update" 160 | echo " Update the toolchain to the newest version." 161 | echo " p4app exec " 162 | echo " Execute a command on the most recent p4app instance." 163 | exit 1 164 | } 165 | 166 | case "$1" in 167 | "run") 168 | run-command "${@:2}" 169 | ;; 170 | "build") 171 | build-command "${@:2}" 172 | ;; 173 | "pack") 174 | pack-command "${@:2}" 175 | ;; 176 | "unpack") 177 | unpack-command "${@:2}" 178 | ;; 179 | "update") 180 | update-command "${@:2}" 181 | ;; 182 | "exec") 183 | exec-command "${@:2}" 184 | ;; 185 | *) 186 | usage-command 187 | ;; 188 | esac 189 | --------------------------------------------------------------------------------