├── README.md ├── p4_14 ├── API │ ├── API_O1_hash.p4 │ ├── API_O3_tcam.p4 │ ├── API_O5_salu.p4 │ ├── API_O6_flowkey.p4 │ ├── API_common.p4 │ └── API_threshold.p4 ├── common_p4 │ ├── headers.p4 │ └── parsers.p4 ├── compile.sh ├── countmin │ └── p414_countmin.p4 ├── countsketch │ └── p414_countsketch.p4 ├── hll │ └── p414_hll.p4 └── univmon │ └── p414_univmon.p4 └── p4_16 ├── API ├── API_O1_hash.p4 ├── API_O2_hash.p4 ├── API_O3_tcam.p4 ├── API_O5_salu.p4 ├── API_O6_flowkey.p4 ├── API_O6_flowkey_fcm.p4 ├── API_O6_flowkey_hhh.p4 ├── API_O6_flowkey_kary.p4 ├── API_O6_flowkey_rhhh.p4 ├── API_common.p4 └── API_threshold.p4 ├── common_p4 ├── headers.p4 ├── parser.p4 └── util.p4 ├── compile.sh ├── countmin └── p416_countmin.p4 ├── countsketch └── p416_countsketch.p4 ├── entropy └── p416_entropy.p4 ├── fcm ├── common │ ├── headers.p4 │ └── util.p4 └── p416_fcm.p4 ├── hhh └── p416_hhh.p4 ├── hll └── p416_hll.p4 ├── kary └── p416_kary.p4 ├── loglog └── p416_loglog.p4 ├── mrac └── p416_mrac.p4 ├── mrb └── p416_mrb.p4 ├── pcsa └── p416_pcsa.p4 ├── rhhh └── p416_rhhh.p4 ├── sketchlearn └── p416_sketchlearn.p4 ├── spreadsketch └── p416_spreadsketch.p4 └── univmon └── p416_univmon.p4 /README.md: -------------------------------------------------------------------------------- 1 | # P4_SketchLib 2 | 3 | This is github repository for SketchLib published at NSDI '22. You can find paper link [here]([https://hnamkung.github.io/assets/pdf/nsdi22-sketchlib.pdf](https://www.usenix.org/conference/nsdi22/presentation/namkung). 4 | 5 | 6 | General Instruction 7 | - In the API folder, there is a list of optimizations/API in each p4 file. 8 | - You can import the header file and can directly use the function call or you may modify it based on the content of the function call for your needs. 9 | - We implemented 15 sketches using SketchLib, thus you can refer to these sketch implementations. 10 | - We used Tofino SDE version 9.1.1 11 | 12 | Sketchovsky (NSDI '23) is extension of SketchLib [[Paper link]](https://www.usenix.org/conference/nsdi23/presentation/namkung) [[github link]](https://github.com/sketchovsky) 13 | - SketchLib only focuses on running a single sketch instance. Sketchovsky runs multiple sketch instances simultaneously. 14 | -------------------------------------------------------------------------------- /p4_14/API/API_O1_hash.p4: -------------------------------------------------------------------------------- 1 | #define hash_consolidate_and_split_5_init(NAME, KEY_FIELDS, POLY_PARAM, PHV0, LEN0, PHV1, PHV2, PHV3, PHV4, PHV5, MASK1, MASK2, MASK3, MASK4, LEN1, LEN2, LEN3, LEN4) \ 2 | field_list_calculation NAME##_hash_func { \ 3 | input { \ 4 | KEY_FIELDS; \ 5 | } \ 6 | algorithm : poly_##POLY_PARAM##_init_0x00000000_xout_0xffffffff; \ 7 | output_width : 16; \ 8 | } \ 9 | table NAME##_compute_all_hash { \ 10 | actions { \ 11 | NAME##_compute_all_hash_act; \ 12 | } \ 13 | default_action: NAME##_compute_all_hash_act; \ 14 | } \ 15 | action NAME##_compute_all_hash_act () { \ 16 | modify_field_with_hash_based_offset(PHV0, 0x0, NAME##_hash_func, LEN0); \ 17 | } \ 18 | table NAME##_split_table { \ 19 | actions { \ 20 | NAME##_split_table_act; \ 21 | } \ 22 | default_action: NAME##_split_table_act; \ 23 | } \ 24 | action NAME##_split_table_act () { \ 25 | modify_field_with_shift(PHV1, PHV0, 0, MASK1); \ 26 | modify_field_with_shift(PHV2, PHV0, LEN1, MASK2); \ 27 | modify_field_with_shift(PHV3, PHV0, LEN2, MASK3); \ 28 | modify_field_with_shift(PHV4, PHV0, LEN3, MASK4); \ 29 | shift_right(PHV5, PHV0, LEN4); \ 30 | } 31 | 32 | #define hash_consolidate_and_split_5_call(NAME) \ 33 | apply(NAME##_compute_all_hash); \ 34 | apply(NAME##_split_table); -------------------------------------------------------------------------------- /p4_14/API/API_O3_tcam.p4: -------------------------------------------------------------------------------- 1 | #define lpm_optimization_init(NAME, SAMPLING_HASH, LEVEL) \ 2 | action NAME##_table_act (level) { \ 3 | modify_field(LEVEL, level); \ 4 | } \ 5 | table NAME##_table { \ 6 | reads { \ 7 | SAMPLING_HASH : lpm; \ 8 | } \ 9 | actions { \ 10 | NAME##_table_act; \ 11 | } \ 12 | } 13 | 14 | #define lpm_optimization_call(NAME) \ 15 | apply(NAME##_table); 16 | -------------------------------------------------------------------------------- /p4_14/API/API_O5_salu.p4: -------------------------------------------------------------------------------- 1 | #define consolidate_update_cs_5_init(NAME, BASE, INDEX, RES, EST, SIZE) \ 2 | table NAME##_add_base_table { \ 3 | actions { \ 4 | NAME##_add_base_table_act; \ 5 | } \ 6 | default_action: NAME##_add_base_table_act; \ 7 | } \ 8 | action NAME##_add_base_table_act () { \ 9 | add_to_field(INDEX, BASE); \ 10 | } \ 11 | register NAME##_register { \ 12 | width: 32; \ 13 | instance_count: SIZE; \ 14 | } \ 15 | blackbox stateful_alu NAME##_salu { \ 16 | reg: NAME##_register; \ 17 | condition_lo: RES > 0; \ 18 | update_lo_1_predicate: condition_lo; /* if (res == 0) */ \ 19 | update_lo_1_value : register_lo + 1; \ 20 | update_lo_2_predicate: not condition_lo; /* else */ \ 21 | update_lo_2_value : register_lo - 1; \ 22 | condition_hi: RES > 0; \ 23 | update_hi_1_predicate: condition_hi; /* if */ \ 24 | update_hi_1_value : register_lo + 1; \ 25 | update_hi_2_predicate: not condition_hi; /* else */ \ 26 | update_hi_2_value : ~register_lo; \ 27 | output_value: alu_hi; \ 28 | output_dst: EST; \ 29 | } \ 30 | table NAME##_update_table { \ 31 | actions { \ 32 | NAME##_update_table_act; \ 33 | } \ 34 | default_action: NAME##_update_table_act; \ 35 | } \ 36 | action NAME##_update_table_act () { \ 37 | NAME##_salu.execute_stateful_alu(INDEX); \ 38 | } 39 | 40 | #define consolidate_update_cs_5_call(NAME) \ 41 | apply(NAME##_add_base_table); \ 42 | apply(NAME##_update_table); 43 | 44 | -------------------------------------------------------------------------------- /p4_14/API/API_O6_flowkey.p4: -------------------------------------------------------------------------------- 1 | 2 | #define heavy_flowkey_storage_step1_5_init(NAME, E1, E2, E3, E4, E5, COMP1, COMP2, COMP3, COMP4, COMP5, THRESHOLD) \ 3 | table NAME##_subtract_table { \ 4 | actions { \ 5 | NAME##_subtract_table_act; \ 6 | } \ 7 | default_action: NAME##_subtract_table_act; \ 8 | } \ 9 | action NAME##_subtract_table_act () { \ 10 | subtract_from_field(E1, THRESHOLD); \ 11 | subtract_from_field(E2, THRESHOLD); \ 12 | subtract_from_field(E3, THRESHOLD); \ 13 | subtract_from_field(E4, THRESHOLD); \ 14 | subtract_from_field(E5, THRESHOLD); \ 15 | } \ 16 | table NAME##_shift_table { \ 17 | actions { \ 18 | NAME##_shift_table_act; \ 19 | } \ 20 | default_action: NAME##_shift_table_act; \ 21 | } \ 22 | action NAME##_shift_table_act () { \ 23 | shift_right(COMP1, E1, 31); \ 24 | shift_right(COMP2, E2, 31); \ 25 | shift_right(COMP3, E3, 31); \ 26 | shift_right(COMP4, E4, 31); \ 27 | shift_right(COMP5, E5, 31); \ 28 | } 29 | 30 | #define heavy_flowkey_storage_step1_5_call(NAME) \ 31 | apply(NAME##_subtract_table); \ 32 | apply(NAME##_shift_table); 33 | 34 | #define heavy_flowkey_storage_step2_5_init(NAME, C1, C2, C3, C4, C5, ABOVE_THRESHOLD, KEY_FIELDS, KEY, POLY_PARAM, HASH_TABLE_SIZE, HASH_ENTRY, MATCH_HIT) \ 35 | field_list_calculation NAME##_hash_func { \ 36 | input { \ 37 | KEY_FIELDS; \ 38 | } \ 39 | algorithm : poly_##POLY_PARAM##_init_0x00000000_xout_0xffffffff; \ 40 | output_width : 14; \ 41 | } \ 42 | register NAME##_hash_table_register { \ 43 | width: 32; \ 44 | instance_count: HASH_TABLE_SIZE; \ 45 | } \ 46 | blackbox stateful_alu NAME##_blackbox { \ 47 | reg: NAME##_hash_table_register; \ 48 | condition_lo: register_lo == 0; \ 49 | update_lo_1_predicate: condition_lo; \ 50 | update_lo_1_value : KEY; \ 51 | update_lo_2_predicate: not condition_lo; /* else */ \ 52 | update_lo_2_value : register_lo; \ 53 | update_hi_1_predicate: condition_lo; /* if */ \ 54 | update_hi_1_value : 0; \ 55 | update_hi_2_predicate: not condition_lo; /* else */ \ 56 | update_hi_2_value : register_lo; \ 57 | output_value: alu_hi; \ 58 | output_dst: HASH_ENTRY; \ 59 | } \ 60 | table NAME##_sum_table { \ 61 | reads { \ 62 | C1: exact; \ 63 | C2: exact; \ 64 | C3: exact; \ 65 | C4: exact; \ 66 | C5: exact; \ 67 | } \ 68 | actions { \ 69 | NAME##_sum_miss; \ 70 | NAME##_sum_hit; \ 71 | } \ 72 | default_action: NAME##_sum_miss; \ 73 | size: 32; \ 74 | } \ 75 | action NAME##_sum_miss() { \ 76 | modify_field(ABOVE_THRESHOLD, 0); \ 77 | } \ 78 | action NAME##_sum_hit() { \ 79 | modify_field(ABOVE_THRESHOLD, 1); \ 80 | NAME##_blackbox.execute_stateful_alu_from_hash(NAME##_hash_func); \ 81 | } \ 82 | table NAME##_match_table { \ 83 | reads { \ 84 | KEY: exact; \ 85 | } \ 86 | actions { \ 87 | NAME##_match_miss; \ 88 | NAME##_match_hit; \ 89 | } \ 90 | default_action: NAME##_match_miss; \ 91 | size : 10000; \ 92 | } \ 93 | action NAME##_match_miss() { \ 94 | modify_field(MATCH_HIT, 0); \ 95 | } \ 96 | action NAME##_match_hit() { \ 97 | modify_field(MATCH_HIT, 1); \ 98 | } 99 | 100 | // if MATCH_HIT == 0 -> send to CPU 101 | 102 | 103 | #define heavy_flowkey_storage_step2_5_call(NAME, ABOVE_THRESHOLD, HASH_ENTRY, KEY) \ 104 | apply(NAME##_sum_table); \ 105 | if (HASH_ENTRY != 0) { \ 106 | if(HASH_ENTRY != KEY) { \ 107 | apply(NAME##_match_table); \ 108 | } \ 109 | } 110 | 111 | -------------------------------------------------------------------------------- /p4_14/API/API_common.p4: -------------------------------------------------------------------------------- 1 | #define hash_init(NAME, KEY_FIELDS, POLY_PARAM, DST, MASK) \ 2 | field_list_calculation NAME##_hash_func { \ 3 | input { \ 4 | KEY_FIELDS; \ 5 | } \ 6 | algorithm : poly_##POLY_PARAM##_init_0x00000000_xout_0xffffffff; \ 7 | output_width : 32; \ 8 | } \ 9 | table NAME##_compute_hash { \ 10 | actions { \ 11 | NAME##_compute_hash_act; \ 12 | } \ 13 | default_action: NAME##_compute_hash_act; \ 14 | } \ 15 | action NAME##_compute_hash_act () { \ 16 | modify_field_with_hash_based_offset(DST, 0x0, NAME##_hash_func, MASK); \ 17 | } 18 | #define hash_call(NAME) \ 19 | apply(NAME##_compute_hash); 20 | -------------------------------------------------------------------------------- /p4_14/API/API_threshold.p4: -------------------------------------------------------------------------------- 1 | #define TH_TABLE(THRESHOLD) \ 2 | action th_table_act (threshold) { \ 3 | modify_field(THRESHOLD, threshold); \ 4 | } \ 5 | table th_table { \ 6 | actions { \ 7 | th_table_act; \ 8 | } \ 9 | } 10 | 11 | #define TH_BASE_TABLE(THRESHOLD, BASE) \ 12 | action th_table_act (threshold, base) { \ 13 | modify_field(THRESHOLD, threshold); \ 14 | modify_field(BASE, base); \ 15 | } \ 16 | table th_table { \ 17 | actions { \ 18 | th_table_act; \ 19 | } \ 20 | } 21 | -------------------------------------------------------------------------------- /p4_14/common_p4/headers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _HEADER_ 2 | #define _HEADER_ 3 | 4 | header_type ethernet_t { 5 | fields { 6 | dstAddr: 48; 7 | srcAddr: 48; 8 | etherType: 16; 9 | } 10 | } 11 | header ethernet_t ethernet; 12 | 13 | header_type ipv4_t { 14 | fields { 15 | version: 4; 16 | ihl: 4; 17 | diffserv: 8; 18 | totalLen: 16; 19 | identification: 16; 20 | flags: 3; 21 | fragOffset: 13; 22 | ttl: 8; 23 | protocol: 8; 24 | hdrChecksum: 16; 25 | srcAddr: 32; 26 | dstAddr: 32; 27 | } 28 | } 29 | header ipv4_t ipv4; 30 | 31 | header_type tcp_t { 32 | fields { 33 | srcPort: 16; 34 | dstPort: 16; 35 | seqNo: 32; 36 | ackNo: 32; 37 | dataOffset: 4; 38 | res: 3; 39 | ecn: 3; 40 | ctrl: 6; 41 | window: 16; 42 | checksum: 16; 43 | urgentPtr: 16; 44 | } 45 | } 46 | header tcp_t tcp; 47 | 48 | header_type udp_t { 49 | fields { 50 | srcPort: 16; 51 | dstPort: 16; 52 | pkt_length: 16; 53 | checksum: 16; 54 | } 55 | } 56 | header udp_t udp; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /p4_14/common_p4/parsers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _PARSER_ 2 | #define _PARSER_ 3 | 4 | #include "headers.p4" 5 | 6 | parser start { 7 | return parse_ethernet; 8 | } 9 | 10 | parser parse_ethernet { 11 | extract (ethernet); 12 | return select (latest.etherType) { 13 | 0x0800: parse_ipv4; 14 | default: ingress; 15 | } 16 | } 17 | 18 | parser parse_ipv4 { 19 | extract (ipv4); 20 | return select (latest.protocol) { 21 | 6: parse_tcp; 22 | 17: parse_udp; 23 | default: ingress; 24 | } 25 | } 26 | 27 | field_list ipv4_field_list { 28 | ipv4.version; 29 | ipv4.ihl; 30 | ipv4.diffserv; 31 | ipv4.totalLen; 32 | ipv4.identification; 33 | ipv4.flags; 34 | ipv4.fragOffset; 35 | ipv4.ttl; 36 | ipv4.protocol; 37 | ipv4.srcAddr; 38 | ipv4.dstAddr; 39 | } 40 | 41 | field_list_calculation ipv4_chksum_calc { 42 | input { 43 | ipv4_field_list; 44 | } 45 | algorithm: csum16; 46 | output_width: 16; 47 | } 48 | 49 | calculated_field ipv4.hdrChecksum { 50 | update ipv4_chksum_calc; 51 | } 52 | 53 | parser parse_tcp { 54 | extract (tcp); 55 | return ingress; 56 | } 57 | 58 | parser parse_udp { 59 | extract (udp); 60 | return ingress; 61 | } 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /p4_14/compile.sh: -------------------------------------------------------------------------------- 1 | CURRENT=`pwd` 2 | 3 | API=$CURRENT/API 4 | common_p4=$CURRENT/common_p4 5 | 6 | $script_home/p4_build.sh $CURRENT/countsketch/p414_countsketch.p4 \ 7 | -- P4_NAME="p414_countsketch" \ 8 | P4FLAGS="--no-dead-code-elimination" \ 9 | P4PPFLAGS="-I ${API} -I ${common_p4}" 10 | 11 | $script_home/p4_build.sh $CURRENT/countmin/p414_countmin.p4 \ 12 | -- P4_NAME="p414_countmin" \ 13 | P4FLAGS="--no-dead-code-elimination" \ 14 | P4PPFLAGS="-I ${API} -I ${common_p4}" 15 | 16 | $script_home/p4_build.sh $CURRENT/hll/p414_hll.p4 \ 17 | -- P4_NAME="p414_hll" \ 18 | P4FLAGS="--no-dead-code-elimination" \ 19 | P4PPFLAGS="-I ${API} -I ${common_p4}" 20 | 21 | $script_home/p4_build.sh $CURRENT/univmon/p414_univmon.p4 \ 22 | -- P4_NAME="p414_univmon" \ 23 | P4FLAGS="--no-dead-code-elimination" \ 24 | P4PPFLAGS="-I ${API} -I ${common_p4}" 25 | -------------------------------------------------------------------------------- /p4_14/countmin/p414_countmin.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "headers.p4" 7 | #include "parsers.p4" 8 | 9 | #include "API_common.p4" 10 | #include "API_O1_hash.p4" 11 | #include "API_O3_tcam.p4" 12 | #include "API_O6_flowkey.p4" 13 | #include "API_threshold.p4" 14 | 15 | field_list key_fields { 16 | ipv4.srcAddr; 17 | } 18 | 19 | header_type md_t { 20 | fields { 21 | res_1: 1; 22 | res_2: 1; 23 | res_3: 1; 24 | res_4: 1; 25 | res_5: 1; 26 | index_1: 16; 27 | index_2: 16; 28 | index_3: 16; 29 | index_4: 16; 30 | index_5: 16; 31 | est_1: 32; 32 | est_2: 32; 33 | est_3: 32; 34 | est_4: 32; 35 | est_5: 32; 36 | threshold: 16; 37 | above_threshold: 1; 38 | hash_entry: 32; 39 | hash_hit: 1; 40 | match_hit: 1; 41 | } 42 | } 43 | metadata md_t md; 44 | 45 | #define WIDTH_BITLEN 11 46 | #define WIDTH 2048 47 | 48 | #define ROW_SKETCH(R) \ 49 | register register_##R { \ 50 | width: 32; \ 51 | instance_count: WIDTH; \ 52 | } \ 53 | blackbox stateful_alu blackbox_##R { \ 54 | reg: register_##R; \ 55 | update_lo_1_value : register_lo + 1; \ 56 | update_hi_1_value : 1+register_lo; \ 57 | output_value: alu_hi; \ 58 | output_dst: md.est_##R; \ 59 | } \ 60 | table sketching_##R##_table { \ 61 | actions { \ 62 | sketching_##R##_act; \ 63 | } \ 64 | default_action: sketching_##R##_act; \ 65 | } \ 66 | action sketching_##R##_act () { \ 67 | blackbox_##R.execute_stateful_alu_from_hash(cs_index_hash_func_##R); \ 68 | } 69 | 70 | field_list_calculation cs_index_hash_func_1 { 71 | input { 72 | key_fields; 73 | } 74 | algorithm : poly_0x30243f0b_init_0x00000000_xout_0ffffffff; 75 | output_width : WIDTH_BITLEN; 76 | } 77 | 78 | field_list_calculation cs_index_hash_func_2 { 79 | input { 80 | key_fields; 81 | } 82 | algorithm : poly_0x0f79f523_init_0x00000000_xout_0ffffffff; 83 | output_width : WIDTH_BITLEN; 84 | } 85 | 86 | field_list_calculation cs_index_hash_func_3 { 87 | input { 88 | key_fields; 89 | } 90 | algorithm : poly_0x6b8cb0c5_init_0x00000000_xout_0ffffffff; 91 | output_width : WIDTH_BITLEN; 92 | } 93 | 94 | field_list_calculation cs_index_hash_func_4 { 95 | input { 96 | key_fields; 97 | } 98 | algorithm : poly_0x00390fc3_init_0x00000000_xout_0ffffffff; 99 | output_width : WIDTH_BITLEN; 100 | } 101 | 102 | field_list_calculation cs_index_hash_func_5 { 103 | input { 104 | key_fields; 105 | } 106 | algorithm : poly_0x298ac671_init_0x00000000_xout_0ffffffff; 107 | output_width : WIDTH_BITLEN; 108 | } 109 | 110 | TH_TABLE(md.threshold) 111 | 112 | ROW_SKETCH(1) 113 | ROW_SKETCH(2) 114 | ROW_SKETCH(3) 115 | ROW_SKETCH(4) 116 | ROW_SKETCH(5) 117 | 118 | heavy_flowkey_storage_step1_5_init(cm_f1, md.est_1, md.est_2, md.est_3, md.est_4, md.est_5, md.res_1, md.res_2, md.res_3, md.res_4, md.res_5, md.threshold) 119 | heavy_flowkey_storage_step2_5_init(cm_f2, md.res_1, md.res_2, md.res_3, md.res_4, md.res_5, md.above_threshold, key_fields, ipv4.srcAddr, 0x11e12a719, 16384, md.hash_entry, md.match_hit) 120 | 121 | control ingress { 122 | apply(th_table); 123 | 124 | apply(sketching_1_table); 125 | apply(sketching_2_table); 126 | apply(sketching_3_table); 127 | apply(sketching_4_table); 128 | apply(sketching_5_table); 129 | 130 | heavy_flowkey_storage_step1_5_call(cm_f1) 131 | heavy_flowkey_storage_step2_5_call(cm_f2, md.above_threshold, md.hash_entry, ipv4.srcAddr) 132 | } 133 | 134 | control egress { 135 | 136 | } -------------------------------------------------------------------------------- /p4_14/countsketch/p414_countsketch.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "headers.p4" 7 | #include "parsers.p4" 8 | 9 | #include "API_common.p4" 10 | #include "API_O1_hash.p4" 11 | #include "API_O3_tcam.p4" 12 | #include "API_O6_flowkey.p4" 13 | #include "API_threshold.p4" 14 | 15 | field_list key_fields { 16 | ipv4.srcAddr; 17 | } 18 | 19 | header_type md_t { 20 | fields { 21 | temp:5; 22 | res_1: 1; 23 | res_2: 1; 24 | res_3: 1; 25 | res_4: 1; 26 | res_5: 1; 27 | index_1: 16; 28 | index_2: 16; 29 | index_3: 16; 30 | index_4: 16; 31 | index_5: 16; 32 | est_1: 32; 33 | est_2: 32; 34 | est_3: 32; 35 | est_4: 32; 36 | est_5: 32; 37 | threshold: 16; 38 | above_threshold: 1; 39 | hash_entry: 32; 40 | hash_hit: 1; 41 | match_hit: 1; 42 | } 43 | } 44 | metadata md_t md; 45 | 46 | #define WIDTH_BITLEN 11 47 | #define WIDTH 2048 48 | 49 | #define ROW_SKETCH(R) \ 50 | register register_##R { \ 51 | width: 32; \ 52 | instance_count: WIDTH; \ 53 | } \ 54 | blackbox stateful_alu blackbox_##R { \ 55 | reg: register_##R; \ 56 | condition_lo: md.res_##R > 0; \ 57 | update_lo_1_predicate: condition_lo; \ 58 | update_lo_1_value : register_lo + 1; \ 59 | update_lo_2_predicate: not condition_lo; \ 60 | update_lo_2_value : register_lo - 1; \ 61 | condition_hi: md.res_##R > 0; \ 62 | update_hi_1_predicate: condition_hi; \ 63 | update_hi_1_value : 1+register_lo; \ 64 | update_hi_2_predicate: not condition_hi; \ 65 | update_hi_2_value : ~register_lo; \ 66 | output_value: alu_hi; \ 67 | output_dst: md.est_##R; \ 68 | } \ 69 | table sketching_##R##_table { \ 70 | actions { \ 71 | sketching_##R##_act; \ 72 | } \ 73 | default_action: sketching_##R##_act; \ 74 | } \ 75 | action sketching_##R##_act () { \ 76 | blackbox_##R.execute_stateful_alu_from_hash(cs_index_hash_func_##R); \ 77 | } 78 | 79 | field_list_calculation cs_index_hash_func_1 { 80 | input { 81 | key_fields; 82 | } 83 | algorithm : poly_0x30243f0b_init_0x00000000_xout_0ffffffff; 84 | output_width : WIDTH_BITLEN; 85 | } 86 | 87 | field_list_calculation cs_index_hash_func_2 { 88 | input { 89 | key_fields; 90 | } 91 | algorithm : poly_0x0f79f523_init_0x00000000_xout_0ffffffff; 92 | output_width : WIDTH_BITLEN; 93 | } 94 | 95 | field_list_calculation cs_index_hash_func_3 { 96 | input { 97 | key_fields; 98 | } 99 | algorithm : poly_0x6b8cb0c5_init_0x00000000_xout_0ffffffff; 100 | output_width : WIDTH_BITLEN; 101 | } 102 | 103 | field_list_calculation cs_index_hash_func_4 { 104 | input { 105 | key_fields; 106 | } 107 | algorithm : poly_0x00390fc3_init_0x00000000_xout_0ffffffff; 108 | output_width : WIDTH_BITLEN; 109 | } 110 | 111 | field_list_calculation cs_index_hash_func_5 { 112 | input { 113 | key_fields; 114 | } 115 | algorithm : poly_0x298ac671_init_0x00000000_xout_0ffffffff; 116 | output_width : WIDTH_BITLEN; 117 | } 118 | 119 | TH_TABLE(md.threshold) 120 | hash_consolidate_and_split_5_init(cs_group, key_fields, 0x11e12a717, md.temp, 32, md.res_1, md.res_2, md.res_3, md.res_4, md.res_5, 1, 1, 1, 1, 1, 2, 3, 4) 121 | 122 | ROW_SKETCH(1) 123 | ROW_SKETCH(2) 124 | ROW_SKETCH(3) 125 | ROW_SKETCH(4) 126 | ROW_SKETCH(5) 127 | 128 | heavy_flowkey_storage_step1_5_init(cs_f1, md.est_1, md.est_2, md.est_3, md.est_4, md.est_5, md.res_1, md.res_2, md.res_3, md.res_4, md.res_5, md.threshold) 129 | heavy_flowkey_storage_step2_5_init(cs_f2, md.res_1, md.res_2, md.res_3, md.res_4, md.res_5, md.above_threshold, key_fields, ipv4.srcAddr, 0x11e12a719, 16384, md.hash_entry, md.match_hit) 130 | 131 | control ingress { 132 | apply(th_table); 133 | hash_consolidate_and_split_5_call(cs_group) 134 | 135 | apply(sketching_1_table); 136 | apply(sketching_2_table); 137 | apply(sketching_3_table); 138 | apply(sketching_4_table); 139 | apply(sketching_5_table); 140 | 141 | heavy_flowkey_storage_step1_5_call(cs_f1) 142 | heavy_flowkey_storage_step2_5_call(cs_f2, md.above_threshold, md.hash_entry, ipv4.srcAddr) 143 | } 144 | 145 | control egress { 146 | 147 | } -------------------------------------------------------------------------------- /p4_14/hll/p414_hll.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "headers.p4" 7 | #include "parsers.p4" 8 | 9 | #include "API_common.p4" 10 | #include "API_O3_tcam.p4" 11 | 12 | field_list key_fields { 13 | ipv4.srcAddr; 14 | } 15 | 16 | header_type md_t { 17 | fields { 18 | sampling_hash_value:32; 19 | level:32; 20 | index:16; 21 | } 22 | } 23 | metadata md_t md; 24 | 25 | hash_init(hll_hash, key_fields, 0x1798f10d1, md.sampling_hash_value, 4294967296) // 2^32 = 4294967296 26 | lpm_optimization_init(hll_tcam, md.sampling_hash_value, md.level) 27 | 28 | register hll_reg { 29 | width: 32; 30 | instance_count: 2048; 31 | } 32 | blackbox stateful_alu hll_blackbox { 33 | reg: hll_reg; 34 | condition_lo: md.level > register_lo; 35 | update_lo_1_predicate: condition_lo; 36 | update_lo_1_value : md.level; 37 | } 38 | table sketching_table { 39 | actions { 40 | sketching_act; 41 | } 42 | default_action: sketching_act; 43 | } 44 | field_list_calculation hll_hash_func { 45 | input { 46 | key_fields; 47 | } 48 | algorithm : poly_0x11e12a717_init_0x00000000_xout_0ffffffff; 49 | output_width : 11; 50 | } 51 | action sketching_act () { 52 | hll_blackbox.execute_stateful_alu_from_hash(hll_hash_func); 53 | } 54 | 55 | control ingress { 56 | hash_call(hll_hash) 57 | lpm_optimization_call(hll_tcam) 58 | apply(sketching_table); 59 | } 60 | 61 | control egress { 62 | 63 | } 64 | -------------------------------------------------------------------------------- /p4_14/univmon/p414_univmon.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "headers.p4" 7 | #include "parsers.p4" 8 | 9 | #include "API_common.p4" 10 | #include "API_O1_hash.p4" 11 | #include "API_O3_tcam.p4" 12 | #include "API_O5_salu.p4" 13 | #include "API_O6_flowkey.p4" 14 | #include "API_threshold.p4" 15 | 16 | field_list key_fields { 17 | ipv4.srcAddr; 18 | } 19 | 20 | header_type md_t { 21 | fields { 22 | temp:5; 23 | sampling_hash_value: 16; 24 | level:32; 25 | base:16; 26 | threshold: 32; 27 | temp1:5; 28 | res_1: 1; 29 | res_2: 1; 30 | res_3: 1; 31 | res_4: 1; 32 | res_5: 1; 33 | index_1: 16; 34 | index_2: 16; 35 | index_3: 16; 36 | index_4: 16; 37 | index_5: 16; 38 | est_1: 32; 39 | est_2: 32; 40 | est_3: 32; 41 | est_4: 32; 42 | est_5: 32; 43 | comp_1: 1; 44 | comp_2: 1; 45 | comp_3: 1; 46 | comp_4: 1; 47 | comp_5: 1; 48 | above_threshold: 1; 49 | hash_entry: 32; 50 | hash_hit: 1; 51 | match_hit: 1; 52 | } 53 | } 54 | 55 | metadata md_t md; 56 | 57 | TH_BASE_TABLE(md.threshold, md.base) 58 | hash_init(um_sampling, key_fields, 0x1198f10d1, md.sampling_hash_value, 65536) 59 | lpm_optimization_init(um_tcam, md.sampling_hash_value, md.level) 60 | hash_consolidate_and_split_5_init(um_group, key_fields, 0x11e12a717, md.temp, 32, md.res_1, md.res_2, md.res_3, md.res_4, md.res_5, 1, 1, 1, 1, 1, 2, 3, 4) 61 | 62 | hash_init(cs_index_1, key_fields, 0x119cf8783, md.index_1, 2048) 63 | hash_init(cs_index_2, key_fields, 0x119cf8785, md.index_2, 2048) 64 | hash_init(cs_index_3, key_fields, 0x119cf8787, md.index_3, 2048) 65 | hash_init(cs_index_4, key_fields, 0x119cf8789, md.index_4, 2048) 66 | hash_init(cs_index_5, key_fields, 0x119cf878b, md.index_5, 2048) 67 | 68 | consolidate_update_cs_5_init(cs_row_1, md.base, md.index_1, md.res_1, md.est_1, 32768) 69 | consolidate_update_cs_5_init(cs_row_2, md.base, md.index_2, md.res_2, md.est_2, 32768) 70 | consolidate_update_cs_5_init(cs_row_3, md.base, md.index_3, md.res_3, md.est_3, 32768) 71 | consolidate_update_cs_5_init(cs_row_4, md.base, md.index_4, md.res_4, md.est_4, 32768) 72 | consolidate_update_cs_5_init(cs_row_5, md.base, md.index_5, md.res_5, md.est_5, 32768) 73 | 74 | heavy_flowkey_storage_step1_5_init(um_f1, md.est_1, md.est_2, md.est_3, md.est_4, md.est_5, md.comp_1, md.comp_2, md.comp_3, md.comp_4, md.comp_5, md.threshold) 75 | heavy_flowkey_storage_step2_5_init(um_f2, md.comp_1, md.comp_2, md.comp_3, md.comp_4, md.comp_5, md.above_threshold, key_fields, ipv4.srcAddr, 0x11ba201b1, 10000, md.hash_entry, md.match_hit) 76 | 77 | 78 | control ingress { 79 | apply(th_table); 80 | 81 | hash_call(um_sampling) 82 | lpm_optimization_call(um_tcam) 83 | 84 | hash_consolidate_and_split_5_call(um_group) 85 | 86 | hash_call(cs_index_1) 87 | hash_call(cs_index_2) 88 | hash_call(cs_index_3) 89 | hash_call(cs_index_4) 90 | hash_call(cs_index_5) 91 | 92 | consolidate_update_cs_5_call(cs_row_1) 93 | consolidate_update_cs_5_call(cs_row_2) 94 | consolidate_update_cs_5_call(cs_row_3) 95 | consolidate_update_cs_5_call(cs_row_4) 96 | consolidate_update_cs_5_call(cs_row_5) 97 | 98 | heavy_flowkey_storage_step1_5_call(um_f1) 99 | heavy_flowkey_storage_step2_5_call(um_f2, md.above_threshold, md.hash_entry, ipv4.srcAddr) 100 | } 101 | 102 | control egress { 103 | } 104 | -------------------------------------------------------------------------------- /p4_16/API/API_O1_hash.p4: -------------------------------------------------------------------------------- 1 | control hash_consolidate_and_split_srcip( 2 | in ipv4_addr_t srcIP, 3 | out bit<16> res_all, 4 | out bit<1> res_1, 5 | out bit<1> res_2, 6 | out bit<1> res_3, 7 | out bit<1> res_4, 8 | out bit<1> res_5)( 9 | bit<32> polynomial) 10 | { 11 | CRCPolynomial>(polynomial, 12 | true, 13 | false, 14 | false, 15 | 32w0xFFFFFFFF, 16 | 32w0xFFFFFFFF 17 | ) poly1; 18 | 19 | Hash>(HashAlgorithm_t.CUSTOM, poly1) hash; 20 | 21 | action action_hash() { 22 | res_all = hash.get({srcIP[31:0]}); 23 | } 24 | 25 | table tbl_hash { 26 | actions = { 27 | action_hash; 28 | } 29 | const default_action = action_hash(); 30 | } 31 | 32 | apply { 33 | tbl_hash.apply(); 34 | res_1 = res_all[0:0]; 35 | res_2 = res_all[1:1]; 36 | res_3 = res_all[2:2]; 37 | res_4 = res_all[3:3]; 38 | res_5 = res_all[4:4]; 39 | } 40 | } 41 | 42 | control hash_consolidate_and_split_srcip_dstip( 43 | in ipv4_addr_t srcIP, 44 | in ipv4_addr_t dstIP, 45 | out bit<16> res_all, 46 | out bit<1> res_1, 47 | out bit<1> res_2, 48 | out bit<1> res_3, 49 | out bit<1> res_4, 50 | out bit<1> res_5)( 51 | bit<32> polynomial) 52 | { 53 | CRCPolynomial>(polynomial, 54 | true, 55 | false, 56 | false, 57 | 32w0xFFFFFFFF, 58 | 32w0xFFFFFFFF 59 | ) poly1; 60 | 61 | Hash>(HashAlgorithm_t.CUSTOM, poly1) hash; 62 | 63 | action action_hash() { 64 | res_all = hash.get({srcIP[31:0], dstIP[31:0]}); 65 | } 66 | 67 | table tbl_hash { 68 | actions = { 69 | action_hash; 70 | } 71 | const default_action = action_hash(); 72 | } 73 | 74 | apply { 75 | tbl_hash.apply(); 76 | res_1 = res_all[0:0]; 77 | res_2 = res_all[1:1]; 78 | res_3 = res_all[2:2]; 79 | res_4 = res_all[3:3]; 80 | res_5 = res_all[4:4]; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /p4_16/API/API_O2_hash.p4: -------------------------------------------------------------------------------- 1 | control select_key( 2 | in bit<5> random_bits, 3 | out bit<16> ret_level, 4 | out bit<16> ret_base, 5 | out bit<32> ret_threshold, 6 | out bit<32> ret_s_mask, 7 | out bit<32> ret_d_mask, 8 | inout bit<32> masked_srcip, 9 | inout bit<32> masked_dstip, 10 | in bit<32> src_addr, 11 | in bit<32> dst_addr) 12 | { 13 | action tbl_act (bit<16> level, bit<16> base, bit<32> threshold, bit<32> s_mask, bit<32> d_mask) { 14 | ret_level = level; 15 | ret_base = base; 16 | ret_threshold = threshold; 17 | ret_s_mask = s_mask; 18 | ret_d_mask = d_mask; 19 | masked_srcip = src_addr & s_mask; 20 | masked_dstip = dst_addr & d_mask; 21 | } 22 | 23 | table tbl_select_level { 24 | key = { 25 | random_bits : exact; 26 | } 27 | actions = { 28 | tbl_act; 29 | } 30 | // const default_action = tbl_act; 31 | } 32 | 33 | apply { 34 | tbl_select_level.apply(); 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /p4_16/API/API_O3_tcam.p4: -------------------------------------------------------------------------------- 1 | control lpm_optimization_32( 2 | in bit<32> sampling_hash, 3 | out bit<32> ret_level) 4 | { 5 | action tbl_act (bit<32> level) { 6 | ret_level = level; 7 | } 8 | 9 | table tbl_select_level { 10 | key = { 11 | sampling_hash : lpm; 12 | } 13 | actions = { 14 | tbl_act; 15 | } 16 | // const default_action = tbl_act; 17 | } 18 | 19 | apply { 20 | tbl_select_level.apply(); 21 | } 22 | } 23 | 24 | control lpm_optimization_mrb( 25 | in bit<15> sampling_hash, 26 | out bit<16> ret_level) 27 | { 28 | action tbl_act (bit<16> level) { 29 | ret_level = level; 30 | } 31 | 32 | table tbl_select_level { 33 | key = { 34 | sampling_hash : lpm; 35 | } 36 | actions = { 37 | tbl_act; 38 | } 39 | // const default_action = tbl_act; 40 | } 41 | 42 | apply { 43 | tbl_select_level.apply(); 44 | } 45 | } 46 | 47 | control lpm_optimization( 48 | in bit<16> sampling_hash, 49 | out bit<16> ret_level, 50 | out bit<16> ret_base, 51 | out bit<32> ret_threshold) 52 | { 53 | action tbl_act (bit<16> level, bit<16> base, bit<32> threshold) { 54 | ret_level = level; 55 | ret_base = base; 56 | ret_threshold = threshold; 57 | } 58 | 59 | table tbl_select_level { 60 | key = { 61 | sampling_hash : lpm; 62 | } 63 | actions = { 64 | tbl_act; 65 | } 66 | // const default_action = tbl_act; 67 | } 68 | 69 | apply { 70 | tbl_select_level.apply(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /p4_16/API/API_O5_salu.p4: -------------------------------------------------------------------------------- 1 | control consolidate_update_univmon( 2 | in bit<16> index, 3 | in bit<1> res, 4 | inout bit<16> level, 5 | inout bit<16> base, 6 | inout bit<16> mem_index, 7 | out bit<32> est) 8 | { 9 | 10 | Register, bit<16>>(32768) cs_table; 11 | 12 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 13 | void apply(inout bit<32> register_data, out bit<32> result) { 14 | if (res == 0) { 15 | register_data = register_data - 1; 16 | } 17 | else { 18 | register_data = register_data + 1; 19 | } 20 | result = register_data; 21 | } 22 | }; 23 | action shift_action() { 24 | base = (level << 11); 25 | } 26 | action add_action() { 27 | mem_index = index+base; 28 | } 29 | apply { 30 | shift_action(); 31 | add_action(); 32 | est = cs_action.execute(mem_index); 33 | if (res == 0) { 34 | est = -est; 35 | } 36 | } 37 | } 38 | 39 | control consolidate_update_rhhh( 40 | in bit<16> index, 41 | in bit<1> res, 42 | inout bit<16> level, 43 | inout bit<16> base, 44 | inout bit<16> mem_index, 45 | out bit<32> est) 46 | { 47 | 48 | Register, bit<16>>(51200) cs_table; 49 | 50 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 51 | void apply(inout bit<32> register_data, out bit<32> result) { 52 | if (res == 0) { 53 | register_data = register_data - 1; 54 | } 55 | else { 56 | register_data = register_data + 1; 57 | } 58 | result = register_data; 59 | } 60 | }; 61 | action shift_action() { 62 | base = (level << 11); 63 | } 64 | action add_action() { 65 | mem_index = index+base; 66 | } 67 | apply { 68 | shift_action(); 69 | add_action(); 70 | est = cs_action.execute(mem_index); 71 | if (res == 0) { 72 | est = -est; 73 | } 74 | } 75 | } 76 | 77 | control consolidate_update_mrac( 78 | in bit<16> index, 79 | inout bit<16> level, 80 | inout bit<16> base, 81 | inout bit<16> mem_index) 82 | { 83 | Register, bit<16>>(24576) cs_table; 84 | 85 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 86 | void apply(inout bit<32> register_data, out bit<32> result) { 87 | register_data = register_data + 1; 88 | } 89 | }; 90 | action shift_action() { 91 | base = (level << 11); 92 | } 93 | action add_action() { 94 | mem_index = base + index; 95 | } 96 | apply { 97 | shift_action(); 98 | add_action(); 99 | cs_action.execute(mem_index); 100 | } 101 | } 102 | 103 | control consolidate_update_mrb( 104 | in bit<16> index, 105 | inout bit<16> level, 106 | inout bit<16> base, 107 | inout bit<16> mem_index) 108 | { 109 | Register, bit<16>>(65536) cs_table; 110 | 111 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 112 | void apply(inout bit<1> register_data, out bit<32> result) { 113 | register_data = 1; 114 | } 115 | }; 116 | 117 | action shift_action() { 118 | base = (level << 12); 119 | } 120 | action add_action() { 121 | mem_index = index+base; 122 | } 123 | apply { 124 | shift_action(); 125 | add_action(); 126 | cs_action.execute(mem_index); 127 | } 128 | } 129 | 130 | control consolidate_update_pcsa( 131 | in bit<16> index, 132 | in bit<16> level, 133 | inout bit<16> base, 134 | inout bit<16> mem_index) 135 | { 136 | Register, bit<16>>(1024) cs_table; 137 | 138 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 139 | void apply(inout bit<1> register_data, out bit<32> result) { 140 | register_data = 1; 141 | } 142 | }; 143 | 144 | action shift_action() { 145 | base = (index << 5); 146 | } 147 | 148 | action add_action() { 149 | mem_index = base + level; 150 | } 151 | 152 | apply { 153 | shift_action(); 154 | add_action(); 155 | cs_action.execute(mem_index); 156 | } 157 | } 158 | 159 | control consolidate_update_ss( 160 | in bit<32> index, 161 | inout bit<32> hash, 162 | inout bit<32> level, 163 | inout bit<32> base_1, 164 | inout bit<32> base_2, 165 | inout bit<32> mem_index) 166 | { 167 | Register, bit<32>>(262144) bitmap; 168 | 169 | RegisterAction, bit<32>, bit<32>>(bitmap) bitmap_action = { 170 | void apply(inout bit<1> register_data, out bit<32> result) { 171 | register_data = 1; 172 | } 173 | }; 174 | 175 | action shift_action() { 176 | base_1 = (index << 7); 177 | base_2 = (level << 5); 178 | } 179 | 180 | action add_action() { 181 | mem_index = base_1 + base_2; 182 | } 183 | action add_action_2() { 184 | mem_index = mem_index + (bit<32>)hash[4:0]; 185 | } 186 | 187 | apply { 188 | shift_action(); 189 | add_action(); 190 | add_action_2(); 191 | 192 | bitmap_action.execute(mem_index); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /p4_16/API/API_O6_flowkey.p4: -------------------------------------------------------------------------------- 1 | #define ETHERTYPE_TO_CPU 0xBF01 2 | 3 | const PortId_t CPU_PORT = 192; // tofino with pipeline 2 4 | // const PortId_t CPU_PORT = 320; // tofino with pipeline 4 5 | 6 | control heavy_flowkey_storage ( 7 | inout header_t hdr, 8 | inout metadata_t ig_md, 9 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 10 | { 11 | // threshold table 12 | action tbl_threshold_above_action() { 13 | ig_md.above_threshold = 1; 14 | } 15 | 16 | table tbl_threshold { 17 | key = { 18 | ig_md.c_1 : exact; 19 | ig_md.c_2 : exact; 20 | ig_md.c_3 : exact; 21 | ig_md.c_4 : exact; 22 | ig_md.c_5 : exact; 23 | } 24 | actions = { 25 | tbl_threshold_above_action; 26 | } 27 | } 28 | 29 | // hash table 30 | // bit<32> : entry size 31 | // bit<16> : index size 32 | // 65536 : SRAM size 33 | 34 | Register, bit<16>>(32w65536) flowkey_hash_table; 35 | 36 | RegisterAction, bit<16>, bit<32>>(flowkey_hash_table) flowkey_action = { 37 | 38 | // Register, bit<2>>(32w4) flowkey_hash_table; 39 | 40 | // RegisterAction, bit<2>, bit<32>>(flowkey_hash_table) flowkey_action = { 41 | void apply(inout bit<32> register_data, out bit<32> result) { 42 | if (register_data == 0) { 43 | register_data = hdr.ipv4.src_addr; 44 | result = 0; 45 | } 46 | else { 47 | result = register_data; 48 | } 49 | } 50 | }; 51 | 52 | 53 | // exact table 54 | action tbl_exact_match_miss() { 55 | 56 | hdr.cpu_ethernet.setValid(); 57 | hdr.cpu_ethernet.dst_addr = 0xFFFFFFFFFFFF; 58 | hdr.cpu_ethernet.src_addr = 0xAAAAAAAAAAAA; 59 | hdr.cpu_ethernet.ether_type = ETHERTYPE_TO_CPU; 60 | ig_tm_md.ucast_egress_port = CPU_PORT; 61 | } 62 | 63 | action tbl_exact_match_hit() { 64 | } 65 | 66 | table tbl_exact_match { 67 | key = { 68 | hdr.ipv4.src_addr : exact; 69 | } 70 | actions = { 71 | tbl_exact_match_miss; 72 | tbl_exact_match_hit; 73 | } 74 | const default_action = tbl_exact_match_miss; 75 | size = 65536; 76 | } 77 | 78 | apply { 79 | 80 | ig_md.est_1 = ig_md.est_1 - ig_md.threshold; 81 | ig_md.est_2 = ig_md.est_2 - ig_md.threshold; 82 | ig_md.est_3 = ig_md.est_3 - ig_md.threshold; 83 | ig_md.est_4 = ig_md.est_4 - ig_md.threshold; 84 | ig_md.est_5 = ig_md.est_5 - ig_md.threshold; 85 | 86 | ig_md.c_1 = (bit<1>) ig_md.est_1 >> 31; 87 | ig_md.c_2 = (bit<1>) ig_md.est_2 >> 31; 88 | ig_md.c_3 = (bit<1>) ig_md.est_3 >> 31; 89 | ig_md.c_4 = (bit<1>) ig_md.est_4 >> 31; 90 | ig_md.c_5 = (bit<1>) ig_md.est_5 >> 31; 91 | 92 | tbl_threshold.apply(); 93 | 94 | if(ig_md.above_threshold == 1) { 95 | // bit<32> hash_entry = flowkey_action.execute(ig_md.res_all[1:0]); 96 | bit<32> hash_entry = flowkey_action.execute(ig_md.res_all[15:0]); 97 | 98 | if (hash_entry != 0) { 99 | if (hash_entry != hdr.ipv4.src_addr) { 100 | tbl_exact_match.apply(); 101 | } 102 | } 103 | // alternatively, we can read flowkey from flowkey_hash_table in the control plane 104 | // else { 105 | // tbl_exact_match_miss(); 106 | // } 107 | } 108 | } 109 | } 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /p4_16/API/API_O6_flowkey_fcm.p4: -------------------------------------------------------------------------------- 1 | #define ETHERTYPE_TO_CPU 0xBF01 2 | 3 | const PortId_t CPU_PORT = 192; // tofino with pipeline 2 4 | // const PortId_t CPU_PORT = 320; // tofino with pipeline 4 5 | 6 | control heavy_flowkey_storage ( 7 | inout header_t hdr, 8 | inout fcm_metadata_t ig_md, 9 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 10 | { 11 | // threshold table 12 | action tbl_threshold_above_action() { 13 | ig_md.above_threshold = 1; 14 | } 15 | 16 | table tbl_threshold { 17 | key = { 18 | ig_md.c_1 : exact; 19 | } 20 | actions = { 21 | tbl_threshold_above_action; 22 | } 23 | } 24 | 25 | // hash table 26 | // bit<32> : entry size 27 | // bit<16> : index size 28 | // 65536 : SRAM size 29 | 30 | Register, bit<16>>(32w65536) flowkey_hash_table; 31 | 32 | RegisterAction, bit<16>, bit<32>>(flowkey_hash_table) flowkey_action = { 33 | 34 | // Register, bit<2>>(32w4) flowkey_hash_table; 35 | 36 | // RegisterAction, bit<2>, bit<32>>(flowkey_hash_table) flowkey_action = { 37 | void apply(inout bit<32> register_data, out bit<32> result) { 38 | if (register_data == 0) { 39 | register_data = hdr.ipv4.src_addr; 40 | result = 0; 41 | } 42 | else { 43 | result = register_data; 44 | } 45 | } 46 | }; 47 | 48 | 49 | // exact table 50 | action tbl_exact_match_miss() { 51 | 52 | hdr.cpu_ethernet.setValid(); 53 | hdr.cpu_ethernet.dst_addr = 0xFFFFFFFFFFFF; 54 | hdr.cpu_ethernet.src_addr = 0xAAAAAAAAAAAA; 55 | hdr.cpu_ethernet.ether_type = ETHERTYPE_TO_CPU; 56 | ig_tm_md.ucast_egress_port = CPU_PORT; 57 | } 58 | 59 | action tbl_exact_match_hit() { 60 | } 61 | 62 | table tbl_exact_match { 63 | key = { 64 | hdr.ipv4.src_addr : exact; 65 | } 66 | actions = { 67 | tbl_exact_match_miss; 68 | tbl_exact_match_hit; 69 | } 70 | const default_action = tbl_exact_match_miss; 71 | size = 65536; 72 | } 73 | 74 | action subtract(){ 75 | ig_md.est_1 = ig_md.est_1 - ig_md.threshold; 76 | } 77 | 78 | apply { 79 | subtract(); 80 | ig_md.c_1 = (bit<1>) ig_md.est_1 >> 31; 81 | tbl_threshold.apply(); 82 | 83 | if(ig_md.above_threshold == 1) { 84 | // bit<32> hash_entry = flowkey_action.execute(ig_md.res_all[1:0]); 85 | bit<32> hash_entry = flowkey_action.execute(ig_md.result_d1[15:0]); 86 | 87 | if (hash_entry != 0) { 88 | if (hash_entry != hdr.ipv4.src_addr) { 89 | tbl_exact_match.apply(); 90 | } 91 | } 92 | else { 93 | tbl_exact_match_miss(); 94 | } 95 | } 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /p4_16/API/API_O6_flowkey_hhh.p4: -------------------------------------------------------------------------------- 1 | #define ETHERTYPE_TO_CPU 0xBF01 2 | 3 | const PortId_t CPU_PORT = 192; // tofino with pipeline 2 4 | // const PortId_t CPU_PORT = 320; // tofino with pipeline 4 5 | 6 | #define O6_TABLE_SETUP(L) \ 7 | action level_##L##_tbl_threshold_above_action() { \ 8 | ig_md.level_##L##_above_threshold = 1; \ 9 | } \ 10 | table level_##L##_tbl_threshold { \ 11 | key = { \ 12 | ig_md.level_##L##_c_1 : exact; \ 13 | ig_md.level_##L##_c_2 : exact; \ 14 | ig_md.level_##L##_c_3 : exact; \ 15 | } \ 16 | actions = { \ 17 | level_##L##_tbl_threshold_above_action; \ 18 | } \ 19 | } 20 | 21 | #define O6_APPLY_SETUP(L) \ 22 | ig_md.level_##L##_est_1 = ig_md.level_##L##_est_1 - ig_md.level_##L##_threshold; \ 23 | ig_md.level_##L##_est_2 = ig_md.level_##L##_est_2 - ig_md.level_##L##_threshold; \ 24 | ig_md.level_##L##_est_3 = ig_md.level_##L##_est_3 - ig_md.level_##L##_threshold; \ 25 | ig_md.level_##L##_c_1 = (bit<1>) ig_md.level_##L##_est_1 >> 31; \ 26 | ig_md.level_##L##_c_2 = (bit<1>) ig_md.level_##L##_est_2 >> 31; \ 27 | ig_md.level_##L##_c_3 = (bit<1>) ig_md.level_##L##_est_3 >> 31; \ 28 | level_##L##_tbl_threshold.apply(); 29 | 30 | control heavy_flowkey_storage ( 31 | inout header_t hdr, 32 | inout metadata_t ig_md, 33 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 34 | { 35 | O6_TABLE_SETUP(1) 36 | O6_TABLE_SETUP(2) 37 | O6_TABLE_SETUP(3) 38 | O6_TABLE_SETUP(4) 39 | 40 | Register, bit<16>>(32w65536) flowkey_hash_table; 41 | 42 | RegisterAction, bit<16>, bit<32>>(flowkey_hash_table) flowkey_action = { 43 | void apply(inout bit<32> register_data, out bit<32> result) { 44 | if (register_data == 0) { 45 | register_data = hdr.ipv4.src_addr; 46 | result = 0; 47 | } 48 | else { 49 | result = register_data; 50 | } 51 | } 52 | }; 53 | 54 | 55 | // exact table 56 | action tbl_exact_match_miss() { 57 | 58 | hdr.cpu_ethernet.setValid(); 59 | hdr.cpu_ethernet.dst_addr = 0xFFFFFFFFFFFF; 60 | hdr.cpu_ethernet.src_addr = 0xAAAAAAAAAAAA; 61 | hdr.cpu_ethernet.ether_type = ETHERTYPE_TO_CPU; 62 | ig_tm_md.ucast_egress_port = CPU_PORT; 63 | } 64 | 65 | action tbl_exact_match_hit() { 66 | } 67 | 68 | table tbl_exact_match { 69 | key = { 70 | hdr.ipv4.src_addr : exact; 71 | } 72 | actions = { 73 | tbl_exact_match_miss; 74 | tbl_exact_match_hit; 75 | } 76 | const default_action = tbl_exact_match_miss; 77 | size = 65536; 78 | } 79 | 80 | apply { 81 | 82 | O6_APPLY_SETUP(1) 83 | O6_APPLY_SETUP(2) 84 | O6_APPLY_SETUP(3) 85 | O6_APPLY_SETUP(4) 86 | 87 | if(ig_md.level_1_above_threshold == 1 || ig_md.level_2_above_threshold == 1 || ig_md.level_3_above_threshold == 1 || ig_md.level_4_above_threshold == 1) { 88 | bit<32> hash_entry = flowkey_action.execute(ig_md.level_1_res_all[15:0]); 89 | 90 | if (hash_entry != 0) { 91 | if (hash_entry != hdr.ipv4.src_addr) { 92 | tbl_exact_match.apply(); 93 | } 94 | } 95 | // alternatively, we can read flowkey from flowkey_hash_table in the control plane 96 | // else { 97 | // tbl_exact_match_miss(); 98 | // } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /p4_16/API/API_O6_flowkey_kary.p4: -------------------------------------------------------------------------------- 1 | #define ETHERTYPE_TO_CPU 0xBF01 2 | 3 | const PortId_t CPU_PORT = 192; // tofino with pipeline 2 4 | // const PortId_t CPU_PORT = 320; // tofino with pipeline 4 5 | 6 | control heavy_flowkey_storage ( 7 | inout header_t hdr, 8 | inout metadata_t ig_md, 9 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 10 | { 11 | // threshold table 12 | action tbl_threshold_above_action() { 13 | ig_md.above_threshold = 1; 14 | } 15 | 16 | table tbl_threshold { 17 | key = { 18 | ig_md.c_1 : exact; 19 | ig_md.c_2 : exact; 20 | ig_md.c_3 : exact; 21 | // ig_md.c_4 : exact; 22 | // ig_md.c_5 : exact; 23 | } 24 | actions = { 25 | tbl_threshold_above_action; 26 | } 27 | } 28 | 29 | // hash table 30 | // bit<32> : entry size 31 | // bit<16> : index size 32 | // 65536 : SRAM size 33 | 34 | Register, bit<16>>(32w65536) flowkey_hash_table; 35 | 36 | RegisterAction, bit<16>, bit<32>>(flowkey_hash_table) flowkey_action = { 37 | 38 | // Register, bit<2>>(32w4) flowkey_hash_table; 39 | 40 | // RegisterAction, bit<2>, bit<32>>(flowkey_hash_table) flowkey_action = { 41 | void apply(inout bit<32> register_data, out bit<32> result) { 42 | if (register_data == 0) { 43 | register_data = hdr.ipv4.src_addr; 44 | result = 0; 45 | } 46 | else { 47 | result = register_data; 48 | } 49 | } 50 | }; 51 | 52 | 53 | // exact table 54 | action tbl_exact_match_miss() { 55 | 56 | hdr.cpu_ethernet.setValid(); 57 | hdr.cpu_ethernet.dst_addr = 0xFFFFFFFFFFFF; 58 | hdr.cpu_ethernet.src_addr = 0xAAAAAAAAAAAA; 59 | hdr.cpu_ethernet.ether_type = ETHERTYPE_TO_CPU; 60 | ig_tm_md.ucast_egress_port = CPU_PORT; 61 | } 62 | 63 | action tbl_exact_match_hit() { 64 | } 65 | 66 | table tbl_exact_match { 67 | key = { 68 | hdr.ipv4.src_addr : exact; 69 | } 70 | actions = { 71 | tbl_exact_match_miss; 72 | tbl_exact_match_hit; 73 | } 74 | const default_action = tbl_exact_match_miss; 75 | size = 65536; 76 | } 77 | 78 | apply { 79 | 80 | ig_md.diff_1 = ig_md.diff_1 - ig_md.threshold; 81 | ig_md.diff_2 = ig_md.diff_2 - ig_md.threshold; 82 | ig_md.diff_3 = ig_md.diff_3 - ig_md.threshold; 83 | // ig_md.diff_4 = ig_md.diff_4 - ig_md.threshold; 84 | // ig_md.diff_5 = ig_md.diff_5 - ig_md.threshold; 85 | 86 | ig_md.c_1 = (bit<1>) ig_md.diff_1 >> 31; 87 | ig_md.c_2 = (bit<1>) ig_md.diff_2 >> 31; 88 | ig_md.c_3 = (bit<1>) ig_md.diff_3 >> 31; 89 | // ig_md.c_4 = (bit<1>) ig_md.diff_4 >> 31; 90 | // ig_md.c_5 = (bit<1>) ig_md.diff_5 >> 31; 91 | 92 | tbl_threshold.apply(); 93 | 94 | if(ig_md.above_threshold == 1) { 95 | // bit<32> hash_entry = flowkey_action.execute(ig_md.res_all[1:0]); 96 | bit<32> hash_entry = flowkey_action.execute(ig_md.res_all[15:0]); 97 | 98 | if (hash_entry != 0) { 99 | if (hash_entry != hdr.ipv4.src_addr) { 100 | tbl_exact_match.apply(); 101 | } 102 | } 103 | else { 104 | tbl_exact_match_miss(); 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /p4_16/API/API_O6_flowkey_rhhh.p4: -------------------------------------------------------------------------------- 1 | #define ETHERTYPE_TO_CPU 0xBF01 2 | 3 | const PortId_t CPU_PORT = 192; // tofino with pipeline 2 4 | // const PortId_t CPU_PORT = 320; // tofino with pipeline 4 5 | 6 | control heavy_flowkey_storage_rhhh ( 7 | inout header_t hdr, 8 | inout metadata_t ig_md, 9 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 10 | { 11 | // threshold table 12 | action tbl_threshold_above_action() { 13 | ig_md.above_threshold = 1; 14 | } 15 | 16 | table tbl_threshold { 17 | key = { 18 | ig_md.c_1 : exact; 19 | ig_md.c_2 : exact; 20 | ig_md.c_3 : exact; 21 | // ig_md.c_4 : exact; 22 | // ig_md.c_5 : exact; 23 | } 24 | actions = { 25 | tbl_threshold_above_action; 26 | } 27 | } 28 | 29 | // Register, bit<2>>(32w4) flowkey_hash_table; 30 | // RegisterAction, bit<2>, bit<32>>(flowkey_hash_table) flowkey_action = { 31 | 32 | // hash table 33 | // bit<32> : entry size 34 | // bit<16> : index size 35 | // 65536 : SRAM size 36 | 37 | Register, bit<16>>(32w65536) srcip_hash_table; 38 | RegisterAction, bit<16>, bit<32>>(srcip_hash_table) srcip_action = { 39 | void apply(inout bit<32> register_data, out bit<32> result) { 40 | if (register_data == 0) { 41 | register_data = ig_md.masked_srcip; 42 | result = 0; 43 | } 44 | else { 45 | result = register_data; 46 | } 47 | } 48 | }; 49 | 50 | Register, bit<16>>(32w65536) dstip_hash_table; 51 | RegisterAction, bit<16>, bit<32>>(dstip_hash_table) dstip_action = { 52 | void apply(inout bit<32> register_data, out bit<32> result) { 53 | if (register_data == 0) { 54 | register_data = ig_md.masked_dstip; 55 | result = 0; 56 | } 57 | else { 58 | result = register_data; 59 | } 60 | } 61 | }; 62 | 63 | Register, bit<16>>(32w65536) level_hash_table; 64 | RegisterAction, bit<16>, bit<8>>(level_hash_table) level_action = { 65 | void apply(inout bit<8> register_data, out bit<8> result) { 66 | if (register_data == 0) { 67 | register_data = (bit<8>)ig_md.level; 68 | result = 0; 69 | } 70 | else { 71 | result = register_data; 72 | } 73 | } 74 | }; 75 | 76 | // exact table 77 | action tbl_exact_match_miss() { 78 | 79 | hdr.cpu_ethernet.setValid(); 80 | hdr.cpu_ethernet.dst_addr = 0xFFFFFFFFFFFF; 81 | hdr.cpu_ethernet.src_addr = 0xAAAAAAAAAAAA; 82 | hdr.cpu_ethernet.ether_type = ETHERTYPE_TO_CPU; 83 | 84 | hdr.ipv4.src_addr = ig_md.masked_srcip; 85 | hdr.ipv4.dst_addr = ig_md.masked_dstip; 86 | hdr.ipv4.protocol = (bit<8>)ig_md.level; 87 | 88 | ig_tm_md.ucast_egress_port = CPU_PORT; 89 | } 90 | 91 | action tbl_exact_match_hit() { 92 | } 93 | 94 | table tbl_exact_match { 95 | key = { 96 | ig_md.masked_srcip : exact; 97 | ig_md.masked_dstip : exact; 98 | ig_md.level : exact; 99 | } 100 | actions = { 101 | tbl_exact_match_miss; 102 | tbl_exact_match_hit; 103 | } 104 | const default_action = tbl_exact_match_miss; 105 | size = 1024; 106 | } 107 | 108 | action subtract_threshold_values() { 109 | ig_md.est_1 = ig_md.est_1 - ig_md.threshold; 110 | ig_md.est_2 = ig_md.est_2 - ig_md.threshold; 111 | ig_md.est_3 = ig_md.est_3 - ig_md.threshold; 112 | // ig_md.est_4 = ig_md.est_4 - ig_md.threshold; 113 | // ig_md.est_5 = ig_md.est_5 - ig_md.threshold; 114 | } 115 | 116 | action shift_est_values() { 117 | ig_md.c_1 = (bit<1>) ig_md.est_1 >> 31; 118 | ig_md.c_2 = (bit<1>) ig_md.est_2 >> 31; 119 | ig_md.c_3 = (bit<1>) ig_md.est_3 >> 31; 120 | // ig_md.c_4 = (bit<1>) ig_md.est_4 >> 31; 121 | // ig_md.c_5 = (bit<1>) ig_md.est_5 >> 31; 122 | } 123 | 124 | action subtract_values() { 125 | ig_md.diff_srcip = ig_md.hash_entry_srcip - ig_md.masked_srcip; 126 | ig_md.diff_dstip = ig_md.hash_entry_dstip - ig_md.masked_dstip; 127 | ig_md.diff_level = ig_md.hash_entry_level - (bit<8>)ig_md.level; 128 | } 129 | 130 | apply { 131 | subtract_threshold_values(); 132 | shift_est_values(); 133 | tbl_threshold.apply(); 134 | 135 | if(ig_md.above_threshold == 1) { 136 | ig_md.hash_entry_srcip = srcip_action.execute(ig_md.res_all[15:0]); 137 | ig_md.hash_entry_dstip = dstip_action.execute(ig_md.res_all[15:0]); 138 | ig_md.hash_entry_level = level_action.execute(ig_md.res_all[15:0]); 139 | 140 | if (ig_md.hash_entry_level != 0) { // result 0 means there was no entry. 141 | subtract_values(); 142 | if (ig_md.diff_srcip != 0) { 143 | tbl_exact_match.apply(); 144 | } else { 145 | if (ig_md.diff_dstip != 0) { 146 | tbl_exact_match.apply(); 147 | } 148 | else { 149 | if (ig_md.diff_level != 0) { 150 | tbl_exact_match.apply(); 151 | } 152 | } 153 | } 154 | } 155 | else { 156 | tbl_exact_match_miss(); 157 | } 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /p4_16/API/API_common.p4: -------------------------------------------------------------------------------- 1 | #define PLAIN_HASH_SRCIP(TOTAL_LENGTH, HASH_LENGTH) \ 2 | control HASH_COMPUTE_SRCIP_##TOTAL_LENGTH##_##HASH_LENGTH## ( \ 3 | in ipv4_addr_t srcIP, \ 4 | out bit<##TOTAL_LENGTH##> result)( \ 5 | bit<32> polynomial) \ 6 | { \ 7 | CRCPolynomial>(polynomial, \ 8 | true, \ 9 | false, \ 10 | false, \ 11 | 32w0xFFFFFFFF, \ 12 | 32w0xFFFFFFFF \ 13 | ) poly1; \ 14 | \ 15 | Hash>(HashAlgorithm_t.CUSTOM, poly1) hash;\ 16 | \ 17 | action action_hash() { \ 18 | result = (bit<##TOTAL_LENGTH##>) hash.get({srcIP}); \ 19 | } \ 20 | \ 21 | table tbl_hash { \ 22 | actions = { \ 23 | action_hash; \ 24 | } \ 25 | const default_action = action_hash(); \ 26 | } \ 27 | \ 28 | apply { \ 29 | tbl_hash.apply(); \ 30 | } \ 31 | } 32 | 33 | PLAIN_HASH_SRCIP(12, 12) 34 | PLAIN_HASH_SRCIP(15, 15) 35 | 36 | PLAIN_HASH_SRCIP(16, 5) 37 | PLAIN_HASH_SRCIP(16, 11) 38 | PLAIN_HASH_SRCIP(16, 12) 39 | PLAIN_HASH_SRCIP(16, 16) 40 | 41 | PLAIN_HASH_SRCIP(20, 20) 42 | 43 | PLAIN_HASH_SRCIP(32, 11) 44 | PLAIN_HASH_SRCIP(32, 20) 45 | 46 | #define PLAIN_HASH_SRCIP_DSTIP(TOTAL_LENGTH, HASH_LENGTH) \ 47 | control HASH_COMPUTE_SRCIP_DSTIP_##TOTAL_LENGTH##_##HASH_LENGTH## (\ 48 | in ipv4_addr_t srcIP, \ 49 | in ipv4_addr_t dstIP, \ 50 | out bit<##TOTAL_LENGTH##> result)( \ 51 | bit<32> polynomial) \ 52 | { \ 53 | CRCPolynomial>(polynomial, \ 54 | true, \ 55 | false, \ 56 | false, \ 57 | 32w0xFFFFFFFF, \ 58 | 32w0xFFFFFFFF \ 59 | ) poly1; \ 60 | \ 61 | Hash>(HashAlgorithm_t.CUSTOM, poly1) hash;\ 62 | \ 63 | action action_hash() { \ 64 | result = (bit<##TOTAL_LENGTH##>) hash.get({srcIP[31:0], dstIP[31:0]}); \ 65 | } \ 66 | \ 67 | table tbl_hash { \ 68 | actions = { \ 69 | action_hash; \ 70 | } \ 71 | const default_action = action_hash(); \ 72 | } \ 73 | \ 74 | apply { \ 75 | tbl_hash.apply(); \ 76 | } \ 77 | } 78 | 79 | PLAIN_HASH_SRCIP_DSTIP(16, 16) 80 | PLAIN_HASH_SRCIP_DSTIP(16, 11) 81 | PLAIN_HASH_SRCIP_DSTIP(32, 32) 82 | 83 | control CS_UPDATE( 84 | in bit<32> key, 85 | in bit<1> res, 86 | out bit<32> est)( 87 | bit<32> polynomial) 88 | { 89 | CRCPolynomial>(polynomial, 90 | true, 91 | false, 92 | false, 93 | 32w0xFFFFFFFF, 94 | 32w0xFFFFFFFF 95 | ) poly1; 96 | 97 | Hash>(HashAlgorithm_t.CUSTOM, poly1) hash; 98 | 99 | Register, bit<16>>(32w4096) cs_table; 100 | 101 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 102 | void apply(inout bit<32> register_data, out bit<32> result) { 103 | if (res == 0) { 104 | register_data = register_data - 1; 105 | } 106 | else { 107 | register_data = register_data + 1; 108 | } 109 | result = register_data; 110 | } 111 | }; 112 | 113 | apply { 114 | est = cs_action.execute(hash.get({key})); 115 | if (res == 0) { 116 | est = -est; 117 | } 118 | } 119 | } 120 | 121 | control CM_UPDATE( 122 | in bit<32> key, 123 | out bit<32> est)( 124 | bit<32> polynomial) 125 | { 126 | CRCPolynomial>(polynomial, 127 | true, 128 | false, 129 | false, 130 | 32w0xFFFFFFFF, 131 | 32w0xFFFFFFFF 132 | ) poly1; 133 | 134 | Hash>(HashAlgorithm_t.CUSTOM, poly1) hash; 135 | 136 | Register, bit<16>>(32w4096) cs_table; 137 | 138 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 139 | void apply(inout bit<32> register_data, out bit<32> result) { 140 | register_data = register_data + 1; 141 | result = register_data; 142 | } 143 | }; 144 | 145 | apply { 146 | est = cs_action.execute(hash.get({key})); 147 | } 148 | } 149 | 150 | control CALC_RNG(out bit<5> random_number) 151 | { 152 | Random>() rng; 153 | action get_random() { 154 | random_number = rng.get(); 155 | } 156 | table random { 157 | actions = { get_random; } 158 | default_action = get_random(); 159 | size = 1; 160 | } 161 | apply { 162 | random.apply(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /p4_16/API/API_threshold.p4: -------------------------------------------------------------------------------- 1 | 2 | control GET_THRESHOLD( 3 | inout header_t hdr, 4 | inout metadata_t ig_md) 5 | { 6 | action tbl_get_threshold_act (bit<32> threshold) { 7 | ig_md.threshold = threshold; 8 | } 9 | table tbl_get_threshold { 10 | key = { 11 | hdr.ethernet.ether_type : exact; 12 | } 13 | actions = { 14 | tbl_get_threshold_act; 15 | } 16 | } 17 | apply { 18 | tbl_get_threshold.apply(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /p4_16/common_p4/headers.p4: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _HEADERS_ 3 | #define _HEADERS_ 4 | 5 | typedef bit<48> mac_addr_t; 6 | typedef bit<32> ipv4_addr_t; 7 | typedef bit<128> ipv6_addr_t; 8 | typedef bit<12> vlan_id_t; 9 | 10 | typedef bit<16> ether_type_t; 11 | const ether_type_t ETHERTYPE_IPV4 = 16w0x0800; 12 | const ether_type_t ETHERTYPE_ARP = 16w0x0806; 13 | const ether_type_t ETHERTYPE_IPV6 = 16w0x86dd; 14 | const ether_type_t ETHERTYPE_VLAN = 16w0x8100; 15 | 16 | typedef bit<8> ip_protocol_t; 17 | const ip_protocol_t IP_PROTOCOLS_ICMP = 1; 18 | const ip_protocol_t IP_PROTOCOLS_TCP = 6; 19 | const ip_protocol_t IP_PROTOCOLS_UDP = 17; 20 | 21 | header ethernet_h { 22 | mac_addr_t dst_addr; 23 | mac_addr_t src_addr; 24 | bit<16> ether_type; 25 | } 26 | 27 | header vlan_tag_h { 28 | bit<3> pcp; 29 | bit<1> cfi; 30 | vlan_id_t vid; 31 | bit<16> ether_type; 32 | } 33 | 34 | header mpls_h { 35 | bit<20> label; 36 | bit<3> exp; 37 | bit<1> bos; 38 | bit<8> ttl; 39 | } 40 | 41 | header ipv4_h { 42 | bit<4> version; 43 | bit<4> ihl; 44 | bit<8> diffserv; 45 | bit<16> total_len; 46 | bit<16> identification; 47 | bit<3> flags; 48 | bit<13> frag_offset; 49 | bit<8> ttl; 50 | bit<8> protocol; 51 | bit<16> hdr_checksum; 52 | ipv4_addr_t src_addr; 53 | ipv4_addr_t dst_addr; 54 | } 55 | 56 | header ipv6_h { 57 | bit<4> version; 58 | bit<8> traffic_class; 59 | bit<20> flow_label; 60 | bit<16> payload_len; 61 | bit<8> next_hdr; 62 | bit<8> hop_limit; 63 | ipv6_addr_t src_addr; 64 | ipv6_addr_t dst_addr; 65 | } 66 | 67 | header tcp_h { 68 | bit<16> src_port; 69 | bit<16> dst_port; 70 | bit<32> seq_no; 71 | bit<32> ack_no; 72 | bit<4> data_offset; 73 | bit<4> res; 74 | bit<8> flags; 75 | bit<16> window; 76 | bit<16> checksum; 77 | bit<16> urgent_ptr; 78 | } 79 | 80 | header udp_h { 81 | bit<16> src_port; 82 | bit<16> dst_port; 83 | bit<16> hdr_length; 84 | bit<16> checksum; 85 | } 86 | 87 | header icmp_h { 88 | bit<8> type_; 89 | bit<8> code; 90 | bit<16> hdr_checksum; 91 | } 92 | 93 | header arp_h { 94 | bit<16> hw_type; 95 | bit<16> proto_type; 96 | bit<8> hw_addr_len; 97 | bit<8> proto_addr_len; 98 | bit<16> opcode; 99 | } 100 | 101 | header ipv6_srh_h { 102 | bit<8> next_hdr; 103 | bit<8> hdr_ext_len; 104 | bit<8> routing_type; 105 | bit<8> seg_left; 106 | bit<8> last_entry; 107 | bit<8> flags; 108 | bit<16> tag; 109 | } 110 | 111 | header vxlan_h { 112 | bit<8> flags; 113 | bit<24> reserved; 114 | bit<24> vni; 115 | bit<8> reserved2; 116 | } 117 | 118 | header gre_h { 119 | bit<1> C; 120 | bit<1> R; 121 | bit<1> K; 122 | bit<1> S; 123 | bit<1> s; 124 | bit<3> recurse; 125 | bit<5> flags; 126 | bit<3> version; 127 | bit<16> proto; 128 | } 129 | 130 | struct header_t { 131 | ethernet_h cpu_ethernet; 132 | ethernet_h ethernet; 133 | vlan_tag_h vlan_tag; 134 | ipv4_h ipv4; 135 | ipv6_h ipv6; 136 | tcp_h tcp; 137 | udp_h udp; 138 | } 139 | 140 | struct empty_header_t {} 141 | 142 | struct empty_metadata_t {} 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /p4_16/common_p4/parser.p4: -------------------------------------------------------------------------------- 1 | parser SwitchIngressParser( 2 | packet_in pkt, 3 | out header_t hdr, 4 | out metadata_t ig_md, 5 | out ingress_intrinsic_metadata_t ig_intr_md) { 6 | 7 | TofinoIngressParser() tofino_parser; 8 | 9 | state start { 10 | tofino_parser.apply(pkt, ig_intr_md); 11 | transition parse_ethernet; 12 | // transition parse_ipv4; 13 | } 14 | 15 | state parse_ethernet { 16 | pkt.extract(hdr.ethernet); 17 | transition select(hdr.ethernet.ether_type) { 18 | ETHERTYPE_VLAN : parse_vlan; 19 | ETHERTYPE_IPV4 : parse_ipv4; 20 | default : reject; 21 | } 22 | } 23 | 24 | state parse_vlan { 25 | pkt.extract(hdr.vlan_tag); 26 | transition select(hdr.vlan_tag.ether_type) { 27 | ETHERTYPE_IPV4 : parse_ipv4; 28 | default : reject; 29 | } 30 | } 31 | 32 | state parse_ipv4 { 33 | pkt.extract(hdr.ipv4); 34 | // transition select(hdr.ipv4.protocol) { 35 | // IP_PROTOCOLS_UDP : parse_udp; 36 | // IP_PROTOCOLS_TCP : parse_tcp; 37 | // default : reject; 38 | // } 39 | } 40 | 41 | // state parse_tcp { 42 | // pkt.extract(hdr.tcp); 43 | // transition accept; 44 | // } 45 | 46 | // state parse_udp { 47 | // pkt.extract(hdr.udp); 48 | // transition accept; 49 | // } 50 | } 51 | 52 | control SwitchIngressDeparser(packet_out pkt, 53 | inout header_t hdr, 54 | in metadata_t ig_md, 55 | in ingress_intrinsic_metadata_for_deparser_t 56 | ig_intr_dprsr_md 57 | ) { 58 | 59 | apply { 60 | pkt.emit(hdr); 61 | } 62 | } -------------------------------------------------------------------------------- /p4_16/common_p4/util.p4: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_ 2 | #define _UTIL_ 3 | 4 | parser TofinoIngressParser( 5 | packet_in pkt, 6 | out ingress_intrinsic_metadata_t ig_intr_md) { 7 | state start { 8 | pkt.extract(ig_intr_md); 9 | transition select(ig_intr_md.resubmit_flag) { 10 | 1 : parse_resubmit; 11 | 0 : parse_port_metadata; 12 | } 13 | } 14 | 15 | state parse_resubmit { 16 | transition reject; 17 | } 18 | 19 | state parse_port_metadata { 20 | pkt.advance(PORT_METADATA_SIZE); 21 | transition accept; 22 | } 23 | } 24 | 25 | parser TofinoEgressParser( 26 | packet_in pkt, 27 | out egress_intrinsic_metadata_t eg_intr_md) { 28 | state start { 29 | pkt.extract(eg_intr_md); 30 | transition accept; 31 | } 32 | } 33 | 34 | control BypassEgress(inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 35 | 36 | action set_bypass_egress() { 37 | ig_tm_md.bypass_egress = 1w1; 38 | } 39 | 40 | table bypass_egress { 41 | actions = { 42 | set_bypass_egress(); 43 | } 44 | const default_action = set_bypass_egress; 45 | } 46 | 47 | apply { 48 | bypass_egress.apply(); 49 | } 50 | } 51 | 52 | parser EmptyEgressParser( 53 | packet_in pkt, 54 | out empty_header_t hdr, 55 | out empty_metadata_t eg_md, 56 | out egress_intrinsic_metadata_t eg_intr_md) { 57 | state start { 58 | transition accept; 59 | } 60 | } 61 | 62 | control EmptyEgressDeparser( 63 | packet_out pkt, 64 | inout empty_header_t hdr, 65 | in empty_metadata_t eg_md, 66 | in egress_intrinsic_metadata_for_deparser_t ig_intr_dprs_md) { 67 | apply {} 68 | } 69 | 70 | control EmptyEgress( 71 | inout empty_header_t hdr, 72 | inout empty_metadata_t eg_md, 73 | in egress_intrinsic_metadata_t eg_intr_md, 74 | in egress_intrinsic_metadata_from_parser_t eg_intr_md_from_prsr, 75 | inout egress_intrinsic_metadata_for_deparser_t ig_intr_dprs_md, 76 | inout egress_intrinsic_metadata_for_output_port_t eg_intr_oport_md) { 77 | apply {} 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /p4_16/compile.sh: -------------------------------------------------------------------------------- 1 | CURRENT=`pwd` 2 | NAME=`basename "$CURRENT"` 3 | 4 | API=$CURRENT/API 5 | common_p4=$CURRENT/common_p4 6 | 7 | $script_home/p4_build.sh $CURRENT/countmin/p416_countmin.p4 \ 8 | -- P4_NAME="p416_countmin" \ 9 | P4FLAGS="--no-dead-code-elimination" \ 10 | P4PPFLAGS="-I ${API} -I ${common_p4}" 11 | 12 | $script_home/p4_build.sh $CURRENT/countsketch/p416_countsketch.p4 \ 13 | -- P4_NAME="p416_countsketch" \ 14 | P4FLAGS="--no-dead-code-elimination" \ 15 | P4PPFLAGS="-I ${API} -I ${common_p4}" 16 | 17 | $script_home/p4_build.sh $CURRENT/fcm/p416_fcm.p4 \ 18 | -- P4_NAME="p416_fcm" \ 19 | P4FLAGS="--no-dead-code-elimination" \ 20 | P4PPFLAGS="-I ${API}" 21 | 22 | $script_home/p4_build.sh $CURRENT/univmon/p416_univmon.p4 \ 23 | -- P4_NAME="p416_univmon" \ 24 | P4FLAGS="--no-dead-code-elimination" \ 25 | P4PPFLAGS="-I ${API} -I ${common_p4}" 26 | 27 | $script_home/p4_build.sh $CURRENT/rhhh/p416_rhhh.p4 \ 28 | -- P4_NAME="p416_rhhh" \ 29 | P4FLAGS="--no-dead-code-elimination" \ 30 | P4PPFLAGS="-I ${API} -I ${common_p4}" 31 | 32 | $script_home/p4_build.sh $CURRENT/hll/p416_hll.p4 \ 33 | -- P4_NAME="p416_hll" \ 34 | P4FLAGS="--no-dead-code-elimination" \ 35 | P4PPFLAGS="-I ${API} -I ${common_p4}" 36 | 37 | $script_home/p4_build.sh $CURRENT/mrac/p416_mrac.p4 \ 38 | -- P4_NAME="p416_mrac" \ 39 | P4FLAGS="--no-dead-code-elimination" \ 40 | P4PPFLAGS="-I ${API} -I ${common_p4}" 41 | 42 | $script_home/p4_build.sh $CURRENT/mrb/p416_mrb.p4 \ 43 | -- P4_NAME="p416_mrb" \ 44 | P4FLAGS="--no-dead-code-elimination" \ 45 | P4PPFLAGS="-I ${API} -I ${common_p4}" 46 | 47 | $script_home/p4_build.sh $CURRENT/pcsa/p416_pcsa.p4 \ 48 | -- P4_NAME="p416_pcsa" \ 49 | P4FLAGS="--no-dead-code-elimination" \ 50 | P4PPFLAGS="-I ${API} -I ${common_p4}" 51 | 52 | $script_home/p4_build.sh $CURRENT/hhh/p416_hhh.p4 \ 53 | -- P4_NAME="p416_hhh" \ 54 | P4FLAGS="--no-dead-code-elimination" \ 55 | P4PPFLAGS="-I ${API} -I ${common_p4}" 56 | 57 | $script_home/p4_build.sh $CURRENT/kary/p416_kary.p4 \ 58 | -- P4_NAME="p416_kary" \ 59 | P4FLAGS="--no-dead-code-elimination" \ 60 | P4PPFLAGS="-I ${API} -I ${common_p4}" 61 | 62 | $script_home/p4_build.sh $CURRENT/loglog/p416_loglog.p4 \ 63 | -- P4_NAME="p416_loglog" \ 64 | P4FLAGS="--no-dead-code-elimination" \ 65 | P4PPFLAGS="-I ${API} -I ${common_p4}" 66 | 67 | $script_home/p4_build.sh $CURRENT/sketchlearn/p416_sketchlearn.p4 \ 68 | -- P4_NAME="p416_sketchlearn" \ 69 | P4FLAGS="--no-dead-code-elimination" \ 70 | P4PPFLAGS="-I ${API} -I ${common_p4}" 71 | 72 | $script_home/p4_build.sh $CURRENT/spreadsketch/p416_spreadsketch.p4 \ 73 | -- P4_NAME="p416_spreadsketch" \ 74 | P4FLAGS="--no-dead-code-elimination" \ 75 | P4PPFLAGS="-I ${API} -I ${common_p4}" 76 | -------------------------------------------------------------------------------- /p4_16/countmin/p416_countmin.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<16> sampling_hash_value; 13 | bit<10> level; 14 | bit<16> base; 15 | bit<32> threshold; 16 | 17 | bit<16> index_1; 18 | bit<16> index_2; 19 | bit<16> index_3; 20 | bit<16> index_4; 21 | bit<16> index_5; 22 | 23 | // bit<5> res_all; 24 | bit<16> res_all; 25 | bit<1> res_1; 26 | bit<1> res_2; 27 | bit<1> res_3; 28 | bit<1> res_4; 29 | bit<1> res_5; 30 | 31 | bit<32> est_1; 32 | bit<32> est_2; 33 | bit<32> est_3; 34 | bit<32> est_4; 35 | bit<32> est_5; 36 | 37 | bit<1> c_1; 38 | bit<1> c_2; 39 | bit<1> c_3; 40 | bit<1> c_4; 41 | bit<1> c_5; 42 | 43 | bit<1> above_threshold; 44 | } 45 | 46 | #include "parser.p4" 47 | 48 | #include "API_common.p4" 49 | #include "API_O1_hash.p4" 50 | #include "API_O2_hash.p4" 51 | #include "API_O3_tcam.p4" 52 | #include "API_O5_salu.p4" 53 | #include "API_O6_flowkey.p4" 54 | #include "API_threshold.p4" 55 | 56 | control SwitchIngress( 57 | inout header_t hdr, 58 | inout metadata_t ig_md, 59 | in ingress_intrinsic_metadata_t ig_intr_md, 60 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 61 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 62 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 63 | 64 | CM_UPDATE(32w0x30243f0b) update_1; 65 | CM_UPDATE(32w0x0f79f523) update_2; 66 | CM_UPDATE(32w0x6b8cb0c5) update_3; 67 | CM_UPDATE(32w0x00390fc3) update_4; 68 | CM_UPDATE(32w0x298ac673) update_5; 69 | 70 | heavy_flowkey_storage() store_flowkey; 71 | 72 | GET_THRESHOLD() get_threshold; 73 | 74 | apply { 75 | 76 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 77 | 78 | get_threshold.apply(hdr, ig_md); 79 | 80 | update_1.apply(hdr.ipv4.src_addr, ig_md.est_1); 81 | update_2.apply(hdr.ipv4.src_addr, ig_md.est_2); 82 | update_3.apply(hdr.ipv4.src_addr, ig_md.est_3); 83 | update_4.apply(hdr.ipv4.src_addr, ig_md.est_4); 84 | update_5.apply(hdr.ipv4.src_addr, ig_md.est_5); 85 | 86 | store_flowkey.apply(hdr, ig_md, ig_tm_md); 87 | 88 | } 89 | } 90 | } 91 | 92 | struct my_egress_headers_t { 93 | } 94 | 95 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 96 | 97 | struct my_egress_metadata_t { 98 | } 99 | 100 | parser EgressParser(packet_in pkt, 101 | /* User */ 102 | out my_egress_headers_t hdr, 103 | out my_egress_metadata_t meta, 104 | /* Intrinsic */ 105 | out egress_intrinsic_metadata_t eg_intr_md) 106 | { 107 | /* This is a mandatory state, required by Tofino Architecture */ 108 | state start { 109 | pkt.extract(eg_intr_md); 110 | transition accept; 111 | } 112 | } 113 | 114 | control EgressDeparser(packet_out pkt, 115 | /* User */ 116 | inout my_egress_headers_t hdr, 117 | in my_egress_metadata_t meta, 118 | /* Intrinsic */ 119 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 120 | { 121 | apply { 122 | pkt.emit(hdr); 123 | } 124 | } 125 | 126 | Pipeline( 127 | SwitchIngressParser(), 128 | SwitchIngress(), 129 | SwitchIngressDeparser(), 130 | EgressParser(), 131 | EmptyEgress(), 132 | EgressDeparser() 133 | ) pipe; 134 | 135 | Switch(pipe) main; 136 | 137 | -------------------------------------------------------------------------------- /p4_16/countsketch/p416_countsketch.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<16> sampling_hash_value; 13 | bit<10> level; 14 | bit<16> base; 15 | bit<32> threshold; 16 | 17 | bit<16> index_1; 18 | bit<16> index_2; 19 | bit<16> index_3; 20 | bit<16> index_4; 21 | bit<16> index_5; 22 | 23 | // bit<5> res_all; 24 | bit<16> res_all; 25 | bit<1> res_1; 26 | bit<1> res_2; 27 | bit<1> res_3; 28 | bit<1> res_4; 29 | bit<1> res_5; 30 | 31 | bit<32> est_1; 32 | bit<32> est_2; 33 | bit<32> est_3; 34 | bit<32> est_4; 35 | bit<32> est_5; 36 | 37 | bit<1> c_1; 38 | bit<1> c_2; 39 | bit<1> c_3; 40 | bit<1> c_4; 41 | bit<1> c_5; 42 | 43 | bit<1> above_threshold; 44 | } 45 | 46 | #include "parser.p4" 47 | 48 | #include "API_common.p4" 49 | #include "API_O1_hash.p4" 50 | #include "API_O2_hash.p4" 51 | #include "API_O3_tcam.p4" 52 | #include "API_O5_salu.p4" 53 | #include "API_O6_flowkey.p4" 54 | #include "API_threshold.p4" 55 | 56 | control SwitchIngress( 57 | inout header_t hdr, 58 | inout metadata_t ig_md, 59 | in ingress_intrinsic_metadata_t ig_intr_md, 60 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 61 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 62 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 63 | 64 | hash_consolidate_and_split_srcip(32w0x5b445b31) res_split; 65 | CS_UPDATE(32w0x30243f0b) update_1; 66 | CS_UPDATE(32w0x0f79f523) update_2; 67 | CS_UPDATE(32w0x6b8cb0c5) update_3; 68 | CS_UPDATE(32w0x00390fc3) update_4; 69 | CS_UPDATE(32w0x298ac673) update_5; 70 | 71 | heavy_flowkey_storage() store_flowkey; 72 | 73 | GET_THRESHOLD() get_threshold; 74 | 75 | apply { 76 | 77 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 78 | 79 | get_threshold.apply(hdr, ig_md); 80 | 81 | res_split.apply(hdr.ipv4.src_addr, ig_md.res_all, 82 | ig_md.res_1, 83 | ig_md.res_2, 84 | ig_md.res_3, 85 | ig_md.res_4, 86 | ig_md.res_5); 87 | 88 | update_1.apply(hdr.ipv4.src_addr, ig_md.res_1, ig_md.est_1); 89 | update_2.apply(hdr.ipv4.src_addr, ig_md.res_2, ig_md.est_2); 90 | update_3.apply(hdr.ipv4.src_addr, ig_md.res_3, ig_md.est_3); 91 | update_4.apply(hdr.ipv4.src_addr, ig_md.res_4, ig_md.est_4); 92 | update_5.apply(hdr.ipv4.src_addr, ig_md.res_5, ig_md.est_5); 93 | 94 | store_flowkey.apply(hdr, ig_md, ig_tm_md); 95 | 96 | } 97 | } 98 | } 99 | 100 | struct my_egress_headers_t { 101 | } 102 | 103 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 104 | 105 | struct my_egress_metadata_t { 106 | } 107 | 108 | parser EgressParser(packet_in pkt, 109 | /* User */ 110 | out my_egress_headers_t hdr, 111 | out my_egress_metadata_t meta, 112 | /* Intrinsic */ 113 | out egress_intrinsic_metadata_t eg_intr_md) 114 | { 115 | /* This is a mandatory state, required by Tofino Architecture */ 116 | state start { 117 | pkt.extract(eg_intr_md); 118 | transition accept; 119 | } 120 | } 121 | 122 | control EgressDeparser(packet_out pkt, 123 | /* User */ 124 | inout my_egress_headers_t hdr, 125 | in my_egress_metadata_t meta, 126 | /* Intrinsic */ 127 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 128 | { 129 | apply { 130 | pkt.emit(hdr); 131 | } 132 | } 133 | 134 | Pipeline( 135 | SwitchIngressParser(), 136 | SwitchIngress(), 137 | SwitchIngressDeparser(), 138 | EgressParser(), 139 | EmptyEgress(), 140 | EgressDeparser() 141 | ) pipe; 142 | 143 | Switch(pipe) main; 144 | 145 | -------------------------------------------------------------------------------- /p4_16/entropy/p416_entropy.p4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SketchLib/P4_SketchLib/369ac9cb30eb7f4ca9c0adcc1503f72988fd74d9/p4_16/entropy/p416_entropy.p4 -------------------------------------------------------------------------------- /p4_16/fcm/common/headers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _HEADERS_ 2 | #define _HEADERS_ 3 | 4 | typedef bit<48> mac_addr_t; 5 | typedef bit<32> ipv4_addr_t; 6 | typedef bit<16> ether_type_t; 7 | const ether_type_t ETHERTYPE_IPV4 = 16w0x0800; 8 | 9 | typedef bit<8> ip_protocol_t; 10 | const ip_protocol_t IP_PROTOCOLS_ICMP = 1; 11 | const ip_protocol_t IP_PROTOCOLS_TCP = 6; 12 | const ip_protocol_t IP_PROTOCOLS_UDP = 17; 13 | 14 | header ethernet_h { 15 | mac_addr_t dst_addr; 16 | mac_addr_t src_addr; 17 | bit<16> ether_type; 18 | } 19 | 20 | header ipv4_h { 21 | bit<4> version; 22 | bit<4> ihl; 23 | bit<8> diffserv; 24 | bit<16> total_len; 25 | bit<16> identification; 26 | bit<3> flags; 27 | bit<13> frag_offset; 28 | bit<8> ttl; 29 | bit<8> protocol; 30 | bit<16> hdr_checksum; 31 | ipv4_addr_t src_addr; 32 | ipv4_addr_t dst_addr; 33 | } 34 | 35 | header tcp_h { 36 | bit<16> src_port; 37 | bit<16> dst_port; 38 | bit<32> seq_no; 39 | bit<32> ack_no; 40 | bit<4> data_offset; 41 | bit<4> res; 42 | bit<8> flags; 43 | bit<16> window; 44 | bit<16> checksum; 45 | bit<16> urgent_ptr; 46 | } 47 | 48 | header udp_h { 49 | bit<16> src_port; 50 | bit<16> dst_port; 51 | bit<16> hdr_length; 52 | bit<16> checksum; 53 | } 54 | 55 | struct header_t { 56 | ethernet_h cpu_ethernet; 57 | ethernet_h ethernet; 58 | ipv4_h ipv4; 59 | tcp_h tcp; 60 | udp_h udp; 61 | } 62 | 63 | // for empty egress 64 | struct empty_header_t {} 65 | struct empty_metadata_t {} 66 | 67 | #endif /* _HEADERS_ */ -------------------------------------------------------------------------------- /p4_16/fcm/common/util.p4: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_ 2 | #define _UTIL_ 3 | 4 | parser TofinoIngressParser( 5 | packet_in pkt, 6 | out ingress_intrinsic_metadata_t ig_intr_md){ 7 | state start { 8 | pkt.extract(ig_intr_md); 9 | transition parse_port_metadata; 10 | } 11 | state parse_port_metadata { 12 | pkt.advance(PORT_METADATA_SIZE); // macro defined in tofino.p4 13 | transition accept; 14 | } 15 | } 16 | 17 | // Empty egress parser/control blocks 18 | parser EmptyEgressParser( 19 | packet_in pkt, 20 | out empty_header_t hdr, 21 | out empty_metadata_t eg_md, 22 | out egress_intrinsic_metadata_t eg_intr_md) { 23 | state start { 24 | transition accept; 25 | } 26 | } 27 | 28 | control EmptyEgressDeparser( 29 | packet_out pkt, 30 | inout empty_header_t hdr, 31 | in empty_metadata_t eg_md, 32 | in egress_intrinsic_metadata_for_deparser_t ig_intr_dprs_md) { 33 | apply {} 34 | } 35 | 36 | control EmptyEgress( 37 | inout empty_header_t hdr, 38 | inout empty_metadata_t eg_md, 39 | in egress_intrinsic_metadata_t eg_intr_md, 40 | in egress_intrinsic_metadata_from_parser_t eg_intr_md_from_prsr, 41 | inout egress_intrinsic_metadata_for_deparser_t ig_intr_dprs_md, 42 | inout egress_intrinsic_metadata_for_output_port_t eg_intr_oport_md) { 43 | apply {} 44 | } 45 | 46 | #endif /* _UTIL */ -------------------------------------------------------------------------------- /p4_16/fcm/p416_fcm.p4: -------------------------------------------------------------------------------- 1 | /* -*- P4_16 -*- */ 2 | 3 | // ------------------------------------------------------------ 4 | // FCM-Sketch P4-16 Implementation 5 | // 6 | // - Flow identification 7 | // You can define our flow identification (currrnetly, we use srcIP) 8 | // in action 'fcm_action_calc_hash_d1' and 'fcm_action_calc_hash_d2'. 9 | // 10 | // - Data Plane Queries 11 | // - Flow Size estimation is supported by bit<32> flow_size. 12 | // Of course, you can in turn classify Heavy hitters and Heavy changes. 13 | // - Cardinality is supported by bit<32> cardinality. 14 | // We reduced the TCAM entries via sensitivity analysis of LC estimator. 15 | // It is a kind of adaptive spacing between TCAM entries with additional error. 16 | // Ideally, we can reduce 100X of TCAM entries with only 0.3 % additional error. 17 | // - Control Plane Queries : Read the bottom of "test_fcm.py". 18 | // - Flow Size distribution 19 | // - Entropy 20 | // 21 | // ------------------------------------------------------------ 22 | 23 | 24 | 25 | #include 26 | #if __TARGET_TOFINO__ == 2 27 | #include 28 | #else 29 | #include 30 | #endif 31 | 32 | #include "common/headers.p4" 33 | #include "common/util.p4" 34 | 35 | 36 | 37 | #define SKETCH_W1 0x80000 // 8 bits, width at layer 1, 2^19 = 524288 38 | #define SKETCH_W2 0x10000 // 16 bits, width at layer 2, 2^16 = 65536 39 | #define SKETCH_W3 0x2000 // 32 bits, width at layer 3, 2^13 = 8192 40 | 41 | #define ADD_LEVEL1 0x000000ff // 2^8 - 2 + 1 (property of SALU) 42 | #define ADD_LEVEL2 0x000100fd // (2^8 - 2) + (2^16 - 2) + 1 (property of SALU) 43 | 44 | 45 | // --------------------------------------------------------------------------- 46 | // Metadata fields 47 | // --------------------------------------------------------------------------- 48 | 49 | // metadata fields for fcm 50 | struct fcm_metadata_t { 51 | bit<32> hash_meta_d1; 52 | bit<32> hash_meta_d2; 53 | 54 | 55 | bit<32> result_d1; 56 | bit<32> result_d2; 57 | bit<32> increment_occupied; 58 | 59 | bit<1> c_1; 60 | bit<32> est_1; 61 | bit<32> threshold; 62 | bit<1> above_threshold; 63 | } 64 | 65 | // for ingress metadata 66 | struct metadata_t { 67 | fcm_metadata_t fcm_mdata; 68 | } 69 | 70 | control GET_THRESHOLD( 71 | inout header_t hdr, 72 | inout fcm_metadata_t ig_md) 73 | { 74 | action tbl_get_threshold_act (bit<32> threshold) { 75 | ig_md.threshold = threshold; 76 | } 77 | table tbl_get_threshold { 78 | key = { 79 | hdr.ethernet.ether_type : exact; 80 | } 81 | actions = { 82 | tbl_get_threshold_act; 83 | } 84 | } 85 | apply { 86 | tbl_get_threshold.apply(); 87 | } 88 | } 89 | 90 | #include "API_O6_flowkey_fcm.p4" 91 | 92 | // --------------------------------------------------------------------------- 93 | // Ingress parser 94 | // --------------------------------------------------------------------------- 95 | 96 | parser SwitchIngressParser( 97 | packet_in pkt, 98 | out header_t hdr, 99 | out metadata_t ig_md, 100 | out ingress_intrinsic_metadata_t ig_intr_md) { 101 | 102 | TofinoIngressParser() tofino_parser; 103 | 104 | state start { 105 | tofino_parser.apply(pkt, ig_intr_md); 106 | // initialize metadata 107 | ig_md.fcm_mdata.result_d1 = 0; 108 | ig_md.fcm_mdata.result_d2 = 0; 109 | ig_md.fcm_mdata.increment_occupied = 0; 110 | 111 | transition parse_ethernet; 112 | } 113 | 114 | state parse_ethernet { 115 | pkt.extract(hdr.ethernet); 116 | transition select (hdr.ethernet.ether_type) { 117 | ETHERTYPE_IPV4 : parse_ipv4; 118 | default : reject; 119 | } 120 | } 121 | 122 | state parse_ipv4 { 123 | pkt.extract(hdr.ipv4); 124 | transition select(hdr.ipv4.protocol) { 125 | IP_PROTOCOLS_TCP : parse_tcp; 126 | IP_PROTOCOLS_UDP : parse_udp; 127 | default : accept; 128 | } 129 | } 130 | 131 | state parse_tcp { 132 | pkt.extract(hdr.tcp); 133 | transition select(hdr.ipv4.total_len) { 134 | default : accept; 135 | } 136 | } 137 | 138 | state parse_udp { 139 | pkt.extract(hdr.udp); 140 | transition select(hdr.udp.dst_port) { 141 | default: accept; 142 | } 143 | } 144 | } 145 | 146 | // --------------------------------------------------------------------------- 147 | // Ingress Deparser 148 | // --------------------------------------------------------------------------- 149 | control SwitchIngressDeparser( 150 | packet_out pkt, 151 | inout header_t hdr, 152 | in metadata_t ig_md, 153 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) { 154 | 155 | apply { 156 | pkt.emit(hdr); 157 | pkt.emit(hdr.ipv4); 158 | pkt.emit(hdr.tcp); 159 | pkt.emit(hdr.udp); 160 | } 161 | } 162 | 163 | // --------------------------------------------------------------------------- 164 | // FCM logic control block 165 | // --------------------------------------------------------------------------- 166 | control FCMSketch ( 167 | inout header_t hdr, 168 | out fcm_metadata_t fcm_mdata, 169 | out bit<19> num_occupied_reg, 170 | out bit<32> flow_size, 171 | out bit<32> cardinality, 172 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 173 | 174 | // +++++++++++++++++++ 175 | // hashings & hash action 176 | // +++++++++++++++++++ 177 | 178 | CRCPolynomial>(32w0x04C11DB7, // polynomial 179 | true, // reversed 180 | false, // use msb? 181 | false, // extended? 182 | 32w0xFFFFFFFF, // initial shift register value 183 | 32w0xFFFFFFFF // result xor 184 | ) CRC32; 185 | Hash>(HashAlgorithm_t.CUSTOM, CRC32) hash_d1; 186 | 187 | // Hash>(HashAlgorithm_t.CRC32) hash_d1; 188 | 189 | 190 | CRCPolynomial>(32w0x04C11DB7, 191 | false, 192 | false, 193 | false, 194 | 32w0xFFFFFFFF, 195 | 32w0x00000000 196 | ) CRC32_MPEG; 197 | Hash>(HashAlgorithm_t.CUSTOM, CRC32_MPEG) hash_d2; 198 | 199 | 200 | // +++++++++++++++++++ 201 | // registers 202 | // +++++++++++++++++++ 203 | 204 | Register, bit<19>>(SKETCH_W1) sketch_reg_l1_d1; 205 | Register, bit<16>>(SKETCH_W2) sketch_reg_l2_d1; 206 | Register, bit<13>>(SKETCH_W3) sketch_reg_l3_d1; 207 | 208 | Register, bit<19>>(SKETCH_W1) sketch_reg_l1_d2; 209 | Register, bit<16>>(SKETCH_W2) sketch_reg_l2_d2; 210 | Register, bit<13>>(SKETCH_W3) sketch_reg_l3_d2; 211 | 212 | // total number of empty registers for all trees 213 | Register, _>(1) reg_num_empty; 214 | 215 | // +++++++++++++++++++ 216 | // register actions 217 | // +++++++++++++++++++ 218 | 219 | // level 1, depth 1 220 | RegisterAction, bit<19>, bit<32>>(sketch_reg_l1_d1) increment_l1_d1 = { 221 | void apply(inout bit<8> value, out bit<32> result) { 222 | value = value |+| 1; 223 | result = (bit<32>)value; // return level 1 value (255 -> count 254) 224 | } 225 | }; 226 | // level 2, depth 1, only when level 1 output is 255 227 | RegisterAction, bit<16>, bit<32>>(sketch_reg_l2_d1) increment_l2_d1 = { 228 | void apply(inout bit<16> value, out bit<32> result) { 229 | result = (bit<32>)value + ADD_LEVEL1; // return level 1 + 2 230 | value = value |+| 1; 231 | } 232 | }; 233 | // level 3, depth 1, only when level 2 output is 65789 234 | RegisterAction, bit<13>, bit<32>>(sketch_reg_l3_d1) increment_l3_d1 = { 235 | void apply(inout bit<32> value, out bit<32> result) { 236 | result = value + ADD_LEVEL2; // return level 1 + 2 + 3 237 | value = value |+| 1; 238 | 239 | } 240 | }; 241 | 242 | // level 1, depth 2 243 | RegisterAction, bit<19>, bit<32>>(sketch_reg_l1_d2) increment_l1_d2 = { 244 | void apply(inout bit<8> value, out bit<32> result) { 245 | value = value |+| 1; 246 | result = (bit<32>)value; // return level 1 value (255 -> count 254) 247 | } 248 | }; 249 | // level 2, depth 2, only when level 1 output is 255 250 | RegisterAction, bit<16>, bit<32>>(sketch_reg_l2_d2) increment_l2_d2 = { 251 | void apply(inout bit<16> value, out bit<32> result) { 252 | result = (bit<32>)value + ADD_LEVEL1; // return level 1 + 2 253 | value = value |+| 1; 254 | } 255 | }; 256 | // level 3, depth 2, only when level 2 output is 65789 257 | RegisterAction, bit<13>, bit<32>>(sketch_reg_l3_d2) increment_l3_d2 = { 258 | void apply(inout bit<32> value, out bit<32> result) { 259 | result = value + ADD_LEVEL2; // return level 1 + 2 + 3 260 | value = value |+| 1; // increment assuming no 32-bit overflow 261 | 262 | } 263 | }; 264 | 265 | // increment number of empty register value for cardinality 266 | RegisterAction, _, bit<32>>(reg_num_empty) increment_occupied_reg = { 267 | void apply(inout bit<32> value, out bit<32> result) { 268 | result = value + fcm_mdata.increment_occupied; 269 | value = value + fcm_mdata.increment_occupied; 270 | } 271 | }; 272 | 273 | 274 | // +++++++++++++++++++ 275 | // actions 276 | // +++++++++++++++++++ 277 | 278 | // action for level 1, depth 1, you can re-define the flow key identification 279 | action fcm_action_l1_d1() { 280 | fcm_mdata.result_d1 = increment_l1_d1.execute(hash_d1.get({ hdr.ipv4.src_addr })[18:0]); 281 | } 282 | // action for level 2, depth 1 283 | action fcm_action_l2_d1() { 284 | fcm_mdata.result_d1 = increment_l2_d1.execute(hash_d1.get({ hdr.ipv4.src_addr })[18:3]); 285 | } 286 | // action for level 3, depth 1 287 | action fcm_action_l3_d1() { 288 | fcm_mdata.result_d1 = increment_l3_d1.execute(hash_d1.get({ hdr.ipv4.src_addr })[18:6]); 289 | } 290 | 291 | // action for level 1, depth 2, you can re-define the flow key identification 292 | action fcm_action_l1_d2() { 293 | fcm_mdata.result_d2 = increment_l1_d2.execute(hash_d2.get({ hdr.ipv4.src_addr })[18:0]); 294 | } 295 | // action for level 2, depth 2 296 | action fcm_action_l2_d2() { 297 | fcm_mdata.result_d2 = increment_l2_d2.execute(hash_d2.get({ hdr.ipv4.src_addr })[18:0][18:3]); 298 | } 299 | // action for level 3, depth 2 300 | action fcm_action_l3_d2() { 301 | fcm_mdata.result_d2 = increment_l3_d2.execute(hash_d2.get({ hdr.ipv4.src_addr })[18:0][18:6]); 302 | } 303 | 304 | 305 | // increment reg of occupied leaf number 306 | action fcm_action_increment_cardreg() { 307 | num_occupied_reg = (increment_occupied_reg.execute(0))[19:1]; 308 | } 309 | 310 | action fcm_action_check_occupied(bit<32> increment_val) { 311 | fcm_mdata.increment_occupied = increment_val; 312 | } 313 | 314 | 315 | action fcm_action_set_cardinality(bit<32> card_match) { 316 | cardinality = card_match; 317 | } 318 | 319 | // +++++++++++++++++++ 320 | // tables 321 | // +++++++++++++++++++ 322 | 323 | // if level 1 is full, move to level 2. 324 | table tb_fcm_l1_to_l2_d1 { 325 | key = { 326 | fcm_mdata.result_d1 : exact; 327 | } 328 | actions = { 329 | fcm_action_l2_d1; 330 | @defaultonly NoAction; 331 | } 332 | const default_action = NoAction(); 333 | const entries = { 334 | 32w255: fcm_action_l2_d1(); 335 | } 336 | size = 2; 337 | } 338 | 339 | // if level 2 is full, move to level 3. 340 | table tb_fcm_l2_to_l3_d1 { 341 | key = { 342 | fcm_mdata.result_d1 : exact; 343 | } 344 | actions = { 345 | fcm_action_l3_d1; 346 | @defaultonly NoAction; 347 | } 348 | const default_action = NoAction(); 349 | const entries = { 350 | 32w65789: fcm_action_l3_d1(); 351 | } 352 | size = 2; 353 | } 354 | 355 | // if level 1 is full, move to level 2. 356 | table tb_fcm_l1_to_l2_d2 { 357 | key = { 358 | fcm_mdata.result_d2 : exact; 359 | } 360 | actions = { 361 | fcm_action_l2_d2; 362 | @defaultonly NoAction; 363 | } 364 | const default_action = NoAction(); 365 | const entries = { 366 | 32w255: fcm_action_l2_d2(); 367 | } 368 | size = 2; 369 | } 370 | 371 | // if level 2 is full, move to level 3. 372 | table tb_fcm_l2_to_l3_d2 { 373 | key = { 374 | fcm_mdata.result_d2 : exact; 375 | } 376 | actions = { 377 | fcm_action_l3_d2; 378 | @defaultonly NoAction; 379 | } 380 | const default_action = NoAction(); 381 | const entries = { 382 | 32w65789: fcm_action_l3_d2(); 383 | } 384 | size = 2; 385 | } 386 | 387 | // Update the number of occupied leaf nodes 388 | table tb_fcm_increment_occupied { 389 | key = { 390 | fcm_mdata.result_d1 : ternary; 391 | fcm_mdata.result_d2 : ternary; 392 | } 393 | actions = { 394 | fcm_action_check_occupied; 395 | } 396 | const default_action = fcm_action_check_occupied(0); 397 | const entries = { 398 | (32w1, 32w1) : fcm_action_check_occupied(2); 399 | (32w1, _) : fcm_action_check_occupied(1); 400 | (_, 32w1) : fcm_action_check_occupied(1); 401 | } 402 | size = 4; 403 | } 404 | 405 | // look up LC cardinality using number of empty counters at level 1 406 | // [30:12] : divide by 2 ("average" empty_reg number). 407 | // Each array size is 2 ** 19, so slice 19 bits 408 | table tb_fcm_cardinality { 409 | key = { 410 | num_occupied_reg : range; // 19 bits 411 | } 412 | actions = { 413 | fcm_action_set_cardinality; 414 | } 415 | const default_action = fcm_action_set_cardinality(0); 416 | size = 4096; 417 | } 418 | 419 | GET_THRESHOLD() get_threshold; 420 | heavy_flowkey_storage() store_flowkey; 421 | 422 | // +++++++++++++++++++ 423 | // apply 424 | // +++++++++++++++++++ 425 | apply { 426 | get_threshold.apply(hdr, fcm_mdata); 427 | 428 | fcm_action_l1_d1(); // increment level 1, depth 1 429 | fcm_action_l1_d2(); // increment level 1, depth 2 430 | /* increment the number of occupied leaf nodes */ 431 | tb_fcm_increment_occupied.apply(); 432 | fcm_action_increment_cardreg(); 433 | tb_fcm_cardinality.apply(); // calculate cardinality estimate 434 | tb_fcm_l1_to_l2_d1.apply(); // conditional increment level 2, depth 1 435 | tb_fcm_l1_to_l2_d2.apply(); // conditional increment level 2, depth 2 436 | tb_fcm_l2_to_l3_d1.apply(); // conditional increment level 3, depth 1 437 | tb_fcm_l2_to_l3_d2.apply(); // conditional increment level 3, depth 2 438 | 439 | /* Take minimum for final count-query. */ 440 | // flow_size = fcm_mdata.result_d1 > fcm_mdata.result_d2 ? fcm_mdata.result_d2 : fcm_mdata.result_d1; 441 | fcm_mdata.est_1 = fcm_mdata.result_d1 > fcm_mdata.result_d2 ? fcm_mdata.result_d2 : fcm_mdata.result_d1; 442 | 443 | store_flowkey.apply(hdr, fcm_mdata, ig_tm_md); 444 | } 445 | } 446 | 447 | 448 | control SwitchIngress( 449 | inout header_t hdr, 450 | inout metadata_t ig_md, 451 | in ingress_intrinsic_metadata_t ig_intr_md, 452 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 453 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 454 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 455 | 456 | 457 | /*** temp ***/ 458 | // increment when packet comes in 459 | Register, _>(1, 0) num_pkt; 460 | RegisterAction, _, bit<32>>(num_pkt) increment_pkt = { 461 | void apply(inout bit<32> value, out bit<32> result) { 462 | value = value |+| 1; 463 | result = value; 464 | } 465 | }; 466 | 467 | action count_pkt() { 468 | increment_pkt.execute(0); 469 | } 470 | /*** temp ***/ 471 | 472 | 473 | FCMSketch() fcmsketch; 474 | apply { 475 | bit<19> num_occupied_reg; // local variable for cardinality 476 | bit<32> flow_size; // local variable for final query 477 | bit<32> cardinality; // local variable for final query 478 | 479 | count_pkt(); // temp 480 | fcmsketch.apply(hdr, 481 | ig_md.fcm_mdata, 482 | num_occupied_reg, 483 | flow_size, 484 | cardinality, 485 | ig_tm_md); 486 | } 487 | } 488 | 489 | 490 | 491 | 492 | Pipeline(SwitchIngressParser(), 493 | SwitchIngress(), 494 | SwitchIngressDeparser(), 495 | EmptyEgressParser(), 496 | EmptyEgress(), 497 | EmptyEgressDeparser() 498 | ) pipe; 499 | 500 | Switch(pipe) main; -------------------------------------------------------------------------------- /p4_16/hhh/p416_hhh.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | #define METADATA_LEVEL_SETUP(L) \ 12 | bit<32> level_##L##_threshold; \ 13 | bit<16> level_##L##_res_all; \ 14 | bit<1> level_##L##_res_1; \ 15 | bit<1> level_##L##_res_2; \ 16 | bit<1> level_##L##_res_3; \ 17 | bit<1> level_##L##_res_4; \ 18 | bit<1> level_##L##_res_5; \ 19 | bit<32> level_##L##_est_1; \ 20 | bit<32> level_##L##_est_2; \ 21 | bit<32> level_##L##_est_3; \ 22 | bit<1> level_##L##_c_1; \ 23 | bit<1> level_##L##_c_2; \ 24 | bit<1> level_##L##_c_3; \ 25 | bit<1> level_##L##_above_threshold; 26 | 27 | #define CONTROL_FUNC_SETUP(L) \ 28 | hash_consolidate_and_split_srcip(32w0x5b445b31) level_##L##_res_split; \ 29 | CS_UPDATE(32w0x30243f0b) level_##L##_update_1; \ 30 | CS_UPDATE(32w0x0f79f523) level_##L##_update_2; \ 31 | CS_UPDATE(32w0x6b8cb0c5) level_##L##_update_3; 32 | 33 | #define APPLY_SETUP(L) \ 34 | level_##L##_res_split.apply(key##L##, ig_md.level_##L##_res_all, \ 35 | ig_md.level_##L##_res_1, \ 36 | ig_md.level_##L##_res_2, \ 37 | ig_md.level_##L##_res_3, \ 38 | ig_md.level_##L##_res_4, \ 39 | ig_md.level_##L##_res_5); \ 40 | level_##L##_update_1.apply(key##L##, ig_md.level_##L##_res_1, ig_md.level_##L##_est_1); \ 41 | level_##L##_update_2.apply(key##L##, ig_md.level_##L##_res_2, ig_md.level_##L##_est_2); \ 42 | level_##L##_update_3.apply(key##L##, ig_md.level_##L##_res_3, ig_md.level_##L##_est_3); 43 | 44 | // level_##L##_update_4.apply(key##L##, ig_md.level_##L##_res_4, ig_md.level_##L##_est_4); \ 45 | // level_##L##_update_5.apply(key##L##, ig_md.level_##L##_res_5, ig_md.level_##L##_est_5); 46 | 47 | struct metadata_t { 48 | METADATA_LEVEL_SETUP(1) 49 | METADATA_LEVEL_SETUP(2) 50 | METADATA_LEVEL_SETUP(3) 51 | METADATA_LEVEL_SETUP(4) 52 | } 53 | 54 | #include "parser.p4" 55 | 56 | #include "API_common.p4" 57 | #include "API_O1_hash.p4" 58 | #include "API_O2_hash.p4" 59 | #include "API_O3_tcam.p4" 60 | #include "API_O5_salu.p4" 61 | #include "API_O6_flowkey_hhh.p4" 62 | 63 | control SwitchIngress( 64 | inout header_t hdr, 65 | inout metadata_t ig_md, 66 | in ingress_intrinsic_metadata_t ig_intr_md, 67 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 68 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 69 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 70 | 71 | 72 | heavy_flowkey_storage() store_flowkey; 73 | 74 | CONTROL_FUNC_SETUP(1) 75 | CONTROL_FUNC_SETUP(2) 76 | CONTROL_FUNC_SETUP(3) 77 | CONTROL_FUNC_SETUP(4) 78 | 79 | apply { 80 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 81 | bit<32> key1 = hdr.ipv4.src_addr & 0xFFFFFFFF; 82 | bit<32> key2 = hdr.ipv4.src_addr & 0xFFFFFF00; 83 | bit<32> key3 = hdr.ipv4.src_addr & 0xFFFF0000; 84 | bit<32> key4 = hdr.ipv4.src_addr & 0xFF000000; 85 | APPLY_SETUP(1) 86 | APPLY_SETUP(2) 87 | APPLY_SETUP(3) 88 | APPLY_SETUP(4) 89 | 90 | store_flowkey.apply(hdr, ig_md, ig_tm_md); 91 | } 92 | } 93 | } 94 | 95 | struct my_egress_headers_t { 96 | } 97 | 98 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 99 | 100 | struct my_egress_metadata_t { 101 | } 102 | 103 | parser EgressParser(packet_in pkt, 104 | /* User */ 105 | out my_egress_headers_t hdr, 106 | out my_egress_metadata_t meta, 107 | /* Intrinsic */ 108 | out egress_intrinsic_metadata_t eg_intr_md) 109 | { 110 | /* This is a mandatory state, required by Tofino Architecture */ 111 | state start { 112 | pkt.extract(eg_intr_md); 113 | transition accept; 114 | } 115 | } 116 | 117 | control EgressDeparser(packet_out pkt, 118 | /* User */ 119 | inout my_egress_headers_t hdr, 120 | in my_egress_metadata_t meta, 121 | /* Intrinsic */ 122 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 123 | { 124 | apply { 125 | pkt.emit(hdr); 126 | } 127 | } 128 | 129 | 130 | Pipeline( 131 | SwitchIngressParser(), 132 | SwitchIngress(), 133 | SwitchIngressDeparser(), 134 | EgressParser(), 135 | EmptyEgress(), 136 | EgressDeparser() 137 | ) pipe; 138 | 139 | Switch(pipe) main; 140 | -------------------------------------------------------------------------------- /p4_16/hll/p416_hll.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<32> sampling_hash_value; 13 | bit<32> level; 14 | bit<16> index; 15 | } 16 | 17 | #include "parser.p4" 18 | 19 | #include "API_common.p4" 20 | #include "API_O3_tcam.p4" 21 | 22 | control HLL_UPDATE( 23 | in bit<16> index, 24 | in bit<32> level) 25 | { 26 | 27 | Register, bit<16>>(32w2048) cs_table; 28 | 29 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 30 | void apply(inout bit<32> register_data, out bit<32> result) { 31 | if (level > register_data) { 32 | register_data = level; 33 | } 34 | } 35 | }; 36 | 37 | apply { 38 | cs_action.execute(index); 39 | } 40 | } 41 | 42 | control SwitchIngress( 43 | inout header_t hdr, 44 | inout metadata_t ig_md, 45 | in ingress_intrinsic_metadata_t ig_intr_md, 46 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 47 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 48 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 49 | 50 | lpm_optimization_32() tcam; 51 | HASH_COMPUTE_SRCIP_32_20(32w0x790900f3) sampling_hash; 52 | HASH_COMPUTE_SRCIP_16_11(32w0x30243f0b) index_hash; 53 | HLL_UPDATE() update; 54 | 55 | apply { 56 | 57 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 58 | sampling_hash.apply(hdr.ipv4.src_addr, ig_md.sampling_hash_value); 59 | tcam.apply(ig_md.sampling_hash_value, ig_md.level); 60 | 61 | index_hash.apply(hdr.ipv4.src_addr, ig_md.index); 62 | update.apply(ig_md.index, ig_md.level); 63 | } 64 | } 65 | } 66 | 67 | struct my_egress_headers_t { 68 | } 69 | 70 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 71 | 72 | struct my_egress_metadata_t { 73 | } 74 | 75 | parser EgressParser(packet_in pkt, 76 | /* User */ 77 | out my_egress_headers_t hdr, 78 | out my_egress_metadata_t meta, 79 | /* Intrinsic */ 80 | out egress_intrinsic_metadata_t eg_intr_md) 81 | { 82 | /* This is a mandatory state, required by Tofino Architecture */ 83 | state start { 84 | pkt.extract(eg_intr_md); 85 | transition accept; 86 | } 87 | } 88 | 89 | control EgressDeparser(packet_out pkt, 90 | /* User */ 91 | inout my_egress_headers_t hdr, 92 | in my_egress_metadata_t meta, 93 | /* Intrinsic */ 94 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 95 | { 96 | apply { 97 | pkt.emit(hdr); 98 | } 99 | } 100 | 101 | 102 | Pipeline( 103 | SwitchIngressParser(), 104 | SwitchIngress(), 105 | SwitchIngressDeparser(), 106 | EgressParser(), 107 | EmptyEgress(), 108 | EgressDeparser() 109 | ) pipe; 110 | 111 | Switch(pipe) main; 112 | -------------------------------------------------------------------------------- /p4_16/kary/p416_kary.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<16> epoch_index; 13 | bit<32> threshold; 14 | 15 | bit<16> res_all; 16 | bit<1> res_1; 17 | bit<1> res_2; 18 | bit<1> res_3; 19 | bit<1> res_4; 20 | bit<1> res_5; 21 | 22 | bit<32> est_1; 23 | bit<32> est_2; 24 | bit<32> est_3; 25 | // bit<32> est_4; 26 | // bit<32> est_5; 27 | 28 | bit<32> est_6; 29 | bit<32> est_7; 30 | bit<32> est_8; 31 | // bit<32> est_9; 32 | // bit<32> est_10; 33 | 34 | bit<32> diff_1; 35 | bit<32> diff_2; 36 | bit<32> diff_3; 37 | // bit<32> diff_4; 38 | // bit<32> diff_5; 39 | 40 | bit<1> c_1; 41 | bit<1> c_2; 42 | bit<1> c_3; 43 | bit<1> c_4; 44 | bit<1> c_5; 45 | 46 | bit<1> above_threshold; 47 | } 48 | 49 | #include "parser.p4" 50 | 51 | #include "API_common.p4" 52 | #include "API_O1_hash.p4" 53 | #include "API_O2_hash.p4" 54 | #include "API_O3_tcam.p4" 55 | #include "API_O5_salu.p4" 56 | #include "API_O6_flowkey_kary.p4" 57 | #include "API_threshold.p4" 58 | 59 | control EPOCH_INDEX(inout bit<16> epoch_index) 60 | { 61 | Register, bit<16>>(32w1024) epoch_index_table; 62 | RegisterAction, bit<16>, bit<32>>(epoch_index_table) epoch_index_action = { 63 | void apply(inout bit<32> register_data, out bit<32> result) { 64 | result = register_data; 65 | } 66 | }; 67 | 68 | apply { 69 | epoch_index = (bit<16>)epoch_index_action.execute(0); 70 | } 71 | } 72 | 73 | #define DEFINE_REGISTER(R, S, POLY) \ 74 | CRCPolynomial>(##POLY##,\ 75 | true, \ 76 | false, \ 77 | false, \ 78 | 32w0xFFFFFFFF, \ 79 | 32w0xFFFFFFFF \ 80 | ) poly_##R##; \ 81 | Hash>(HashAlgorithm_t.CUSTOM, poly_##R##) hash_##R##;\ 82 | Register, bit<16>>(32w4096) cs_table_##R##;\ 83 | RegisterAction, bit<16>, bit<32>>(cs_table_##R##) cs_update_##R## = {\ 84 | void apply(inout bit<32> register_data, out bit<32> result) {\ 85 | if (ig_md.res_##S## == 0) {\ 86 | register_data = register_data - 1;\ 87 | }\ 88 | else {\ 89 | register_data = register_data + 1;\ 90 | }\ 91 | result = register_data;\ 92 | }\ 93 | };\ 94 | RegisterAction, bit<16>, bit<32>>(cs_table_##R##) cs_read_##R## = {\ 95 | void apply(inout bit<32> register_data, out bit<32> result) {\ 96 | result = register_data;\ 97 | }\ 98 | }; 99 | 100 | #define UPDATE(R, S) \ 101 | ig_md.est_##R## = cs_update_##R##.execute(hash_##R##.get({hdr.ipv4.src_addr})); \ 102 | if (ig_md.res_##S## == 0) { \ 103 | ig_md.est_##R## = -ig_md.est_##R##; \ 104 | } 105 | 106 | #define READ(R, S) \ 107 | ig_md.est_##R## = cs_read_##R##.execute(hash_##R##.get({hdr.ipv4.src_addr})); \ 108 | if (ig_md.res_##S## == 0) { \ 109 | ig_md.est_##R## = -ig_md.est_##R##; \ 110 | } 111 | 112 | control SwitchIngress( 113 | inout header_t hdr, 114 | inout metadata_t ig_md, 115 | in ingress_intrinsic_metadata_t ig_intr_md, 116 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 117 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 118 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 119 | 120 | hash_consolidate_and_split_srcip(32w0x5b445b31) res_split; 121 | 122 | 123 | EPOCH_INDEX() get_epoch_index; 124 | 125 | GET_THRESHOLD() get_threshold; 126 | 127 | DEFINE_REGISTER(1, 1, 32w0x30243f0b) 128 | DEFINE_REGISTER(2, 2, 32w0x0f79f523) 129 | DEFINE_REGISTER(3, 3, 32w0x6b8cb0c5) 130 | // DEFINE_REGISTER(4, 4, 32w0x00390fc3) 131 | // DEFINE_REGISTER(5, 5, 32w0x298ac673) 132 | 133 | DEFINE_REGISTER(6, 1, 32w0x30243f0b) 134 | DEFINE_REGISTER(7, 2, 32w0x0f79f523) 135 | DEFINE_REGISTER(8, 3, 32w0x6b8cb0c5) 136 | // DEFINE_REGISTER(9, 4, 32w0x00390fc3) 137 | // DEFINE_REGISTER(10, 5, 32w0x298ac673) 138 | 139 | heavy_flowkey_storage() store_flowkey; 140 | 141 | apply { 142 | 143 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 144 | get_epoch_index.apply(ig_md.epoch_index); 145 | get_threshold.apply(hdr, ig_md); 146 | 147 | res_split.apply(hdr.ipv4.src_addr, ig_md.res_all, 148 | ig_md.res_1, 149 | ig_md.res_2, 150 | ig_md.res_3, 151 | ig_md.res_4, 152 | ig_md.res_5); 153 | 154 | 155 | if (ig_md.epoch_index % 2 == 0) { 156 | READ(1, 1) 157 | READ(2, 2) 158 | READ(3, 3) 159 | // READ(4, 4) 160 | // READ(5, 5) 161 | 162 | UPDATE(6, 1) 163 | UPDATE(7, 2) 164 | UPDATE(8, 3) 165 | // UPDATE(9, 4) 166 | // UPDATE(10, 5) 167 | 168 | ig_md.est_1 = ig_md.est_6 - ig_md.est_1; 169 | ig_md.est_2 = ig_md.est_7 - ig_md.est_2; 170 | ig_md.est_3 = ig_md.est_8 - ig_md.est_3; 171 | // ig_md.est_4 = ig_md.est_4 - ig_md.est_9; 172 | // ig_md.est_5 = ig_md.est_5 - ig_md.est_10; 173 | } 174 | else { 175 | UPDATE(1, 1) 176 | UPDATE(2, 2) 177 | UPDATE(3, 3) 178 | // UPDATE(4, 4) 179 | // UPDATE(5, 5) 180 | 181 | READ(6, 1) 182 | READ(7, 2) 183 | READ(8, 3) 184 | // READ(9, 4) 185 | // READ(10, 5) 186 | 187 | ig_md.est_1 = ig_md.est_1 - ig_md.est_6; 188 | ig_md.est_2 = ig_md.est_2 - ig_md.est_7; 189 | ig_md.est_3 = ig_md.est_3 - ig_md.est_8; 190 | // ig_md.diff_4 = ig_md.est_9 - ig_md.est_4; 191 | // ig_md.diff_5 = ig_md.est_10 - ig_md.est_5; 192 | } 193 | 194 | store_flowkey.apply(hdr, ig_md, ig_tm_md); 195 | 196 | } 197 | } 198 | } 199 | 200 | struct my_egress_headers_t { 201 | } 202 | 203 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 204 | 205 | struct my_egress_metadata_t { 206 | } 207 | 208 | parser EgressParser(packet_in pkt, 209 | /* User */ 210 | out my_egress_headers_t hdr, 211 | out my_egress_metadata_t meta, 212 | /* Intrinsic */ 213 | out egress_intrinsic_metadata_t eg_intr_md) 214 | { 215 | /* This is a mandatory state, required by Tofino Architecture */ 216 | state start { 217 | pkt.extract(eg_intr_md); 218 | transition accept; 219 | } 220 | } 221 | 222 | control EgressDeparser(packet_out pkt, 223 | /* User */ 224 | inout my_egress_headers_t hdr, 225 | in my_egress_metadata_t meta, 226 | /* Intrinsic */ 227 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 228 | { 229 | apply { 230 | pkt.emit(hdr); 231 | } 232 | } 233 | 234 | Pipeline( 235 | SwitchIngressParser(), 236 | SwitchIngress(), 237 | SwitchIngressDeparser(), 238 | EgressParser(), 239 | EmptyEgress(), 240 | EgressDeparser() 241 | ) pipe; 242 | 243 | Switch(pipe) main; 244 | -------------------------------------------------------------------------------- /p4_16/loglog/p416_loglog.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<32> sampling_hash; 13 | bit<32> level; 14 | bit<16> index; 15 | } 16 | 17 | #include "parser.p4" 18 | 19 | #include "API_common.p4" 20 | #include "API_O3_tcam.p4" 21 | 22 | control LL_UPDATE( 23 | in bit<16> index, 24 | in bit<32> level) 25 | { 26 | 27 | Register, bit<16>>(32w2048) cs_table; 28 | 29 | RegisterAction, bit<16>, bit<32>>(cs_table) cs_action = { 30 | void apply(inout bit<32> register_data, out bit<32> result) { 31 | if (level > register_data) { 32 | register_data = level; 33 | } 34 | } 35 | }; 36 | 37 | apply { 38 | cs_action.execute(index); 39 | } 40 | } 41 | 42 | control SwitchIngress( 43 | inout header_t hdr, 44 | inout metadata_t ig_md, 45 | in ingress_intrinsic_metadata_t ig_intr_md, 46 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 47 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 48 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 49 | 50 | lpm_optimization_32() tcam; 51 | LL_UPDATE() update; 52 | 53 | action split() { 54 | ig_md.sampling_hash = (bit<32>)hdr.ipv4.src_addr[19:0]; 55 | ig_md.index = (bit<16>)hdr.ipv4.src_addr[31:20]; 56 | } 57 | apply { 58 | 59 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 60 | split(); 61 | tcam.apply(ig_md.sampling_hash, ig_md.level); 62 | update.apply(ig_md.index, ig_md.level); 63 | } 64 | } 65 | } 66 | 67 | struct my_egress_headers_t { 68 | } 69 | 70 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 71 | 72 | struct my_egress_metadata_t { 73 | } 74 | 75 | parser EgressParser(packet_in pkt, 76 | /* User */ 77 | out my_egress_headers_t hdr, 78 | out my_egress_metadata_t meta, 79 | /* Intrinsic */ 80 | out egress_intrinsic_metadata_t eg_intr_md) 81 | { 82 | /* This is a mandatory state, required by Tofino Architecture */ 83 | state start { 84 | pkt.extract(eg_intr_md); 85 | transition accept; 86 | } 87 | } 88 | 89 | control EgressDeparser(packet_out pkt, 90 | /* User */ 91 | inout my_egress_headers_t hdr, 92 | in my_egress_metadata_t meta, 93 | /* Intrinsic */ 94 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 95 | { 96 | apply { 97 | pkt.emit(hdr); 98 | } 99 | } 100 | 101 | 102 | Pipeline( 103 | SwitchIngressParser(), 104 | SwitchIngress(), 105 | SwitchIngressDeparser(), 106 | EgressParser(), 107 | EmptyEgress(), 108 | EgressDeparser() 109 | ) pipe; 110 | 111 | Switch(pipe) main; 112 | -------------------------------------------------------------------------------- /p4_16/mrac/p416_mrac.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<15> sampling_hash_value; 13 | bit<16> level; 14 | bit<16> index; 15 | bit<16> base; 16 | bit<16> mem_index; 17 | } 18 | 19 | #include "parser.p4" 20 | 21 | #include "API_common.p4" 22 | #include "API_O1_hash.p4" 23 | #include "API_O2_hash.p4" 24 | #include "API_O3_tcam.p4" 25 | #include "API_O5_salu.p4" 26 | 27 | control SwitchIngress( 28 | inout header_t hdr, 29 | inout metadata_t ig_md, 30 | in ingress_intrinsic_metadata_t ig_intr_md, 31 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 32 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 33 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 34 | 35 | lpm_optimization_mrb() tcam; 36 | HASH_COMPUTE_SRCIP_15_15(32w0x790900f3) sampling_hash; 37 | HASH_COMPUTE_SRCIP_16_11(32w0x30243f0b) index_hash; 38 | consolidate_update_mrac() update; 39 | 40 | apply { 41 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 42 | sampling_hash.apply(hdr.ipv4.src_addr, ig_md.sampling_hash_value); 43 | tcam.apply(ig_md.sampling_hash_value, ig_md.level); 44 | index_hash.apply(hdr.ipv4.src_addr, ig_md.index); 45 | update.apply(ig_md.index, ig_md.level, ig_md.base, ig_md.mem_index); 46 | } 47 | } 48 | } 49 | 50 | struct my_egress_headers_t { 51 | } 52 | 53 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 54 | 55 | struct my_egress_metadata_t { 56 | } 57 | 58 | parser EgressParser(packet_in pkt, 59 | /* User */ 60 | out my_egress_headers_t hdr, 61 | out my_egress_metadata_t meta, 62 | /* Intrinsic */ 63 | out egress_intrinsic_metadata_t eg_intr_md) 64 | { 65 | /* This is a mandatory state, required by Tofino Architecture */ 66 | state start { 67 | pkt.extract(eg_intr_md); 68 | transition accept; 69 | } 70 | } 71 | 72 | control EgressDeparser(packet_out pkt, 73 | /* User */ 74 | inout my_egress_headers_t hdr, 75 | in my_egress_metadata_t meta, 76 | /* Intrinsic */ 77 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 78 | { 79 | apply { 80 | pkt.emit(hdr); 81 | } 82 | } 83 | 84 | 85 | Pipeline( 86 | SwitchIngressParser(), 87 | SwitchIngress(), 88 | SwitchIngressDeparser(), 89 | EgressParser(), 90 | EmptyEgress(), 91 | EgressDeparser() 92 | ) pipe; 93 | 94 | Switch(pipe) main; 95 | -------------------------------------------------------------------------------- /p4_16/mrb/p416_mrb.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<15> sampling_hash_value; 13 | bit<16> level; 14 | bit<16> index; 15 | bit<16> base; 16 | bit<16> mem_index; 17 | } 18 | 19 | #include "parser.p4" 20 | 21 | #include "API_common.p4" 22 | #include "API_O1_hash.p4" 23 | #include "API_O2_hash.p4" 24 | #include "API_O3_tcam.p4" 25 | #include "API_O5_salu.p4" 26 | 27 | control SwitchIngress( 28 | inout header_t hdr, 29 | inout metadata_t ig_md, 30 | in ingress_intrinsic_metadata_t ig_intr_md, 31 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 32 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 33 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 34 | 35 | lpm_optimization_mrb() tcam; 36 | HASH_COMPUTE_SRCIP_15_15(32w0x790900f3) sampling_hash; 37 | HASH_COMPUTE_SRCIP_16_12(32w0x30243f0b) index_hash; 38 | consolidate_update_mrb() update; 39 | 40 | apply { 41 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 42 | sampling_hash.apply(hdr.ipv4.src_addr, ig_md.sampling_hash_value); 43 | tcam.apply(ig_md.sampling_hash_value, ig_md.level); 44 | index_hash.apply(hdr.ipv4.src_addr, ig_md.index); 45 | update.apply(ig_md.index, ig_md.level, ig_md.base, ig_md.mem_index); 46 | } 47 | } 48 | } 49 | 50 | struct my_egress_headers_t { 51 | } 52 | 53 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 54 | 55 | struct my_egress_metadata_t { 56 | } 57 | 58 | parser EgressParser(packet_in pkt, 59 | /* User */ 60 | out my_egress_headers_t hdr, 61 | out my_egress_metadata_t meta, 62 | /* Intrinsic */ 63 | out egress_intrinsic_metadata_t eg_intr_md) 64 | { 65 | /* This is a mandatory state, required by Tofino Architecture */ 66 | state start { 67 | pkt.extract(eg_intr_md); 68 | transition accept; 69 | } 70 | } 71 | 72 | control EgressDeparser(packet_out pkt, 73 | /* User */ 74 | inout my_egress_headers_t hdr, 75 | in my_egress_metadata_t meta, 76 | /* Intrinsic */ 77 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 78 | { 79 | apply { 80 | pkt.emit(hdr); 81 | } 82 | } 83 | 84 | 85 | Pipeline( 86 | SwitchIngressParser(), 87 | SwitchIngress(), 88 | SwitchIngressDeparser(), 89 | EgressParser(), 90 | EmptyEgress(), 91 | EgressDeparser() 92 | ) pipe; 93 | 94 | Switch(pipe) main; 95 | -------------------------------------------------------------------------------- /p4_16/pcsa/p416_pcsa.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<32> sampling_hash_value; 13 | bit<32> level; 14 | bit<16> index; 15 | bit<16> base; 16 | bit<16> mem_index; 17 | } 18 | 19 | #include "parser.p4" 20 | 21 | #include "API_common.p4" 22 | #include "API_O1_hash.p4" 23 | #include "API_O2_hash.p4" 24 | #include "API_O3_tcam.p4" 25 | #include "API_O5_salu.p4" 26 | 27 | control SwitchIngress( 28 | inout header_t hdr, 29 | inout metadata_t ig_md, 30 | in ingress_intrinsic_metadata_t ig_intr_md, 31 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 32 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 33 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 34 | 35 | lpm_optimization_32() tcam; 36 | 37 | HASH_COMPUTE_SRCIP_32_20(32w0x790900f3) sampling_hash; 38 | HASH_COMPUTE_SRCIP_16_5(32w0x30243f0b) index_hash; 39 | consolidate_update_pcsa() update; 40 | 41 | apply { 42 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 43 | index_hash.apply(hdr.ipv4.src_addr, ig_md.index); 44 | sampling_hash.apply(hdr.ipv4.src_addr, ig_md.sampling_hash_value); 45 | tcam.apply(ig_md.sampling_hash_value, ig_md.level); 46 | update.apply(ig_md.index, (bit<16>)ig_md.level, ig_md.base, ig_md.mem_index); 47 | } 48 | } 49 | } 50 | 51 | struct my_egress_headers_t { 52 | } 53 | 54 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 55 | 56 | struct my_egress_metadata_t { 57 | } 58 | 59 | parser EgressParser(packet_in pkt, 60 | /* User */ 61 | out my_egress_headers_t hdr, 62 | out my_egress_metadata_t meta, 63 | /* Intrinsic */ 64 | out egress_intrinsic_metadata_t eg_intr_md) 65 | { 66 | /* This is a mandatory state, required by Tofino Architecture */ 67 | state start { 68 | pkt.extract(eg_intr_md); 69 | transition accept; 70 | } 71 | } 72 | 73 | control EgressDeparser(packet_out pkt, 74 | /* User */ 75 | inout my_egress_headers_t hdr, 76 | in my_egress_metadata_t meta, 77 | /* Intrinsic */ 78 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 79 | { 80 | apply { 81 | pkt.emit(hdr); 82 | } 83 | } 84 | 85 | 86 | Pipeline( 87 | SwitchIngressParser(), 88 | SwitchIngress(), 89 | SwitchIngressDeparser(), 90 | EgressParser(), 91 | EmptyEgress(), 92 | EgressDeparser() 93 | ) pipe; 94 | 95 | Switch(pipe) main; 96 | -------------------------------------------------------------------------------- /p4_16/rhhh/p416_rhhh.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<5> random_bits; 13 | bit<16> level; 14 | bit<16> base; 15 | bit<32> threshold; 16 | bit<32> s_mask; 17 | bit<32> d_mask; 18 | 19 | bit<32> masked_srcip; 20 | bit<32> masked_dstip; 21 | bit<64> flowkey; 22 | 23 | bit<16> index_1; 24 | bit<16> index_2; 25 | bit<16> index_3; 26 | bit<16> index_4; 27 | bit<16> index_5; 28 | 29 | // bit<5> res_all; 30 | bit<16> res_all; 31 | bit<1> res_1; 32 | bit<1> res_2; 33 | bit<1> res_3; 34 | bit<1> res_4; 35 | bit<1> res_5; 36 | 37 | bit<32> est_1; 38 | bit<32> est_2; 39 | bit<32> est_3; 40 | bit<32> est_4; 41 | bit<32> est_5; 42 | 43 | bit<16> base_1; 44 | bit<16> base_2; 45 | bit<16> base_3; 46 | bit<16> base_4; 47 | bit<16> base_5; 48 | 49 | bit<16> mem_index_1; 50 | bit<16> mem_index_2; 51 | bit<16> mem_index_3; 52 | bit<16> mem_index_4; 53 | bit<16> mem_index_5; 54 | 55 | bit<1> c_1; 56 | bit<1> c_2; 57 | bit<1> c_3; 58 | bit<1> c_4; 59 | bit<1> c_5; 60 | 61 | bit<1> above_threshold; 62 | 63 | bit<32> hash_entry_srcip; 64 | bit<32> hash_entry_dstip; 65 | bit<8> hash_entry_level; 66 | 67 | bit<32> diff_srcip; 68 | bit<32> diff_dstip; 69 | bit<8> diff_level; 70 | } 71 | 72 | #include "parser.p4" 73 | 74 | #include "API_common.p4" 75 | #include "API_O1_hash.p4" 76 | #include "API_O2_hash.p4" 77 | #include "API_O3_tcam.p4" 78 | #include "API_O5_salu.p4" 79 | #include "API_O6_flowkey_rhhh.p4" 80 | 81 | control SwitchIngress( 82 | inout header_t hdr, 83 | inout metadata_t ig_md, 84 | in ingress_intrinsic_metadata_t ig_intr_md, 85 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 86 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 87 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 88 | 89 | CALC_RNG() calc_rng; 90 | select_key() sram; 91 | 92 | hash_consolidate_and_split_srcip_dstip(32w0x5b445b31) res_split; 93 | HASH_COMPUTE_SRCIP_DSTIP_16_11(32w0x30243f0b) index_hash_1; 94 | HASH_COMPUTE_SRCIP_DSTIP_16_11(32w0x0f79f523) index_hash_2; 95 | HASH_COMPUTE_SRCIP_DSTIP_16_11(32w0x6b8cb0c5) index_hash_3; 96 | HASH_COMPUTE_SRCIP_DSTIP_16_11(32w0x00390fc3) index_hash_4; 97 | HASH_COMPUTE_SRCIP_DSTIP_16_11(32w0x298ac673) index_hash_5; 98 | 99 | consolidate_update_rhhh() update_1; 100 | consolidate_update_rhhh() update_2; 101 | consolidate_update_rhhh() update_3; 102 | // consolidate_update_rhhh() update_4; 103 | // consolidate_update_rhhh() update_5; 104 | 105 | heavy_flowkey_storage_rhhh() store_flowkey; 106 | 107 | apply { 108 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 109 | calc_rng.apply(ig_md.random_bits); 110 | if (0 < ig_md.random_bits && ig_md.random_bits < 25) { 111 | sram.apply(ig_md.random_bits, ig_md.level, ig_md.base, ig_md.threshold, ig_md.s_mask, ig_md.d_mask, ig_md.masked_srcip, ig_md.masked_dstip, hdr.ipv4.src_addr, hdr.ipv4.dst_addr); 112 | 113 | res_split.apply(ig_md.masked_srcip, ig_md.masked_dstip, ig_md.res_all, 114 | ig_md.res_1, 115 | ig_md.res_2, 116 | ig_md.res_3, 117 | ig_md.res_4, 118 | ig_md.res_5); 119 | 120 | index_hash_1.apply(ig_md.masked_srcip, ig_md.masked_dstip, ig_md.index_1); 121 | index_hash_2.apply(ig_md.masked_srcip, ig_md.masked_dstip, ig_md.index_2); 122 | index_hash_3.apply(ig_md.masked_srcip, ig_md.masked_dstip, ig_md.index_3); 123 | index_hash_4.apply(ig_md.masked_srcip, ig_md.masked_dstip, ig_md.index_4); 124 | index_hash_5.apply(ig_md.masked_srcip, ig_md.masked_dstip, ig_md.index_5); 125 | 126 | update_1.apply(ig_md.index_1, ig_md.res_1, ig_md.level, ig_md.base_1, ig_md.mem_index_1, ig_md.est_1); 127 | update_2.apply(ig_md.index_2, ig_md.res_2, ig_md.level, ig_md.base_2, ig_md.mem_index_2, ig_md.est_2); 128 | update_3.apply(ig_md.index_3, ig_md.res_3, ig_md.level, ig_md.base_3, ig_md.mem_index_3, ig_md.est_3); 129 | // update_4.apply(ig_md.index_4, ig_md.res_4, ig_md.level, ig_md.base_4, ig_md.mem_index_4, ig_md.est_4); 130 | // update_5.apply(ig_md.index_5, ig_md.res_5, ig_md.level, ig_md.base_5, ig_md.mem_index_5, ig_md.est_5); 131 | 132 | store_flowkey.apply(hdr, ig_md, ig_tm_md); 133 | } 134 | } 135 | } 136 | } 137 | 138 | struct my_egress_headers_t { 139 | } 140 | 141 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 142 | 143 | struct my_egress_metadata_t { 144 | } 145 | 146 | parser EgressParser(packet_in pkt, 147 | /* User */ 148 | out my_egress_headers_t hdr, 149 | out my_egress_metadata_t meta, 150 | /* Intrinsic */ 151 | out egress_intrinsic_metadata_t eg_intr_md) 152 | { 153 | /* This is a mandatory state, required by Tofino Architecture */ 154 | state start { 155 | pkt.extract(eg_intr_md); 156 | transition accept; 157 | } 158 | } 159 | 160 | control EgressDeparser(packet_out pkt, 161 | /* User */ 162 | inout my_egress_headers_t hdr, 163 | in my_egress_metadata_t meta, 164 | /* Intrinsic */ 165 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 166 | { 167 | apply { 168 | pkt.emit(hdr); 169 | } 170 | } 171 | 172 | 173 | Pipeline( 174 | SwitchIngressParser(), 175 | SwitchIngress(), 176 | SwitchIngressDeparser(), 177 | EgressParser(), 178 | EmptyEgress(), 179 | EgressDeparser() 180 | ) pipe; 181 | 182 | Switch(pipe) main; 183 | -------------------------------------------------------------------------------- /p4_16/sketchlearn/p416_sketchlearn.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<16> index; 13 | 14 | bit<1> f1; 15 | bit<1> f2; 16 | bit<1> f3; 17 | bit<1> f4; 18 | bit<1> f5; 19 | bit<1> f6; 20 | bit<1> f7; 21 | bit<1> f8; 22 | bit<1> f9; 23 | bit<1> f10; 24 | 25 | bit<1> f11; 26 | bit<1> f12; 27 | bit<1> f13; 28 | bit<1> f14; 29 | bit<1> f15; 30 | bit<1> f16; 31 | bit<1> f17; 32 | bit<1> f18; 33 | bit<1> f19; 34 | bit<1> f20; 35 | 36 | bit<1> f21; 37 | bit<1> f22; 38 | bit<1> f23; 39 | bit<1> f24; 40 | bit<1> f25; 41 | bit<1> f26; 42 | bit<1> f27; 43 | bit<1> f28; 44 | bit<1> f29; 45 | bit<1> f30; 46 | 47 | bit<1> f31; 48 | bit<1> f32; 49 | } 50 | 51 | #include "parser.p4" 52 | 53 | #include "API_common.p4" 54 | #include "API_O1_hash.p4" 55 | #include "API_O2_hash.p4" 56 | #include "API_O3_tcam.p4" 57 | #include "API_O5_salu.p4" 58 | 59 | #define DEFINE_REGISTER(R) \ 60 | Register, bit<16>>(32w4096) reg_table_##R##;\ 61 | RegisterAction, bit<16>, bit<32>>(reg_table_##R##) reg_update_##R## = {\ 62 | void apply(inout bit<32> register_data, out bit<32> result) {\ 63 | register_data = register_data + 1;\ 64 | }\ 65 | }; 66 | 67 | #define UPDATE(R) \ 68 | reg_update_##R##.execute(ig_md.index); 69 | 70 | #define APPLY(R) \ 71 | if (ig_md.f##R## == 1) { \ 72 | UPDATE(##R##) \ 73 | } 74 | 75 | #define SPLIT(R) \ 76 | ig_md.f##R## = hdr.ipv4.src_addr[##R##:##R##]; 77 | 78 | control SwitchIngress( 79 | inout header_t hdr, 80 | inout metadata_t ig_md, 81 | in ingress_intrinsic_metadata_t ig_intr_md, 82 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 83 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 84 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 85 | 86 | DEFINE_REGISTER(1) 87 | DEFINE_REGISTER(2) 88 | DEFINE_REGISTER(3) 89 | DEFINE_REGISTER(4) 90 | DEFINE_REGISTER(5) 91 | DEFINE_REGISTER(6) 92 | DEFINE_REGISTER(7) 93 | DEFINE_REGISTER(8) 94 | DEFINE_REGISTER(9) 95 | DEFINE_REGISTER(10) 96 | 97 | DEFINE_REGISTER(11) 98 | DEFINE_REGISTER(12) 99 | DEFINE_REGISTER(13) 100 | DEFINE_REGISTER(14) 101 | DEFINE_REGISTER(15) 102 | DEFINE_REGISTER(16) 103 | DEFINE_REGISTER(17) 104 | DEFINE_REGISTER(18) 105 | DEFINE_REGISTER(19) 106 | DEFINE_REGISTER(20) 107 | 108 | DEFINE_REGISTER(21) 109 | DEFINE_REGISTER(22) 110 | DEFINE_REGISTER(23) 111 | DEFINE_REGISTER(24) 112 | DEFINE_REGISTER(25) 113 | DEFINE_REGISTER(26) 114 | DEFINE_REGISTER(27) 115 | DEFINE_REGISTER(28) 116 | DEFINE_REGISTER(29) 117 | DEFINE_REGISTER(30) 118 | 119 | DEFINE_REGISTER(31) 120 | DEFINE_REGISTER(32) 121 | 122 | HASH_COMPUTE_SRCIP_16_11(32w0x30243f0b) index_hash; 123 | 124 | action split() { 125 | SPLIT(1) 126 | SPLIT(2) 127 | SPLIT(3) 128 | SPLIT(4) 129 | SPLIT(5) 130 | SPLIT(6) 131 | SPLIT(7) 132 | SPLIT(8) 133 | SPLIT(9) 134 | SPLIT(10) 135 | 136 | SPLIT(11) 137 | SPLIT(12) 138 | SPLIT(13) 139 | SPLIT(14) 140 | SPLIT(15) 141 | SPLIT(16) 142 | SPLIT(17) 143 | SPLIT(18) 144 | SPLIT(19) 145 | SPLIT(20) 146 | 147 | SPLIT(21) 148 | SPLIT(22) 149 | SPLIT(23) 150 | SPLIT(24) 151 | SPLIT(25) 152 | SPLIT(26) 153 | SPLIT(27) 154 | SPLIT(28) 155 | SPLIT(29) 156 | SPLIT(30) 157 | 158 | SPLIT(31) 159 | ig_md.f32 = hdr.ipv4.src_addr[0:0]; 160 | } 161 | apply { 162 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 163 | split(); 164 | index_hash.apply(hdr.ipv4.src_addr, ig_md.index); 165 | APPLY(1) 166 | APPLY(2) 167 | APPLY(3) 168 | APPLY(4) 169 | APPLY(5) 170 | APPLY(6) 171 | APPLY(7) 172 | APPLY(8) 173 | APPLY(9) 174 | APPLY(10) 175 | 176 | APPLY(11) 177 | APPLY(12) 178 | APPLY(13) 179 | APPLY(14) 180 | APPLY(15) 181 | APPLY(16) 182 | APPLY(17) 183 | APPLY(18) 184 | APPLY(19) 185 | APPLY(20) 186 | 187 | APPLY(21) 188 | APPLY(22) 189 | APPLY(23) 190 | APPLY(24) 191 | APPLY(25) 192 | APPLY(26) 193 | APPLY(27) 194 | APPLY(28) 195 | APPLY(29) 196 | APPLY(30) 197 | 198 | APPLY(31) 199 | APPLY(32) 200 | } 201 | } 202 | } 203 | 204 | struct my_egress_headers_t { 205 | } 206 | 207 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 208 | 209 | struct my_egress_metadata_t { 210 | } 211 | 212 | parser EgressParser(packet_in pkt, 213 | /* User */ 214 | out my_egress_headers_t hdr, 215 | out my_egress_metadata_t meta, 216 | /* Intrinsic */ 217 | out egress_intrinsic_metadata_t eg_intr_md) 218 | { 219 | /* This is a mandatory state, required by Tofino Architecture */ 220 | state start { 221 | pkt.extract(eg_intr_md); 222 | transition accept; 223 | } 224 | } 225 | 226 | control EgressDeparser(packet_out pkt, 227 | /* User */ 228 | inout my_egress_headers_t hdr, 229 | in my_egress_metadata_t meta, 230 | /* Intrinsic */ 231 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 232 | { 233 | apply { 234 | pkt.emit(hdr); 235 | } 236 | } 237 | 238 | Pipeline( 239 | SwitchIngressParser(), 240 | SwitchIngress(), 241 | SwitchIngressDeparser(), 242 | EgressParser(), 243 | EmptyEgress(), 244 | EgressDeparser() 245 | ) pipe; 246 | 247 | Switch(pipe) main; 248 | 249 | -------------------------------------------------------------------------------- /p4_16/spreadsketch/p416_spreadsketch.p4: -------------------------------------------------------------------------------- 1 | // This code is written based on the original paper's implementation 2 | // https://github.com/Grace-TL/SpreadSketch/blob/master/p4/ss.p4 3 | 4 | #include 5 | #if __TARGET_TOFINO__ == 2 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | #include "headers.p4" 12 | #include "util.p4" 13 | 14 | struct metadata_t { 15 | bit<32> srcip_dstip_hash; 16 | bit<32> level; 17 | bit<32> short_level; 18 | 19 | bit<32> index_1; 20 | bit<32> index_2; 21 | bit<32> index_3; 22 | 23 | bit<32> base_1_1; 24 | bit<32> base_2_1; 25 | bit<32> base_3_1; 26 | 27 | bit<32> base_1_2; 28 | bit<32> base_2_2; 29 | bit<32> base_3_2; 30 | 31 | bit<32> mem_index_1; 32 | bit<32> mem_index_2; 33 | bit<32> mem_index_3; 34 | } 35 | 36 | #include "parser.p4" 37 | 38 | #include "API_common.p4" 39 | #include "API_O1_hash.p4" 40 | #include "API_O2_hash.p4" 41 | #include "API_O3_tcam.p4" 42 | #include "API_O5_salu.p4" 43 | 44 | control max_level( 45 | in bit<32> srcIP, 46 | in bit<32> index, 47 | in bit<32> level) 48 | { 49 | Register, bit<32>>(2048) store_max_level; 50 | Register, bit<32>>(2048) store_candidate_ss_srcIP; 51 | 52 | RegisterAction, bit<32>, bit<1>>(store_max_level) max_level_action = { 53 | void apply(inout bit<32> register_data, out bit<1> result) { 54 | if (level > register_data) { 55 | register_data = level; 56 | result = 1; 57 | } 58 | else { 59 | result = 0; 60 | } 61 | } 62 | }; 63 | 64 | RegisterAction, bit<32>, bit<32>>(store_candidate_ss_srcIP) candidate_ss_srcIP_action = { 65 | void apply(inout bit<32> register_data, out bit<32> result) { 66 | register_data = srcIP; 67 | } 68 | }; 69 | 70 | apply{ 71 | bit<1> result; 72 | result = max_level_action.execute(index); 73 | if (result == 1) { 74 | candidate_ss_srcIP_action.execute(index); 75 | } 76 | } 77 | } 78 | 79 | control SwitchIngress( 80 | inout header_t hdr, 81 | inout metadata_t ig_md, 82 | in ingress_intrinsic_metadata_t ig_intr_md, 83 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 84 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 85 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 86 | 87 | HASH_COMPUTE_SRCIP_DSTIP_32_32(32w0x790900f3) sampling_hash; 88 | lpm_optimization_32() tcam; 89 | 90 | HASH_COMPUTE_SRCIP_32_11(32w0x30243f0b) index_hash_1; 91 | HASH_COMPUTE_SRCIP_32_11(32w0x0f79f523) index_hash_2; 92 | HASH_COMPUTE_SRCIP_32_11(32w0x6b8cb0c5) index_hash_3; 93 | 94 | consolidate_update_ss() update_sketch_1; 95 | consolidate_update_ss() update_sketch_2; 96 | consolidate_update_ss() update_sketch_3; 97 | 98 | max_level() update_info_1; 99 | max_level() update_info_2; 100 | max_level() update_info_3; 101 | 102 | apply { 103 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 104 | sampling_hash.apply(hdr.ipv4.src_addr, hdr.ipv4.dst_addr, ig_md.srcip_dstip_hash); 105 | tcam.apply(ig_md.srcip_dstip_hash, ig_md.level); 106 | 107 | ig_md.short_level = ig_md.level; 108 | if(ig_md.level > 3) { 109 | ig_md.short_level = 4; 110 | } 111 | 112 | index_hash_1.apply(hdr.ipv4.src_addr, ig_md.index_1); 113 | index_hash_2.apply(hdr.ipv4.src_addr, ig_md.index_2); 114 | index_hash_3.apply(hdr.ipv4.src_addr, ig_md.index_3); 115 | 116 | update_sketch_1.apply(ig_md.index_1, ig_md.srcip_dstip_hash, ig_md.short_level, ig_md.base_1_1, ig_md.base_1_2, ig_md.mem_index_1); 117 | update_sketch_2.apply(ig_md.index_2, ig_md.srcip_dstip_hash, ig_md.short_level, ig_md.base_2_1, ig_md.base_2_2, ig_md.mem_index_2); 118 | update_sketch_3.apply(ig_md.index_3, ig_md.srcip_dstip_hash, ig_md.short_level, ig_md.base_3_1, ig_md.base_3_2, ig_md.mem_index_3); 119 | 120 | update_info_1.apply(hdr.ipv4.src_addr, ig_md.index_1, ig_md.level); 121 | update_info_2.apply(hdr.ipv4.src_addr, ig_md.index_2, ig_md.level); 122 | update_info_3.apply(hdr.ipv4.src_addr, ig_md.index_3, ig_md.level); 123 | } 124 | } 125 | } 126 | 127 | struct my_egress_headers_t { 128 | } 129 | 130 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 131 | 132 | struct my_egress_metadata_t { 133 | } 134 | 135 | parser EgressParser(packet_in pkt, 136 | /* User */ 137 | out my_egress_headers_t hdr, 138 | out my_egress_metadata_t meta, 139 | /* Intrinsic */ 140 | out egress_intrinsic_metadata_t eg_intr_md) 141 | { 142 | /* This is a mandatory state, required by Tofino Architecture */ 143 | state start { 144 | pkt.extract(eg_intr_md); 145 | transition accept; 146 | } 147 | } 148 | 149 | control EgressDeparser(packet_out pkt, 150 | /* User */ 151 | inout my_egress_headers_t hdr, 152 | in my_egress_metadata_t meta, 153 | /* Intrinsic */ 154 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 155 | { 156 | apply { 157 | pkt.emit(hdr); 158 | } 159 | } 160 | 161 | 162 | Pipeline( 163 | SwitchIngressParser(), 164 | SwitchIngress(), 165 | SwitchIngressDeparser(), 166 | EgressParser(), 167 | EmptyEgress(), 168 | EgressDeparser() 169 | ) pipe; 170 | 171 | Switch(pipe) main; 172 | -------------------------------------------------------------------------------- /p4_16/univmon/p416_univmon.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #if __TARGET_TOFINO__ == 2 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #include "headers.p4" 9 | #include "util.p4" 10 | 11 | struct metadata_t { 12 | bit<16> sampling_hash_value; 13 | bit<16> level; 14 | bit<16> base; 15 | bit<32> threshold; 16 | 17 | bit<16> index_1; 18 | bit<16> index_2; 19 | bit<16> index_3; 20 | bit<16> index_4; 21 | bit<16> index_5; 22 | 23 | // bit<5> res_all; 24 | bit<16> res_all; 25 | bit<1> res_1; 26 | bit<1> res_2; 27 | bit<1> res_3; 28 | bit<1> res_4; 29 | bit<1> res_5; 30 | 31 | bit<32> est_1; 32 | bit<32> est_2; 33 | bit<32> est_3; 34 | bit<32> est_4; 35 | bit<32> est_5; 36 | 37 | bit<16> base_1; 38 | bit<16> base_2; 39 | bit<16> base_3; 40 | bit<16> base_4; 41 | bit<16> base_5; 42 | 43 | bit<16> mem_index_1; 44 | bit<16> mem_index_2; 45 | bit<16> mem_index_3; 46 | bit<16> mem_index_4; 47 | bit<16> mem_index_5; 48 | 49 | bit<1> c_1; 50 | bit<1> c_2; 51 | bit<1> c_3; 52 | bit<1> c_4; 53 | bit<1> c_5; 54 | 55 | bit<1> above_threshold; 56 | } 57 | 58 | #include "parser.p4" 59 | 60 | #include "API_common.p4" 61 | #include "API_O1_hash.p4" 62 | #include "API_O2_hash.p4" 63 | #include "API_O3_tcam.p4" 64 | #include "API_O5_salu.p4" 65 | #include "API_O6_flowkey.p4" 66 | 67 | control SwitchIngress( 68 | inout header_t hdr, 69 | inout metadata_t ig_md, 70 | in ingress_intrinsic_metadata_t ig_intr_md, 71 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 72 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 73 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 74 | 75 | lpm_optimization() tcam; 76 | 77 | HASH_COMPUTE_SRCIP_16_16(32w0x790900f3) sampling_hash; 78 | hash_consolidate_and_split_srcip(32w0x5b445b31) res_split; 79 | HASH_COMPUTE_SRCIP_16_11(32w0x30243f0b) index_hash_1; 80 | HASH_COMPUTE_SRCIP_16_11(32w0x0f79f523) index_hash_2; 81 | HASH_COMPUTE_SRCIP_16_11(32w0x6b8cb0c5) index_hash_3; 82 | HASH_COMPUTE_SRCIP_16_11(32w0x00390fc3) index_hash_4; 83 | HASH_COMPUTE_SRCIP_16_11(32w0x298ac673) index_hash_5; 84 | 85 | consolidate_update_univmon() update_1; 86 | consolidate_update_univmon() update_2; 87 | consolidate_update_univmon() update_3; 88 | consolidate_update_univmon() update_4; 89 | consolidate_update_univmon() update_5; 90 | 91 | heavy_flowkey_storage() store_flowkey; 92 | 93 | apply { 94 | 95 | if(hdr.ethernet.ether_type == ETHERTYPE_IPV4) { 96 | sampling_hash.apply(hdr.ipv4.src_addr, ig_md.sampling_hash_value); 97 | tcam.apply(ig_md.sampling_hash_value, ig_md.level, ig_md.base, ig_md.threshold); 98 | 99 | res_split.apply(hdr.ipv4.src_addr, ig_md.res_all, 100 | ig_md.res_1, 101 | ig_md.res_2, 102 | ig_md.res_3, 103 | ig_md.res_4, 104 | ig_md.res_5); 105 | 106 | index_hash_1.apply(hdr.ipv4.src_addr, ig_md.index_1); 107 | index_hash_2.apply(hdr.ipv4.src_addr, ig_md.index_2); 108 | index_hash_3.apply(hdr.ipv4.src_addr, ig_md.index_3); 109 | index_hash_4.apply(hdr.ipv4.src_addr, ig_md.index_4); 110 | index_hash_5.apply(hdr.ipv4.src_addr, ig_md.index_5); 111 | 112 | if ((bit<10>)ig_md.level <= 16) { 113 | update_1.apply(ig_md.index_1, ig_md.res_1, ig_md.level, ig_md.base_1, ig_md.mem_index_1, ig_md.est_1); 114 | update_2.apply(ig_md.index_2, ig_md.res_2, ig_md.level, ig_md.base_2, ig_md.mem_index_2, ig_md.est_2); 115 | update_3.apply(ig_md.index_3, ig_md.res_3, ig_md.level, ig_md.base_3, ig_md.mem_index_3, ig_md.est_3); 116 | update_4.apply(ig_md.index_4, ig_md.res_4, ig_md.level, ig_md.base_4, ig_md.mem_index_4, ig_md.est_4); 117 | update_5.apply(ig_md.index_5, ig_md.res_5, ig_md.level, ig_md.base_5, ig_md.mem_index_5, ig_md.est_5); 118 | 119 | store_flowkey.apply(hdr, ig_md, ig_tm_md); 120 | } 121 | } 122 | } 123 | } 124 | 125 | struct my_egress_headers_t { 126 | } 127 | 128 | /******** G L O B A L E G R E S S M E T A D A T A *********/ 129 | 130 | struct my_egress_metadata_t { 131 | } 132 | 133 | parser EgressParser(packet_in pkt, 134 | /* User */ 135 | out my_egress_headers_t hdr, 136 | out my_egress_metadata_t meta, 137 | /* Intrinsic */ 138 | out egress_intrinsic_metadata_t eg_intr_md) 139 | { 140 | /* This is a mandatory state, required by Tofino Architecture */ 141 | state start { 142 | pkt.extract(eg_intr_md); 143 | transition accept; 144 | } 145 | } 146 | 147 | control EgressDeparser(packet_out pkt, 148 | /* User */ 149 | inout my_egress_headers_t hdr, 150 | in my_egress_metadata_t meta, 151 | /* Intrinsic */ 152 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 153 | { 154 | apply { 155 | pkt.emit(hdr); 156 | } 157 | } 158 | 159 | 160 | Pipeline( 161 | SwitchIngressParser(), 162 | SwitchIngress(), 163 | SwitchIngressDeparser(), 164 | EgressParser(), 165 | EmptyEgress(), 166 | EgressDeparser() 167 | ) pipe; 168 | 169 | Switch(pipe) main; 170 | --------------------------------------------------------------------------------