├── .gitignore ├── LICENSE ├── README.md ├── control_plane └── rules.md ├── data_plane ├── cheetah_distinct.p4 ├── cheetah_filtering.p4 ├── cheetah_groupby.p4 ├── cheetah_join.p4 ├── cheetah_lru_import_efficient.p4 ├── cheetah_lru_import_efficient_2.p4 ├── cheetah_lru_import_efficient_3.p4 ├── cheetah_lru_import_efficient_4.p4 ├── cheetah_skyline.p4 └── cheetah_topn.p4 └── host ├── Makefile_master ├── Makefile_worker ├── build.sh ├── cheetah_aggregate_processing.c ├── cheetah_aggregate_processing.h ├── cheetah_benchmark.c ├── cheetah_benchmark.h ├── cheetah_constants.h ├── cheetah_control_flow.c ├── cheetah_control_flow.h ├── cheetah_control_message.c ├── cheetah_control_message.h ├── cheetah_dpdk.c ├── cheetah_dpdk.h ├── cheetah_hdfs_backend.c ├── cheetah_hdfs_backend.h ├── cheetah_join.c ├── cheetah_join.h ├── cheetah_master.c ├── cheetah_memory_sim.c ├── cheetah_memory_sim.h ├── cheetah_resource_manager.c ├── cheetah_resource_manager.h ├── cheetah_worker.c ├── connection_state.c ├── connection_state.h ├── control_flow_constants.py ├── control_message_manager.c ├── control_message_manager.h ├── fast_packet_stream.c ├── fast_packet_stream.h ├── filter_offline_validator.py ├── meson.build ├── packet_crafter.c ├── packet_crafter.h ├── packet_manager.c ├── packet_manager.h ├── packet_stream_receiver.c ├── packet_stream_receiver.h ├── receive_ack_end.py └── send_ack_end.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Swap 2 | [._]*.s[a-v][a-z] 3 | !*.svg # comment out if you don't need vector files 4 | [._]*.sw[a-p] 5 | [._]s[a-rt-v][a-z] 6 | [._]ss[a-gi-z] 7 | [._]sw[a-p] 8 | 9 | # Session 10 | Session.vim 11 | Sessionx.vim 12 | 13 | # Temporary 14 | .netrwhist 15 | *~ 16 | # Auto-generated tag files 17 | tags 18 | # Persistent undo 19 | [._]*.un~ 20 | 21 | .DS_Store 22 | 23 | # Prerequisites 24 | *.d 25 | 26 | # Object files 27 | *.o 28 | *.ko 29 | *.obj 30 | *.elf 31 | 32 | # Linker output 33 | *.ilk 34 | *.map 35 | *.exp 36 | 37 | # Precompiled Headers 38 | *.gch 39 | *.pch 40 | 41 | # Libraries 42 | *.lib 43 | *.a 44 | *.la 45 | *.lo 46 | 47 | # Shared objects (inc. Windows DLLs) 48 | *.dll 49 | *.so 50 | *.so.* 51 | *.dylib 52 | 53 | # Executables 54 | *.exe 55 | *.out 56 | *.app 57 | *.i*86 58 | *.x86_64 59 | *.hex 60 | 61 | # Debug files 62 | *.dSYM/ 63 | *.su 64 | *.idb 65 | *.pdb 66 | 67 | # Kernel Module Compile Results 68 | *.mod* 69 | *.cmd 70 | .tmp_versions/ 71 | modules.order 72 | Module.symvers 73 | Mkfile.old 74 | dkms.conf 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Harvard Cloud Networking and Systems Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cheetah 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | 5 | Cheetah is a system that optimizes queries using programmable switches. 6 | 7 | ## Related publications 8 | * Cheetah: Accelerating Database Queries with Switch Pruning (ACM SIGMOD 2020) \[[link](https://dl.acm.org/doi/10.1145/3318464.3389698)\] 9 | * Extended version (Arxiv 2020) \[[link](https://arxiv.org/abs/2004.05076)\] 10 | * Poster (ACM SIGCOMM 2019) \[[link](https://dl.acm.org/doi/10.1145/3342280.3342311)\] 11 | 12 | ## Repository structure 13 | The code in this repository is classified into three categories. 14 | 15 | ### Data Plane 16 | The `data_plane` directory contains code designed for Intel's [Barefoot Tofino](https://barefootnetworks.com/products/brief-tofino/) programmable switch. The code is written in a Tofino-specific variant of the P4-14 programming language. See [here](https://p4.org/) for more information on standard P4. 17 | 18 | ### Control Plane 19 | The `control_plane` directory contains the control plane rules you need to install to enable pruning for the queries implemented in the data plane. They are in a markdown file with separate sections for each query. The rules in each section are intended to be installed in the same order they are presented. 20 | 21 | ### Host 22 | The `host` directory contains code used to serialize / deserialize any given list of values into a cheetah packet. This code is generic and does not make any assumptions regarding the query engine you are using. You can make it work with any kind of query engine or key value store as long as you write some patchwork code to allow Cheetah's packet serializer / deserializer to understand the file format(s) of the system you are integrating Cheetah with. Cheetah's packet serializer and deserializer is optimized using Intel's Dataplane Development Kit ([DPDK](https://www.dpdk.org/)). Therefore, you can only run this code on a DPDK-compliant NIC. For our evaluation, we used version 18.11 of Intel's DPDK along with Mellanox NICs. 23 | 24 | 25 | ## Deploying Cheetah 26 | 27 | You need a proprietary compiler, the P4 compiler that is packaged with Intel's Barefoot Software Development Environment, to compile this code regardless of whether or not you intend to run it on real hardware. This is why we have chosen to release the code under the MIT License instead of one of the GNU GPL family of licenses ([relevant](https://softwareengineering.stackexchange.com/questions/318503/can-i-release-software-under-the-gpl-if-it-must-be-built-with-a-proprietary-comp)). 28 | 29 | To deploy our implementation on hardware, we recommend using the first generation of Intel's Barefoot Tofino switches. We did not test Cheetah on the more recent Intel Barefoot Tofino 2 chip and do not know if our implementation of Cheetah is compatible with it. **Note that we have not included code required for TCP/IP forwarding and match-action table placement in our P4 scripts**. You will need to add your switch deployment's implementation TCP/IP forwarding to the P4 scripts before you can deploy our implementation. Depending on your hardware, you may also need to add some code related to match-action table placement in order to be conformant with switch constraints (discussed in our ACM SIGMOD publication and Arxiv report). 30 | 31 | You need to define the following constants based on your hardware: 32 | 33 | - For DISTINCT, `LRU_WIDTH` 34 | - For GROUP-BY and JOIN, `REGISTER_COUNT_MAX` 35 | - For TOP-N, `CHEETAH_TOPN_INT_MAX` 36 | 37 | You also need to define the following constants based on the particular query you are optimizing: 38 | - For TOP-N, `CHEETAH_TOPN_VALUE` 39 | - For FILTERING, `FILTERING_CUTOFF` 40 | 41 | ## Tuning queries 42 | 43 | We have included the default implementation of Cheetah's queries. However, to get optimal performance, you need to tune these queries based on your hardware constraints, the workload you are running, the query engine you are using and other factors. Here is a (not necessarily complete) set of knobs you can tune in our dataplane implementation. Note that these will also require (fairly intuitive) modifications / additions to control plane rules. 44 | 45 | - For DISTINCT, you can increase or decrease the number of LRU caches (see the `cheetah_lru_import` files) used or assign more memory to each cache (tune `LRU_WIDTH`) 46 | - For JOIN, you can increase or decrease the number of bloom filter blocks (see the definition for `CREATE_BLOOM`) or the memory assigned for each block (tune `REGISTER_COUNT_MAX`) 47 | - For SKYLINE, you can change the heuristic you use for pruning (see our Arxiv report for more details on this) by modifying `alu_heuristic` 48 | - For TOP-N, you can increase or decrease the number of cutoffs (see our Arxiv report for more details on this) by modifying the definition (or the number of times you use) the `GENERATE_PACKET_COUNTER_ALU` and `GENERATE_TOPN_MIN_ALU` macros 49 | - For DISTINCT, JOIN and GROUP-BY, you can try changing the hash function(s) you use; our implementation uses CRC32 with offsets by default 50 | 51 | ## Question and discussion 52 | Please feel free to use the Cheetah project mailing list: harvard-cns-cheetah AT googlegroups DOT com. However, this is a low volume mailing list. You are more likely to receive a helpful response if your question is specific, self-contained and concise. 53 | -------------------------------------------------------------------------------- /control_plane/rules.md: -------------------------------------------------------------------------------- 1 | # Control Plane Rules For Cheetah Queries 2 | 3 | ## Filtering 4 | pd cheetah_filter_table add_entry cheetah_filter cheetah_flowId 1 action_index 1 5 | pd cheetah_filter_table add_entry cheetah_filter cheetah_flowId 0 action_index 0 6 | pd cheetah_prune_check add_entry prune cheetah_md_prune 1 7 | pd cheetah_prune_check add_entry nop cheetah_md_prune 0 8 | 9 | 10 | ## Distinct 11 | pd lru_cache_hi add_entry lru_action_hi cheetah_flowId 1 12 | pd lru_cache_lo add_entry lru_action_lo cheetah_flowId 1 13 | pd lru_cache_lo_2 add_entry lru_action_lo_2 cheetah_flowId 1 14 | pd lru_cache_hi_2 add_entry lru_action_hi_2 cheetah_flowId 1 15 | pd lru_cache_lo_3 add_entry lru_action_lo_3 cheetah_flowId 1 16 | pd lru_cache_hi_3 add_entry lru_action_hi_3 cheetah_flowId 1 17 | pd lru_cache_lo_4 add_entry lru_action_lo_4 cheetah_flowId 1 18 | pd lru_cache_hi_4 add_entry lru_action_hi_4 cheetah_flowId 1 19 | pd prune_table add_entry prune cheetah_flowId 1 20 | pd prune_table_2 add_entry prune cheetah_flowId 1 21 | pd metadata_copy_table add_entry copy_to_metadata_action cheetah_flowId 1 22 | 23 | 24 | ## Deterministic Top-N - 4 cutoffs (t0 to t3) 25 | pd cheetah_topn_table_count add_entry cheetah_topn_count cheetah_flowId 1 action_index 1 26 | pd cheetah_topn_table_min add_entry cheetah_topn_min_action cheetah_flowId 1 cheetah_md_topn_more_than_n 0 action_index 1 27 | pd cheetah_topn_table_min add_entry cheetah_topn_min_pack_a_action cheetah_flowId 1 cheetah_md_topn_more_than_n 1 action_index 1 28 | pd cheetah_topn_table_min_appendix_two add_entry cheetah_topn_min_pack_b_action cheetah_flowId 1 cheetah_md_topn_more_than_n 1 action_index 1 29 | pd cheetah_topn_t_one_table add_entry cheetah_topn_t_one_action cheetah_flowId 1 cheetah_md_topn_more_than_n 1 action_index 1 30 | pd cheetah_topn_t_one_table_check add_entry cheetah_topn_t_one_check_action cheetah_flowId 1 cheetah_md_topn_t1_cutoff_reached 1 action_index 1 31 | pd cheetah_topn_t_two_table add_entry cheetah_topn_t_two_action cheetah_flowId 1 cheetah_md_topn_t1_cutoff_reached 1 action_index 1 32 | pd cheetah_topn_t_two_table_check add_entry cheetah_topn_t_two_check_action cheetah_flowId 1 cheetah_md_topn_t2_cutoff_reached 1 action_index 1 33 | pd cheetah_topn_t_three_table add_entry cheetah_topn_t_three_action cheetah_flowId 1 cheetah_md_topn_t2_cutoff_reached 1 action_index 1 34 | pd cheetah_topn_t_three_table_check add_entry cheetah_topn_t_three_check_action cheetah_flowId 1 cheetah_md_topn_t3_cutoff_reached 1 action_index 1 35 | pd cheetah_topn_prune_check add_entry prune cheetah_md_prune 1 36 | pd register_write cheetah_topn_min_reg_one index 1 register_value 10000 37 | 38 | 39 | 40 | 41 | ## Top-N 42 | pd cheetah_topn_table_min add_entry cheetah_topn_min_action cheetah_flowId 1 cheetah_md_topn_more_than_n 0 action_index 1 43 | pd cheetah_topn_table_min add_entry cheetah_topn_min_pack_action cheetah_flowId 1 cheetah_md_topn_more_than_n 1 action_index 1 44 | pd cheetah_topn_prune_check add_entry prune cheetah_md_topn_less_than_min 0 cheetah_md_topn_less_than_min_two 1 cheetah_md_topn_more_than_n 1 45 | pd cheetah_topn_prune_check add_entry prune cheetah_md_topn_less_than_min 1 cheetah_md_topn_less_than_min_two 1 cheetah_md_topn_more_than_n 1 46 | pd cheetah_topn_prune_check add_entry prune cheetah_md_topn_less_than_min 1 cheetah_md_topn_less_than_min_two 0 cheetah_md_topn_more_than_n 1 47 | pd cheetah_topn_table_count add_entry cheetah_topn_count cheetah_flowId 1 action_index 1 48 | pd cheetah_topn_t_one_table add_entry cheetah_topn_t_one_action cheetah_flowId 1 cheetah_md_topn_more_than_n 1 action_index 1 49 | pd cheetah_topn_t_one_table add_entry nop cheetah_flowId 1 cheetah_md_topn_more_than_n 0 50 | pd cheetah_topn_debug_table add_entry cheetah_topn_debug_one_action cheetah_flowId 1 action_index 1 51 | pd register_write cheetah_topn_min_reg_one index 1 register_value 10000 52 | 53 | 54 | ## Group By 55 | pd table_sketch_one_key add_entry action_sketch_one_key cheetah_flowId 1 56 | pd table_sketch_one_value add_entry action_sketch_one_value cheetah_flowId 1 57 | pd table_sketch_two_key add_entry action_sketch_two_key cheetah_flowId 1 58 | pd table_sketch_two_value add_entry action_sketch_two_value cheetah_flowId 1 59 | pd table_sketch_three_key add_entry action_sketch_three_key cheetah_flowId 1 60 | pd table_sketch_three_value add_entry action_sketch_three_value cheetah_flowId 1 61 | pd table_sketch_four_key add_entry action_sketch_four_key cheetah_flowId 1 62 | pd table_sketch_four_value add_entry action_sketch_four_value cheetah_flowId 1 63 | pd table_sketch_five_key add_entry action_sketch_five_key cheetah_flowId 1 64 | pd table_sketch_five_value add_entry action_sketch_five_value cheetah_flowId 1 65 | pd table_hash_init add_entry modify_hash cheetah_flowId 1 66 | pd table_hash_init_two add_entry modify_hash_two cheetah_flowId 1 67 | pd table_hash_init_three add_entry modify_hash_three cheetah_flowId 1 68 | pd table_hash_init_four add_entry modify_hash_four cheetah_flowId 1 69 | pd table_hash_init_five add_entry modify_hash_five cheetah_flowId 1 70 | pd table_prune add_entry prune cheetah_flowId 1 71 | 72 | 73 | ## Join 74 | pd tbl_prune add_entry prune udp_dstPort 4242 75 | pd tbl_bloom_1 add_entry act_bloom_1 cheetah_flowId 1 76 | pd tbl_bloom_1 add_entry act_bloom_1_r cheetah_flowId 2 77 | pd tbl_bloom_2 add_entry act_bloom_2 cheetah_flowId 1 78 | pd tbl_bloom_2 add_entry act_bloom_2_r cheetah_flowId 2 79 | pd tbl_bloom_3 add_entry act_bloom_3 cheetah_flowId 1 80 | pd tbl_bloom_3 add_entry act_bloom_3_r cheetah_flowId 1 81 | pd tbl_bloom_4 add_entry act_bloom_4 cheetah_flowId 1 82 | pd tbl_bloom_4 add_entry act_bloom_4_r cheetah_flowId 2 83 | pd tbl_bloom_5 add_entry act_bloom_5 cheetah_flowId 1 84 | pd tbl_bloom_5 add_entry act_bloom_5_r cheetah_flowId 2 85 | pd tbl_bloom_6 add_entry act_bloom_6 cheetah_flowId 1 86 | pd tbl_bloom_6 add_entry act_bloom_6 cheetah_flowId 2 87 | pd tbl_prepare_keys add_entry act_prepare_keys udp_dstPort 4242 88 | pd tbl_prepare_keys_2 add_entry act_prepare_keys_2 udp_dstPort 4242 89 | -------------------------------------------------------------------------------- /data_plane/cheetah_distinct.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | header_type cheetah_t { 6 | fields { 7 | flowId : 16; 8 | rowId : 32; 9 | value_hi : 32; 10 | value_lo : 32; 11 | } 12 | } 13 | 14 | header_type cheetah_md_t { 15 | fields { 16 | rowId : 32; 17 | prune : 8; 18 | replace_value_lo : 32; 19 | replace_value_hi : 32; 20 | } 21 | } 22 | 23 | metadata cheetah_md_t cheetah_md; 24 | metadata cheetah_md_t cheetah_md_2; 25 | 26 | 27 | 28 | 29 | header cheetah_t cheetah; 30 | 31 | parser parse_cheetah { 32 | extract(cheetah); 33 | set_metadata(cheetah_md.rowId, cheetah.rowId); 34 | return ingress; 35 | } 36 | 37 | 38 | 39 | 40 | action prune() { 41 | drop(); 42 | } 43 | 44 | action copy_to_metadata_action() { 45 | modify_field(cheetah_md.replace_value_lo, cheetah.value_lo); 46 | modify_field(cheetah_md.replace_value_hi, cheetah.value_hi); 47 | } 48 | 49 | table metadata_copy_table { 50 | reads { 51 | cheetah.flowId : exact; 52 | } 53 | 54 | actions { 55 | copy_to_metadata_action; 56 | } 57 | 58 | default_action : copy_to_metadata_action(); 59 | } 60 | 61 | field_list lru_cache_hash_fields { 62 | cheetah.value_lo; 63 | cheetah.value_hi; 64 | } 65 | 66 | field_list_calculation lru_cache_hash { 67 | input { lru_cache_hash_fields; } 68 | algorithm : crc32; 69 | output_width : 16; 70 | } 71 | 72 | #include "cheetah_lru_import_efficient.p4" 73 | #include "cheetah_lru_import_efficient_2.p4" 74 | #include "cheetah_lru_import_efficient_3.p4" 75 | #include "cheetah_lru_import_efficient_4.p4" 76 | 77 | control ingress { 78 | apply(metadata_copy_table); 79 | 80 | apply(lru_cache_lo); 81 | apply(lru_cache_hi); 82 | 83 | if ((cheetah_md_2.replace_value_lo & 0x80000000 == 0x80000000) and (cheetah_md_2.replace_value_hi & 0x80000000 == 0x80000000)) { 84 | apply(prune_table); 85 | } 86 | 87 | else { 88 | apply(lru_cache_lo_2); 89 | apply(lru_cache_hi_2); 90 | 91 | if ((cheetah_md.replace_value_lo & 0x80000000 == 0x80000000) and (cheetah_md.replace_value_hi & 0x80000000 == 0x80000000)) { 92 | apply(prune_table_2); 93 | } 94 | 95 | else { 96 | apply(lru_cache_lo_3); 97 | apply(lru_cache_hi_3); 98 | 99 | if ((cheetah_md_2.replace_value_lo & 0x80000000 == 0x80000000) and (cheetah_md_2.replace_value_hi & 0x80000000 == 0x80000000)) { 100 | apply(prune_table_3); 101 | } 102 | 103 | else { 104 | apply(lru_cache_lo_4); 105 | apply(lru_cache_hi_4); 106 | 107 | if ((cheetah_md.replace_value_lo & 0x80000000 == 0x80000000) and (cheetah_md.replace_value_hi & 0x80000000 == 0x80000000)) { 108 | apply(prune_table_4); 109 | } 110 | } 111 | } 112 | } 113 | } 114 | 115 | -------------------------------------------------------------------------------- /data_plane/cheetah_filtering.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | header_type cheetah_t { 6 | fields { 7 | flowId : 16; 8 | rowId : 32; 9 | value : 32; 10 | } 11 | } 12 | 13 | header_type cheetah_md_t { 14 | fields { 15 | rowId : 32; 16 | prune : 8; 17 | } 18 | } 19 | 20 | metadata cheetah_md_t cheetah_md; 21 | 22 | header cheetah_t cheetah; 23 | 24 | parser parse_cheetah { 25 | extract(cheetah); 26 | set_metadata(cheetah_md.rowId, cheetah.rowId); 27 | return ingress; 28 | } 29 | 30 | action prune() { 31 | drop(); 32 | } 33 | 34 | table table_prune { 35 | reads { 36 | cheetah.flowId : exact; 37 | } 38 | 39 | actions { 40 | prune; 41 | } 42 | } 43 | 44 | register filter_reg { 45 | width : 32; 46 | instance_count : 1; 47 | } 48 | 49 | blackbox stateful_alu alu_filter { 50 | reg : filter_reg; 51 | 52 | condition_lo : cheetah.value < FILTER_CONSTANT; 53 | 54 | update_hi_1_predicate : condition_lo; 55 | update_hi_1_value : 0; 56 | update_hi_2_predicate: not condition_lo; 57 | update_hi_2_value : 1; 58 | 59 | output_value : alu_hi; 60 | output_dst : cheetah_md.prune; 61 | } 62 | 63 | action action_filter() { 64 | alu_filter.execute_stateful_alu(0); 65 | } 66 | 67 | table table_filter { 68 | reads { 69 | cheetah.flowId : exact; 70 | } 71 | 72 | actions { 73 | action_filter; 74 | } 75 | } 76 | 77 | control ingress { 78 | apply(table_filter); 79 | if (cheetah_md.prune == 0x1) { 80 | apply(table_prune); 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /data_plane/cheetah_groupby.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | header_type cheetah_t { 6 | fields { 7 | flowId : 16; 8 | rowId : 32; 9 | key : 32; 10 | value : 32; 11 | } 12 | } 13 | 14 | header_type cheetah_md_t { 15 | fields { 16 | prune : 8; 17 | sketch_one_same_key : 8; 18 | sketch_two_same_key : 8; 19 | sketch_three_same_key : 8; 20 | sketch_four_same_key : 8; 21 | sketch_five_same_key : 8; 22 | hash_value : 32; 23 | } 24 | } 25 | 26 | metadata cheetah_md_t cheetah_md; 27 | 28 | header cheetah_t cheetah; 29 | 30 | parser parse_cheetah { 31 | extract(cheetah); 32 | return ingress; 33 | } 34 | 35 | action set_egr(egress_spec) { 36 | modify_field(ig_intr_md_for_tm.ucast_egress_port, egress_spec); 37 | } 38 | 39 | action nop() { 40 | } 41 | 42 | action _drop() { 43 | drop(); 44 | } 45 | 46 | action prune() { 47 | drop(); 48 | } 49 | 50 | register reg_sketch_one_key { 51 | width : 32; 52 | instance_count : REGISTER_COUNT_MAX; 53 | } 54 | 55 | blackbox stateful_alu alu_sketch_one_key { 56 | reg : reg_sketch_one_key; 57 | 58 | condition_lo : cheetah.key - register_lo == 0; 59 | 60 | update_lo_1_predicate : not condition_lo; 61 | update_lo_1_value : cheetah.key; 62 | 63 | update_hi_1_predicate : condition_lo; 64 | update_hi_1_value : 1; 65 | update_hi_2_predicate : not condition_lo; 66 | update_hi_2_value : 0; 67 | 68 | output_value : alu_hi; 69 | output_dst : cheetah_md.sketch_one_same_key; 70 | } 71 | 72 | register reg_sketch_one_value { 73 | width : 32; 74 | instance_count : REGISTER_COUNT_MAX; 75 | } 76 | 77 | blackbox stateful_alu alu_sketch_one_value { 78 | reg : reg_sketch_one_value; 79 | 80 | condition_lo : cheetah_md.sketch_one_same_key == 1; 81 | condition_hi : register_lo - cheetah.value > 0; 82 | 83 | update_lo_1_predicate : not condition_lo or not condition_hi; 84 | update_lo_1_value : cheetah.value; 85 | 86 | update_hi_1_predicate : condition_lo and condition_hi; 87 | update_hi_1_value : 1; 88 | update_hi_2_predicate : condition_lo or not condition_hi; 89 | update_hi_2_value : 0; 90 | 91 | output_value : alu_hi; 92 | output_dst : cheetah_md.prune; 93 | } 94 | 95 | field_list hash_list_one { 96 | cheetah_md.hash_value; 97 | } 98 | 99 | field_list_calculation hash_one { 100 | input { 101 | hash_list_one; 102 | } 103 | 104 | algorithm : crc32; 105 | output_width : 32; 106 | } 107 | 108 | action action_sketch_one_key() { 109 | alu_sketch_one_key.execute_stateful_alu_from_hash(hash_one); 110 | } 111 | 112 | 113 | action action_sketch_one_value() { 114 | alu_sketch_one_value.execute_stateful_alu_from_hash(hash_one); 115 | } 116 | 117 | 118 | 119 | table table_sketch_one_key { 120 | reads { 121 | cheetah.flowId : exact; 122 | } 123 | 124 | actions { 125 | action_sketch_one_key; 126 | nop; 127 | } 128 | } 129 | 130 | 131 | table table_sketch_one_value { 132 | reads { 133 | cheetah.flowId : exact; 134 | } 135 | 136 | actions { 137 | action_sketch_one_value; 138 | nop; 139 | } 140 | } 141 | 142 | 143 | register reg_sketch_two_key { 144 | width : 32; 145 | instance_count : REGISTER_COUNT_MAX; 146 | } 147 | 148 | 149 | blackbox stateful_alu alu_sketch_two_key { 150 | reg : reg_sketch_two_key; 151 | 152 | condition_lo : cheetah.key - register_lo == 0; 153 | 154 | update_lo_1_predicate : not condition_lo; 155 | update_lo_1_value : cheetah.key; 156 | 157 | update_hi_1_predicate : condition_lo; 158 | update_hi_1_value : 1; 159 | update_hi_2_predicate : not condition_lo; 160 | update_hi_2_value : 0; 161 | 162 | output_value : alu_hi; 163 | output_dst : cheetah_md.sketch_two_same_key; 164 | } 165 | 166 | 167 | register reg_sketch_two_value { 168 | width : 32; 169 | instance_count : REGISTER_COUNT_MAX; 170 | } 171 | 172 | 173 | blackbox stateful_alu alu_sketch_two_value { 174 | reg : reg_sketch_two_value; 175 | 176 | condition_lo : cheetah_md.sketch_two_same_key == 1; 177 | condition_hi : register_lo - cheetah.value > 0; 178 | 179 | update_lo_1_predicate : not condition_lo or not condition_hi; 180 | update_lo_1_value : cheetah.value; 181 | 182 | update_hi_1_predicate : condition_lo and condition_hi; 183 | update_hi_1_value : 1; 184 | update_hi_2_predicate : condition_lo or not condition_hi; 185 | update_hi_2_value : 0; 186 | 187 | output_value : alu_hi; 188 | output_dst : cheetah_md.prune; 189 | } 190 | 191 | field_list hash_list_two { 192 | cheetah_md.hash_value; 193 | } 194 | 195 | 196 | field_list_calculation hash_two { 197 | input { 198 | hash_list_two; 199 | } 200 | 201 | algorithm : crc32; 202 | output_width : 17; 203 | } 204 | 205 | 206 | action action_sketch_two_key() { 207 | alu_sketch_two_key.execute_stateful_alu_from_hash(hash_two); 208 | } 209 | 210 | 211 | action action_sketch_two_value() { 212 | alu_sketch_two_value.execute_stateful_alu_from_hash(hash_two); 213 | } 214 | 215 | 216 | table table_sketch_two_key { 217 | reads { 218 | cheetah.flowId : exact; 219 | } 220 | 221 | actions { 222 | action_sketch_two_key; 223 | nop; 224 | } 225 | } 226 | 227 | 228 | table table_sketch_two_value { 229 | reads { 230 | cheetah.flowId : exact; 231 | } 232 | 233 | actions { 234 | action_sketch_two_value; 235 | nop; 236 | } 237 | } 238 | 239 | 240 | register reg_sketch_three_key { 241 | width : 32; 242 | instance_count : REGISTER_COUNT_MAX; 243 | } 244 | 245 | 246 | blackbox stateful_alu alu_sketch_three_key { 247 | reg : reg_sketch_three_key; 248 | 249 | condition_lo : cheetah.key - register_lo == 0; 250 | 251 | update_lo_1_predicate : not condition_lo; 252 | update_lo_1_value : cheetah.key; 253 | 254 | update_hi_1_predicate : condition_lo; 255 | update_hi_1_value : 1; 256 | update_hi_2_predicate : not condition_lo; 257 | update_hi_2_value : 0; 258 | 259 | output_value : alu_hi; 260 | output_dst : cheetah_md.sketch_three_same_key; 261 | } 262 | 263 | 264 | register reg_sketch_three_value { 265 | width : 32; 266 | instance_count : REGISTER_COUNT_MAX; 267 | } 268 | 269 | 270 | blackbox stateful_alu alu_sketch_three_value { 271 | reg : reg_sketch_three_value; 272 | 273 | condition_lo : cheetah_md.sketch_three_same_key == 1; 274 | condition_hi : register_lo - cheetah.value > 0; 275 | 276 | update_lo_1_predicate : not condition_lo or not condition_hi; 277 | update_lo_1_value : cheetah.value; 278 | 279 | update_hi_1_predicate : condition_lo and condition_hi; 280 | update_hi_1_value : 1; 281 | update_hi_2_predicate : condition_lo or not condition_hi; 282 | update_hi_2_value : 0; 283 | 284 | output_value : alu_hi; 285 | output_dst : cheetah_md.prune; 286 | } 287 | 288 | field_list hash_list_three { 289 | cheetah_md.hash_value; 290 | } 291 | 292 | 293 | field_list_calculation hash_three { 294 | input { 295 | hash_list_three; 296 | } 297 | 298 | algorithm : crc32; 299 | output_width : 17; 300 | } 301 | 302 | 303 | action action_sketch_three_key() { 304 | alu_sketch_three_key.execute_stateful_alu_from_hash(hash_three); 305 | } 306 | 307 | 308 | action action_sketch_three_value() { 309 | alu_sketch_three_value.execute_stateful_alu_from_hash(hash_three); 310 | } 311 | 312 | 313 | table table_sketch_three_key { 314 | reads { 315 | cheetah.flowId : exact; 316 | } 317 | 318 | actions { 319 | action_sketch_three_key; 320 | nop; 321 | } 322 | } 323 | 324 | 325 | table table_sketch_three_value { 326 | reads { 327 | cheetah.flowId : exact; 328 | } 329 | 330 | actions { 331 | action_sketch_three_value; 332 | nop; 333 | } 334 | } 335 | 336 | 337 | register reg_sketch_four_key { 338 | width : 32; 339 | instance_count : REGISTER_COUNT_MAX; 340 | } 341 | 342 | 343 | blackbox stateful_alu alu_sketch_four_key { 344 | reg : reg_sketch_four_key; 345 | 346 | condition_lo : cheetah.key - register_lo == 0; 347 | 348 | update_lo_1_predicate : not condition_lo; 349 | update_lo_1_value : cheetah.key; 350 | 351 | update_hi_1_predicate : condition_lo; 352 | update_hi_1_value : 1; 353 | update_hi_2_predicate : not condition_lo; 354 | update_hi_2_value : 0; 355 | 356 | output_value : alu_hi; 357 | output_dst : cheetah_md.sketch_four_same_key; 358 | } 359 | 360 | 361 | register reg_sketch_four_value { 362 | width : 32; 363 | instance_count : REGISTER_COUNT_MAX; 364 | } 365 | 366 | 367 | blackbox stateful_alu alu_sketch_four_value { 368 | reg : reg_sketch_four_value; 369 | 370 | condition_lo : cheetah_md.sketch_four_same_key == 1; 371 | condition_hi : register_lo - cheetah.value > 0; 372 | 373 | update_lo_1_predicate : not condition_lo or not condition_hi; 374 | update_lo_1_value : cheetah.value; 375 | 376 | update_hi_1_predicate : condition_lo and condition_hi; 377 | update_hi_1_value : 1; 378 | update_hi_2_predicate : condition_lo or not condition_hi; 379 | update_hi_2_value : 0; 380 | 381 | output_value : alu_hi; 382 | output_dst : cheetah_md.prune; 383 | } 384 | 385 | field_list hash_list_four { 386 | cheetah_md.hash_value; 387 | } 388 | 389 | 390 | field_list_calculation hash_four { 391 | input { 392 | hash_list_four; 393 | } 394 | 395 | algorithm : crc32; 396 | output_width : 17; 397 | } 398 | 399 | 400 | action action_sketch_four_key() { 401 | alu_sketch_four_key.execute_stateful_alu_from_hash(hash_four); 402 | } 403 | 404 | 405 | action action_sketch_four_value() { 406 | alu_sketch_four_value.execute_stateful_alu_from_hash(hash_four); 407 | } 408 | 409 | 410 | table table_sketch_four_key { 411 | reads { 412 | cheetah.flowId : exact; 413 | } 414 | 415 | actions { 416 | action_sketch_four_key; 417 | nop; 418 | } 419 | } 420 | 421 | 422 | table table_sketch_four_value { 423 | reads { 424 | cheetah.flowId : exact; 425 | } 426 | 427 | actions { 428 | action_sketch_four_value; 429 | nop; 430 | } 431 | } 432 | 433 | 434 | register reg_sketch_five_key { 435 | width : 32; 436 | instance_count : REGISTER_COUNT_MAX; 437 | } 438 | 439 | 440 | blackbox stateful_alu alu_sketch_five_key { 441 | reg : reg_sketch_five_key; 442 | 443 | condition_lo : cheetah.key - register_lo == 0; 444 | 445 | update_lo_1_predicate : not condition_lo; 446 | update_lo_1_value : cheetah.key; 447 | 448 | update_hi_1_predicate : condition_lo; 449 | update_hi_1_value : 1; 450 | update_hi_2_predicate : not condition_lo; 451 | update_hi_2_value : 0; 452 | 453 | output_value : alu_hi; 454 | output_dst : cheetah_md.sketch_five_same_key; 455 | } 456 | 457 | 458 | register reg_sketch_five_value { 459 | width : 32; 460 | instance_count : REGISTER_COUNT_MAX; 461 | } 462 | 463 | 464 | blackbox stateful_alu alu_sketch_five_value { 465 | reg : reg_sketch_five_value; 466 | 467 | condition_lo : cheetah_md.sketch_five_same_key == 1; 468 | condition_hi : register_lo - cheetah.value > 0; 469 | 470 | update_lo_1_predicate : not condition_lo or not condition_hi; 471 | update_lo_1_value : cheetah.value; 472 | 473 | update_hi_1_predicate : condition_lo and condition_hi; 474 | update_hi_1_value : 1; 475 | update_hi_2_predicate : condition_lo or not condition_hi; 476 | update_hi_2_value : 0; 477 | 478 | output_value : alu_hi; 479 | output_dst : cheetah_md.prune; 480 | } 481 | 482 | field_list hash_list_five { 483 | cheetah_md.hash_value; 484 | } 485 | 486 | 487 | field_list_calculation hash_five { 488 | input { 489 | hash_list_five; 490 | } 491 | 492 | algorithm : crc32; 493 | output_width : 17; 494 | } 495 | 496 | 497 | action action_sketch_five_key() { 498 | alu_sketch_five_key.execute_stateful_alu_from_hash(hash_five); 499 | } 500 | 501 | 502 | action action_sketch_five_value() { 503 | alu_sketch_five_value.execute_stateful_alu_from_hash(hash_five); 504 | } 505 | 506 | 507 | table table_sketch_five_key { 508 | reads { 509 | cheetah.flowId : exact; 510 | } 511 | 512 | actions { 513 | action_sketch_five_key; 514 | nop; 515 | } 516 | } 517 | 518 | 519 | table table_sketch_five_value { 520 | reads { 521 | cheetah.flowId : exact; 522 | } 523 | 524 | actions { 525 | action_sketch_five_value; 526 | nop; 527 | } 528 | } 529 | 530 | action modify_hash() { 531 | modify_field(cheetah_md.hash_value, cheetah.key); 532 | } 533 | 534 | action modify_hash_two() { 535 | add_to_field(cheetah_md.hash_value, 3); 536 | } 537 | 538 | action modify_hash_three() { 539 | add_to_field(cheetah_md.hash_value, 2); 540 | } 541 | 542 | action modify_hash_four() { 543 | add_to_field(cheetah_md.hash_value, 2); 544 | } 545 | 546 | action modify_hash_five() { 547 | add_to_field(cheetah_md.hash_value, 2); 548 | } 549 | 550 | 551 | table table_hash_init { 552 | reads { 553 | cheetah.flowId : exact; 554 | } 555 | 556 | actions { 557 | modify_hash; 558 | nop; 559 | } 560 | } 561 | 562 | 563 | table table_hash_init_two { 564 | reads { 565 | cheetah.flowId : exact; 566 | } 567 | 568 | actions { 569 | modify_hash_two; 570 | nop; 571 | } 572 | } 573 | 574 | 575 | table table_hash_init_three { 576 | reads { 577 | cheetah.flowId : exact; 578 | } 579 | 580 | actions { 581 | modify_hash_three; 582 | nop; 583 | } 584 | } 585 | 586 | 587 | table table_hash_init_four { 588 | reads { 589 | cheetah.flowId : exact; 590 | } 591 | 592 | actions { 593 | modify_hash_four; 594 | nop; 595 | } 596 | } 597 | 598 | 599 | table table_hash_init_five { 600 | reads { 601 | cheetah.flowId : exact; 602 | } 603 | 604 | actions { 605 | modify_hash_five; 606 | nop; 607 | } 608 | } 609 | 610 | table table_prune { 611 | reads { 612 | cheetah.flowId : exact; 613 | } 614 | 615 | actions { 616 | prune; 617 | } 618 | } 619 | 620 | control ingress { 621 | apply(table_hash_init); 622 | 623 | apply(table_sketch_one_key); 624 | apply(table_sketch_one_value); 625 | 626 | apply(table_hash_init_two); 627 | 628 | if (cheetah_md.prune == 0x0) { 629 | apply(table_sketch_two_key); 630 | apply(table_sketch_two_value); 631 | } 632 | 633 | apply(table_hash_init_three); 634 | 635 | if (cheetah_md.prune == 0x0) { 636 | apply(table_sketch_three_key); 637 | apply(table_sketch_three_value); 638 | } 639 | 640 | apply(table_hash_init_four); 641 | 642 | if (cheetah_md.prune == 0x0) { 643 | apply(table_sketch_four_key); 644 | apply(table_sketch_four_value); 645 | } 646 | 647 | apply(table_hash_init_five); 648 | 649 | if (cheetah_md.prune == 0x0) { 650 | apply(table_sketch_five_key); 651 | apply(table_sketch_five_value); 652 | } 653 | 654 | if (cheetah_md.prune == 0x1) { 655 | apply(table_prune); 656 | } 657 | } 658 | -------------------------------------------------------------------------------- /data_plane/cheetah_join.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | header_type cheetah_t { 6 | fields { 7 | flowId : 16; 8 | rowId : 32; 9 | key : 32; 10 | value : 32; 11 | } 12 | } 13 | 14 | header_type cheetah_md_t { 15 | fields { 16 | prune : 8; 17 | not_in_bloom : 1; 18 | key_1 : 32; 19 | key_2 : 32; 20 | key_3 : 32; 21 | key_4 : 32; 22 | key_5 : 32; 23 | key_6 : 32; 24 | } 25 | } 26 | 27 | metadata cheetah_md_t cheetah_md; 28 | 29 | header cheetah_t cheetah; 30 | 31 | parser parse_cheetah { 32 | extract(cheetah); 33 | return ingress; 34 | } 35 | 36 | action prune() { 37 | drop(); 38 | } 39 | 40 | #define CREATE_BLOOM(N)\ 41 | register reg_bloom_##N { \ 42 | width : 1; \ 43 | instance_count : REGISTER_COUNT_MAX;\ 44 | } \ 45 | \ 46 | blackbox stateful_alu alu_bloom_##N { \ 47 | reg : reg_bloom_##N; \ 48 | update_lo_1_value: set_bitc; \ 49 | output_value : alu_lo; \ 50 | output_dst : cheetah_md.not_in_bloom; \ 51 | } \ 52 | \ 53 | blackbox stateful_alu alu_bloom_##N##_r { \ 54 | reg : reg_bloom_##N; \ 55 | update_lo_1_value : read_bit; \ 56 | output_value : alu_lo; \ 57 | output_dst : cheetah_md.not_in_bloom; \ 58 | } \ 59 | \ 60 | field_list list_##N { \ 61 | cheetah_md.key_##N; \ 62 | } \ 63 | \ 64 | field_list_calculation hash_bloom_##N { \ 65 | input { \ 66 | list_##N; \ 67 | } \ 68 | algorithm : crc32; \ 69 | output_width : 17; \ 70 | } \ 71 | \ 72 | action act_bloom_##N() { \ 73 | alu_bloom_##N.execute_stateful_alu_from_hash(hash_bloom_##N); \ 74 | } \ 75 | \ 76 | action act_bloom_##N##_r() { \ 77 | alu_bloom_##N##_r.execute_stateful_alu_from_hash(hash_bloom_##N);\ 78 | } \ 79 | \ 80 | table tbl_bloom_##N { \ 81 | reads { \ 82 | cheetah.flowId : exact; \ 83 | } \ 84 | \ 85 | actions { \ 86 | act_bloom_##N; \ 87 | act_bloom_##N##_r; \ 88 | } \ 89 | } 90 | 91 | CREATE_BLOOM(1) 92 | CREATE_BLOOM(2) 93 | CREATE_BLOOM(3) 94 | CREATE_BLOOM(4) 95 | CREATE_BLOOM(5) 96 | CREATE_BLOOM(6) 97 | 98 | action act_prepare_keys() { 99 | modify_field(cheetah_md.key_1, cheetah.key); 100 | modify_field(cheetah_md.key_2, cheetah.key); 101 | modify_field(cheetah_md.key_3, cheetah.key); 102 | modify_field(cheetah_md.key_4, cheetah.key); 103 | modify_field(cheetah_md.key_5, cheetah.key); 104 | modify_field(cheetah_md.key_6, cheetah.key); 105 | } 106 | 107 | table tbl_prepare_keys { 108 | reads { 109 | udp.dstPort : exact; 110 | } 111 | 112 | actions { 113 | act_prepare_keys; 114 | } 115 | } 116 | 117 | action act_prepare_keys_2() { 118 | add_to_field(cheetah_md.key_2, 3); 119 | add_to_field(cheetah_md.key_3, 5); 120 | add_to_field(cheetah_md.key_4, 7); 121 | add_to_field(cheetah_md.key_5, 11); 122 | add_to_field(cheetah_md.key_6, 13); 123 | } 124 | 125 | table tbl_prepare_keys_2 { 126 | reads { 127 | udp.dstPort : exact; 128 | } 129 | 130 | actions { 131 | act_prepare_keys_2; 132 | } 133 | } 134 | 135 | table tbl_prune { 136 | reads { 137 | udp.dstPort : exact; 138 | } 139 | 140 | actions { 141 | prune; 142 | } 143 | } 144 | 145 | control ingress { 146 | apply(tbl_prepare_keys); 147 | apply(tbl_prepare_keys_2); 148 | 149 | apply(tbl_bloom_1); 150 | 151 | if (cheetah_md.not_in_bloom == 1) { 152 | apply(tbl_prune); 153 | } else { 154 | apply(tbl_bloom_2); 155 | 156 | if (cheetah_md.not_in_bloom == 1) { 157 | apply(tbl_prune); 158 | } else { 159 | apply(tbl_bloom_3); 160 | 161 | if (cheetah_md.not_in_bloom == 1) { 162 | apply(tbl_prune); 163 | } else { 164 | apply(tbl_bloom_4); 165 | 166 | if (cheetah_md.not_in_bloom == 1) { 167 | apply(tbl_prune); 168 | } else { 169 | apply(tbl_bloom_5); 170 | 171 | if (cheetah_md.not_in_bloom == 1) { 172 | apply(tbl_prune); 173 | } else { 174 | apply(tbl_bloom_6); 175 | 176 | if (cheetah_md.not_in_bloom == 1) { 177 | apply(tbl_prune); 178 | } 179 | } 180 | } 181 | } 182 | } 183 | } 184 | } 185 | 186 | -------------------------------------------------------------------------------- /data_plane/cheetah_lru_import_efficient.p4: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_LRU_IMPORT_P4 2 | #define CHEETAH_LRU_IMPORT_P4 3 | 4 | register lru_reg_lo { 5 | width : 32; 6 | instance_count : LRU_WIDTH; 7 | } 8 | 9 | register lru_reg_hi { 10 | width : 32; 11 | instance_count : LRU_WIDTH; 12 | } 13 | 14 | blackbox stateful_alu lru_one_lo { 15 | reg : lru_reg_lo; 16 | 17 | condition_lo : cheetah.value_lo - register_lo == 0; 18 | 19 | update_lo_1_value : cheetah_md.replace_value_lo; 20 | 21 | update_hi_1_predicate : condition_lo; 22 | update_hi_1_value : register_lo | 0x80000000; 23 | update_hi_2_predicate : not condition_lo; 24 | update_hi_2_value : register_lo; 25 | 26 | output_value : alu_hi; 27 | output_dst : cheetah_md_2.replace_value_lo; 28 | } 29 | 30 | blackbox stateful_alu lru_one_hi { 31 | reg : lru_reg_hi; 32 | 33 | condition_lo : cheetah.value_hi - register_lo == 0; 34 | 35 | update_lo_1_value : cheetah_md.replace_value_hi; 36 | 37 | update_hi_1_predicate : condition_lo; 38 | update_hi_1_value : register_lo | 0x80000000; 39 | update_hi_2_predicate : not condition_lo; 40 | update_hi_2_value : register_lo; 41 | 42 | output_value : alu_hi; 43 | output_dst : cheetah_md_2.replace_value_hi; 44 | } 45 | 46 | action lru_action_lo() { 47 | lru_one_lo.execute_stateful_alu_from_hash(lru_cache_hash); 48 | } 49 | 50 | action lru_action_hi() { 51 | lru_one_hi.execute_stateful_alu_from_hash(lru_cache_hash); 52 | } 53 | 54 | table lru_cache_lo { 55 | reads { 56 | cheetah.flowId : exact; 57 | } 58 | 59 | actions { 60 | lru_action_lo; 61 | } 62 | } 63 | 64 | table lru_cache_hi { 65 | reads { 66 | cheetah.flowId : exact; 67 | } 68 | 69 | actions { 70 | lru_action_hi; 71 | } 72 | } 73 | 74 | table prune_table { 75 | reads { 76 | cheetah.flowId : exact; 77 | } 78 | 79 | actions { 80 | prune; 81 | } 82 | 83 | default_action : prune; 84 | } 85 | 86 | #endif /* CHEETAH_LRU_IMPORT_P4 */ 87 | -------------------------------------------------------------------------------- /data_plane/cheetah_lru_import_efficient_2.p4: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_LRU_IMPORT_P4_2 2 | #define CHEETAH_LRU_IMPORT_P4_2 3 | 4 | register lru_reg_lo_2 { 5 | width : 32; 6 | instance_count : LRU_WIDTH; 7 | } 8 | 9 | register lru_reg_hi_2 { 10 | width : 32; 11 | instance_count : LRU_WIDTH; 12 | } 13 | 14 | blackbox stateful_alu lru_one_lo_2 { 15 | reg : lru_reg_lo_2; 16 | 17 | condition_lo : cheetah.value_lo - register_lo == 0; 18 | 19 | update_lo_1_value : cheetah_md_2.replace_value_lo; 20 | 21 | update_hi_1_predicate : condition_lo; 22 | update_hi_1_value : register_lo | 0x80000000; 23 | update_hi_2_predicate : not condition_lo; 24 | update_hi_2_value : register_lo; 25 | 26 | output_value : alu_hi; 27 | output_dst : cheetah_md.replace_value_lo; 28 | } 29 | 30 | blackbox stateful_alu lru_one_hi_2 { 31 | reg : lru_reg_hi_2; 32 | 33 | condition_lo : cheetah.value_hi - register_lo == 0; 34 | 35 | update_lo_1_value : cheetah_md_2.replace_value_hi; 36 | 37 | update_hi_1_predicate : condition_lo; 38 | update_hi_1_value : register_lo | 0x80000000; 39 | update_hi_2_predicate : not condition_lo; 40 | update_hi_2_value : register_lo; 41 | 42 | output_value : alu_hi; 43 | output_dst : cheetah_md.replace_value_hi; 44 | } 45 | 46 | action lru_action_lo_2() { 47 | lru_one_lo_2.execute_stateful_alu_from_hash(lru_cache_hash); 48 | } 49 | 50 | action lru_action_hi_2() { 51 | lru_one_hi_2.execute_stateful_alu_from_hash(lru_cache_hash); 52 | } 53 | 54 | table lru_cache_lo_2 { 55 | reads { 56 | cheetah.flowId : exact; 57 | } 58 | 59 | actions { 60 | lru_action_lo_2; 61 | } 62 | } 63 | 64 | table lru_cache_hi_2 { 65 | reads { 66 | cheetah.flowId : exact; 67 | } 68 | 69 | actions { 70 | lru_action_hi_2; 71 | } 72 | } 73 | 74 | table prune_table_2 { 75 | reads { 76 | cheetah.flowId : exact; 77 | } 78 | 79 | actions { 80 | prune; 81 | } 82 | 83 | default_action : prune; 84 | } 85 | 86 | #endif /* CHEETAH_LRU_IMPORT_P4_2 */ 87 | 88 | -------------------------------------------------------------------------------- /data_plane/cheetah_lru_import_efficient_3.p4: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_LRU_IMPORT_P4_3 2 | #define CHEETAH_LRU_IMPORT_P4_3 3 | 4 | register lru_reg_lo_3 { 5 | width : 32; 6 | instance_count : LRU_WIDTH; 7 | } 8 | 9 | register lru_reg_hi_3 { 10 | width : 32; 11 | instance_count : LRU_WIDTH; 12 | } 13 | 14 | blackbox stateful_alu lru_one_lo_3 { 15 | reg : lru_reg_lo_3; 16 | 17 | condition_lo : cheetah.value_lo - register_lo == 0; 18 | 19 | update_lo_1_value : cheetah_md.replace_value_lo; 20 | 21 | update_hi_1_predicate : condition_lo; 22 | update_hi_1_value : register_lo | 0x80000000; 23 | update_hi_2_predicate : not condition_lo; 24 | update_hi_2_value : register_lo; 25 | 26 | output_value : alu_hi; 27 | output_dst : cheetah_md_2.replace_value_lo; 28 | } 29 | 30 | blackbox stateful_alu lru_one_hi_3 { 31 | reg : lru_reg_hi_3; 32 | 33 | condition_lo : cheetah.value_hi - register_lo == 0; 34 | 35 | update_lo_1_value : cheetah_md.replace_value_hi; 36 | 37 | update_hi_1_predicate : condition_lo; 38 | update_hi_1_value : register_lo | 0x80000000; 39 | update_hi_2_predicate : not condition_lo; 40 | update_hi_2_value : register_lo; 41 | 42 | output_value : alu_hi; 43 | output_dst : cheetah_md_2.replace_value_hi; 44 | } 45 | 46 | action lru_action_lo_3() { 47 | lru_one_lo_3.execute_stateful_alu_from_hash(lru_cache_hash); 48 | } 49 | 50 | action lru_action_hi_3() { 51 | lru_one_hi_3.execute_stateful_alu_from_hash(lru_cache_hash); 52 | } 53 | 54 | table lru_cache_lo_3 { 55 | reads { 56 | cheetah.flowId : exact; 57 | } 58 | 59 | actions { 60 | lru_action_lo_3; 61 | } 62 | } 63 | 64 | table lru_cache_hi_3 { 65 | reads { 66 | cheetah.flowId : exact; 67 | } 68 | 69 | actions { 70 | lru_action_hi_3; 71 | } 72 | } 73 | 74 | table prune_table_3 { 75 | reads { 76 | cheetah.flowId : exact; 77 | } 78 | 79 | actions { 80 | prune; 81 | } 82 | 83 | default_action : prune; 84 | } 85 | 86 | #endif /* CHEETAH_LRU_IMPORT_P4_3 */ 87 | -------------------------------------------------------------------------------- /data_plane/cheetah_lru_import_efficient_4.p4: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_LRU_IMPORT_P4_4 2 | #define CHEETAH_LRU_IMPORT_P4_4 3 | 4 | register lru_reg_lo_4 { 5 | width : 32; 6 | instance_count : LRU_WIDTH; 7 | } 8 | 9 | register lru_reg_hi_4 { 10 | width : 32; 11 | instance_count : LRU_WIDTH; 12 | } 13 | 14 | blackbox stateful_alu lru_one_lo_4 { 15 | reg : lru_reg_lo_4; 16 | 17 | condition_lo : cheetah.value_lo - register_lo == 0; 18 | 19 | update_lo_1_value : cheetah_md.replace_value_lo; 20 | 21 | update_hi_1_predicate : condition_lo; 22 | update_hi_1_value : register_lo | 0x80000000; 23 | update_hi_2_predicate : not condition_lo; 24 | update_hi_2_value : register_lo; 25 | 26 | output_value : alu_hi; 27 | output_dst : cheetah_md.replace_value_lo; 28 | } 29 | 30 | blackbox stateful_alu lru_one_hi_4 { 31 | reg : lru_reg_hi_4; 32 | 33 | condition_lo : cheetah.value_hi - register_lo == 0; 34 | 35 | update_lo_1_value : cheetah_md.replace_value_hi; 36 | 37 | update_hi_1_predicate : condition_lo; 38 | update_hi_1_value : register_lo | 0x80000000; 39 | update_hi_2_predicate : not condition_lo; 40 | update_hi_2_value : register_lo; 41 | 42 | output_value : alu_hi; 43 | output_dst : cheetah_md.replace_value_hi; 44 | } 45 | 46 | action lru_action_lo_4() { 47 | lru_one_lo_4.execute_stateful_alu_from_hash(lru_cache_hash); 48 | } 49 | 50 | action lru_action_hi_4() { 51 | lru_one_hi_4.execute_stateful_alu_from_hash(lru_cache_hash); 52 | } 53 | 54 | table lru_cache_lo_4 { 55 | reads { 56 | cheetah.flowId : exact; 57 | } 58 | 59 | actions { 60 | lru_action_lo_4; 61 | } 62 | } 63 | 64 | table lru_cache_hi_4 { 65 | reads { 66 | cheetah.flowId : exact; 67 | } 68 | 69 | actions { 70 | lru_action_hi_4; 71 | } 72 | } 73 | 74 | table prune_table_4 { 75 | reads { 76 | cheetah.flowId : exact; 77 | } 78 | 79 | actions { 80 | prune; 81 | } 82 | 83 | default_action : prune; 84 | } 85 | 86 | #endif /* CHEETAH_LRU_IMPORT_P4_4 */ 87 | -------------------------------------------------------------------------------- /data_plane/cheetah_skyline.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | header_type cheetah_t { 6 | fields { 7 | flowId : 16; 8 | rowId : 32; 9 | x : 32; 10 | y : 32; 11 | } 12 | } 13 | 14 | header_type cheetah_md_t { 15 | fields { 16 | prune : 8; 17 | replace_next : 8; 18 | val_sum : 32; 19 | dominates_x : 8; 20 | dominates_y : 8; 21 | } 22 | } 23 | 24 | header cheetah_t cheetah; 25 | 26 | metadata cheetah_md_t cheetah_md; 27 | 28 | parser parse_cheetah { 29 | extract(cheetah); 30 | set_metadata(cheetah_md.val_sum, cheetah.x); 31 | return ingress; 32 | } 33 | 34 | action set_egr(egress_spec) { 35 | modify_field(ig_intr_md_for_tm.ucast_egress_port, egress_spec); 36 | } 37 | 38 | action prune() { 39 | drop(); 40 | } 41 | 42 | action action_heuristic_pkt() { 43 | add_to_field(cheetah_md.val_sum, cheetah.y); 44 | } 45 | 46 | table table_heuristic_pkt { 47 | reads { 48 | cheetah.flowId : exact; 49 | } 50 | 51 | actions { 52 | action_heuristic_pkt; 53 | } 54 | } 55 | 56 | register reg_heuristic { 57 | width : 32; 58 | instance_count : 1; 59 | } 60 | 61 | blackbox stateful_alu alu_heuristic { 62 | reg : reg_heuristic; 63 | 64 | condition_lo : register_lo - cheetah_md.val_sum < 0; 65 | update_lo_1_predicate : condition_lo; 66 | update_lo_1_value : cheetah_md.val_sum; 67 | 68 | update_hi_1_predicate : condition_lo; 69 | update_hi_1_value : 1; 70 | update_hi_2_predicate : not condition_lo; 71 | update_hi_2_value : 0; 72 | 73 | output_value : alu_hi; 74 | output_dst : cheetah_md.replace_next; 75 | } 76 | 77 | action action_heuristic() { 78 | alu_heuristic.execute_stateful_alu(0); 79 | } 80 | 81 | 82 | table table_heuristic { 83 | reads { 84 | cheetah.flowId : exact; 85 | } 86 | 87 | actions { 88 | action_heuristic; 89 | } 90 | } 91 | 92 | register reg_x { 93 | width : 32; 94 | instance_count : 1; 95 | } 96 | 97 | blackbox stateful_alu alu_x { 98 | reg : reg_x; 99 | 100 | condition_lo : cheetah_md.replace_next == 1; 101 | condition_hi : register_lo - cheetah.x > 0; 102 | 103 | update_lo_1_predicate : condition_lo; 104 | update_lo_1_value : cheetah.x; 105 | 106 | update_hi_1_predicate : condition_hi and not condition_lo; 107 | update_hi_1_value : 1; 108 | update_hi_2_predicate : not condition_hi or condition_lo; 109 | update_hi_2_value : 0; 110 | 111 | output_value : alu_hi; 112 | output_dst : cheetah_md.dominates_x; 113 | } 114 | 115 | action action_x () { 116 | alu_x.execute_stateful_alu(0); 117 | } 118 | 119 | table table_x { 120 | reads { 121 | cheetah.flowId : exact; 122 | } 123 | 124 | actions { 125 | action_x; 126 | } 127 | } 128 | 129 | register reg_y { 130 | width : 32; 131 | instance_count : 1; 132 | } 133 | 134 | blackbox stateful_alu alu_y { 135 | reg : reg_y; 136 | 137 | condition_lo : cheetah_md.replace_next == 1; 138 | condition_hi : register_lo - cheetah.y > 0; 139 | 140 | update_lo_1_predicate : condition_lo; 141 | update_lo_1_value : cheetah.y; 142 | 143 | update_hi_1_predicate : condition_hi and not condition_lo; 144 | update_hi_1_value : 1; 145 | update_hi_2_predicate : not condition_hi or condition_lo; 146 | update_hi_2_value : 0; 147 | 148 | output_value : alu_hi; 149 | output_dst : cheetah_md.dominates_y; 150 | } 151 | 152 | action action_y() { 153 | alu_y.execute_stateful_alu(0); 154 | } 155 | 156 | table table_y { 157 | reads { 158 | cheetah.flowId : exact; 159 | } 160 | 161 | actions { 162 | action_y; 163 | } 164 | } 165 | 166 | table forward { 167 | reads { 168 | ethernet.dstAddr : exact; 169 | } 170 | actions { 171 | set_egr; nop; 172 | } 173 | default_action: set_egr(40); 174 | } 175 | 176 | table acl { 177 | reads { 178 | ethernet.dstAddr : ternary; 179 | ethernet.srcAddr : ternary; 180 | } 181 | actions { 182 | nop; 183 | _drop; 184 | } 185 | } 186 | 187 | table table_prune { 188 | reads { 189 | cheetah.flowId : exact; 190 | } 191 | 192 | actions { 193 | prune; 194 | } 195 | } 196 | 197 | control ingress { 198 | apply(table_heuristic_pkt); 199 | apply(table_heuristic); 200 | apply(table_x); 201 | apply(table_y); 202 | if (cheetah_md.dominates_x == 0x1 and cheetah_md.dominates_y == 0x1) { 203 | apply(table_prune); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /data_plane/cheetah_topn.p4: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | header_type cheetah_t { 6 | fields { 7 | flowId : 16; 8 | rowId : 32; 9 | value : 32; 10 | } 11 | } 12 | 13 | header_type cheetah_md_t { 14 | fields { 15 | rowId : 32; 16 | diff : 32; 17 | process : 8; 18 | prune : 8; 19 | topn_min_val_one : 32; 20 | topn_less_than_min : 8; 21 | topn_more_than_n : 8; 22 | topn_less_than_min_two : 8; 23 | } 24 | } 25 | 26 | metadata cheetah_md_t cheetah_md; 27 | 28 | header cheetah_t cheetah; 29 | 30 | parser parse_cheetah { 31 | extract(cheetah); 32 | set_metadata(cheetah_md.rowId, cheetah.rowId); 33 | return ingress; 34 | } 35 | 36 | #define GENERATE_TOPN_MIN_ALU(name, reg_name, store_dest)\ 37 | blackbox stateful_alu cheetah_topn_query_ ## name {\ 38 | reg : reg_name;\ 39 | \ 40 | condition_lo : register_lo - cheetah.value > 0;\ 41 | \ 42 | update_lo_1_predicate : condition_lo;\ 43 | update_lo_1_value : cheetah.value;\ 44 | update_lo_2_predicate : not condition_lo;\ 45 | update_lo_2_value : register_lo;\ 46 | \ 47 | update_hi_1_predicate : condition_lo;\ 48 | update_hi_1_value : 1;\ 49 | update_hi_2_predicate : not condition_lo;\ 50 | update_hi_2_value : 0;\ 51 | \ 52 | output_value : alu_hi;\ 53 | output_dst : store_dest;\ 54 | } 55 | 56 | register cheetah_topn_counter_reg { 57 | width : 32; 58 | instance_count : 1; 59 | } 60 | 61 | register cheetah_topn_min_reg_one { 62 | width : 32; 63 | instance_count : 1; 64 | } 65 | 66 | register cheetah_topn_pack_reg { 67 | width : 32; 68 | instance_count : 1; 69 | } 70 | 71 | register cheetah_topn_counter_two_reg { 72 | width : 32; 73 | instance_count : 1; 74 | } 75 | 76 | #define GENERATE_PACKET_COUNTER_ALU(name, reg_name, cutoff, store_dest)\ 77 | blackbox stateful_alu cheetah_topn_count_pkt_ ## name {\ 78 | reg : reg_name;\ 79 | \ 80 | condition_lo : register_lo < cutoff;\ 81 | \ 82 | update_lo_1_predicate : condition_lo;\ 83 | update_lo_1_value : register_lo + 1;\ 84 | update_lo_2_predicate : not condition_lo;\ 85 | update_lo_2_value : register_lo;\ 86 | \ 87 | update_hi_1_predicate : condition_lo;\ 88 | update_hi_1_value : 0;\ 89 | update_hi_2_predicate : not condition_lo;\ 90 | update_hi_2_value : 1;\ 91 | \ 92 | output_value : alu_hi;\ 93 | output_dst : store_dest;\ 94 | } 95 | 96 | GENERATE_PACKET_COUNTER_ALU(one, cheetah_topn_counter_reg, 97 | CHEETAH_TOPN_VALUE, cheetah_md.topn_more_than_n) 98 | 99 | GENERATE_TOPN_MIN_ALU(one, cheetah_topn_min_reg_one, cheetah_md.topn_less_than_min) 100 | 101 | blackbox stateful_alu cheetah_topn_min_pack { 102 | reg : cheetah_topn_min_reg_one; 103 | 104 | update_lo_1_value : register_lo; 105 | output_value : alu_lo; 106 | output_dst : cheetah_md.topn_min_val_one; 107 | } 108 | 109 | blackbox stateful_alu cheetah_topn_t_one { 110 | reg : cheetah_topn_counter_two_reg; 111 | 112 | condition_lo : cheetah_md.topn_min_val_one > CHEETAH_TOPN_INT_MAX; 113 | condition_hi : register_lo - CHEETAH_TOPN_VALUE > 0; 114 | 115 | update_lo_1_predicate : condition_lo and not condition_hi; 116 | update_lo_1_value : register_lo + 1; 117 | 118 | update_hi_1_predicate : condition_lo and condition_hi; 119 | update_hi_1_value : 1; 120 | update_hi_2_predicate : not condition_lo or not condition_hi; 121 | update_hi_2_value : 0; 122 | 123 | output_value : alu_hi; 124 | output_dst : cheetah_md.topn_less_than_min_two; 125 | } 126 | 127 | action cheetah_topn_count(index) { 128 | cheetah_topn_count_pkt_one.execute_stateful_alu(index); 129 | } 130 | 131 | action cheetah_topn_min_action(index) { 132 | cheetah_topn_query_one.execute_stateful_alu(index); 133 | } 134 | 135 | action cheetah_topn_min_pack_action(index) { 136 | cheetah_topn_min_pack.execute_stateful_alu(index); 137 | } 138 | 139 | action cheetah_topn_t_one_action(index) { 140 | cheetah_topn_t_one.execute_stateful_alu(index); 141 | } 142 | 143 | action cheetah_topn_debug_one_action(index) { 144 | cheetah_topn_debug_one.execute_stateful_alu(index); 145 | } 146 | 147 | action prune() { 148 | drop(); 149 | } 150 | 151 | action cheetah_topn_double_action() { 152 | shift_left(cheetah_md.topn_min_val_one, cheetah_md.topn_min_val_one, 1); 153 | } 154 | 155 | action cheetah_topn_subtract_action() { 156 | subtract_from_field(cheetah_md.topn_min_val_one, cheetah.value); 157 | } 158 | 159 | table cheetah_topn_table_count { 160 | reads { 161 | cheetah.flowId : exact; 162 | } 163 | 164 | actions { 165 | cheetah_topn_count; 166 | } 167 | 168 | default_action : cheetah_topn_count(0); 169 | } 170 | 171 | table cheetah_topn_table_min { 172 | reads { 173 | cheetah.flowId : exact; 174 | cheetah_md.topn_more_than_n : exact; 175 | } 176 | 177 | actions { 178 | cheetah_topn_min_action; 179 | cheetah_topn_min_pack_action; 180 | } 181 | 182 | default_action : cheetah_topn_min_action(0); 183 | } 184 | 185 | table cheetah_topn_double { 186 | reads { 187 | cheetah.flowId : exact; 188 | } 189 | 190 | actions { 191 | cheetah_topn_double_action; 192 | } 193 | 194 | default_action : cheetah_topn_double_action(); 195 | } 196 | 197 | table cheetah_topn_subtract { 198 | reads { 199 | cheetah.flowId : exact; 200 | } 201 | 202 | actions { 203 | cheetah_topn_subtract_action; 204 | nop; 205 | } 206 | 207 | default_action : cheetah_topn_subtract_action(); 208 | } 209 | 210 | table cheetah_topn_t_one_table { 211 | reads { 212 | cheetah.flowId : exact; 213 | cheetah_md.topn_more_than_n : exact; 214 | } 215 | 216 | actions { 217 | cheetah_topn_t_one_action; 218 | nop; 219 | } 220 | 221 | default_action : nop; 222 | } 223 | 224 | table cheetah_topn_prune_check { 225 | reads { 226 | cheetah_md.topn_less_than_min : exact; 227 | cheetah_md.topn_less_than_min_two : exact; 228 | cheetah_md.topn_more_than_n : exact; 229 | } 230 | 231 | actions { 232 | nop; 233 | prune; 234 | } 235 | 236 | default_action : nop; 237 | } 238 | 239 | control ingress { 240 | apply(cheetah_topn_table_count); 241 | apply(cheetah_topn_table_min); 242 | apply(cheetah_topn_double); 243 | apply(cheetah_topn_subtract); 244 | apply(cheetah_topn_t_one_table); 245 | apply(cheetah_topn_prune_check); 246 | } 247 | -------------------------------------------------------------------------------- /host/Makefile_master: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright(c) 2010-2014 Intel Corporation 3 | 4 | # binary name 5 | APP = cheetah_master 6 | 7 | # all source are stored in SRCS-y 8 | MAIN_FILE = $(APP).c 9 | SRCS-y = cheetah_dpdk.c connection_state.c packet_crafter.c packet_manager.c fast_packet_stream.c cheetah_memory_sim.c packet_stream_receiver.c cheetah_benchmark.c control_message_manager.c cheetah_control_message.c cheetah_aggregate_processing.c cheetah_resource_manager.c cheetah_join.c cheetah_control_flow.c $(MAIN_FILE) 10 | 11 | # Build using pkg-config variables if possible 12 | $(shell pkg-config --exists libdpdk) 13 | ifeq ($(.SHELLSTATUS),0) 14 | 15 | all: shared 16 | .PHONY: shared static 17 | shared: build/$(APP)-shared 18 | ln -sf $(APP)-shared build/$(APP) 19 | static: build/$(APP)-static 20 | ln -sf $(APP)-static build/$(APP) 21 | 22 | PC_FILE := $(shell pkg-config --path libdpdk) 23 | CFLAGS += -Wall -Werror 24 | CFLAGS += -I include/ 25 | CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) 26 | LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) 27 | LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) 28 | 29 | build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build 30 | $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) 31 | 32 | build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build 33 | $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) 34 | 35 | build: 36 | @mkdir -p $@ 37 | 38 | .PHONY: clean 39 | clean: 40 | rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared 41 | rmdir --ignore-fail-on-non-empty build 42 | 43 | else # Build using legacy build system 44 | 45 | ifeq ($(RTE_SDK),) 46 | $(error "Please define RTE_SDK environment variable") 47 | endif 48 | 49 | # Default target, can be overridden by command line or environment 50 | RTE_TARGET ?= x86_64-native-linuxapp-gcc 51 | 52 | include $(RTE_SDK)/mk/rte.vars.mk 53 | 54 | CFLAGS += -O3 55 | CFLAGS += $(WERROR_FLAGS) 56 | CFLAGS += -I $(pwd)/include/ 57 | CFLAGS += -I $(pwd)/xxHash/ 58 | 59 | include $(RTE_SDK)/mk/rte.extapp.mk 60 | endif 61 | -------------------------------------------------------------------------------- /host/Makefile_worker: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright(c) 2010-2014 Intel Corporation 3 | 4 | # binary name 5 | APP = cheetah_worker 6 | 7 | # all source are stored in SRCS-y 8 | MAIN_FILE = $(APP).c 9 | SRCS-y = cheetah_dpdk.c connection_state.c packet_crafter.c packet_manager.c fast_packet_stream.c cheetah_memory_sim.c packet_stream_receiver.c cheetah_benchmark.c control_message_manager.c cheetah_control_message.c cheetah_aggregate_processing.c cheetah_resource_manager.c cheetah_join.c cheetah_control_flow.c $(MAIN_FILE) 10 | 11 | # Build using pkg-config variables if possible 12 | $(shell pkg-config --exists libdpdk) 13 | ifeq ($(.SHELLSTATUS),0) 14 | 15 | all: shared 16 | .PHONY: shared static 17 | shared: build/$(APP)-shared 18 | ln -sf $(APP)-shared build/$(APP) 19 | static: build/$(APP)-static 20 | ln -sf $(APP)-static build/$(APP) 21 | 22 | PC_FILE := $(shell pkg-config --path libdpdk) 23 | CFLAGS += -Wall -Werror 24 | CFLAGS += -I include/ 25 | CFLAGS += -I $(pwd)/xxHash/ 26 | CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) 27 | LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) 28 | LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) 29 | 30 | build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build 31 | $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) 32 | 33 | build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build 34 | $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) 35 | 36 | build: 37 | @mkdir -p $@ 38 | 39 | .PHONY: clean 40 | clean: 41 | rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared 42 | rmdir --ignore-fail-on-non-empty build 43 | 44 | else # Build using legacy build system 45 | 46 | ifeq ($(RTE_SDK),) 47 | $(error "Please define RTE_SDK environment variable") 48 | endif 49 | 50 | # Default target, can be overridden by command line or environment 51 | RTE_TARGET ?= x86_64-native-linuxapp-gcc 52 | 53 | include $(RTE_SDK)/mk/rte.vars.mk 54 | 55 | CFLAGS += -O3 56 | CFLAGS += $(WERROR_FLAGS) 57 | CFLAGS += -I $(pwd)/include/ 58 | CFLAGS += -I $(pwd)/xxHash/ 59 | 60 | include $(RTE_SDK)/mk/rte.extapp.mk 61 | endif 62 | -------------------------------------------------------------------------------- /host/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" == "test" ]; then 4 | printf "Building tests.." 5 | gcc cheetah_aggregate_processing.c -o build/cheetah_test 6 | echo "done." 7 | else 8 | rm -rf Makefile 9 | cp Makefile_worker Makefile 10 | make 11 | rm -rf Makefile 12 | cp Makefile_master Makefile 13 | make 14 | rm -rf Makefile 15 | fi 16 | -------------------------------------------------------------------------------- /host/cheetah_aggregate_processing.c: -------------------------------------------------------------------------------- 1 | /* #define CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 2 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 3 | #define _GNU_SOURCE 4 | #include "cheetah_aggregate_processing.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #else 12 | #include "cheetah_dpdk.h" 13 | #endif 14 | 15 | struct cheetah_aggregate_processing_topn_state * 16 | cheetah_aggregate_processing_topn_init(const int n) { 17 | 18 | struct cheetah_aggregate_processing_topn_state *state = 19 | malloc(sizeof(struct cheetah_aggregate_processing_topn_state)); 20 | 21 | state->n = n; 22 | state->current_entries = 0; 23 | state->result_array = malloc(sizeof(uint32_t) * n); 24 | return state; 25 | } 26 | 27 | void cheetah_aggregate_processing_topn_free( 28 | struct cheetah_aggregate_processing_topn_state *state) { 29 | free(state->result_array); 30 | free(state); 31 | } 32 | 33 | void cheetah_aggregate_processing_topn_update( 34 | struct cheetah_aggregate_processing_topn_state *state, 35 | const uint32_t value) { 36 | 37 | register int i; 38 | register int j; 39 | 40 | if (state->current_entries < state->n) { 41 | i = state->current_entries - 1; 42 | 43 | while (i >= 0 && state->result_array[i] < value) { 44 | i--; 45 | } 46 | 47 | if (i < ((int)state->current_entries - 1)) { 48 | for (j = state->current_entries - 1; j > i; j--) { 49 | state->result_array[j + 1] = state->result_array[j]; 50 | } 51 | } 52 | 53 | state->result_array[i + 1] = value; 54 | state->current_entries++; 55 | } 56 | 57 | else { 58 | i = state->n - 1; 59 | while (i >= 0 && state->result_array[i] < value) { 60 | i--; 61 | } 62 | 63 | if (i < ((int)state->n - 1)) { 64 | for (j = state->n - 2; j > i; j--) { 65 | state->result_array[j + 1] = state->result_array[j]; 66 | } 67 | 68 | state->result_array[i + 1] = value; 69 | } 70 | } 71 | } 72 | 73 | struct cheetah_aggregate_processing_distinct_state * 74 | cheetah_aggregate_processing_distinct_init(const uint32_t size) { 75 | 76 | struct cheetah_aggregate_processing_distinct_state *state; 77 | 78 | state = malloc(sizeof(struct cheetah_aggregate_processing_distinct_state)); 79 | 80 | state->size = size; 81 | state->current_entries = 0; 82 | state->current_hash_bins = 0; 83 | 84 | hcreate_r(size, &state->htab); 85 | 86 | state->result_array = malloc(sizeof(uint64_t) * size); 87 | state->ptr_array = malloc( 88 | sizeof(struct cheetah_aggregate_processing_distinct_entries *) * size); 89 | 90 | return state; 91 | } 92 | 93 | static void 94 | free_distinct_entry(struct cheetah_aggregate_processing_distinct_entries *e) { 95 | if (e) { 96 | free(e->next); 97 | free(e); 98 | } 99 | } 100 | 101 | void cheetah_aggregate_processing_distinct_free( 102 | struct cheetah_aggregate_processing_distinct_state *state) { 103 | 104 | register uint32_t i; 105 | 106 | hdestroy_r(&state->htab); 107 | 108 | for (i = 0; i < state->current_entries; i++) { 109 | free_distinct_entry(state->ptr_array[i]); 110 | } 111 | 112 | free(state->result_array); 113 | free(state); 114 | } 115 | 116 | void cheetah_aggregate_processing_distinct_update( 117 | struct cheetah_aggregate_processing_distinct_state *state, 118 | const uint64_t value) { 119 | 120 | /* 8 chars = 8 * 8 = 64 bits */ 121 | char key[8]; 122 | ENTRY e, *ep; 123 | unsigned int n; 124 | struct cheetah_aggregate_processing_distinct_entries *bin; 125 | struct cheetah_aggregate_processing_distinct_entries *bin_prev; 126 | 127 | n = 0; 128 | bin = NULL; 129 | bin_prev = NULL; 130 | 131 | memcpy(key, &value, 8); 132 | 133 | e.key = key; 134 | n = hsearch_r(e, FIND, &ep, &state->htab); 135 | 136 | if (n) { 137 | 138 | bin = (struct cheetah_aggregate_processing_distinct_entries *)ep->data; 139 | 140 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 141 | assert(bin); 142 | #else 143 | RTE_ASSERT(bin); 144 | #endif 145 | 146 | while (bin && bin->value != value) { 147 | bin_prev = bin; 148 | bin = bin->next; 149 | } 150 | 151 | if (!bin) { 152 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 153 | assert(bin_prev); 154 | assert(bin_prev->next == NULL); 155 | #else 156 | RTE_ASSERT(bin_prev); 157 | RTE_ASSERT(bin_prev->next == NULL); 158 | #endif /* CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 159 | 160 | bin_prev->next = 161 | malloc(sizeof(struct cheetah_aggregate_processing_distinct_entries)); 162 | 163 | bin = bin_prev->next; 164 | bin->value = value; 165 | bin->next = NULL; 166 | 167 | state->result_array[state->current_entries] = value; 168 | state->current_entries++; 169 | } 170 | } 171 | 172 | else { 173 | /* add it to hash table */ 174 | state->result_array[state->current_entries] = value; 175 | state->current_entries++; 176 | 177 | bin = malloc(sizeof(struct cheetah_aggregate_processing_distinct_entries)); 178 | bin->next = NULL; 179 | bin->value = value; 180 | 181 | e.data = (void *)bin; 182 | n = hsearch_r(e, ENTER, &ep, &state->htab); 183 | 184 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 185 | assert(n); 186 | #else 187 | RTE_ASSERT(n); 188 | #endif /* CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 189 | 190 | state->ptr_array[state->current_hash_bins] = bin; 191 | state->current_hash_bins++; 192 | } 193 | } 194 | 195 | struct cheetah_aggregate_processing_groupby_state * 196 | cheetah_aggregate_processing_groupby_init(const uint32_t size) { 197 | 198 | struct cheetah_aggregate_processing_groupby_state *state; 199 | 200 | state = malloc(sizeof(struct cheetah_aggregate_processing_groupby_state)); 201 | 202 | state->size = size; 203 | state->current_entries = 0; 204 | state->current_hash_bins = 0; 205 | 206 | hcreate_r(size, &state->htab); 207 | 208 | state->ptr_array = 209 | malloc(sizeof(struct cheetah_aggregate_processing_group_state *) * size); 210 | 211 | return state; 212 | } 213 | 214 | static void 215 | free_groupby_entry(struct cheetah_aggregate_processing_groupby_entries *e) { 216 | if (e) { 217 | free(e->next); 218 | free(e); 219 | } 220 | } 221 | 222 | void cheetah_aggregate_processing_groupby_free( 223 | struct cheetah_aggregate_processing_groupby_state *state) { 224 | register uint32_t i; 225 | 226 | hdestroy_r(&state->htab); 227 | 228 | for (i = 0; i < state->current_entries; i++) { 229 | free_groupby_entry(state->ptr_array[i]); 230 | } 231 | 232 | free(state); 233 | } 234 | 235 | void cheetah_aggregate_processing_groupby_update( 236 | struct cheetah_aggregate_processing_groupby_state *state, 237 | const uint32_t key, const uint32_t value) { 238 | /* 4 chars = 4 * 8 = 32 bits */ 239 | char formatted_key[4]; 240 | ENTRY e; 241 | ENTRY *ep; 242 | 243 | unsigned int n; 244 | struct cheetah_aggregate_processing_groupby_entries *bin; 245 | struct cheetah_aggregate_processing_groupby_entries *bin_prev; 246 | 247 | n = 0; 248 | bin = NULL; 249 | bin_prev = NULL; 250 | 251 | memcpy(formatted_key, &key, 4); 252 | 253 | e.key = formatted_key; 254 | n = hsearch_r(e, FIND, &ep, &state->htab); 255 | 256 | /* found */ 257 | if (n) { 258 | bin = (struct cheetah_aggregate_processing_groupby_entries *)ep->data; 259 | 260 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 261 | assert(bin); 262 | #else 263 | RTE_ASSERT(bin); 264 | #endif /* CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 265 | 266 | while (bin && bin->key != key) { 267 | bin_prev = bin; 268 | bin = bin->next; 269 | } 270 | 271 | if (!bin) { 272 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 273 | assert(bin_prev); 274 | assert(bin_prev->next == NULL); 275 | #else 276 | RTE_ASSERT(bin_prev); 277 | RTE_ASSERT(bin_prev->next == NULL); 278 | #endif /* CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 279 | 280 | bin_prev->next = 281 | malloc(sizeof(struct cheetah_aggregate_processing_groupby_entries)); 282 | 283 | bin = bin_prev->next; 284 | bin->value = value; 285 | bin->key = key; 286 | bin->next = NULL; 287 | 288 | state->ptr_array[state->current_entries] = bin; 289 | state->current_entries++; 290 | } else { 291 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 292 | assert(bin->key == key); 293 | #else 294 | RTE_ASSERT(bin->key == key); 295 | #endif /* CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 296 | if (bin->value < value) { 297 | bin->value = value; 298 | } 299 | } 300 | } else { 301 | bin = malloc(sizeof(struct cheetah_aggregate_processing_groupby_entries)); 302 | bin->next = NULL; 303 | bin->key = key; 304 | bin->value = value; 305 | 306 | e.data = (void *)bin; 307 | n = hsearch_r(e, ENTER, &ep, &state->htab); 308 | 309 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 310 | assert(n); 311 | #else 312 | RTE_ASSERT(n); 313 | #endif /* CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 314 | 315 | state->ptr_array[state->current_entries] = bin; 316 | state->current_entries++; 317 | state->current_hash_bins++; 318 | } 319 | } 320 | 321 | #ifdef CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS 322 | int main() { 323 | struct cheetah_aggregate_processing_topn_state *state; 324 | struct cheetah_aggregate_processing_distinct_state *distinct_state; 325 | struct cheetah_aggregate_processing_groupby_state *groupby_state; 326 | register int i; 327 | 328 | puts("Testing groupby"); 329 | groupby_state = cheetah_aggregate_processing_groupby_init(4); 330 | 331 | cheetah_aggregate_processing_groupby_update(groupby_state, 1, 3); 332 | 333 | assert(groupby_state->current_entries == 1); 334 | assert(groupby_state->current_hash_bins == 1); 335 | assert(groupby_state->ptr_array[0]->key == 1); 336 | assert(groupby_state->ptr_array[0]->value == 3); 337 | 338 | cheetah_aggregate_processing_groupby_update(groupby_state, 42, 11); 339 | cheetah_aggregate_processing_groupby_update(groupby_state, 1, 5); 340 | 341 | assert(groupby_state->current_entries == 2); 342 | assert(groupby_state->ptr_array[0]->key == 1); 343 | assert(groupby_state->ptr_array[0]->value == 5); 344 | assert(groupby_state->ptr_array[1]->key == 42); 345 | assert(groupby_state->ptr_array[1]->value == 11); 346 | 347 | cheetah_aggregate_processing_groupby_update(groupby_state, 42, 10); 348 | 349 | assert(groupby_state->current_entries == 2); 350 | assert(groupby_state->ptr_array[0]->key == 1); 351 | assert(groupby_state->ptr_array[0]->value == 5); 352 | assert(groupby_state->ptr_array[1]->key == 42); 353 | assert(groupby_state->ptr_array[1]->value == 11); 354 | 355 | cheetah_aggregate_processing_groupby_free(groupby_state); 356 | puts("All tests passed."); 357 | 358 | puts("Testing Top-N"); 359 | state = cheetah_aggregate_processing_topn_init(4); 360 | 361 | cheetah_aggregate_processing_topn_update(state, 11); 362 | cheetah_aggregate_processing_topn_update(state, 9); 363 | cheetah_aggregate_processing_topn_update(state, 13); 364 | cheetah_aggregate_processing_topn_update(state, 10); 365 | 366 | assert(state->result_array[0] == 13); 367 | assert(state->result_array[1] == 11); 368 | assert(state->result_array[2] == 10); 369 | assert(state->result_array[3] == 9); 370 | 371 | cheetah_aggregate_processing_topn_update(state, 8); 372 | 373 | assert(state->result_array[0] == 13); 374 | assert(state->result_array[1] == 11); 375 | assert(state->result_array[2] == 10); 376 | assert(state->result_array[3] == 9); 377 | 378 | cheetah_aggregate_processing_topn_update(state, 15); 379 | 380 | assert(state->result_array[0] == 15); 381 | assert(state->result_array[1] == 13); 382 | assert(state->result_array[2] == 11); 383 | assert(state->result_array[3] == 10); 384 | 385 | cheetah_aggregate_processing_topn_update(state, 11); 386 | 387 | assert(state->result_array[0] == 15); 388 | assert(state->result_array[1] == 13); 389 | assert(state->result_array[2] == 11); 390 | assert(state->result_array[3] == 11); 391 | 392 | cheetah_aggregate_processing_topn_update(state, 12); 393 | 394 | assert(state->result_array[0] == 15); 395 | assert(state->result_array[1] == 13); 396 | assert(state->result_array[2] == 12); 397 | assert(state->result_array[3] == 11); 398 | 399 | cheetah_aggregate_processing_topn_free(state); 400 | 401 | puts("All tests passed."); 402 | 403 | puts("Testing Distinct"); 404 | 405 | distinct_state = cheetah_aggregate_processing_distinct_init(10); 406 | 407 | cheetah_aggregate_processing_distinct_update(distinct_state, 10); 408 | 409 | cheetah_aggregate_processing_distinct_update(distinct_state, 10); 410 | 411 | assert(distinct_state->current_entries == 1); 412 | assert(distinct_state->current_hash_bins == 1); 413 | assert(distinct_state->result_array[0] == 10); 414 | 415 | cheetah_aggregate_processing_distinct_update(distinct_state, 11); 416 | 417 | assert(distinct_state->current_entries == 2); 418 | assert(distinct_state->result_array[0] == 10); 419 | assert(distinct_state->result_array[1] == 11); 420 | assert(distinct_state->current_hash_bins <= 2); 421 | 422 | cheetah_aggregate_processing_distinct_update(distinct_state, 10); 423 | 424 | assert(distinct_state->current_entries == 2); 425 | assert(distinct_state->result_array[0] == 10); 426 | assert(distinct_state->result_array[1] == 11); 427 | assert(distinct_state->current_hash_bins <= 2); 428 | 429 | for (i = 0; i < 100000; i++) { 430 | cheetah_aggregate_processing_distinct_update(distinct_state, 11); 431 | } 432 | 433 | assert(distinct_state->current_entries == 2); 434 | assert(distinct_state->result_array[0] == 10); 435 | assert(distinct_state->result_array[1] == 11); 436 | assert(distinct_state->current_hash_bins <= 2); 437 | 438 | cheetah_aggregate_processing_distinct_free(distinct_state); 439 | puts("All tests passed"); 440 | } 441 | 442 | #endif /* CHEETAH_AGGREGATE_PROCESSING_ENABLE_TESTS */ 443 | -------------------------------------------------------------------------------- /host/cheetah_aggregate_processing.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_AGGREGATE_PROCESSING_H 2 | #define CHEETAH_AGGREGATE_PROCESSING_H 3 | 4 | struct cheetah_aggregate_processing_topn_state { 5 | uint32_t n; 6 | uint32_t *result_array; 7 | uint32_t current_entries; 8 | }; 9 | 10 | struct cheetah_aggregate_processing_topn_state * 11 | cheetah_aggregate_processing_topn_init(const int n); 12 | 13 | void cheetah_aggregate_processing_topn_free( 14 | struct cheetah_aggregate_processing_topn_state *state); 15 | 16 | void cheetah_aggregate_processing_topn_update( 17 | struct cheetah_aggregate_processing_topn_state *state, 18 | const uint32_t value); 19 | 20 | struct cheetah_aggregate_processing_distinct_entries { 21 | uint64_t value; 22 | struct cheetah_aggregate_processing_distinct_entries *next; 23 | }; 24 | 25 | struct cheetah_aggregate_processing_distinct_state { 26 | uint32_t current_entries; 27 | uint32_t current_hash_bins; 28 | uint32_t size; 29 | struct hsearch_data htab; 30 | uint64_t *result_array; 31 | struct cheetah_aggregate_processing_distinct_entries **ptr_array; 32 | }; 33 | 34 | struct cheetah_aggregate_processing_distinct_state * 35 | cheetah_aggregate_processing_distinct_init(const uint32_t size); 36 | 37 | void cheetah_aggregate_processing_distinct_free( 38 | struct cheetah_aggregate_processing_distinct_state *state); 39 | 40 | void cheetah_aggregate_processing_distinct_update( 41 | struct cheetah_aggregate_processing_distinct_state *state, 42 | const uint64_t value); 43 | 44 | struct cheetah_aggregate_processing_groupby_entries { 45 | uint32_t key; 46 | uint32_t value; 47 | struct cheetah_aggregate_processing_groupby_entries *next; 48 | }; 49 | 50 | struct cheetah_aggregate_processing_groupby_state { 51 | uint32_t current_entries; 52 | uint32_t current_hash_bins; 53 | uint32_t size; 54 | struct hsearch_data htab; 55 | struct cheetah_aggregate_processing_groupby_entries **ptr_array; 56 | }; 57 | 58 | struct cheetah_aggregate_processing_groupby_state * 59 | cheetah_aggregate_processing_groupby_init(const uint32_t size); 60 | 61 | void cheetah_aggregate_processing_groupby_free( 62 | struct cheetah_aggregate_processing_groupby_state *state); 63 | 64 | void cheetah_aggregate_processing_groupby_update( 65 | struct cheetah_aggregate_processing_groupby_state *state, 66 | const uint32_t key, const uint32_t value); 67 | 68 | #endif /* CHEETAH_AGGREGATE_PROCESSING_H */ 69 | -------------------------------------------------------------------------------- /host/cheetah_benchmark.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | void cheetah_benchmark_packet_rate_start( 4 | struct cheetah_benchmarker *const benchmarker, 5 | const unsigned int packets_to_send) { 6 | benchmarker->packets_to_send = packets_to_send; 7 | 8 | gettimeofday(&benchmarker->tv_start, NULL); 9 | } 10 | 11 | void cheetah_benchmark_packet_rate_stop( 12 | struct cheetah_benchmarker *const benchmarker) { 13 | gettimeofday(&benchmarker->tv_end, NULL); 14 | timersub(&benchmarker->tv_end, &benchmarker->tv_start, 15 | &benchmarker->tv_difference); 16 | 17 | benchmarker->time_elapsed_usec = 18 | (1000000.0 * benchmarker->tv_difference.tv_sec) + 19 | benchmarker->tv_difference.tv_usec; 20 | benchmarker->packet_rate = (benchmarker->packets_to_send * 1000000.0) / 21 | benchmarker->time_elapsed_usec; 22 | } 23 | -------------------------------------------------------------------------------- /host/cheetah_benchmark.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_BENCHMARK_H 2 | #define CHEETAH_BENCHMARK_H 3 | 4 | struct cheetah_benchmarker { 5 | struct timeval tv_start; 6 | struct timeval tv_end; 7 | struct timeval tv_difference; 8 | unsigned int packets_to_send; 9 | double time_elapsed_usec; 10 | double packet_rate; 11 | }; 12 | 13 | void cheetah_benchmark_packet_rate_start( 14 | struct cheetah_benchmarker *const benchmarker, 15 | const unsigned int packets_to_send); 16 | 17 | void cheetah_benchmark_packet_rate_stop( 18 | struct cheetah_benchmarker *const benchmarker); 19 | 20 | #endif /* CHEETAH_BENCHMARK_H */ 21 | -------------------------------------------------------------------------------- /host/cheetah_constants.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_CONSTANTS_H 2 | #define CHEETAH_CONSTANTS_H 3 | 4 | #ifndef _GNU_SOURCE 5 | #define _GNU_SOURCE 6 | #endif /* _GNU_SOURCE */ 7 | 8 | /* #define CHEETAH_USE_MULTICORE_DPDK */ 9 | 10 | /* +1 if including "master" */ 11 | #define CHEETAH_WORKER_COUNT 1 12 | 13 | /* Resource limits */ 14 | //#define CHEETAH_ENABLE_RESOURCE_LIMITS 15 | 16 | /* in bytes */ 17 | #define CHEETAH_WORKER_MEMORY_LIMIT 17179869184 18 | 19 | /* in cores */ 20 | #define CHEETAH_WORKER_CORE_LIMIT 2 21 | 22 | /* #define CHEETAH_DATASET_USER_VALUES */ 23 | 24 | #define CHEETAH_TESTBED_DR_MINLAN 25 | 26 | #define CHEETAH_RXTX_DESC_DEFAULT 1024 27 | #define CHEETAH_MAX_PKT_BURST_DEFAULT 32 28 | 29 | #define CHEETAH_PACKET_MBUF 8192U 30 | #define CHEETAH_MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE 31 | #define CHEETAH_MEMPOOL_CACHE_SIZE 256 32 | 33 | #define CHEETAH_RX_QUEUE_ID 0 34 | #define CHEETAH_TX_QUEUE_ID 0 35 | 36 | #define CHEETAH_ROWS_ON_SWITCH 16000 37 | 38 | /* 39 | * UDP Size : 8 Bytes 40 | * IPv4 Size : 20 Bytes 41 | * Payload size : (32 / 8) + (32 / 8) + (16 / 8) = 10 Bytes 42 | */ 43 | 44 | #define CHEETAH_DATAGRAM_LENGTH 38 45 | #define CHEETAH_UDP_DATAGRAM_LENGTH 18 46 | #define CHEETAH_ETHERNET_FULL_LENGTH 52 47 | 48 | #define CHEETAH_MEMORY_ENTRY_COUNT 50000000 49 | #define CHEETAH_RECEIVER_MEMORY_ENTRY_COUNT 100000000 50 | 51 | #define CHEETAH_ENABLE_PACKET_MONITORING 52 | // #define CHEETAH_ENABLE_RECEIVER_PACKET_MONITORING 53 | 54 | #define CHEETAH_CSV_ENTRY_MAX_LENGTH 1024 55 | 56 | #define CHEETAH_CONTROL_MESSAGE_BUFFER_LENGTH 1024 57 | 58 | #define CHEETAH_CONTROL_MESSAGE_PORT "23456" 59 | 60 | #ifdef CHEETAH_TESTBED_DR_XIN 61 | #define CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_1 "10.161.159.60" 62 | #define CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_2 "10.161.159.61" 63 | #define CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_3 "10.161.159.34" 64 | #define CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_4 "10.161.159.35" 65 | #define CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_5 "10.161.159.36" 66 | #endif /* CHEETAH_TESTBED_DR_XIN */ 67 | 68 | #ifdef CHEETAH_TESTBED_DR_MINLAN 69 | 70 | #define CHEETAH_MULTIPLE_NODES_SAME_IP 71 | 72 | #define CHEETAH_CONTROL_MESSAGE_MASTER_IP "10.243.38.88" 73 | #define CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_1 "10.243.38.89" 74 | #define CHEETAH_CONTROL_MESSAGE_PORT_2 "23457" 75 | 76 | #define CHEETAH_WORKER_ID 1 77 | 78 | #endif /* CHEETAH_TESTBED_DR_MINLAN */ 79 | 80 | #define CHEETAH_MEMORY_SIM_DATASET_PATH \ 81 | "../../tpch_scale1/both_tbl_with_flow.csv" 82 | 83 | #define CHEETAH_DEFAULT_FLOW_ID 1 84 | 85 | /* #define CHEETAH_USE_64_BIT_VALUES */ 86 | /* #define CHEETAH_USE_HASH_AT_WORKER */ 87 | /* #define CHEETAH_USE_STRING_VALUES */ 88 | #define CHEETAH_USE_KEY_AT_WORKER 89 | #define CHEETAH_USE_FLOW_ID_AT_WORKER 90 | 91 | /* #define CHEETAH_DATASET_USER_VISITS */ 92 | /* #define CHEETAH_DATASET_RANDOM_KV */ 93 | /*#define CHEETAH_DATASET_USER_DATA_HASHED*/ 94 | #define CHEETAH_DATASET_TPCH 95 | 96 | #define CHEETAH_ENABLE_AGGREGATE_PROCESSING 97 | 98 | /* 25.25.25.1 */ 99 | #define CHEETAH_MASTER_DPDK_IP 0x19191901 100 | 101 | /* 25.25.25.7 */ 102 | #define CHEETAH_WORKER_DPDK_IP 0x19191907 103 | 104 | #ifdef CHEETAH_TESTBED_DR_MINLAN 105 | 106 | /* ec:0d:9a:07:dc:90 */ 107 | #define CHEETAH_WORKER_MAC_1 0xec 108 | #define CHEETAH_WORKER_MAC_2 0x0d 109 | #define CHEETAH_WORKER_MAC_3 0x9a 110 | #define CHEETAH_WORKER_MAC_4 0x07 111 | #define CHEETAH_WORKER_MAC_5 0xdc 112 | #define CHEETAH_WORKER_MAC_6 0x90 113 | 114 | /* ec:0d:9a:07:dd:a0 */ 115 | /* Dr. Minlan's servers */ 116 | #define CHEETAH_MASTER_MAC_1 0xec 117 | #define CHEETAH_MASTER_MAC_2 0x0d 118 | #define CHEETAH_MASTER_MAC_3 0x9a 119 | #define CHEETAH_MASTER_MAC_4 0x07 120 | #define CHEETAH_MASTER_MAC_5 0xdd 121 | #define CHEETAH_MASTER_MAC_6 0xa0 122 | 123 | #endif /* CHEETAH_TESTBED_DR_MINLAN */ 124 | 125 | /* Dr. Xin's servers */ 126 | #ifdef CHEETAH_TESTBED_DR_XIN 127 | 128 | #define CHEETAH_WORKER_MAC_1 0x3c 129 | #define CHEETAH_WORKER_MAC_2 0xfd 130 | #define CHEETAH_WORKER_MAC_3 0xfe 131 | #define CHEETAH_WORKER_MAC_4 0xa6 132 | #define CHEETAH_WORKER_MAC_5 0xeb 133 | #define CHEETAH_WORKER_MAC_6 0x10 134 | 135 | #define CHEETAH_MASTER_MAC_1 0x3c 136 | #define CHEETAH_MASTER_MAC_2 0xfd 137 | #define CHEETAH_MASTER_MAC_3 0xfe 138 | #define CHEETAH_MASTER_MAC_4 0xab 139 | #define CHEETAH_MASTER_MAC_5 0xde 140 | #define CHEETAH_MASTER_MAC_6 0xd8 141 | 142 | #endif /* CHEETAH_TESTBED_DR_XIN */ 143 | 144 | #endif /* CHEETAH_CONSTANTS_H */ 145 | -------------------------------------------------------------------------------- /host/cheetah_control_flow.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | #include 3 | 4 | /* #define CHEETAH_DISABLE_DPDK */ 5 | #define CHEETAH_CONTROL_FLOW_MASTER_DEBUG 6 | /* #define CHEETAH_CONTROL_FLOW_WORKER_DEBUG */ 7 | 8 | int cheetah_control_flow_master(int argc, char **const argv) { 9 | #ifdef CHEETAH_DISABLE_DPDK 10 | cheetah_unused_var(argc); 11 | cheetah_unused_var(argv); 12 | #endif 13 | 14 | #ifndef CHEETAH_DISABLE_DPDK 15 | struct cheetah_connection_state *state; 16 | struct cheetah_packet_stream_receiver *receiver; 17 | struct ether_addr dest_addr; 18 | struct cheetah_benchmarker benchmarker; 19 | uint64_t packets_received; 20 | uint64_t packets_received_current_batch; 21 | uint8_t offloaded; 22 | uint8_t started; 23 | int worker_acks_left; 24 | 25 | /* purely to remove warnings */ 26 | worker_acks_left = 0; 27 | cheetah_unused_var(worker_acks_left); 28 | 29 | cheetah_debug("DPDK is enabled\n"); 30 | cheetah_debug_flush(); 31 | 32 | char current_query_type[] = CHEETAH_CONTROL_MESSAGE_QUERY_JOIN; 33 | 34 | #ifdef CHEETAH_ENABLE_AGGREGATE_PROCESSING 35 | /* Pointers to all query aggregate processing states. 36 | * Hopefully the compiler will optimize out the unnecessary ones */ 37 | struct cheetah_aggregate_processing_distinct_state *distinct_state; 38 | struct cheetah_aggregate_processing_topn_state *topn_state; 39 | struct cheetah_aggregate_processing_groupby_state *groupby_state; 40 | struct cheetah_join_state *join_state; 41 | 42 | register uint64_t i; 43 | uint64_t update_count = 0; 44 | 45 | distinct_state = NULL; 46 | topn_state = NULL; 47 | groupby_state = NULL; 48 | join_state = cheetah_join_init(100000, 40000); 49 | 50 | /* Suppress warnings for the above states */ 51 | cheetah_unused_var(distinct_state); 52 | cheetah_unused_var(topn_state); 53 | cheetah_unused_var(groupby_state); 54 | 55 | #endif /* CHEETAH_ENABLE_AGGREGATE_PROCESSING */ 56 | 57 | cheetah_init(argc, argv); 58 | cheetah_packet_ether_addr_populate(&dest_addr, CHEETAH_WORKER_MAC_1, 59 | CHEETAH_WORKER_MAC_2, CHEETAH_WORKER_MAC_3, 60 | CHEETAH_WORKER_MAC_4, CHEETAH_WORKER_MAC_5, 61 | CHEETAH_WORKER_MAC_6); 62 | 63 | #ifdef CHEETAH_ENABLE_RESOURCE_LIMITS 64 | cheetah_debug("Limiting resources..."); 65 | cheetah_debug_flush(); 66 | 67 | cheetah_set_memory_limit(CHEETAH_WORKER_MEMORY_LIMIT); 68 | cheetah_set_cpu_core_limit(CHEETAH_WORKER_CORE_LIMIT); 69 | 70 | cheetah_debug("Success!\n"); 71 | cheetah_debug_flush(); 72 | #endif /* CHEETAH_ENABLE_RESOURCE_LIMITS */ 73 | 74 | state = cheetah_connection_state_create(0, dest_addr); 75 | receiver = cheetah_packet_stream_receiver_create(RECEIVER_BATCH_SIZE); 76 | #endif /* Not CHEETAH_DISABLE_DPDK */ 77 | 78 | #ifndef CHEETAH_DISABLE_DPDK 79 | packets_received = 0; 80 | offloaded = 0; 81 | started = 0; 82 | worker_acks_left = CHEETAH_WORKER_COUNT; 83 | 84 | #endif /* Not CHEETAH_DISABLE_DPDK */ 85 | 86 | #ifndef CHEETAH_DISABLE_DPDK 87 | while (!cheetah_global_force_quit) { 88 | packets_received_current_batch = 89 | cheetah_packet_stream_receiver_receive(receiver, state); 90 | 91 | packets_received += packets_received_current_batch; 92 | 93 | #ifdef CHEETAH_ENABLE_AGGREGATE_PROCESSING 94 | for (i = 0; i < packets_received_current_batch; i++) { 95 | if (strncmp(current_query_type, CHEETAH_CONTROL_MESSAGE_QUERY_GROUPBY, 96 | CHEETAH_CONTROL_MESSAGE_MAX_SIZE) == 0) { 97 | 98 | cheetah_aggregate_processing_groupby_update( 99 | groupby_state, receiver->payload_key_arr[i], 100 | receiver->payload_value_arr[i]); 101 | } 102 | 103 | if (strncmp(current_query_type, CHEETAH_CONTROL_MESSAGE_QUERY_DISTINCT, 104 | CHEETAH_CONTROL_MESSAGE_MAX_SIZE) == 0) { 105 | cheetah_aggregate_processing_distinct_update( 106 | distinct_state, receiver->payload_value_arr[i]); 107 | } 108 | 109 | if (strncmp(current_query_type, CHEETAH_CONTROL_MESSAGE_QUERY_JOIN, 110 | CHEETAH_CONTROL_MESSAGE_MAX_SIZE) == 0) { 111 | enum cheetah_join_table tbl = (receiver->payload_flow_id_arr[i] == 1) 112 | ? CHEETAH_JOIN_TABLE_PRIMARY 113 | : CHEETAH_JOIN_TABLE_SECONDARY; 114 | 115 | cheetah_join_update(join_state, receiver->payload_key_arr[i], 116 | receiver->payload_row_id_arr[i], tbl); 117 | update_count++; 118 | } 119 | } 120 | #endif /* CHEETAH_ENABLE_AGGREGATE_PROCESSING */ 121 | 122 | if (started) { 123 | // cheetah_control_message_receive_acks(&worker_acks_left); 124 | } 125 | 126 | if (offloaded && !started && packets_received) { 127 | puts("HELLO"); 128 | cheetah_debug_flush(); 129 | cheetah_benchmark_packet_rate_start(&benchmarker, 0); 130 | system("python3 receive_ack_end.py &"); 131 | started = 1; 132 | } 133 | 134 | if (!offloaded) { 135 | sleep(3); 136 | 137 | cheetah_debug("Offloading query..."); 138 | cheetah_debug_flush(); 139 | 140 | cheetah_control_message_offload_query(current_query_type); 141 | 142 | cheetah_debug("Success!\n"); 143 | cheetah_debug_flush(); 144 | 145 | offloaded = 1; 146 | } 147 | } 148 | 149 | cheetah_benchmark_packet_rate_stop(&benchmarker); 150 | 151 | cheetah_debug("Packets received: %" PRIu64 "\n", packets_received); 152 | cheetah_debug("Time elapsed (us): %f\n", benchmarker.time_elapsed_usec); 153 | 154 | cheetah_debug("Updates: %" PRIu64 "\n", update_count); 155 | 156 | cheetah_debug_flush(); 157 | 158 | for (i = 0; i < groupby_state->current_entries; i++) { 159 | printf("Key: %d, Value: %d\n", groupby_state->ptr_array[i]->key, 160 | groupby_state->ptr_array[i]->value); 161 | } 162 | 163 | cheetah_packet_stream_receiver_free(receiver); 164 | cheetah_connection_state_free(state); 165 | 166 | #endif /* CHEETAH_DISABLE_DPDK */ 167 | 168 | return EXIT_SUCCESS; 169 | } 170 | 171 | int cheetah_control_flow_worker(int argc, char **const argv) { 172 | struct cheetah_connection_state *state; 173 | struct cheetah_fast_packet_stream *fast_pktstream; 174 | struct ether_addr dest_addr; 175 | struct cheetah_benchmarker benchmarker; 176 | struct cheetah_memory_sim *sim; 177 | 178 | register unsigned int i; 179 | register unsigned int j; 180 | 181 | #ifdef CHEETAH_USE_MULTICORE_DPDK 182 | unsigned int lcore_id; 183 | #endif /* CHEETAH_USE_MULTICORE_DPDK */ 184 | 185 | const char *dataset_filename = CHEETAH_MEMORY_SIM_DATASET_PATH; 186 | 187 | cheetah_init(argc, argv); 188 | /* cheetah_packet_ether_addr_populate(&dest_addr, 0x24, 0x8a, 0x07, 0xc5, 189 | * 0x2e, 0xd0); */ 190 | /* 3c:fd:fe:ab:de:d8 */ 191 | cheetah_packet_ether_addr_populate(&dest_addr, CHEETAH_MASTER_MAC_1, 192 | CHEETAH_MASTER_MAC_2, CHEETAH_MASTER_MAC_3, 193 | CHEETAH_MASTER_MAC_4, CHEETAH_MASTER_MAC_5, 194 | CHEETAH_MASTER_MAC_6); 195 | 196 | state = cheetah_connection_state_create(0, dest_addr); 197 | 198 | #ifdef CHEETAH_ENABLE_RESOURCE_LIMITS 199 | cheetah_debug("Limiting resources..."); 200 | cheetah_debug_flush(); 201 | 202 | cheetah_set_memory_limit(CHEETAH_WORKER_MEMORY_LIMIT); 203 | cheetah_set_cpu_core_limit(CHEETAH_WORKER_CORE_LIMIT); 204 | 205 | cheetah_debug("Success!\n"); 206 | cheetah_debug_flush(); 207 | #endif /* CHEETAH_ENABLE_RESOURCE_LIMITS */ 208 | 209 | fast_pktstream = cheetah_fast_packet_stream_create(state, BATCH_SIZE); 210 | 211 | sim = cheetah_memory_sim_create(dataset_filename, CHEETAH_MEMORY_ENTRY_COUNT); 212 | 213 | cheetah_debug("Waiting for query signal..."); 214 | cheetah_debug_flush(); 215 | 216 | #ifndef CHEETAH_CONTROL_FLOW_WORKER_DEBUG 217 | cheetah_control_message_await_query(CHEETAH_WORKER_ID); 218 | #endif /* CHEETAH_CONTROL_FLOW_WORKER_DEBUG */ 219 | 220 | cheetah_debug("Success!\n"); 221 | cheetah_debug_flush(); 222 | 223 | cheetah_benchmark_packet_rate_start(&benchmarker, sim->entry_count); 224 | 225 | for (i = 0; i < (sim->entry_count / BATCH_SIZE); i++) { 226 | for (j = 0; j < BATCH_SIZE; j++) { 227 | 228 | cheetah_fast_packet_stream_modify(fast_pktstream, j, 229 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 230 | sim->flow_id_arr[i * BATCH_SIZE + j], 231 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 232 | #ifdef CHEETAH_USE_KEY_AT_WORKER 233 | sim->key_arr[i * BATCH_SIZE + j], 234 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 235 | sim->value_arr[i * BATCH_SIZE + j], 236 | sim->row_id_arr[i * BATCH_SIZE + j]); 237 | 238 | #ifdef CHEETAH_CONTROL_FLOW_WORKER_DEBUG 239 | /* 240 | rte_pktmbuf_dump(stdout, fast_pktstream->mbuf_burst_arr[j], 241 | CHEETAH_ETHERNET_FULL_LENGTH); fflush(stdout); 242 | */ 243 | #endif /* CHEETAH_CONTROL_FLOW_WORKER_DEBUG */ 244 | } 245 | 246 | #ifdef CHEETAH_USE_MULTICORE_DPDK 247 | RTE_LCORE_FOREACH(lcore_id) { 248 | #endif /* CHEETAH_USE_MULTICORE_DPDK */ 249 | cheetah_fast_packet_stream_send(fast_pktstream, state); 250 | 251 | /* 252 | if (unlikely(i % 7) == 0) { 253 | usleep(7); 254 | } 255 | */ 256 | #ifdef CHEETAH_USE_MULTICORE_DPDK 257 | } 258 | #endif /* CHEETAH_USE_MULTICORE_DPDK */ 259 | 260 | #ifdef CHEETAH_CONTROL_FLOW_WORKER_DEBUG 261 | /* break; */ 262 | #endif /* CHEETAH_CONTROL_FLOW_WORKER_DEBUG */ 263 | } 264 | 265 | cheetah_benchmark_packet_rate_stop(&benchmarker); 266 | 267 | cheetah_control_message_send_ack(); 268 | 269 | cheetah_debug("Packet rate: %f.\n", benchmarker.packet_rate); 270 | cheetah_debug("Time: %f.\n", benchmarker.time_elapsed_usec); 271 | cheetah_debug_flush(); 272 | 273 | cheetah_fast_packet_stream_free(fast_pktstream); 274 | cheetah_memory_sim_free(sim); 275 | cheetah_connection_state_free(state); 276 | 277 | return EXIT_SUCCESS; 278 | } 279 | -------------------------------------------------------------------------------- /host/cheetah_control_flow.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_CONTROL_FLOW_H 2 | #define CHEETAH_CONTROL_FLOW_H 3 | 4 | #define BATCH_SIZE 32 5 | #define RECEIVER_BATCH_SIZE 32 6 | 7 | /* #define CHEETAH_CONTROL_FLOW_WORKER_DEBUG */ 8 | /* #define CHEETAH_CONTROL_FLOW_MASTER_DEBUG */ 9 | 10 | int cheetah_control_flow_worker(int argc, char **const argv); 11 | 12 | int cheetah_control_flow_master(int argc, char **const argv); 13 | 14 | #endif /* CHEETAH_CONTROL_FLOW_H */ 15 | -------------------------------------------------------------------------------- /host/cheetah_control_message.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | static int cheetah_control_message_receive(const char *const ip, 4 | const char *port, 5 | const uint8_t non_blocking) { 6 | int socket_file_descriptor; 7 | struct addrinfo hints; 8 | struct addrinfo *server_information; 9 | struct addrinfo *addr_iterator; 10 | char recv_buffer[CHEETAH_CONTROL_MESSAGE_BUFFER_LENGTH]; 11 | socklen_t address_length; 12 | int return_placeholder; 13 | struct sockaddr_storage sender_address; 14 | int bytes_received; 15 | int flags; 16 | 17 | cheetah_unused_var(return_placeholder); 18 | cheetah_unused_var(bytes_received); 19 | 20 | socket_file_descriptor = -1; 21 | 22 | memset(&hints, 0, sizeof(struct addrinfo)); 23 | hints.ai_family = AF_INET; 24 | hints.ai_socktype = SOCK_DGRAM; 25 | 26 | return_placeholder = getaddrinfo(ip, port, &hints, &server_information); 27 | 28 | RTE_ASSERT(return_placeholder == 0); 29 | 30 | for (addr_iterator = server_information; addr_iterator != NULL; 31 | addr_iterator = addr_iterator->ai_next) { 32 | socket_file_descriptor = 33 | socket(addr_iterator->ai_family, addr_iterator->ai_socktype, 34 | addr_iterator->ai_protocol); 35 | 36 | if (socket_file_descriptor != -1) { 37 | return_placeholder = bind(socket_file_descriptor, addr_iterator->ai_addr, 38 | addr_iterator->ai_addrlen); 39 | 40 | if (return_placeholder != -1) { 41 | break; 42 | } 43 | } 44 | } 45 | 46 | RTE_ASSERT(addr_iterator != NULL); 47 | 48 | freeaddrinfo(server_information); 49 | 50 | if (non_blocking) { 51 | flags = fcntl(socket_file_descriptor, F_GETFL); 52 | RTE_ASSERT(flags != -1); 53 | 54 | return_placeholder = 55 | fcntl(socket_file_descriptor, F_SETFL, flags | O_NONBLOCK); 56 | RTE_ASSERT(return_placeholder != -1); 57 | } 58 | 59 | address_length = sizeof(struct sockaddr_storage); 60 | bytes_received = 61 | recvfrom(socket_file_descriptor, recv_buffer, 62 | CHEETAH_CONTROL_MESSAGE_BUFFER_LENGTH - 1, 0, 63 | (struct sockaddr *)&sender_address, &address_length); 64 | 65 | if (!non_blocking) { 66 | RTE_ASSERT(bytes_received != -1); 67 | } else { 68 | if (bytes_received == -1) { 69 | return -1; 70 | } 71 | } 72 | 73 | if (strncmp(CHEETAH_CONTROL_MESSAGE_QUERY_FILTER, recv_buffer, 74 | bytes_received) == 0) { 75 | return CHEETAH_CONTROL_MESSAGE_ID_FILTER; 76 | } 77 | 78 | if (strncmp(CHEETAH_CONTROL_MESSAGE_QUERY_TOPN, recv_buffer, 79 | bytes_received) == 0) { 80 | return CHEETAH_CONTROL_MESSAGE_ID_TOPN; 81 | } 82 | 83 | if (strncmp(CHEETAH_CONTROL_MESSAGE_QUERY_DISTINCT, recv_buffer, 84 | bytes_received) == 0) { 85 | return CHEETAH_CONTROL_MESSAGE_ID_DISTINCT; 86 | } 87 | 88 | if (strncmp(CHEETAH_CONTROL_MESSAGE_ACK, recv_buffer, bytes_received) == 0) { 89 | return CHEETAH_CONTROL_MESSAGE_ID_ACK; 90 | } 91 | 92 | return CHEETAH_CONTROL_MESSAGE_ID_UNDEFINED; 93 | } 94 | 95 | static void cheetah_control_message_send(const char *const ip, 96 | const char *const port, 97 | const char *const message, 98 | const size_t message_len) { 99 | 100 | int socket_file_descriptor; 101 | struct addrinfo hints; 102 | struct addrinfo *server_information; 103 | struct addrinfo *addr_iterator; 104 | int return_placeholder; 105 | int bytes_sent; 106 | 107 | cheetah_unused_var(return_placeholder); 108 | cheetah_unused_var(bytes_sent); 109 | 110 | memset(&hints, 0, sizeof(struct addrinfo)); 111 | hints.ai_family = AF_UNSPEC; 112 | hints.ai_socktype = SOCK_DGRAM; 113 | 114 | cheetah_debug("Sending control message to %s...", ip); 115 | cheetah_debug_flush(); 116 | 117 | return_placeholder = getaddrinfo(ip, port, &hints, &server_information); 118 | RTE_ASSERT(return_placeholder != 0); 119 | 120 | for (addr_iterator = server_information; addr_iterator != NULL; 121 | addr_iterator = addr_iterator->ai_next) { 122 | socket_file_descriptor = 123 | socket(addr_iterator->ai_family, addr_iterator->ai_socktype, 124 | addr_iterator->ai_protocol); 125 | 126 | if (socket_file_descriptor != -1) { 127 | break; 128 | } 129 | } 130 | 131 | RTE_ASSERT(addr_iterator != NULL); 132 | 133 | bytes_sent = sendto(socket_file_descriptor, message, message_len, 0, 134 | addr_iterator->ai_addr, addr_iterator->ai_addrlen); 135 | RTE_ASSERT(bytes_sent != -1); 136 | 137 | cheetah_debug("Done.\n"); 138 | cheetah_debug_flush(); 139 | 140 | freeaddrinfo(server_information); 141 | close(socket_file_descriptor); 142 | } 143 | 144 | void cheetah_control_message_offload_query(const char *const query_type) { 145 | cheetah_control_message_send( 146 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_1, CHEETAH_CONTROL_MESSAGE_PORT, 147 | query_type, strnlen(query_type, CHEETAH_CONTROL_MESSAGE_MAX_SIZE)); 148 | 149 | #ifdef CHEETAH_MULTIPLE_NODES_SAME_IP 150 | cheetah_control_message_send( 151 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_1, 152 | CHEETAH_CONTROL_MESSAGE_PORT_2, query_type, 153 | strnlen(query_type, CHEETAH_CONTROL_MESSAGE_MAX_SIZE)); 154 | #elif defined(CHEETAH_MULTIPLE_NODES) 155 | cheetah_control_message_send( 156 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_2, CHEETAH_CONTROL_MESSAGE_PORT, 157 | query_type, strnlen(query_type, CHEETAH_CONTROL_MESSAGE_MAX_SIZE)); 158 | 159 | cheetah_control_message_send( 160 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_3, CHEETAH_CONTROL_MESSAGE_PORT, 161 | query_type, strnlen(query_type, CHEETAH_CONTROL_MESSAGE_MAX_SIZE)); 162 | 163 | cheetah_control_message_send( 164 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_4, CHEETAH_CONTROL_MESSAGE_PORT, 165 | query_type, strnlen(query_type, CHEETAH_CONTROL_MESSAGE_MAX_SIZE)); 166 | 167 | cheetah_control_message_send( 168 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_5, CHEETAH_CONTROL_MESSAGE_PORT, 169 | query_type, strnlen(query_type, CHEETAH_CONTROL_MESSAGE_MAX_SIZE)); 170 | #endif /* CHEETAH_MULTIPLE_NODES*/ 171 | } 172 | 173 | int cheetah_control_message_await_query(const int worker_id) { 174 | RTE_ASSERT(worker_id > 0); 175 | 176 | if (worker_id == 1) { 177 | return cheetah_control_message_receive( 178 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_1, 179 | CHEETAH_CONTROL_MESSAGE_PORT, 0); 180 | } 181 | 182 | #ifdef CHEETAH_MULTIPLE_NODES_SAME_IP 183 | if (worker_id == 2) { 184 | return cheetah_control_message_receive( 185 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_1, 186 | CHEETAH_CONTROL_MESSAGE_PORT_2, 0); 187 | } 188 | 189 | #elif defined(CHEETAH_MULTIPLE_NODES) 190 | if (worker_id == 2) { 191 | return cheetah_control_message_receive( 192 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_2, 193 | CHEETAH_CONTROL_MESSAGE_PORT, 0); 194 | } 195 | 196 | if (worker_id == 3) { 197 | return cheetah_control_message_receive( 198 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_3, 199 | CHEETAH_CONTROL_MESSAGE_PORT, 0); 200 | } 201 | 202 | if (worker_id == 4) { 203 | return cheetah_control_message_receive( 204 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_4, 205 | CHEETAH_CONTROL_MESSAGE_PORT, 0); 206 | } 207 | 208 | if (worker_id == 5) { 209 | return cheetah_control_message_receive( 210 | CHEETAH_CONTROL_MESSAGE_DESTINATION_HOST_5, 211 | CHEETAH_CONTROL_MESSAGE_PORT, 0); 212 | } 213 | #endif /* CHEETAH_MULTIPLE_NODES */ 214 | 215 | RTE_ASSERT(0); 216 | return -1; 217 | } 218 | 219 | void cheetah_control_message_send_ack(void) { 220 | cheetah_control_message_send( 221 | CHEETAH_CONTROL_MESSAGE_MASTER_IP, CHEETAH_CONTROL_MESSAGE_PORT, 222 | CHEETAH_CONTROL_MESSAGE_ACK, 223 | strnlen(CHEETAH_CONTROL_MESSAGE_ACK, CHEETAH_CONTROL_MESSAGE_MAX_SIZE)); 224 | } 225 | 226 | void cheetah_control_message_receive_acks(int *pn_workers) { 227 | int message_id; 228 | 229 | cheetah_unused_var(message_id); 230 | 231 | RTE_ASSERT(*pn_workers > 0); 232 | 233 | message_id = cheetah_control_message_receive( 234 | CHEETAH_CONTROL_MESSAGE_MASTER_IP, CHEETAH_CONTROL_MESSAGE_PORT, 0); 235 | 236 | if (message_id != -1) { 237 | RTE_ASSERT(message_id == CHEETAH_CONTROL_MESSAGE_ID_ACK); 238 | *pn_workers -= 1; 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /host/cheetah_control_message.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_CONTROL_MESSAGE_H 2 | #define CHEETAH_CONTROL_MESSAGE_H 3 | 4 | #define CHEETAH_CONTROL_MESSAGE_QUERY_FILTER "FILT" 5 | #define CHEETAH_CONTROL_MESSAGE_QUERY_TOPN "TOPN" 6 | #define CHEETAH_CONTROL_MESSAGE_QUERY_DISTINCT "DIST" 7 | #define CHEETAH_CONTROL_MESSAGE_QUERY_GROUPBY "GRBY" 8 | #define CHEETAH_CONTROL_MESSAGE_QUERY_JOIN "JOIN" 9 | #define CHEETAH_CONTROL_MESSAGE_ACK "ACK" 10 | 11 | #define CHEETAH_CONTROL_MESSAGE_ID_UNDEFINED 0 12 | #define CHEETAH_CONTROL_MESSAGE_ID_FILTER 1 13 | #define CHEETAH_CONTROL_MESSAGE_ID_TOPN 2 14 | #define CHEETAH_CONTROL_MESSAGE_ID_DISTINCT 3 15 | #define CHEETAH_CONTROL_MESSAGE_ID_ACK 4 16 | 17 | #define CHEETAH_CONTROL_MESSAGE_MAX_SIZE 5 18 | 19 | void cheetah_control_message_offload_query(const char *const query_type); 20 | 21 | int cheetah_control_message_await_query(const int worker_id); 22 | 23 | void cheetah_control_message_send_ack(void); 24 | 25 | void cheetah_control_message_receive_acks(int *pn_workers); 26 | 27 | #endif /* CHEETAH_CONTROL_MESSAGE_H */ 28 | -------------------------------------------------------------------------------- /host/cheetah_dpdk.c: -------------------------------------------------------------------------------- 1 | /* Author: Muhammad Tirmazi 2 | * Harvard - Cloud, Networks & Systems (CNS) Lab 3 | */ 4 | 5 | #include "cheetah_dpdk.h" 6 | 7 | static void cheetah_signal_handler(const int signum) { 8 | if (signum == SIGINT || signum == SIGTERM) { 9 | printf("\n\nSignal %d received, preparing to exit...\n", signum); 10 | cheetah_global_force_quit = true; 11 | } 12 | } 13 | 14 | int cheetah_init(const int argc, char **argv) { 15 | /* Initialize DPDK's EAL */ 16 | if (rte_eal_init(argc, argv) < 0) 17 | rte_exit(EXIT_FAILURE, "Invalid EAL arguments"); 18 | 19 | cheetah_global_force_quit = false; 20 | signal(SIGINT, cheetah_signal_handler); 21 | signal(SIGTERM, cheetah_signal_handler); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /host/cheetah_dpdk.h: -------------------------------------------------------------------------------- 1 | /* Author: Muhammad Tirmazi 2 | * Harvard - Cloud, Networks & Systems (CNS) Lab 3 | */ 4 | 5 | #ifndef CHEETAH_DPDK_H 6 | #define CHEETAH_DPDK_H 7 | 8 | /* TODO: convert this to the 9 | "each header only including what it needs" 10 | model advocated by the Google C++ convention 11 | (even though this is C, not C++) 12 | */ 13 | 14 | #include /* <- Testing this */ 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | /* #include */ 36 | 37 | #ifndef _GNU_SOURCE 38 | #define _GNU_SOURCE 39 | #endif /* _GNU_SOURCE */ 40 | 41 | /* Used in cheetah_aggregate_processing */ 42 | #include 43 | 44 | /* Used in cheetah_resource_manager */ 45 | #include 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | #include "cheetah_constants.h" 71 | 72 | #define CHEETAH_LOG_DEBUG 73 | /* #define CHEETAH_ONLINE_DEBUG */ 74 | 75 | #define CHEETAH_DEBUG_COLOR_GREEN "\x1b[32m" 76 | #define CHEETAH_DEBUG_COLOR_RESET "\x1b[0m" 77 | #define CHEETAH_DEBUG_COLOR_CYAN "\x1b[36m" 78 | 79 | #ifdef CHEETAH_MEMORY_DEBUG 80 | #define cheetah_memory_debug(...) \ 81 | { \ 82 | fprintf(stderr, "\x1b[32m"); \ 83 | fprintf(stderr, __VA_ARGS__); \ 84 | fprintf(stderr, "\x1b[0m"); \ 85 | } 86 | #define cheetah_memory_debug_flush() fflush(stderr) 87 | #else 88 | #define cheetah_memory_debug(...) 89 | #define cheetah_memory_debug_flush() 90 | #endif 91 | 92 | #ifdef CHEETAH_LOG_DEBUG 93 | #define cheetah_debug(...) \ 94 | { \ 95 | fprintf(stderr, "\x1b[36m"); \ 96 | fprintf(stderr, __VA_ARGS__); \ 97 | fprintf(stderr, "\x1b[0m"); \ 98 | } 99 | 100 | #define cheetah_debug_flush() fflush(stderr) 101 | #else 102 | #define cheetah_debug(...) 103 | #define cheetah_debug_flush() 104 | #endif 105 | 106 | #ifdef CHEETAH_ONLINE_DEBUG 107 | #define cheetah_online_debug(...) fprintf(stderr, __VA_ARGS__) 108 | #define cheetah_online_debug_flush() fflush(stderr) 109 | #else 110 | #define cheetah_online_debug(...) 111 | #define cheetah_online_debug_flush() 112 | #endif 113 | 114 | /* For variables unused *for good reason* e.g 115 | * used inside assert / RTE_ASSERT */ 116 | #define cheetah_unused_var(x) ((void)(x)) 117 | 118 | int cheetah_init(const int argc, char **argv); 119 | 120 | #include "connection_state.h" 121 | #include "packet_manager.h" 122 | #include "packet_stream_receiver.h" 123 | 124 | #include "fast_packet_stream.h" 125 | #include "packet_crafter.h" 126 | 127 | #ifdef CHEETAH_USE_HDFS_BACKEND 128 | #include "cheetah_hdfs_backend.h" 129 | #else 130 | #include "cheetah_memory_sim.h" 131 | #endif /* CHEETAH_USE_HDFS_BACKEND */ 132 | 133 | #include "cheetah_aggregate_processing.h" 134 | #include "cheetah_benchmark.h" 135 | #include "cheetah_control_flow.h" 136 | #include "cheetah_control_message.h" 137 | #include "cheetah_join.h" 138 | #include "cheetah_resource_manager.h" 139 | #include "control_message_manager.h" 140 | 141 | volatile bool cheetah_global_force_quit; 142 | 143 | #endif /* CHEETAH_DPDK_H */ 144 | -------------------------------------------------------------------------------- /host/cheetah_hdfs_backend.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | -------------------------------------------------------------------------------- /host/cheetah_hdfs_backend.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_HDFS_BACKEND_H 2 | #define CHEETAH_HDFS_BACKEND_H 3 | 4 | #endif /* CHEETAH_HDFS_BACKEND_H */ 5 | -------------------------------------------------------------------------------- /host/cheetah_join.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_join.h" 2 | #include 3 | #include 4 | #include 5 | 6 | struct cheetah_join_state *cheetah_join_init(const uint64_t size, 7 | const uint64_t hash_size) { 8 | assert(size > 0); 9 | 10 | int rtn; 11 | struct cheetah_join_state *state; 12 | 13 | state = malloc(sizeof(struct cheetah_join_state)); 14 | assert(state != NULL); 15 | 16 | state->entries = malloc(sizeof(struct cheetah_join_entry) * size); 17 | assert(state->entries != NULL); 18 | 19 | state->size = size; 20 | state->current_entries = 0; 21 | 22 | rtn = hcreate_r(hash_size, &state->htab); 23 | assert(rtn != 0); 24 | 25 | return state; 26 | } 27 | 28 | struct hash_bin { 29 | uint32_t key; 30 | uint32_t *row_ids; 31 | uint64_t row_id_count; 32 | uint64_t row_id_cap; 33 | 34 | struct hash_bin *next; 35 | }; 36 | 37 | void cheetah_join_free(struct cheetah_join_state *state) { 38 | assert(state != NULL); 39 | assert(state->entries != NULL); 40 | 41 | hdestroy_r(&state->htab); 42 | 43 | free(state->entries); 44 | free(state); 45 | } 46 | 47 | void cheetah_join_update(struct cheetah_join_state *state, const uint32_t key, 48 | const uint32_t row_id, 49 | const enum cheetah_join_table tbl) { 50 | /* 4 chars = 4 * 8 = 32 bits */ 51 | char formatted_key[4]; 52 | ENTRY e; 53 | ENTRY *ep; 54 | struct hash_bin *bin; 55 | struct hash_bin *bin_prev; 56 | 57 | unsigned int n; 58 | 59 | n = 0; 60 | 61 | /* 4 because char is 1 byte */ 62 | memcpy(formatted_key, &key, 4); 63 | 64 | e.key = formatted_key; 65 | n = hsearch_r(e, FIND, &ep, &state->htab); 66 | 67 | if (n) { 68 | bin = (struct hash_bin *)ep->data; 69 | 70 | assert(bin); 71 | 72 | while (bin && bin->key != key) { 73 | bin_prev = bin; 74 | bin = bin->next; 75 | } 76 | 77 | if (!bin) { 78 | if (tbl == CHEETAH_JOIN_TABLE_PRIMARY) { 79 | assert(bin_prev); 80 | assert(bin_prev->next == NULL); 81 | 82 | bin_prev->next = malloc(sizeof(struct hash_bin)); 83 | 84 | bin = bin_prev->next; 85 | bin->key = key; 86 | bin->next = NULL; 87 | bin->row_id_cap = 1024; 88 | bin->row_ids = malloc(sizeof(uint32_t) * bin->row_id_cap); 89 | assert(bin->row_ids != NULL); 90 | bin->row_id_count = 1; 91 | bin->row_ids[0] = row_id; 92 | } 93 | } else { 94 | assert(bin->key == key); 95 | 96 | if (tbl == CHEETAH_JOIN_TABLE_PRIMARY) { 97 | if (bin->row_id_cap == bin->row_id_count) { 98 | uint64_t next_size = 2 * bin->row_id_cap; 99 | uint32_t *temp = malloc(sizeof(uint32_t) * next_size); 100 | memcpy(temp, bin->row_ids, sizeof(uint32_t) * bin->row_id_cap); 101 | free(bin->row_ids); 102 | bin->row_ids = temp; 103 | bin->row_id_cap = next_size; 104 | } 105 | 106 | bin->row_ids[bin->row_id_count] = row_id; 107 | bin->row_id_count++; 108 | } else { 109 | uint64_t i; 110 | 111 | for (i = 0; i < bin->row_id_count; i++) { 112 | assert(state->current_entries < state->size); 113 | struct cheetah_join_entry *curr_entry = 114 | &state->entries[state->current_entries]; 115 | 116 | curr_entry->tbl_1_row = bin->row_ids[i]; 117 | curr_entry->tbl_2_row = row_id; 118 | 119 | state->current_entries++; 120 | } 121 | } 122 | } 123 | } else { 124 | bin = malloc(sizeof(struct hash_bin)); 125 | assert(bin != NULL); 126 | bin->key = key; 127 | bin->next = NULL; 128 | bin->row_id_cap = 1024; 129 | bin->row_ids = malloc(sizeof(uint32_t) * bin->row_id_cap); 130 | assert(bin->row_ids != NULL); 131 | bin->row_id_count = 1; 132 | bin->row_ids[0] = row_id; 133 | 134 | e.data = (void *)bin; 135 | 136 | n = hsearch_r(e, ENTER, &ep, &state->htab); 137 | assert(n); 138 | } 139 | } 140 | 141 | #ifdef CHEETAH_JOIN_ENABLE_TESTS 142 | int main() { 143 | struct cheetah_join_state *state; 144 | 145 | puts("Trivial test."); 146 | state = cheetah_join_init(40000, 15000); 147 | assert(state != NULL); 148 | cheetah_join_free(state); 149 | puts("Passed."); 150 | 151 | puts("Disjoint join test."); 152 | state = cheetah_join_init(40000, 15000); 153 | 154 | cheetah_join_update(state, 13, 2, CHEETAH_JOIN_TABLE_PRIMARY); 155 | cheetah_join_update(state, 14, 1, CHEETAH_JOIN_TABLE_SECONDARY); 156 | 157 | assert(state->current_entries == 0); 158 | cheetah_join_free(state); 159 | puts("Passed."); 160 | 161 | puts("Unique key test."); 162 | state = cheetah_join_init(40000, 15000); 163 | 164 | cheetah_join_update(state, 14, 2, CHEETAH_JOIN_TABLE_PRIMARY); 165 | cheetah_join_update(state, 14, 1, CHEETAH_JOIN_TABLE_SECONDARY); 166 | 167 | assert(state->current_entries == 1); 168 | cheetah_join_free(state); 169 | puts("Passed."); 170 | 171 | puts("Duplicate key test."); 172 | state = cheetah_join_init(40000, 15000); 173 | 174 | cheetah_join_update(state, 14, 2, CHEETAH_JOIN_TABLE_PRIMARY); 175 | cheetah_join_update(state, 14, 3, CHEETAH_JOIN_TABLE_PRIMARY); 176 | cheetah_join_update(state, 14, 1, CHEETAH_JOIN_TABLE_SECONDARY); 177 | 178 | assert(state->current_entries == 2); 179 | cheetah_join_free(state); 180 | puts("Passed."); 181 | } 182 | 183 | #endif /* CHEETAH_JOIN_ENABLE_TESTS */ 184 | -------------------------------------------------------------------------------- /host/cheetah_join.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_JOIN_H 2 | #define CHEETAH_JOIN_H 3 | 4 | #ifndef _GNU_SOURCE 5 | #define _GNU_SOURCE 6 | #endif /* _GNU_SOURCE */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | enum cheetah_join_table { 13 | CHEETAH_JOIN_TABLE_PRIMARY, 14 | CHEETAH_JOIN_TABLE_SECONDARY 15 | }; 16 | 17 | /* Implements aggregate join at master */ 18 | 19 | struct cheetah_join_entry { 20 | uint32_t tbl_1_row; 21 | uint32_t tbl_2_row; 22 | }; 23 | 24 | struct cheetah_join_state { 25 | struct cheetah_join_entry *entries; 26 | uint64_t size; 27 | uint64_t current_entries; 28 | 29 | struct hsearch_data htab; 30 | }; 31 | 32 | struct cheetah_join_state *cheetah_join_init(const uint64_t size, 33 | const uint64_t hash_size); 34 | 35 | void cheetah_join_free(struct cheetah_join_state *state); 36 | 37 | void cheetah_join_update(struct cheetah_join_state *state, const uint32_t key, 38 | const uint32_t row_id, 39 | const enum cheetah_join_table tbl); 40 | #endif /* CHEETAH_JOIN_H */ 41 | -------------------------------------------------------------------------------- /host/cheetah_master.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | int main(int argc, char **const argv) { 4 | /* cheetah_set_memory_limit(CHEETAH_WORKER_MEMORY_LIMIT); */ 5 | return cheetah_control_flow_master(argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /host/cheetah_memory_sim.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | struct cheetah_memory_sim *cheetah_memory_sim_create(const char *filename, 4 | const size_t size) { 5 | struct cheetah_memory_sim *sim; 6 | FILE *stream; 7 | int scan_output; 8 | 9 | #ifdef CHEETAH_USE_STRING_VALUES 10 | char value[CHEETAH_CSV_ENTRY_MAX_LENGTH]; 11 | #else 12 | int value; 13 | #endif /* CHEETAH_USE_STRING_VALUES */ 14 | 15 | #ifdef CHEETAH_USE_KEY_AT_WORKER 16 | int key; 17 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 18 | 19 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 20 | int flow_id; 21 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 22 | 23 | cheetah_unused_var(key); 24 | cheetah_unused_var(value); 25 | cheetah_unused_var(flow_id); 26 | 27 | register unsigned int i; 28 | 29 | sim = malloc(sizeof(struct cheetah_memory_sim)); 30 | RTE_ASSERT(sim != NULL); 31 | 32 | sim->array_count = size; 33 | 34 | cheetah_debug("Allocating memory for dataset..."); 35 | cheetah_debug_flush(); 36 | 37 | sim->row_id_arr = malloc(sizeof(cheetah_header_field_t) * size); 38 | RTE_ASSERT(sim->row_id_arr != NULL); 39 | 40 | #ifdef CHEETAH_USE_STRING_VALUES 41 | sim->value_arr = malloc(sizeof(char *) * size); 42 | #elif defined(CHEETAH_USE_64_BIT_VALUES) 43 | sim->value_arr = malloc(sizeof(cheetah_header_field_large_t) * size); 44 | #else 45 | sim->value_arr = malloc(sizeof(cheetah_header_field_t) * size); 46 | #endif /* CHEETAH_USE_STRING_VALUES */ 47 | 48 | RTE_ASSERT(sim->value_arr != NULL); 49 | 50 | #ifdef CHEETAH_USE_KEY_AT_WORKER 51 | sim->key_arr = malloc(sizeof(cheetah_header_field_t) * size); 52 | RTE_ASSERT(sim->key_arr != NULL); 53 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 54 | 55 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 56 | sim->flow_id_arr = malloc(sizeof(cheetah_header_field_small_t) * size); 57 | RTE_ASSERT(sim->flow_id_arr != NULL); 58 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 59 | 60 | cheetah_debug("Success!\n"); 61 | cheetah_debug_flush(); 62 | 63 | cheetah_debug("Parsing dataset..."); 64 | cheetah_debug_flush(); 65 | 66 | stream = fopen(filename, "r"); 67 | RTE_ASSERT(stream != NULL); 68 | 69 | cheetah_debug("Opened..."); 70 | cheetah_debug_flush(); 71 | 72 | i = 0; 73 | while ((scan_output = 74 | fscanf(stream, 75 | 76 | #ifdef CHEETAH_DATASET_USER_VALUES 77 | "%*[^,],%*[^,],%*[^,],%*[^,],%[^,],%*[^\n]\n", &value 78 | #elif defined(CHEETAH_DATASET_TPCH) 79 | "%d,%d\n", &flow_id, &key 80 | #elif defined(CHEETAH_DATASET_RANDOM_KV) 81 | "%d,%d\n", &key, &value 82 | #elif defined(CHEETAH_DATASET_USER_DATA_HASHED) 83 | "%*d,%d\n", &value 84 | #else /* CHEETAH_DATASET_USER_VALUES */ 85 | "%*[^,],%d,%*d\n", &value 86 | #endif /* CHEETAH_DATASET_USER_VALUES */ 87 | )) != EOF) { 88 | sim->row_id_arr[i] = i; 89 | 90 | #if defined(CHEETAH_USE_FLOW_ID_AT_WORKER) && defined(CHEETAH_DATASET_TPCH) 91 | sim->flow_id_arr[i] = (cheetah_header_field_small_t)flow_id; 92 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER && CHEETAH_DATASET_TPCH */ 93 | 94 | #if defined(CHEETAH_USE_KEY_AT_WORKER) && \ 95 | (defined(CHEETAH_DATASET_RANDOM_KV) || defined(CHEETAH_DATASET_TPCH)) 96 | sim->key_arr[i] = (cheetah_header_field_t)key; 97 | #endif /* CHEETAH_USE_KEY_AT_WORKER && (CHEETAH_DATASET_RANDOM_KV || \ 98 | CHEETAH_DATASET_TPCH)*/ 99 | 100 | #ifndef CHEETAH_DATASET_TPCH 101 | #ifdef CHEETAH_USE_64_BIT_VALUES 102 | sim->value_arr[i] = (cheetah_header_field_large_t)value; 103 | #elif defined(CHEETAH_USE_STRING_VALUES) 104 | sim->value_arr[i] = strndup(value, CHEETAH_CSV_ENTRY_MAX_LENGTH); 105 | #else 106 | sim->value_arr[i] = value; 107 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 108 | #endif /* CHEETAH_DATASET_TPCH */ 109 | 110 | i++; 111 | 112 | RTE_ASSERT(i != size); 113 | } 114 | 115 | fclose(stream); 116 | 117 | cheetah_debug("Success!\n"); 118 | cheetah_debug_flush(); 119 | 120 | sim->entry_count = i; 121 | 122 | return sim; 123 | } 124 | 125 | void cheetah_memory_sim_free(struct cheetah_memory_sim *sim) { 126 | 127 | #ifdef CHEETAH_USE_STRING_VALUES 128 | register size_t i; 129 | 130 | for (i = 0; i < sim->entry_count; i++) { 131 | free(sim->value_arr[i]); 132 | } 133 | #endif /* CHEETAH_USE_STRING_VALUES */ 134 | 135 | free(sim->row_id_arr); 136 | free(sim->value_arr); 137 | 138 | #ifdef CHEETAH_USE_KEY_AT_WORKER 139 | free(sim->key_arr); 140 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 141 | 142 | free(sim); 143 | } 144 | -------------------------------------------------------------------------------- /host/cheetah_memory_sim.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_MEMORY_SIM_H 2 | #define CHEETAH_MEMORY_SIM_H 3 | 4 | struct cheetah_memory_sim { 5 | cheetah_header_field_t *row_id_arr; 6 | 7 | #ifdef CHEETAH_USE_64_BIT_VALUES 8 | cheetah_header_field_large_t *value_arr; 9 | #elif defined(CHEETAH_USE_STRING_VALUES) 10 | char **value_arr; 11 | #else 12 | cheetah_header_field_t *value_arr; 13 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 14 | 15 | #ifdef CHEETAH_USE_KEY_AT_WORKER 16 | cheetah_header_field_t *key_arr; 17 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 18 | 19 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 20 | cheetah_header_field_small_t *flow_id_arr; 21 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 22 | 23 | size_t entry_count; 24 | size_t array_count; 25 | }; 26 | 27 | struct cheetah_memory_sim *cheetah_memory_sim_create(const char *filename, 28 | const size_t size); 29 | 30 | void cheetah_memory_sim_free(struct cheetah_memory_sim *sim); 31 | #endif /* CHEETAH_MEMORY_SIM_H */ 32 | -------------------------------------------------------------------------------- /host/cheetah_resource_manager.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | void cheetah_set_memory_limit(const cheetah_resource_limit_t lim) { 4 | rlim_t internal_limit; 5 | struct rlimit memory_limit; 6 | 7 | internal_limit = (rlim_t)lim; 8 | cheetah_debug("Setting memory limit to %ju...", (uintmax_t)internal_limit); 9 | cheetah_debug_flush(); 10 | 11 | memory_limit.rlim_cur = internal_limit; 12 | memory_limit.rlim_max = internal_limit; 13 | setrlimit(RLIMIT_AS, &memory_limit); 14 | 15 | cheetah_debug("Done.\n"); 16 | cheetah_debug_flush(); 17 | } 18 | 19 | void cheetah_set_cpu_core_limit(const cheetah_resource_limit_t lim) { 20 | rlim_t internal_limit; 21 | struct rlimit nproc_limit; 22 | 23 | internal_limit = (rlim_t)lim; 24 | 25 | cheetah_debug("Setting core limit to %ju...", (uintmax_t)internal_limit); 26 | cheetah_debug("(using RLIMIT_NPROC)..."); 27 | cheetah_debug_flush(); 28 | 29 | nproc_limit.rlim_cur = internal_limit; 30 | nproc_limit.rlim_max = internal_limit; 31 | setrlimit(RLIMIT_NPROC, &nproc_limit); 32 | 33 | cheetah_debug("Done.\n"); 34 | cheetah_debug_flush(); 35 | } 36 | -------------------------------------------------------------------------------- /host/cheetah_resource_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_RESOURCE_MANAGER_H 2 | #define CHEETAH_RESOURCE_MANAGER_H 3 | 4 | typedef uintmax_t cheetah_resource_limit_t; 5 | 6 | void cheetah_set_memory_limit(const cheetah_resource_limit_t lim); 7 | 8 | void cheetah_set_cpu_core_limit(const cheetah_resource_limit_t lim); 9 | 10 | #endif /* CHEETAH_RESOURCE_MANAGER_H */ 11 | -------------------------------------------------------------------------------- /host/cheetah_worker.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | int main(int argc, char **const argv) { 4 | return cheetah_control_flow_worker(argc, argv); 5 | } 6 | -------------------------------------------------------------------------------- /host/connection_state.c: -------------------------------------------------------------------------------- 1 | /* Author: Muhammad Tirmazi 2 | * Harvard - Cloud, Networks & Systems (CNS) Lab 3 | */ 4 | 5 | #include "cheetah_dpdk.h" 6 | 7 | static int cheetah_network_open(struct cheetah_connection_state *const state); 8 | 9 | static int 10 | cheetah_network_close(const struct cheetah_connection_state *const state); 11 | 12 | struct cheetah_connection_state * 13 | cheetah_connection_state_create(const uint16_t portid, 14 | struct ether_addr dest_mac) { 15 | struct cheetah_connection_state *state; 16 | 17 | state = malloc(sizeof(struct cheetah_connection_state)); 18 | state->portid = portid; 19 | 20 | /* Initialize all struct values to defaults */ 21 | state->nb_rxd = CHEETAH_RXTX_DESC_DEFAULT; 22 | state->nb_txd = CHEETAH_RXTX_DESC_DEFAULT; 23 | 24 | state->tx_buffer = NULL; 25 | 26 | state->destination_mac = dest_mac; 27 | 28 | RTE_ASSERT(inet_pton(AF_INET, "192.168.1.2", &state->source_ip) != 0); 29 | RTE_ASSERT(inet_pton(AF_INET, "192.168.1.1", &state->destination_ip) != 0); 30 | 31 | /* Choosing arbitrary ports for now. 32 | * TODO: See if something better is required 33 | */ 34 | state->udp_source_port = 4242; 35 | state->udp_destination_port = 4242; 36 | 37 | cheetah_network_open(state); 38 | 39 | return state; 40 | } 41 | 42 | void cheetah_connection_state_free(struct cheetah_connection_state *state) { 43 | cheetah_network_close(state); 44 | /* TODO: free tx_buffer if needed */ 45 | free(state); 46 | } 47 | 48 | static int cheetah_network_open(struct cheetah_connection_state *const state) { 49 | int ret; 50 | /* using 1 lcore */ 51 | /* struct lcore_queue_conf *qconf;*/ 52 | 53 | /* designated initializer - used to configure device */ 54 | struct rte_eth_conf default_port_config = { 55 | .rxmode = 56 | { 57 | .split_hdr_size = 0, 58 | }, 59 | .txmode = 60 | { 61 | .mq_mode = ETH_MQ_TX_NONE, 62 | }, 63 | }; 64 | 65 | struct rte_eth_conf port_config = default_port_config; 66 | 67 | const char *shared_tx_packet_pool_name = "tx_packet_pool"; 68 | const char *shared_rx_packet_pool_name = "rx_packet_pool"; 69 | 70 | state->proc_type = rte_eal_process_type(); 71 | 72 | if (state->proc_type == RTE_PROC_SECONDARY) { 73 | cheetah_debug("Worker is secondary process.\n"); 74 | cheetah_debug("Looking up primary worker's " 75 | "RX and TX memory pools..."); 76 | cheetah_debug_flush(); 77 | 78 | state->tx_packet_pool = rte_mempool_lookup(shared_tx_packet_pool_name); 79 | if (state->tx_packet_pool == NULL) 80 | rte_exit(EXIT_FAILURE, "Cannot lookup tx packet pool\n"); 81 | 82 | state->rx_packet_pool = rte_mempool_lookup(shared_rx_packet_pool_name); 83 | if (state->rx_packet_pool == NULL) 84 | rte_exit(EXIT_FAILURE, "Cannot lookup rx packet pool\n"); 85 | 86 | cheetah_debug("Success!\n"); 87 | cheetah_debug_flush(); 88 | 89 | return 0; 90 | 91 | } else { 92 | cheetah_debug("Worker is primary process.\n"); 93 | cheetah_debug("Allocating RX and TX memory pools..."); 94 | cheetah_debug_flush(); 95 | 96 | state->tx_packet_pool = rte_pktmbuf_pool_create( 97 | shared_tx_packet_pool_name, CHEETAH_PACKET_MBUF, 128, 0, 98 | CHEETAH_MBUF_DATA_SIZE, rte_socket_id()); 99 | 100 | if (state->tx_packet_pool == NULL) 101 | rte_exit(EXIT_FAILURE, "Cannot init tx packet pool\n"); 102 | 103 | state->rx_packet_pool = rte_pktmbuf_pool_create( 104 | shared_rx_packet_pool_name, CHEETAH_PACKET_MBUF, 105 | CHEETAH_MEMPOOL_CACHE_SIZE, 0, CHEETAH_MBUF_DATA_SIZE, rte_socket_id()); 106 | 107 | if (state->rx_packet_pool == NULL) 108 | rte_exit(EXIT_FAILURE, "Cannot init rx packet pool\n"); 109 | } 110 | 111 | cheetah_debug("Success!\n"); 112 | cheetah_debug_flush(); 113 | 114 | cheetah_debug("Configuring device..."); 115 | cheetah_debug_flush(); 116 | 117 | rte_eth_dev_info_get(state->portid, &state->dev_info); 118 | 119 | if (state->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 120 | port_config.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; 121 | 122 | ret = rte_eth_dev_configure(state->portid, 1, 1, &port_config); 123 | if (ret < 0) 124 | rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, 125 | state->portid); 126 | 127 | cheetah_debug("Success!\n"); 128 | cheetah_debug("Adjusting descriptor numbers..."); 129 | cheetah_debug_flush(); 130 | 131 | ret = rte_eth_dev_adjust_nb_rx_tx_desc(state->portid, &state->nb_rxd, 132 | &state->nb_txd); 133 | 134 | if (ret < 0) 135 | rte_exit(EXIT_FAILURE, 136 | "Cannot adjust number of descriptors: err=%d, port=%u\n", ret, 137 | state->portid); 138 | 139 | cheetah_debug("Success!\n"); 140 | 141 | /* Get mac address of device */ 142 | rte_eth_macaddr_get(state->portid, &state->mac_address); 143 | 144 | /* For some reason, the DPDK docs flush stdout 145 | * before initializing RX / TX queues */ 146 | fflush(stdout); /* Why am I doing this? Check later */ 147 | 148 | cheetah_debug("Initializing RX queue..."); 149 | cheetah_debug_flush(); 150 | 151 | state->rxq_conf = state->dev_info.default_rxconf; 152 | state->rxq_conf.offloads = port_config.rxmode.offloads; 153 | 154 | ret = 155 | rte_eth_rx_queue_setup(state->portid, CHEETAH_RX_QUEUE_ID, state->nb_rxd, 156 | rte_eth_dev_socket_id(state->portid), 157 | &state->rxq_conf, state->rx_packet_pool); 158 | if (ret < 0) 159 | rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d, port=%u\n", ret, 160 | state->portid); 161 | 162 | cheetah_debug("Success!\n"); 163 | cheetah_debug_flush(); 164 | 165 | fflush(stdout); /* Why am I doing this? (2) Check later */ 166 | 167 | cheetah_debug("Initializing TX queue..."); 168 | cheetah_debug_flush(); 169 | 170 | state->txq_conf = state->dev_info.default_txconf; 171 | state->txq_conf.offloads = port_config.txmode.offloads; 172 | 173 | ret = rte_eth_tx_queue_setup( 174 | state->portid, CHEETAH_TX_QUEUE_ID, state->nb_txd, 175 | rte_eth_dev_socket_id(state->portid), &state->txq_conf); 176 | 177 | if (ret < 0) 178 | rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", ret, 179 | state->portid); 180 | 181 | cheetah_debug("Success!\n"); 182 | cheetah_debug("Initializing TX buffers..."); 183 | cheetah_debug_flush(); 184 | 185 | state->tx_buffer = rte_zmalloc_socket( 186 | "tx_buffer", RTE_ETH_TX_BUFFER_SIZE(CHEETAH_MAX_PKT_BURST_DEFAULT), 0, 187 | rte_eth_dev_socket_id(state->portid)); 188 | 189 | if (state->tx_buffer == NULL) 190 | rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", 191 | state->portid); 192 | 193 | rte_eth_tx_buffer_init(state->tx_buffer, CHEETAH_MAX_PKT_BURST_DEFAULT); 194 | 195 | cheetah_debug("Success!\n"); 196 | cheetah_debug_flush(); 197 | 198 | /* TODO: Set tx buffer error callback if needed later */ 199 | 200 | cheetah_debug("Starting device..."); 201 | cheetah_debug_flush(); 202 | 203 | ret = rte_eth_dev_start(state->portid); 204 | if (ret < 0) 205 | rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, 206 | state->portid); 207 | 208 | cheetah_debug("Success!\n"); 209 | cheetah_debug_flush(); 210 | 211 | return 0; 212 | } 213 | 214 | static int 215 | cheetah_network_close(const struct cheetah_connection_state *const state) { 216 | cheetah_debug("Closing device on port %d....", state->portid); 217 | cheetah_debug_flush(); 218 | 219 | rte_eth_dev_stop(state->portid); 220 | rte_eth_dev_close(state->portid); 221 | 222 | cheetah_debug("Success!\n"); 223 | cheetah_debug_flush(); 224 | 225 | return 0; 226 | } 227 | -------------------------------------------------------------------------------- /host/connection_state.h: -------------------------------------------------------------------------------- 1 | /* Author: Muhammad Tirmazi 2 | * Harvard - Cloud, Networks & Systems Group (CNS) 3 | */ 4 | 5 | #ifndef CHEETAH_CONNECTION_STATE 6 | #define CHEETAH_CONNECTION_STATE 7 | 8 | /* DPDK state for an ethernet device */ 9 | struct cheetah_connection_state { 10 | /* The port for the ethernet device 11 | * make sure the device is bound to DPDK */ 12 | uint16_t portid; 13 | 14 | /* The receiver queue configuration */ 15 | struct rte_eth_rxconf rxq_conf; 16 | 17 | /* The transmit queue configuration */ 18 | struct rte_eth_txconf txq_conf; 19 | 20 | /* The device information */ 21 | struct rte_eth_dev_info dev_info; 22 | 23 | /* rx and tx descriptors */ 24 | uint16_t nb_rxd, nb_txd; 25 | 26 | /* Mac address of device */ 27 | struct ether_addr mac_address; 28 | 29 | /* Memory pool for packet buffering */ 30 | struct rte_mempool *pktmbuf_pool; 31 | 32 | /* TX buffer for the device */ 33 | struct rte_eth_dev_tx_buffer *tx_buffer; 34 | 35 | /* Memory pool for the packets sent */ 36 | struct rte_mempool *tx_packet_pool; 37 | 38 | /* Memory pool for the packets received */ 39 | struct rte_mempool *rx_packet_pool; 40 | 41 | /* MAC Address of the destination */ 42 | struct ether_addr destination_mac; 43 | 44 | /* IP Address of device */ 45 | uint32_t source_ip; 46 | 47 | /* IP Address of destination */ 48 | uint32_t destination_ip; 49 | 50 | /* UDP source port */ 51 | uint16_t udp_source_port; 52 | 53 | /* UDP destination port */ 54 | uint16_t udp_destination_port; 55 | 56 | /* process type */ 57 | enum rte_proc_type_t proc_type; 58 | }; 59 | 60 | /* state constructor */ 61 | struct cheetah_connection_state * 62 | cheetah_connection_state_create(const uint16_t portid, 63 | struct ether_addr dest_mac); 64 | 65 | /* state destructor */ 66 | void cheetah_connection_state_free(struct cheetah_connection_state *state); 67 | 68 | /* Opens a DPDK port linked to an ethernet device */ 69 | /* int cheetah_network_open(struct cheetah_connection_state* const state); */ 70 | 71 | /* Closes a DPDK port linked to an ethernet device */ 72 | /* int cheetah_network_close(const struct cheetah_connection_state* const 73 | * state); */ 74 | 75 | #endif /* CHEETAH_CONNECTION_STATE */ 76 | -------------------------------------------------------------------------------- /host/control_flow_constants.py: -------------------------------------------------------------------------------- 1 | CHEETAH_MASTER_IP = '10.243.38.88' 2 | CHEETAH_MASTER_PORT = 23456 3 | CHEETAH_WORKER_NODES = 1 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /host/control_message_manager.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | struct cheetah_control_connection_state * 4 | cheetah_control_connection_state_create(const uint16_t port) { 5 | 6 | struct cheetah_control_connection_state *state; 7 | 8 | state = malloc(sizeof(struct cheetah_control_connection_state)); 9 | 10 | state->server_address_info = malloc(sizeof(struct sockaddr_in)); 11 | state->client_address_info = malloc(sizeof(struct sockaddr_in)); 12 | 13 | memset(state->server_address_info, 0, sizeof(struct sockaddr_in)); 14 | memset(state->client_address_info, 0, sizeof(struct sockaddr_in)); 15 | 16 | state->server_address_info->sin_family = AF_INET; 17 | state->server_address_info->sin_addr.s_addr = INADDR_ANY; 18 | state->server_address_info->sin_port = htons(port); 19 | 20 | state->port = port; 21 | state->socket_file_descriptor = -1; 22 | 23 | return state; 24 | } 25 | 26 | void cheetah_control_connection_state_free( 27 | struct cheetah_control_connection_state *state) { 28 | 29 | close(state->socket_file_descriptor); 30 | 31 | free(state->server_address_info); 32 | free(state->client_address_info); 33 | free(state); 34 | } 35 | -------------------------------------------------------------------------------- /host/control_message_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_CONTROL_MESSAGE_MANAGER_H 2 | #define CHEETAH_CONTROL_MESSAGE_MANAGER_H 3 | 4 | struct cheetah_control_connection_state { 5 | int socket_file_descriptor; 6 | uint16_t port; 7 | struct sockaddr_in *server_address_info; 8 | struct sockaddr_in *client_address_info; 9 | }; 10 | 11 | struct cheetah_control_connection_state * 12 | cheetah_control_connection_state_create(const uint16_t port); 13 | 14 | void cheetah_control_connection_state_free( 15 | struct cheetah_control_connection_state *state); 16 | 17 | #endif /* CHEETAH_CONTROL_MESSAGE_MANAGER_H */ 18 | -------------------------------------------------------------------------------- /host/fast_packet_stream.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | void cheetah_fast_packet_stream_send( 4 | const struct cheetah_fast_packet_stream *const stream, 5 | const struct cheetah_connection_state *const state) { 6 | 7 | struct rte_mbuf **mbuf_burst_arr_clone; 8 | uint16_t packets_sent; 9 | size_t packets_left; 10 | register size_t i; 11 | 12 | mbuf_burst_arr_clone = 13 | malloc(sizeof(struct rte_mbuf *) * stream->packet_count); 14 | 15 | for (i = 0; i < stream->packet_count; i++) { 16 | mbuf_burst_arr_clone[i] = 17 | rte_pktmbuf_clone(stream->mbuf_burst_arr[i], state->tx_packet_pool); 18 | 19 | RTE_ASSERT(mbuf_burst_arr_clone[i] != NULL); 20 | } 21 | 22 | packets_left = stream->packet_count; 23 | 24 | do { 25 | packets_sent = rte_eth_tx_burst(state->portid, CHEETAH_TX_QUEUE_ID, 26 | mbuf_burst_arr_clone, packets_left); 27 | packets_left -= packets_sent; 28 | mbuf_burst_arr_clone += packets_sent; 29 | } while (packets_left != 0); 30 | } 31 | 32 | void cheetah_fast_packet_stream_modify( 33 | const struct cheetah_fast_packet_stream *const stream, 34 | const size_t packet_index, 35 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 36 | const cheetah_header_field_small_t flow_id_new, 37 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 38 | #ifdef CHEETAH_USE_KEY_AT_WORKER 39 | const cheetah_header_field_t key_new, 40 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 41 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 42 | const cheetah_header_field_large_t value_new, 43 | #else 44 | const cheetah_header_field_t value_new, 45 | #endif /* CHEETAH_USE_64_BIT_VALUES or CHEETAH_USE_STRING_VALUES*/ 46 | const cheetah_header_field_t row_id_new) { 47 | 48 | cheetah_header_field_t *prow_id; 49 | 50 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 51 | cheetah_header_field_large_t *pvalue; 52 | #else 53 | cheetah_header_field_t *pvalue; 54 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 55 | 56 | #ifdef CHEETAH_USE_KEY_AT_WORKER 57 | cheetah_header_field_t *pkey; 58 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 59 | 60 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 61 | cheetah_header_field_small_t *pflow_id; 62 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 63 | 64 | RTE_ASSERT(stream != NULL); 65 | RTE_ASSERT(packet_index < stream->packet_count); 66 | 67 | prow_id = stream->payload_row_id_arr[packet_index]; 68 | pvalue = stream->payload_value_arr[packet_index]; 69 | 70 | #ifdef CHEETAH_USE_KEY_AT_WORKER 71 | pkey = stream->payload_key_arr[packet_index]; 72 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 73 | 74 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 75 | pflow_id = stream->payload_flow_id_arr[packet_index]; 76 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 77 | 78 | *prow_id = rte_cpu_to_be_32(row_id_new); 79 | 80 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 81 | *pvalue = rte_cpu_to_be_64(value_new); 82 | #else 83 | *pvalue = rte_cpu_to_be_32(value_new); 84 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 85 | 86 | #ifdef CHEETAH_USE_KEY_AT_WORKER 87 | *pkey = rte_cpu_to_be_32(key_new); 88 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 89 | 90 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 91 | *pflow_id = rte_cpu_to_be_16(flow_id_new); 92 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 93 | } 94 | 95 | void cheetah_fast_packet_stream_free( 96 | struct cheetah_fast_packet_stream *stream) { 97 | register unsigned int i; 98 | 99 | RTE_ASSERT(stream != NULL); 100 | 101 | for (i = 0; i < stream->packet_count; i++) { 102 | rte_pktmbuf_free(stream->mbuf_burst_arr[i]); 103 | } 104 | 105 | free(stream->mbuf_burst_arr); 106 | free(stream->payload_row_id_arr); 107 | free(stream->payload_value_arr); 108 | 109 | #ifdef CHEETAH_USE_KEY_AT_WORKER 110 | free(stream->payload_key_arr); 111 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 112 | 113 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 114 | free(stream->payload_flow_id_arr); 115 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 116 | 117 | free(stream); 118 | } 119 | 120 | struct cheetah_fast_packet_stream *cheetah_fast_packet_stream_create( 121 | const struct cheetah_connection_state *const state, 122 | const size_t packet_count) { 123 | struct cheetah_fast_packet_stream *stream; 124 | struct rte_mbuf *mbuf; 125 | cheetah_header_field_t *row_id; 126 | 127 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 128 | cheetah_header_field_large_t *value; 129 | #else 130 | cheetah_header_field_t *value; 131 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 132 | 133 | #ifdef CHEETAH_USE_KEY_AT_WORKER 134 | cheetah_header_field_t *key; 135 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 136 | 137 | cheetah_header_field_small_t *flow_id; 138 | 139 | register unsigned int i; 140 | 141 | stream = malloc(sizeof(struct cheetah_fast_packet_stream)); 142 | RTE_ASSERT(stream != NULL); 143 | 144 | RTE_ASSERT(packet_count != 0); 145 | stream->packet_count = packet_count; 146 | 147 | stream->mbuf_burst_arr = malloc(sizeof(struct rte_mbuf *) * packet_count); 148 | RTE_ASSERT(stream->mbuf_burst_arr != NULL); 149 | 150 | stream->payload_row_id_arr = 151 | malloc(sizeof(cheetah_header_field_t *) * packet_count); 152 | RTE_ASSERT(stream->payload_row_id_arr != NULL); 153 | 154 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 155 | stream->payload_value_arr = 156 | malloc(sizeof(cheetah_header_field_large_t *) * packet_count); 157 | #else 158 | stream->payload_value_arr = 159 | malloc(sizeof(cheetah_header_field_t *) * packet_count); 160 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 161 | 162 | RTE_ASSERT(stream->payload_value_arr != NULL); 163 | 164 | #ifdef CHEETAH_USE_KEY_AT_WORKER 165 | stream->payload_key_arr = 166 | malloc(sizeof(cheetah_header_field_t *) * packet_count); 167 | 168 | RTE_ASSERT(stream->payload_key_arr != NULL); 169 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 170 | 171 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 172 | stream->payload_flow_id_arr = 173 | malloc(sizeof(cheetah_header_field_small_t *) * packet_count); 174 | 175 | RTE_ASSERT(stream->payload_flow_id_arr != NULL); 176 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 177 | 178 | for (i = 0; i < packet_count; i++) { 179 | mbuf = rte_pktmbuf_alloc(state->tx_packet_pool); 180 | RTE_ASSERT(mbuf != NULL); 181 | 182 | stream->mbuf_burst_arr[i] = mbuf; 183 | 184 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 185 | value = (cheetah_header_field_large_t *)rte_pktmbuf_prepend( 186 | mbuf, sizeof(cheetah_header_field_large_t)); 187 | #else 188 | value = (cheetah_header_field_t *)rte_pktmbuf_prepend( 189 | mbuf, sizeof(cheetah_header_field_t)); 190 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 191 | 192 | #ifdef CHEETAH_USE_KEY_AT_WORKER 193 | key = (cheetah_header_field_t *)rte_pktmbuf_prepend( 194 | mbuf, sizeof(cheetah_header_field_t)); 195 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 196 | 197 | row_id = (cheetah_header_field_t *)rte_pktmbuf_prepend( 198 | mbuf, sizeof(cheetah_header_field_t)); 199 | 200 | /* temporary hack for flow_id */ 201 | flow_id = (uint16_t *)rte_pktmbuf_prepend(mbuf, sizeof(uint16_t)); 202 | 203 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 204 | stream->payload_flow_id_arr[i] = flow_id; 205 | #else /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 206 | *flow_id = rte_cpu_to_be_16(CHEETAH_DEFAULT_FLOW_ID); 207 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 208 | 209 | stream->payload_row_id_arr[i] = row_id; 210 | 211 | #ifdef CHEETAH_USE_KEY_AT_WORKER 212 | stream->payload_key_arr[i] = key; 213 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 214 | 215 | stream->payload_value_arr[i] = value; 216 | 217 | cheetah_prepend_udp_header(state, mbuf); 218 | cheetah_prepend_ip_header(state, mbuf); 219 | cheetah_prepend_ethernet_header(state, mbuf); 220 | } 221 | 222 | return stream; 223 | } 224 | -------------------------------------------------------------------------------- /host/fast_packet_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef FAST_PACKET_STREAM_H 2 | #define FAST_PACKET_STREAM_H 3 | 4 | struct cheetah_fast_packet_stream { 5 | struct rte_mbuf **mbuf_burst_arr; 6 | 7 | cheetah_header_field_t **payload_row_id_arr; 8 | 9 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 10 | cheetah_header_field_large_t **payload_value_arr; 11 | #else /* not string or 64-bit */ 12 | cheetah_header_field_t **payload_value_arr; 13 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 14 | 15 | #ifdef CHEETAH_USE_HASH_AT_WORKER 16 | cheetah_header_field_t **payload_hash_arr; 17 | #endif /* CHEETAH_USE_HASH_AT_WORKER */ 18 | 19 | #ifdef CHEETAH_USE_KEY_AT_WORKER 20 | cheetah_header_field_t **payload_key_arr; 21 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 22 | 23 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 24 | cheetah_header_field_small_t **payload_flow_id_arr; 25 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 26 | 27 | size_t packet_count; 28 | }; 29 | 30 | struct cheetah_fast_packet_stream *cheetah_fast_packet_stream_create( 31 | const struct cheetah_connection_state *const state, 32 | const size_t packet_count); 33 | 34 | void cheetah_fast_packet_stream_send( 35 | const struct cheetah_fast_packet_stream *const stream, 36 | const struct cheetah_connection_state *const state); 37 | 38 | void cheetah_fast_packet_stream_modify( 39 | const struct cheetah_fast_packet_stream *const stream, 40 | const size_t packet_index, 41 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 42 | const cheetah_header_field_small_t flow_id_new, 43 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 44 | #ifdef CHEETAH_USE_KEY_AT_WORKER 45 | const cheetah_header_field_t key_new, 46 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 47 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 48 | const cheetah_header_field_large_t value_new, 49 | #else 50 | const cheetah_header_field_t value_new, 51 | #endif /* CHEETAH_USE_64_BIT_VALUES or CHEETAH_USE_STRING_VALUES*/ 52 | const cheetah_header_field_t row_id_new); 53 | 54 | void cheetah_fast_packet_stream_free(struct cheetah_fast_packet_stream *stream); 55 | 56 | #endif /* FAST_PACKET_STREAM_H */ 57 | -------------------------------------------------------------------------------- /host/filter_offline_validator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # To check if I send and receive the correct result for my filter query 4 | 5 | import csv 6 | import sys 7 | 8 | if __name__ == '__main__': 9 | with open(sys.argv[1], 'r') as f: 10 | reader = csv.reader(f) 11 | count = 0 12 | for row in reader: 13 | if int(row[-1]) < 50: 14 | count += 1 15 | 16 | print(count) 17 | -------------------------------------------------------------------------------- /host/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright(c) 2017 Intel Corporation 3 | 4 | # meson file, for building this example as part of a main DPDK build. 5 | # 6 | # To build this example as a standalone application with an already-installed 7 | # DPDK instance, use 'make' 8 | 9 | sources = files( 10 | 'main.c' 11 | ) 12 | -------------------------------------------------------------------------------- /host/packet_crafter.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | void cheetah_packet_ether_addr_populate(struct ether_addr *addr, uint8_t a, 4 | uint8_t b, uint8_t c, uint8_t d, 5 | uint8_t e, uint8_t f) { 6 | addr->addr_bytes[0] = a; 7 | addr->addr_bytes[1] = b; 8 | addr->addr_bytes[2] = c; 9 | addr->addr_bytes[3] = d; 10 | addr->addr_bytes[4] = e; 11 | addr->addr_bytes[5] = f; 12 | } 13 | 14 | void cheetah_prepend_packet_payload(const struct cheetah_packet *const pkt, 15 | struct rte_mbuf *mbuf) { 16 | cheetah_header_field_t *row_id; 17 | 18 | #ifdef CHEETAH_USE_64_BIT_VALUES 19 | cheetah_header_field_large_t *value; 20 | #else 21 | cheetah_header_field_t *value; 22 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 23 | 24 | #ifdef CHEETAH_USE_KEY_AT_WORKER 25 | cheetah_header_field_t *key; 26 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 27 | 28 | cheetah_header_field_small_t *flow_id; 29 | 30 | RTE_ASSERT(pkt != NULL); 31 | RTE_ASSERT(state != NULL); 32 | 33 | #ifdef CHEETAH_USE_64_BIT_VALUES 34 | value = (cheetah_header_field_large_t *)rte_pktmbuf_prepend( 35 | mbuf, sizeof(cheetah_header_field_large_t)); 36 | #else 37 | value = (cheetah_header_field_t *)rte_pktmbuf_prepend( 38 | mbuf, sizeof(cheetah_header_field_t)); 39 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 40 | 41 | RTE_ASSERT(value != NULL); 42 | 43 | *value = pkt->value; 44 | 45 | #ifdef CHEETAH_USE_KEY_AT_WORKER 46 | key = (cheetah_header_field_t *)rte_pktmbuf_prepend( 47 | mbuf, sizeof(cheetah_header_field_t)); 48 | RTE_ASSERT(key != NULL); 49 | 50 | *key = pkt->key; 51 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 52 | 53 | row_id = (cheetah_header_field_t *)rte_pktmbuf_prepend( 54 | mbuf, sizeof(cheetah_header_field_t)); 55 | RTE_ASSERT(row_id != NULL); 56 | 57 | *row_id = pkt->row_id; 58 | 59 | /* temporary hack */ 60 | flow_id = (uint16_t *)rte_pktmbuf_prepend(mbuf, sizeof(uint16_t)); 61 | RTE_ASSERT(flow_id != NULL); 62 | 63 | *flow_id = pkt->flow_id; 64 | } 65 | 66 | void cheetah_prepend_ethernet_header( 67 | const struct cheetah_connection_state *const state, struct rte_mbuf *mbuf) { 68 | struct ether_hdr *hdr; 69 | 70 | hdr = (struct ether_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(struct ether_hdr)); 71 | if (hdr == NULL) 72 | rte_exit(EXIT_FAILURE, "Could not append header to packet pool."); 73 | 74 | ether_addr_copy(&state->destination_mac, &hdr->d_addr); 75 | ether_addr_copy(&state->mac_address, &hdr->s_addr); 76 | 77 | hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 78 | } 79 | 80 | void cheetah_unpack_ethernet_header(struct rte_mbuf *mbuf) { 81 | cheetah_unused_var(mbuf); 82 | RTE_ASSERT(rte_pktmbuf_adj(mbuf, (uint16_t)sizeof(struct ether_hdr)) != NULL); 83 | } 84 | 85 | void cheetah_unpack_ip_header(struct rte_mbuf *mbuf) { 86 | cheetah_unused_var(mbuf); 87 | RTE_ASSERT(RTE_ETH_IS_IPV4_HDR(mbuf->packet_type)); 88 | RTE_ASSERT(mbuf->next_proto_id == 0x11); /* UDP Check */ 89 | 90 | RTE_ASSERT(rte_pktmbuf_adj(mbuf, (uint16_t)sizeof(struct ipv4_hdr)) != NULL); 91 | } 92 | 93 | void cheetah_unpack_payload(struct rte_mbuf *mbuf, 94 | cheetah_header_field_t *row_id, 95 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 96 | cheetah_header_field_small_t *flow_id, 97 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 98 | #ifdef CHEETAH_USE_KEY_AT_WORKER 99 | cheetah_header_field_t *key, 100 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 101 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 102 | cheetah_header_field_large_t *value 103 | #else 104 | cheetah_header_field_t *value 105 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 106 | ) { 107 | uint16_t total_header_size; 108 | 109 | total_header_size = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + 110 | sizeof(struct udp_hdr); 111 | 112 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 113 | *flow_id = *(rte_pktmbuf_mtod_offset(mbuf, cheetah_header_field_small_t *, 114 | total_header_size)); 115 | 116 | *flow_id = rte_be_to_cpu_16(*flow_id); 117 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 118 | 119 | total_header_size += sizeof(cheetah_header_field_small_t); 120 | 121 | *row_id = *(rte_pktmbuf_mtod_offset(mbuf, cheetah_header_field_t *, 122 | total_header_size)); 123 | 124 | *row_id = rte_be_to_cpu_32(*row_id); 125 | 126 | total_header_size += sizeof(cheetah_header_field_t); 127 | 128 | #ifdef CHEETAH_USE_KEY_AT_WORKER 129 | *key = *(rte_pktmbuf_mtod_offset(mbuf, cheetah_header_field_t *, 130 | total_header_size)); 131 | *key = rte_be_to_cpu_32(*key); 132 | total_header_size += sizeof(cheetah_header_field_t); 133 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 134 | 135 | #ifdef CHEETAH_USE_64_BIT_VALUES 136 | *value = *(rte_pktmbuf_mtod_offset(mbuf, cheetah_header_field_large_t *, 137 | total_header_size)); 138 | 139 | *value = rte_be_to_cpu_64(*value); 140 | #else 141 | *value = *(rte_pktmbuf_mtod_offset(mbuf, cheetah_header_field_t *, 142 | total_header_size)); 143 | 144 | *value = rte_be_to_cpu_32(*value); 145 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 146 | } 147 | 148 | void cheetah_unpack_udp_header(struct rte_mbuf *mbuf) { 149 | cheetah_unused_var(mbuf); 150 | RTE_ASSERT(rte_pktmbuf_adj(mbuf, (uint16_t)sizeof(struct udp_hdr)) != NULL); 151 | } 152 | 153 | void cheetah_prepend_ip_header( 154 | const struct cheetah_connection_state *const state, struct rte_mbuf *mbuf) { 155 | struct ipv4_hdr *hdr; 156 | 157 | hdr = (struct ipv4_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(struct ipv4_hdr)); 158 | RTE_ASSERT(hdr != NULL); 159 | 160 | /* Version (4 bits) | Internal header length (4 bits) */ 161 | hdr->version_ihl = 0x40 | 0x05; 162 | 163 | hdr->type_of_service = 0x0; 164 | hdr->total_length = rte_cpu_to_be_16(CHEETAH_DATAGRAM_LENGTH); 165 | hdr->packet_id = rte_cpu_to_be_16(1); 166 | hdr->fragment_offset = rte_cpu_to_be_16(0); 167 | hdr->time_to_live = 64; 168 | 169 | /* UDP = 0x11 */ 170 | hdr->next_proto_id = IPPROTO_UDP; 171 | 172 | /* 173 | hdr->src_addr = state->source_ip; 174 | hdr->dst_addr = state->destination_ip; 175 | */ 176 | 177 | /* IP Addr Hack */ 178 | 179 | hdr->src_addr = rte_cpu_to_be_32(CHEETAH_WORKER_DPDK_IP); 180 | hdr->dst_addr = rte_cpu_to_be_32(CHEETAH_MASTER_DPDK_IP); 181 | 182 | /* TODO: remove this and fix ip issue above */ 183 | cheetah_unused_var(state); 184 | 185 | hdr->hdr_checksum = rte_ipv4_cksum(hdr); 186 | } 187 | 188 | void cheetah_prepend_udp_header( 189 | const struct cheetah_connection_state *const state, struct rte_mbuf *mbuf) { 190 | struct udp_hdr *hdr; 191 | 192 | hdr = (struct udp_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(struct udp_hdr)); 193 | RTE_ASSERT(hdr != NULL); 194 | 195 | hdr->src_port = rte_cpu_to_be_16(state->udp_source_port); 196 | hdr->dst_port = rte_cpu_to_be_16(state->udp_destination_port); 197 | 198 | hdr->dgram_len = rte_cpu_to_be_16(CHEETAH_UDP_DATAGRAM_LENGTH); 199 | hdr->dgram_cksum = rte_cpu_to_be_16(0); 200 | } 201 | -------------------------------------------------------------------------------- /host/packet_crafter.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_PACKET_CRAFTER_H 2 | #define CHEETAH_PACKET_CRAFTER_H 3 | 4 | void cheetah_packet_ether_addr_populate(struct ether_addr *addr, uint8_t a, 5 | uint8_t b, uint8_t c, uint8_t d, 6 | uint8_t e, uint8_t f); 7 | 8 | void cheetah_prepend_ethernet_header( 9 | const struct cheetah_connection_state *const state, struct rte_mbuf *mbuf); 10 | 11 | void cheetah_prepend_packet_payload(const struct cheetah_packet *const pkt, 12 | struct rte_mbuf *mbuf); 13 | 14 | void cheetah_prepend_ip_header( 15 | const struct cheetah_connection_state *const state, struct rte_mbuf *mbuf); 16 | 17 | void cheetah_prepend_udp_header( 18 | const struct cheetah_connection_state *const state, struct rte_mbuf *mbuf); 19 | 20 | void cheetah_unpack_ethernet_header(struct rte_mbuf *mbuf); 21 | 22 | void cheetah_unpack_ip_header(struct rte_mbuf *mbuf); 23 | 24 | void cheetah_unpack_udp_header(struct rte_mbuf *mbuf); 25 | 26 | void cheetah_unpack_payload(struct rte_mbuf *mbuf, 27 | cheetah_header_field_t *row_id, 28 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 29 | cheetah_header_field_small_t *flow_id, 30 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 31 | #ifdef CHEETAH_USE_KEY_AT_WORKER 32 | cheetah_header_field_t *key, 33 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 34 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 35 | cheetah_header_field_large_t *value 36 | #else 37 | cheetah_header_field_t *value 38 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 39 | ); 40 | 41 | #endif /* CHEETAH_PACKET_CRAFTER_H */ 42 | -------------------------------------------------------------------------------- /host/packet_manager.c: -------------------------------------------------------------------------------- 1 | /* Author: Muham,ad Tirmazi 2 | * Harvard - Cloud, Networks & Systems (CNS) Lab 3 | */ 4 | 5 | #include "cheetah_dpdk.h" 6 | 7 | struct cheetah_packet * 8 | cheetah_packet_create(const cheetah_header_field_t row_id, 9 | const cheetah_header_field_t value) { 10 | struct cheetah_packet *pkt = malloc(sizeof(struct cheetah_packet)); 11 | pkt->row_id = row_id; 12 | pkt->value = value; 13 | pkt->flow_id = 1; 14 | 15 | return pkt; 16 | } 17 | 18 | void cheetah_packet_free(struct cheetah_packet *pkt) { free(pkt); } 19 | 20 | void cheetah_packet_stream_send( 21 | const struct cheetah_connection_state *const state, 22 | struct cheetah_packet_stream *const pktstream) { 23 | int pkt_len; 24 | int ret; 25 | struct cheetah_packet_stream *iter_stream; 26 | struct rte_mbuf **mbuf_burst_arr; 27 | struct rte_mbuf *mbuf; 28 | 29 | RTE_ASSERT(state != NULL); 30 | RTE_ASSERT(pktstream != NULL); 31 | 32 | pkt_len = 0; 33 | 34 | mbuf_burst_arr = NULL; 35 | 36 | cheetah_online_debug("Prepending packets..."); 37 | cheetah_online_debug_flush(); 38 | 39 | for (iter_stream = pktstream; iter_stream != NULL; 40 | iter_stream = iter_stream->next) { 41 | if (pkt_len == 0) 42 | mbuf_burst_arr = malloc(sizeof(struct rte_mbuf *)); 43 | else 44 | mbuf_burst_arr = 45 | realloc(mbuf_burst_arr, (pkt_len + 1) * sizeof(struct rte_mbuf *)); 46 | 47 | RTE_ASSERT(mbuf_burst_arr != NULL); 48 | 49 | mbuf_burst_arr[pkt_len] = rte_pktmbuf_alloc(state->tx_packet_pool); 50 | RTE_ASSERT(mbuf_burst_arr[pkt_len] != NULL); 51 | 52 | mbuf = mbuf_burst_arr[pkt_len]; 53 | 54 | cheetah_prepend_packet_payload(iter_stream->packet, mbuf); 55 | cheetah_prepend_udp_header(state, mbuf); 56 | cheetah_prepend_ip_header(state, mbuf); 57 | cheetah_prepend_ethernet_header(state, mbuf); 58 | 59 | pkt_len++; 60 | } 61 | 62 | cheetah_online_debug("Success!\n"); 63 | cheetah_online_debug_flush(); 64 | 65 | ret = rte_eth_tx_burst(state->portid, CHEETAH_TX_QUEUE_ID, mbuf_burst_arr, 66 | pkt_len); 67 | 68 | while (ret < pkt_len) { 69 | rte_pktmbuf_free(mbuf_burst_arr[ret]); 70 | ret++; 71 | } 72 | 73 | free(mbuf_burst_arr); 74 | } 75 | 76 | struct cheetah_packet_stream *cheetah_packet_stream_create(void) { 77 | struct cheetah_packet_stream *stream; 78 | 79 | stream = malloc(sizeof(struct cheetah_packet_stream)); 80 | stream->packet = NULL; 81 | stream->next = NULL; 82 | 83 | return stream; 84 | } 85 | 86 | struct cheetah_packet_stream * 87 | cheetah_packet_stream_add(struct cheetah_packet_stream *const stream, 88 | const cheetah_header_field_t row_id, 89 | const cheetah_header_field_t value) { 90 | 91 | cheetah_online_debug("Adding packet to stream with value: %d, %d...", row_id, 92 | value); 93 | cheetah_online_debug_flush(); 94 | 95 | RTE_ASSERT(state->next == NULL); 96 | 97 | if (stream->packet == NULL) { 98 | stream->packet = cheetah_packet_create(row_id, value); 99 | 100 | cheetah_online_debug("Success!\n"); 101 | cheetah_online_debug_flush(); 102 | 103 | return stream; 104 | } else { 105 | stream->next = cheetah_packet_stream_create(); 106 | stream->next->packet = cheetah_packet_create(row_id, value); 107 | 108 | cheetah_online_debug("Success!\n"); 109 | cheetah_online_debug_flush(); 110 | 111 | return stream->next; 112 | } 113 | } 114 | 115 | /* int cheetah_packet_send(struct cheetah_connection_state const *state) { */ 116 | -------------------------------------------------------------------------------- /host/packet_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef CHEETAH_PACKET_MANAGER_H 2 | #define CHEETAH_PACKET_MANAGER_H 3 | 4 | typedef uint16_t cheetah_header_field_small_t; 5 | typedef uint32_t cheetah_header_field_t; 6 | typedef uint64_t cheetah_header_field_large_t; 7 | 8 | struct cheetah_packet { 9 | 10 | #ifdef CHEETAH_USE_64_BIT_VALUES 11 | cheetah_header_field_large_t value; 12 | #else 13 | cheetah_header_field_t value; 14 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 15 | 16 | #ifdef CHEETAH_USE_HASH_AT_WORKER 17 | cheetah_header_field_t hash_val; 18 | #endif /* CHEETAH_USE_HASH_AT_WORKER */ 19 | 20 | #ifdef CHEETAH_USE_KEY_AT_WORKER 21 | cheetah_header_field_t key; 22 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 23 | 24 | cheetah_header_field_t row_id; 25 | 26 | cheetah_header_field_small_t flow_id; 27 | }; 28 | 29 | struct cheetah_packet_stream { 30 | struct cheetah_packet *packet; 31 | struct cheetah_packet_stream *next; 32 | }; 33 | 34 | struct cheetah_packet_stream *cheetah_packet_stream_create(void); 35 | 36 | struct cheetah_packet * 37 | cheetah_packet_create(const cheetah_header_field_t row_id, 38 | const cheetah_header_field_t value); 39 | 40 | void cheetah_packet_free(struct cheetah_packet *pkt); 41 | 42 | struct cheetah_packet_stream * 43 | cheetah_packet_stream_add(struct cheetah_packet_stream *const stream, 44 | const cheetah_header_field_t row_id, 45 | const cheetah_header_field_t value); 46 | 47 | void cheetah_packet_stream_send( 48 | const struct cheetah_connection_state *const state, 49 | struct cheetah_packet_stream *const pktstream); 50 | 51 | #endif /* CHEETAH_PACKET_MANAGER_H */ 52 | -------------------------------------------------------------------------------- /host/packet_stream_receiver.c: -------------------------------------------------------------------------------- 1 | #include "cheetah_dpdk.h" 2 | 3 | void cheetah_packet_stream_receiver_free( 4 | struct cheetah_packet_stream_receiver *receiver) { 5 | #ifdef CHEETAH_ENABLE_RECEIVER_PACKET_MONITORING 6 | free(receiver->payload_value_arr); 7 | free(receiver->payload_row_id_arr); 8 | #endif /* CHEETAH_ENABLE_RECEIVER_PACKET_MONITORING */ 9 | 10 | free(receiver->mbuf_burst_arr); 11 | free(receiver); 12 | } 13 | 14 | struct cheetah_packet_stream_receiver * 15 | cheetah_packet_stream_receiver_create(const size_t packet_batch_size) { 16 | struct cheetah_packet_stream_receiver *receiver; 17 | 18 | receiver = malloc(sizeof(struct cheetah_packet_stream_receiver)); 19 | RTE_ASSERT(receiver != NULL); 20 | 21 | receiver->packet_batch_size = packet_batch_size; 22 | 23 | receiver->mbuf_burst_arr = 24 | malloc(sizeof(struct rte_mbuf *) * packet_batch_size); 25 | RTE_ASSERT(receiver->mbuf_burst_arr != NULL); 26 | 27 | #if defined(CHEETAH_ENABLE_PACKET_MONITORING) || \ 28 | defined(CHEETAH_ENABLE_AGGREGATE_PROCESSING) 29 | 30 | /* Commenting out. Only storing last N packets received now */ 31 | /* (better memory useage) */ 32 | 33 | /* 34 | receiver->payload_current_index = 0; 35 | 36 | receiver->payload_row_id_arr = malloc(sizeof(cheetah_header_field_t) 37 | * 38 | CHEETAH_RECEIVER_MEMORY_ENTRY_COUNT); RTE_ASSERT(receiver->payload_row_id_arr 39 | != NULL); 40 | 41 | receiver->payload_value_arr = malloc(sizeof(cheetah_header_field_t) 42 | * 43 | CHEETAH_RECEIVER_MEMORY_ENTRY_COUNT); RTE_ASSERT(receiver->payload_value_arr 44 | != NULL); 45 | */ 46 | 47 | receiver->payload_row_id_arr = 48 | malloc(sizeof(cheetah_header_field_t) * packet_batch_size); 49 | 50 | RTE_ASSERT(receiver->payload_row_id_arr != NULL); 51 | 52 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 53 | receiver->payload_value_arr = 54 | malloc(sizeof(cheetah_header_field_large_t) * packet_batch_size); 55 | #else 56 | receiver->payload_value_arr = 57 | malloc(sizeof(cheetah_header_field_t) * packet_batch_size); 58 | #endif /* CHEETAH_USE_64_BIT_VALUES or CHEETAH_USE_STRING_VALUES */ 59 | 60 | RTE_ASSERT(receiver->payload_value_arr != NULL); 61 | 62 | #ifdef CHEETAH_USE_KEY_AT_WORKER 63 | receiver->payload_key_arr = 64 | malloc(sizeof(cheetah_header_field_t) * packet_batch_size); 65 | 66 | RTE_ASSERT(receiver->payload_key_arr != NULL); 67 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 68 | 69 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 70 | receiver->payload_flow_id_arr = 71 | malloc(sizeof(cheetah_header_field_small_t) * packet_batch_size); 72 | 73 | RTE_ASSERT(receiver->payload_flow_id_arr != NULL); 74 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 75 | 76 | #endif /* CHEETAH_ENABLE_PACKET_MONITORING */ 77 | 78 | return receiver; 79 | } 80 | 81 | /* #define CHEETAH_DISABLE_PACKET_PARSING */ 82 | 83 | uint32_t cheetah_packet_stream_receiver_receive( 84 | struct cheetah_packet_stream_receiver *const receiver, 85 | const struct cheetah_connection_state *state) { 86 | 87 | uint32_t packets_received; 88 | register uint32_t i; 89 | struct rte_mbuf *mbuf; 90 | 91 | #if defined(CHEETAH_ENABLE_PACKET_MONITORING) || \ 92 | defined(CHEETAH_ENABLE_AGGREGATE_PROCESSING) 93 | cheetah_header_field_t row_id; 94 | 95 | #ifdef CHEETAH_USE_KEY_AT_WORKER 96 | cheetah_header_field_t key; 97 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 98 | 99 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 100 | cheetah_header_field_small_t flow_id; 101 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 102 | 103 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 104 | cheetah_header_field_large_t value; 105 | #else 106 | cheetah_header_field_t value; 107 | #endif /* CHEETAH_USE_64_BIT_VALUES or CHEETAH_USE_STRING_VALUES*/ 108 | 109 | #endif /* CHEETAH_ENABLE_RECEIVER_PACKET_MONITORING or \ 110 | CHEETAH_ENABLE_AGGREGATE_PROCESSING */ 111 | packets_received = rte_eth_rx_burst( 112 | state->portid, 0, receiver->mbuf_burst_arr, receiver->packet_batch_size); 113 | 114 | for (i = 0; i < packets_received; i++) { 115 | mbuf = receiver->mbuf_burst_arr[i]; 116 | 117 | /* No longer needed since changed parsing style */ 118 | /* 119 | cheetah_unpack_ethernet_header(mbuf); 120 | cheetah_unpack_ip_header(mbuf); 121 | cheetah_unpack_udp_header(mbuf); 122 | */ 123 | 124 | /* 125 | cheetah_debug("Here\n"); 126 | cheetah_debug_flush(); 127 | */ 128 | 129 | /* Uncomment for monitoring 130 | rte_pktmbuf_dump(stdout, mbuf, CHEETAH_ETHERNET_FULL_LENGTH); 131 | fflush(stdout); 132 | */ 133 | 134 | #if defined(CHEETAH_ENABLE_PACKET_MONITORING) || \ 135 | defined(CHEETAH_ENABLE_AGGREGATE_PROCESSING) 136 | 137 | cheetah_unpack_payload(mbuf, &row_id, 138 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 139 | &flow_id, 140 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 141 | #ifdef CHEETAH_USE_KEY_AT_WORKER 142 | &key, 143 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 144 | &value); 145 | receiver->payload_row_id_arr[i] = row_id; 146 | receiver->payload_value_arr[i] = value; 147 | 148 | #ifdef CHEETAH_USE_KEY_AT_WORKER 149 | receiver->payload_key_arr[i] = key; 150 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 151 | 152 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 153 | receiver->payload_flow_id_arr[i] = flow_id; 154 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 155 | 156 | #endif /* CHEETAH_ENABLE_PACKET_MONITORING */ 157 | 158 | rte_pktmbuf_free(mbuf); 159 | } 160 | 161 | return packets_received; 162 | } 163 | -------------------------------------------------------------------------------- /host/packet_stream_receiver.h: -------------------------------------------------------------------------------- 1 | #ifndef PACKET_STREAM_RECEIVER_H 2 | #define PACKET_STREAM_RECEIVER_H 3 | 4 | struct cheetah_packet_stream_receiver { 5 | struct rte_mbuf **mbuf_burst_arr; 6 | 7 | #if defined(CHEETAH_ENABLE_PACKET_MONITORING) || \ 8 | defined(CHEETAH_ENABLE_AGGREGATE_PROCESSING) 9 | cheetah_header_field_t *payload_row_id_arr; 10 | 11 | #if defined(CHEETAH_USE_64_BIT_VALUES) || defined(CHEETAH_USE_STRING_VALUES) 12 | cheetah_header_field_large_t *payload_value_arr; 13 | #else 14 | cheetah_header_field_t *payload_value_arr; 15 | #endif /* CHEETAH_USE_64_BIT_VALUES */ 16 | 17 | #ifdef CHEETAH_USE_KEY_AT_WORKER 18 | cheetah_header_field_t *payload_key_arr; 19 | #endif /* CHEETAH_USE_KEY_AT_WORKER */ 20 | 21 | #ifdef CHEETAH_USE_FLOW_ID_AT_WORKER 22 | cheetah_header_field_small_t *payload_flow_id_arr; 23 | #endif /* CHEETAH_USE_FLOW_ID_AT_WORKER */ 24 | 25 | #endif /* CHEETAH_ENABLE_RECEIVER_PACKET_MONITORING */ 26 | 27 | size_t packet_batch_size; 28 | }; 29 | 30 | void cheetah_packet_stream_receiver_free( 31 | struct cheetah_packet_stream_receiver *receiver); 32 | 33 | uint32_t cheetah_packet_stream_receiver_receive( 34 | struct cheetah_packet_stream_receiver *const receiver, 35 | const struct cheetah_connection_state *state); 36 | 37 | struct cheetah_packet_stream_receiver * 38 | cheetah_packet_stream_receiver_create(const size_t packet_batch_size); 39 | 40 | #endif /* PACKET_STREAM_RECEIVER_H */ 41 | -------------------------------------------------------------------------------- /host/receive_ack_end.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import sys 3 | import os 4 | 5 | from control_flow_constants import * 6 | 7 | print("HELLO") 8 | from timeit import default_timer as timer 9 | 10 | start = timer() 11 | 12 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 13 | 14 | server_address = (CHEETAH_MASTER_IP, CHEETAH_MASTER_PORT) 15 | sock.bind(server_address) 16 | 17 | for i in range(CHEETAH_WORKER_NODES): 18 | sock.recvfrom(4096) 19 | 20 | end = timer() 21 | print("End to end delay:", end - start, "s") 22 | -------------------------------------------------------------------------------- /host/send_ack_end.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import sys 3 | 4 | from control_flow_constants import * 5 | 6 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 7 | server_address = (CHEETAH_MASTER_IP, CHEETAH_MASTER_PORT) 8 | msg = b'ACK' 9 | 10 | try: 11 | sent = sock.sendto(msg, server_address) 12 | 13 | finally: 14 | sock.close() 15 | --------------------------------------------------------------------------------