├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── create.c ├── create.h ├── db_types.h ├── ddp-artifacts ├── My-YCSB │ ├── core │ │ ├── client.cpp │ │ ├── include │ │ │ ├── client.h │ │ │ ├── measurement.h │ │ │ ├── worker.h │ │ │ └── workload.h │ │ ├── measurement.cpp │ │ ├── worker.cpp │ │ └── workload.cpp │ ├── redis │ │ ├── init_redis.cpp │ │ ├── redis_client.cpp │ │ ├── redis_client.h │ │ └── run_redis.cpp │ └── wiredtiger │ │ ├── init_wt.cpp │ │ ├── run_wt.cpp │ │ ├── wt_client.cpp │ │ └── wt_client.h ├── build.sh ├── configs │ ├── .config │ └── 6apr.config ├── db.c ├── db.h ├── libbpf-boot │ ├── .gitmodules │ ├── LICENSE │ ├── README.md │ ├── libbpf │ │ ├── .lgtm.yml │ │ ├── .travis.yml │ │ ├── BPF-CHECKPOINT-COMMIT │ │ ├── CHECKPOINT-COMMIT │ │ ├── LICENSE │ │ ├── LICENSE.BSD-2-Clause │ │ ├── LICENSE.LPGL-2.1 │ │ ├── README.md │ │ ├── include │ │ │ ├── asm │ │ │ │ └── barrier.h │ │ │ ├── linux │ │ │ │ ├── compiler.h │ │ │ │ ├── err.h │ │ │ │ ├── filter.h │ │ │ │ ├── kernel.h │ │ │ │ ├── list.h │ │ │ │ ├── overflow.h │ │ │ │ ├── ring_buffer.h │ │ │ │ └── types.h │ │ │ └── uapi │ │ │ │ └── linux │ │ │ │ ├── bpf.h │ │ │ │ ├── bpf_common.h │ │ │ │ ├── btf.h │ │ │ │ ├── if_link.h │ │ │ │ ├── if_xdp.h │ │ │ │ └── netlink.h │ │ ├── scripts │ │ │ ├── coverity.sh │ │ │ └── sync-kernel.sh │ │ ├── src │ │ │ ├── .gitignore │ │ │ ├── Makefile │ │ │ ├── README.rst │ │ │ ├── bpf.c │ │ │ ├── bpf.h │ │ │ ├── bpf_core_read.h │ │ │ ├── bpf_endian.h │ │ │ ├── bpf_helper_defs.h │ │ │ ├── bpf_helpers.h │ │ │ ├── bpf_prog_linfo.c │ │ │ ├── bpf_tracing.h │ │ │ ├── btf.c │ │ │ ├── btf.h │ │ │ ├── btf_dump.c │ │ │ ├── hashmap.c │ │ │ ├── hashmap.h │ │ │ ├── libbpf.c │ │ │ ├── libbpf.h │ │ │ ├── libbpf.map │ │ │ ├── libbpf.pc.template │ │ │ ├── libbpf_common.h │ │ │ ├── libbpf_errno.c │ │ │ ├── libbpf_internal.h │ │ │ ├── libbpf_probes.c │ │ │ ├── libbpf_util.h │ │ │ ├── netlink.c │ │ │ ├── nlattr.c │ │ │ ├── nlattr.h │ │ │ ├── ringbuf.c │ │ │ ├── str_error.c │ │ │ ├── str_error.h │ │ │ ├── xsk.c │ │ │ └── xsk.h │ │ └── travis-ci │ │ │ ├── managers │ │ │ ├── debian.sh │ │ │ ├── travis_wait.bash │ │ │ └── ubuntu.sh │ │ │ └── vmtest │ │ │ ├── build_pahole.sh │ │ │ ├── build_selftests.sh │ │ │ ├── checkout_latest_kernel.sh │ │ │ ├── configs │ │ │ ├── INDEX │ │ │ ├── blacklist │ │ │ │ ├── BLACKLIST-5.5.0 │ │ │ │ └── BLACKLIST-latest │ │ │ ├── latest.config │ │ │ └── whitelist │ │ │ │ └── WHITELIST-4.9.0 │ │ │ ├── helpers.sh │ │ │ ├── mkrootfs.sh │ │ │ ├── prepare_selftests-4.9.0.sh │ │ │ ├── prepare_selftests-5.5.0.sh │ │ │ ├── prepare_selftests.sh │ │ │ ├── run.sh │ │ │ ├── run_selftests.sh │ │ │ ├── run_vmtest.sh │ │ │ └── vmlinux.h │ ├── src │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── bootstrap.bpf.c │ │ ├── bootstrap.c │ │ ├── bootstrap.h │ │ ├── fentry.bpf.c │ │ ├── fentry.c │ │ ├── kprobe.bpf.c │ │ ├── kprobe.c │ │ ├── minimal.bpf.c │ │ ├── minimal.c │ │ ├── uprobe.bpf.c │ │ ├── uprobe.c │ │ ├── vmlinux.h │ │ └── vmlinux_508.h │ └── tools │ │ ├── bpftool │ │ └── gen_vmlinux_h.sh ├── nnbuild.sh ├── nndb.c ├── nndb.h ├── nnnbuild.sh ├── nnndb ├── nnndb.c ├── nnndb.h ├── patches │ ├── 10jun.patch │ ├── 14apr.patch │ ├── 14jul.patch │ ├── 17apra.patch │ ├── 22jun.patch │ ├── 23c.patch │ ├── 23w1.patch │ ├── 24apr.patch │ ├── 2apr.patch │ ├── 4aug.patch │ ├── 4auga.patch │ ├── 6may.patch │ ├── 7apr.patch │ ├── apr12.patch │ └── apr6.patch ├── scripts │ └── setup.sh ├── tdp │ ├── .gitignore │ ├── Makefile │ ├── bpf_helper_defs.h │ ├── bpf_helpers.h │ ├── bpf_util.h │ ├── bye.c │ ├── bye.sh │ ├── ddp_loader │ ├── ddp_loader.c │ ├── ddp_test.c │ ├── drop.c │ ├── drop2.c │ ├── drop3.c │ ├── droptree.c │ ├── run.sh │ ├── run2.sh │ ├── run3.sh │ ├── runtree.sh │ ├── simplekvspec.h │ ├── test.c │ ├── test2.c │ ├── test3.c │ └── testree.c └── trace │ └── cmd.sh ├── get.c ├── get.h ├── helpers.c ├── helpers.h ├── parse.c ├── parse.h ├── range.c ├── range.h ├── simplekv.c ├── simplekv.h └── xrp-bpf ├── .gitignore ├── Makefile ├── get.c ├── range.c └── simplekvspec.h /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | 13 | ci: 14 | name: ci 15 | runs-on: ubuntu-20.04 16 | steps: 17 | - name: Check out code 18 | uses: actions/checkout@v2 19 | 20 | - name: Build 21 | run: make simplekv 22 | 23 | # XXX: We use 5 layers because the GitHub runners don't have enough space 24 | - name: Test create command 25 | run: ./simplekv 5-layer-db 5 create 26 | 27 | - name: Test get command (userspace-mode) 28 | run: ./simplekv 5-layer-db 5 get --threads=1 --requests=10000 29 | 30 | - name: Test range command (userspace-mode) 31 | run: ./simplekv 5-layer-db 5 range --range-size=10 --requests=10000 32 | 33 | # TODO: Investigate how to run XRP tests 34 | # Needs either: 35 | # - VM running capabilities 36 | # - A machine with the custom kernel 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw* 2 | *.txt 3 | onlyonmachine/ 4 | 5 | # Binaries 6 | nndb 7 | db 8 | simplekv 9 | *.o 10 | 11 | # Dev cookies 12 | .idea 13 | .vscode 14 | 15 | # Makefile junk 16 | *.d 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -D_GNU_SOURCE -Wunused 3 | LDLIBS = -pthread -lbpf -lm 4 | 5 | 6 | all: simplekv bpf 7 | 8 | 9 | simplekv: simplekv.c simplekv.h db_types.h helpers.o range.o parse.o create.o get.o 10 | 11 | helpers.o: helpers.c helpers.h db_types.h 12 | 13 | range.o: range.c range.h db_types.h parse.h db_types.h simplekv.h helpers.h 14 | 15 | parse.o: parse.c parse.h helpers.h 16 | 17 | create.o: create.c create.h parse.h db_types.h simplekv.h 18 | 19 | get.o : get.c get.h db_types.h parse.h simplekv.h 20 | 21 | .PHONY: bpf 22 | bpf: 23 | make -C xrp-bpf -f Makefile 24 | 25 | .PHONY: clean 26 | clean: 27 | rm -rf simplekv *.o 28 | make -C xrp-bpf -f Makefile clean 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimpleKV 2 | SimpleKV is a simple key-value benchmark that performs simple get and range 3 | query operations. SimpleKV supports low-latency IO via the XRP BPF interface 4 | and can also run using user-space IO (`pread()`) on mainline (and XRP 5 | compatible) kernels. 6 | 7 | For usage instructions run `./simplekv --help` after compiling. 8 | 9 | 10 | # Building 11 | SimpleKV is built using the provided Makefile. Compiling the simplekv binary 12 | is as simple as running `make`. To perform IO with XRP via the `--use-xrp` 13 | flag the corresponding BPF programs in the `xrp-bpf` directory must be 14 | compiled. 15 | 16 | These BPF programs require [libbpf](https://github.com/libbpf/libbpf) and an XRP compatible kernel. 17 | Before compiling, install libbpf via your distribution's package manager or source. 18 | 19 | To compile on an XRP compatible kernel with libbpf, run: 20 | ``` 21 | make 22 | ``` 23 | 24 | Alternatively, you can compile simplekv without the BPF programs and use userspace IO: 25 | ``` 26 | make simplekv 27 | ``` 28 | 29 | # Running 30 | 31 | ## Create a Database File 32 | If this is your first time running SimpleKV you'll need to create a database 33 | file first. We recommend creating a database with at least 5 or 6 layers since 34 | the benefits of XRP will be more apparent. Approximate database sizes for 35 | various numbers of layers are given below as an estimate of the required disk 36 | space. 37 | ``` 38 | 4.0K 1-layer-db 39 | 80K 2-layer-db 40 | 2.4M 3-layer-db 41 | 72M 4-layer-db 42 | 2.2G 5-layer-db 43 | 68G 6-layer-db 44 | ``` 45 | 46 | To create a 6-layer database file: 47 | ``` 48 | ./simplekv 6-layer-db 6 create 49 | ``` 50 | 51 | ## Running the benchmark 52 | SimpleKV supports get queries and range queries, both of which can be run with various options. 53 | Usage and option docs can be reviewed by passing the `--help` flag to either command: 54 | ``` 55 | ./simplekv 6-layer-db 6 get --help 56 | ./simplekv 6-layer-db 6 range --help 57 | ``` 58 | 59 | ### Using XRP 60 | Before running with XRP you must load the corresponding BPF function using the 61 | `xrp_loader` program built via the default make target. Note that GET and RANGE operations 62 | use separate BPF programs, so be sure to load the correct one. 63 | 64 | For GET operations: 65 | ``` 66 | LD_PRELOAD="/usr/lib64/libbpf.so.0" ./xrp_loader xrp-bpf/get_op.o 67 | ``` 68 | 69 | For RANGE operations: 70 | ``` 71 | LD_PRELOAD="/usr/lib64/libbpf.so.0" ./xrp_loader xrp-bpf/range_op.o 72 | ``` 73 | 74 | NOTE: You may need to change `LD_PRELOAD` depending on where `libbpf.so.0` is located on your machine. 75 | 76 | With the BPF program loaded, you can run a basic GET benchmark as follows: 77 | ``` 78 | ./simplekv 6-layer-db 6 get --requests=100000 --use-xrp 79 | ``` 80 | 81 | ### CPU Configuration 82 | For consistent benchmark results you may need to disable CPU frequency scaling. 83 | 84 | 85 | # Old code 86 | 87 | The `ddp-artifacts` folder contains earlier code from the `ddp` kernel, which 88 | was developed in earlier versions of XRP. It will eventually be removed from 89 | the repo. 90 | 91 | # Contact 92 | Please reach out to Ioannis Zarkadas at `iz2175 AT columbia DOT edu` or Evan 93 | Mesterhazy at `etm2131 AT columbia DOT edu` with questions. 94 | -------------------------------------------------------------------------------- /create.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "create.h" 6 | #include "parse.h" 7 | #include "db_types.h" 8 | #include "simplekv.h" 9 | 10 | 11 | int do_create_cmd(int argc, char *argv[], struct ArgState *as) { 12 | parse_create_opts(argc, argv); 13 | return load(as->layers, as->filename); 14 | } 15 | 16 | /* Create a new database on disk at [db_path] with [layer_num] layers */ 17 | int load(size_t layer_num, char *db_path) { 18 | printf("Load the database of %lu layers\n", layer_num); 19 | int db = initialize(layer_num, LOAD_MODE, db_path); 20 | int const MB = (1<<20); 21 | 22 | // 1. Load the index 23 | Node * const node_begin; 24 | int node_entries = (MB * 10) / sizeof(Node); 25 | if (posix_memalign((void **)&node_begin, 512, node_entries * sizeof(Node))) { 26 | perror("posix_memalign failed"); 27 | close(db); 28 | free_globals(); 29 | exit(1); 30 | } 31 | /* 32 | Disk layout: 33 | B+ tree nodes, each with 31 keys and 31 associated block offsets to other nodes 34 | Nodes are written by level in order, so, the root is first, followed by all nodes on the second level. 35 | Since each node has pointers to 31 other nodes, fanout is 31 36 | | 0 - 1 2 3 4 ... 31 - .... | ### LOG DATA ### | 37 | 38 | Leaf nodes have pointers into the log data, which is appended as a "heap" in the same file 39 | at the end of the B+tree. Once we reach a leaf node, we scan through its keys and if one matches 40 | the key we need, we read the offset into the heap and can retrieve the value. 41 | */ 42 | ptr__t next_pos = 1; 43 | long next_node_offset = 1; 44 | Node *node = node_begin; 45 | Node * const node_buf_end = node_begin + node_entries; 46 | for (size_t i = 0; i < layer_num; i++) { 47 | size_t extent = max_key / layer_cap[i], start_key = 0; 48 | printf("layer %lu extent %lu\n", i, extent); 49 | for (size_t j = 0; j < layer_cap[i]; ++j, ++next_node_offset) { 50 | node->type = (i == layer_num - 1) ? LEAF : INTERNAL; 51 | size_t sub_extent = extent / NODE_CAPACITY; 52 | if (j == layer_cap[i] - 1) { 53 | /* Last node in this level */ 54 | node->next = 0; 55 | } else { 56 | /* Pointer to the next node in this level; used for efficient scans */ 57 | node->next = next_node_offset * sizeof(Node); 58 | } 59 | for (size_t k = 0; k < NODE_CAPACITY; k++) { 60 | node->key[k] = start_key + k * sub_extent; 61 | node->ptr[k] = node->type == INTERNAL ? 62 | encode(next_pos * BLK_SIZE) : 63 | encode(total_node * BLK_SIZE + (next_pos - total_node) * VAL_SIZE); 64 | next_pos++; 65 | } 66 | 67 | node += 1; 68 | if (node == node_buf_end) { 69 | ssize_t write_size = node_entries * sizeof(Node); 70 | ssize_t bytes_written = write(db, node_begin, write_size); 71 | if (bytes_written != write_size) { 72 | fprintf(stderr, "failure: partial write of index node\n"); 73 | exit(1); 74 | } 75 | node = node_begin; 76 | } 77 | start_key += extent; 78 | } 79 | } 80 | /* Write any remaining node buffer */ 81 | if (node > node_begin) { 82 | ssize_t write_size = (node - node_begin) * sizeof(Node); 83 | ssize_t bytes_written = write(db, node_begin, write_size); 84 | if (bytes_written != write_size) { 85 | fprintf(stderr, "failure: partial write of index node\n"); 86 | exit(1); 87 | } 88 | } 89 | free(node_begin); 90 | 91 | // 2. Load the value log 92 | Log * const log_begin; 93 | int const log_entries = (MB * 10) / sizeof(Log); 94 | if (posix_memalign((void **)&log_begin, 512, log_entries * sizeof(Log))) { 95 | perror("posix_memalign failed"); 96 | close(db); 97 | free_globals(); 98 | exit(1); 99 | } 100 | printf("Writing value heap\n"); 101 | Log *log = log_begin; 102 | Log * const log_end = log_begin + log_entries; 103 | for (size_t i = 0; i < max_key; i += LOG_CAPACITY) { 104 | for (size_t j = 0; j < LOG_CAPACITY; j++) { 105 | sprintf((char *) log->val[j], "%63lu", i + j); 106 | } 107 | ++log; 108 | if (log == log_end) { 109 | ssize_t write_size = log_entries * sizeof(Log); 110 | ssize_t bytes_written = write(db, log_begin, write_size); 111 | if (bytes_written != write_size) { 112 | fprintf(stderr, "failure: partial write of log data\n"); 113 | exit(1); 114 | } 115 | log = log_begin; 116 | } 117 | } 118 | /* Write any remaining entries */ 119 | if (log != log_begin) { 120 | ssize_t write_size = (log - log_begin) * sizeof(Log); 121 | ssize_t bytes_written = write(db, log_begin, write_size); 122 | if (bytes_written != write_size) { 123 | fprintf(stderr, "failure: partial write of log data\n"); 124 | exit(2); 125 | } 126 | } 127 | 128 | free(log_begin); 129 | close(db); 130 | return terminate(); 131 | } 132 | -------------------------------------------------------------------------------- /create.h: -------------------------------------------------------------------------------- 1 | #ifndef _CREATE_H_ 2 | #define _CREATE_H_ 3 | 4 | struct ArgState; 5 | 6 | int do_create_cmd(int argc, char *argv[], struct ArgState *as); 7 | 8 | int load(size_t layer_num, char *db_path); 9 | 10 | #endif /* _CREATE_H_ */ -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/core/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | Client::Client(int id, ClientFactory *factory) 4 | : id(id), factory(factory) { 5 | ; 6 | } 7 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/core/include/client.h: -------------------------------------------------------------------------------- 1 | #ifndef YCSB_CLIENT_H 2 | #define YCSB_CLIENT_H 3 | 4 | #include 5 | #include 6 | 7 | struct ClientFactory; 8 | 9 | struct Client { 10 | int id; 11 | ClientFactory *factory; 12 | 13 | Client(int id, ClientFactory *factory); 14 | virtual int do_set(char *key_buffer, char *value_buffer) = 0; 15 | virtual int do_get(char *key_buffer, char **value) = 0; 16 | virtual int reset() = 0; 17 | virtual void close() = 0; 18 | }; 19 | 20 | struct ClientFactory { 21 | virtual Client *create_client() = 0; 22 | virtual void destroy_client(Client *client) = 0; 23 | }; 24 | 25 | #endif //YCSB_CLIENT_H 26 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/core/include/measurement.h: -------------------------------------------------------------------------------- 1 | #ifndef YCSB_MEASUREMENT_H 2 | #define YCSB_MEASUREMENT_H 3 | 4 | #include "workload.h" 5 | #include 6 | #include 7 | 8 | struct OpMeasurement { 9 | std::atomic op_count_arr[NR_OP_TYPE]; 10 | std::chrono::steady_clock::time_point start_time; 11 | std::chrono::steady_clock::time_point end_time; 12 | 13 | std::atomic rt_op_count_arr[NR_OP_TYPE]; 14 | std::chrono::steady_clock::time_point rt_time; 15 | 16 | long max_progress; 17 | std::atomic cur_progress; 18 | std::atomic finished; 19 | 20 | OpMeasurement(); 21 | void set_max_progress(long new_max_progress); 22 | void start_measure(); 23 | void finish_measure(); 24 | 25 | void record_op(OperationType type); 26 | void record_progress(long progress_delta); 27 | 28 | long get_op_count(OperationType type); 29 | double get_throughput(OperationType type); 30 | void get_rt_throughput(double *throughput_arr); 31 | double get_progress_percent(); 32 | }; 33 | 34 | #endif //YCSB_MEASUREMENT_H 35 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/core/include/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef YCSB_WORKER_H 2 | #define YCSB_WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "measurement.h" 9 | #include "client.h" 10 | #include "workload.h" 11 | 12 | void worker_thread_fn(Client *client, Workload *workload, OpMeasurement *measurement); 13 | void monitor_thread_fn(const char *task, OpMeasurement *measurement); 14 | 15 | void run_workload_with_op_measurement(const char *task, ClientFactory *factory, Workload **workload_arr, 16 | int nr_thread, long nr_op, long max_progress); 17 | void run_init_workload_with_op_measurement(const char *task, ClientFactory *factory, long nr_entry, long key_size, long value_size, 18 | int nr_thread); 19 | void run_uniform_workload_with_op_measurement(const char *task, ClientFactory *factory, long nr_entry, long key_size, long value_size, 20 | int nr_thread, double read_ratio, long nr_op); 21 | void run_zipfian_workload_with_op_measurement(const char *task, ClientFactory *factory, long nr_entry, long key_size, long value_size, 22 | int nr_thread, double read_ratio, double zipfian_constant, long nr_op); 23 | 24 | #endif //YCSB_WORKER_H 25 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/core/include/workload.h: -------------------------------------------------------------------------------- 1 | #ifndef YCSB_WORKLOAD_H 2 | #define YCSB_WORKLOAD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | enum OperationType { 13 | SET = 0, 14 | GET, 15 | NR_OP_TYPE, 16 | }; 17 | 18 | struct Workload { 19 | long key_size; 20 | long value_size; 21 | 22 | Workload(long key_size, long value_size); 23 | virtual void next_op(OperationType *type, char *key_buffer, char *value_buffer) = 0; 24 | virtual bool has_next_op() = 0; 25 | 26 | protected: 27 | static long generate_random_long(unsigned int *seedp); 28 | static double generate_random_double(unsigned int *seedp); 29 | }; 30 | 31 | struct UniformWorkload : public Workload { 32 | /* configuration */ 33 | long nr_entry; 34 | long nr_op; 35 | double read_ratio; 36 | 37 | /* constants */ 38 | static constexpr int key_format_len = 64; 39 | 40 | /* states */ 41 | unsigned int seed; 42 | long cur_nr_op; 43 | char key_format[key_format_len]; 44 | 45 | UniformWorkload(long key_size, long value_size, long nr_entry, long nr_op, double read_ratio, unsigned int seed); 46 | void next_op(OperationType *type, char *key_buffer, char *value_buffer) override; 47 | bool has_next_op() override; 48 | 49 | private: 50 | void generate_key_string(char *key_buffer, long key); 51 | void generate_value_string(char *value_buffer); 52 | }; 53 | 54 | struct ZipfianWorkload : public Workload { 55 | /* configuration */ 56 | long nr_entry; 57 | long nr_op; 58 | double read_ratio; 59 | double zipfian_constant; 60 | 61 | /* constants */ 62 | static constexpr int key_format_len = 64; 63 | 64 | /* states */ 65 | unsigned int seed; 66 | long cur_nr_op; 67 | char key_format[key_format_len]; 68 | 69 | double zetan; 70 | double theta; 71 | double zeta2theta; 72 | double alpha; 73 | double eta; 74 | 75 | ZipfianWorkload(long key_size, long value_size, long nr_entry, long nr_op, double read_ratio, double zipfian_constant, unsigned int seed); 76 | void next_op(OperationType *type, char *key_buffer, char *value_buffer) override; 77 | bool has_next_op() override; 78 | ZipfianWorkload *clone(unsigned int new_seed); 79 | 80 | private: 81 | static unsigned long fnv1_64_hash(unsigned long value); 82 | unsigned long generate_zipfian_random_ulong(); 83 | void generate_key_string(char *key_buffer, long key); 84 | void generate_value_string(char *value_buffer); 85 | }; 86 | 87 | struct InitWorkload : public Workload { 88 | /* configuration */ 89 | long nr_entry; 90 | long start_key; 91 | 92 | /* constants */ 93 | static constexpr int key_format_len = 64; 94 | 95 | /* states */ 96 | unsigned int seed; 97 | long cur_nr_entry; 98 | char key_format[key_format_len]; 99 | 100 | InitWorkload(long nr_entry, long start_key, long key_size, long value_size, unsigned int seed); 101 | void next_op(OperationType *type, char *key_buffer, char *value_buffer) override; 102 | bool has_next_op() override; 103 | private: 104 | void generate_key_string(char *key_buffer, long key); 105 | void generate_value_string(char *value_buffer); 106 | }; 107 | 108 | #endif //YCSB_WORKLOAD_H 109 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/core/measurement.cpp: -------------------------------------------------------------------------------- 1 | #include "measurement.h" 2 | 3 | OpMeasurement::OpMeasurement() { 4 | for (int i = 0; i < NR_OP_TYPE; ++i) { 5 | this->op_count_arr[i] = 0; 6 | this->rt_op_count_arr[i] = 0; 7 | } 8 | this->cur_progress = 0; 9 | this->finished = false; 10 | } 11 | 12 | void OpMeasurement::set_max_progress(long new_max_progress) { 13 | this->max_progress = new_max_progress; 14 | } 15 | 16 | void OpMeasurement::start_measure() { 17 | this->start_time = std::chrono::steady_clock::now(); 18 | this->rt_time = std::chrono::steady_clock::now(); 19 | } 20 | 21 | void OpMeasurement::finish_measure() { 22 | this->end_time = std::chrono::steady_clock::now(); 23 | this->finished = true; 24 | } 25 | 26 | void OpMeasurement::record_op(OperationType type) { 27 | ++this->op_count_arr[type]; 28 | ++this->rt_op_count_arr[type]; 29 | } 30 | 31 | void OpMeasurement::record_progress(long progress_delta) { 32 | this->cur_progress += progress_delta; 33 | } 34 | 35 | long OpMeasurement::get_op_count(OperationType type) { 36 | return this->op_count_arr[type]; 37 | } 38 | 39 | double OpMeasurement::get_throughput(OperationType type) { 40 | long duration = std::chrono::duration_cast( 41 | this->end_time - this->start_time 42 | ).count(); 43 | return ((double) this->op_count_arr[type]) * 1000000 / duration; 44 | } 45 | 46 | void OpMeasurement::get_rt_throughput(double *throughput_arr) { 47 | std::chrono::steady_clock::time_point cur_time = std::chrono::steady_clock::now(); 48 | long duration = std::chrono::duration_cast( 49 | cur_time - this->rt_time 50 | ).count(); 51 | for (int i = 0; i < NR_OP_TYPE; ++i) { 52 | throughput_arr[i] = ((double) this->rt_op_count_arr[i].exchange(0)) * 1000000 / duration; 53 | } 54 | this->rt_time = cur_time; 55 | } 56 | 57 | double OpMeasurement::get_progress_percent() { 58 | return ((double) this->cur_progress) / ((double) this->max_progress); 59 | } 60 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/core/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | void worker_thread_fn(Client *client, Workload *workload, OpMeasurement *measurement) { 4 | OperationType type; 5 | char *key_buffer = new char[workload->key_size]; 6 | char *value_buffer= new char[workload->value_size]; 7 | 8 | while (workload->has_next_op()) { 9 | workload->next_op(&type, key_buffer, value_buffer); 10 | switch (type) { 11 | case SET: 12 | client->do_set(key_buffer, value_buffer); 13 | break; 14 | case GET: 15 | char *value; 16 | client->do_get(key_buffer, &value); 17 | break; 18 | default: 19 | throw std::invalid_argument("invalid op type"); 20 | } 21 | measurement->record_op(type); 22 | measurement->record_progress(1); 23 | } 24 | delete[] key_buffer; 25 | delete[] value_buffer; 26 | } 27 | 28 | void monitor_thread_fn(const char *task, OpMeasurement *measurement) { 29 | double rt_throughput[NR_OP_TYPE]; 30 | double progress; 31 | long epoch = 0; 32 | for (;!measurement->finished 33 | ;std::this_thread::sleep_for(std::chrono::seconds(1)), ++epoch) { 34 | measurement->get_rt_throughput(rt_throughput); 35 | progress = measurement->get_progress_percent(); 36 | printf("%s (epoch %ld, progress %.2f%%): read throughput %.2lf ops/sec, write throughput %.2lf ops/sec, total throughput %.2lf ops/sec\n", 37 | task, epoch, 100 * progress, rt_throughput[GET], rt_throughput[SET], rt_throughput[GET] + rt_throughput[SET]); 38 | std::cout << std::flush; 39 | } 40 | printf("%s overall: read throughput %.2lf ops/sec, write throughput %.2lf ops/sec, total throughput %.2lf ops/sec\n", 41 | task, measurement->get_throughput(GET), measurement->get_throughput(SET), 42 | measurement->get_throughput(GET) + measurement->get_throughput(SET)); 43 | std::cout << std::flush; 44 | } 45 | 46 | void run_workload_with_op_measurement(const char *task, ClientFactory *factory, Workload **workload_arr, int nr_thread, long nr_op, long max_progress) { 47 | /* allocate resources */ 48 | Client **client_arr = new Client *[nr_thread]; 49 | std::thread **thread_arr = new std::thread *[nr_thread]; 50 | OpMeasurement measurement; 51 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 52 | client_arr[thread_index] = factory->create_client(); 53 | } 54 | 55 | /* start running workload */ 56 | measurement.start_measure(); 57 | measurement.set_max_progress(max_progress); 58 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 59 | thread_arr[thread_index] = new std::thread(worker_thread_fn, client_arr[thread_index], workload_arr[thread_index], &measurement); 60 | } 61 | std::thread stat_thread(monitor_thread_fn, task, &measurement); 62 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 63 | thread_arr[thread_index]->join(); 64 | } 65 | measurement.finish_measure(); 66 | stat_thread.join(); 67 | 68 | /* cleanup */ 69 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 70 | factory->destroy_client(client_arr[thread_index]); 71 | delete thread_arr[thread_index]; 72 | } 73 | delete[] client_arr; 74 | delete[] thread_arr; 75 | } 76 | 77 | void run_init_workload_with_op_measurement(const char *task, ClientFactory *factory, long nr_entry, long key_size, long value_size, int nr_thread) { 78 | InitWorkload **workload_arr = new InitWorkload *[nr_thread]; 79 | long nr_entry_per_thread = (nr_entry + nr_thread - 1) / nr_thread; 80 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 81 | long start_key = nr_entry_per_thread * thread_index; 82 | long end_key = std::min(nr_entry_per_thread * (thread_index + 1), nr_entry); 83 | workload_arr[thread_index] = new InitWorkload(end_key - start_key, start_key, key_size, value_size, thread_index); 84 | } 85 | 86 | run_workload_with_op_measurement(task, factory, (Workload **)workload_arr, nr_thread, nr_entry, nr_entry); 87 | 88 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 89 | delete workload_arr[thread_index]; 90 | } 91 | delete[] workload_arr; 92 | } 93 | 94 | void run_uniform_workload_with_op_measurement(const char *task, ClientFactory *factory, long nr_entry, long key_size, long value_size, 95 | int nr_thread, double read_ratio, long nr_op) { 96 | UniformWorkload **workload_arr = new UniformWorkload *[nr_thread]; 97 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 98 | workload_arr[thread_index] = new UniformWorkload(key_size, value_size, nr_entry, nr_op, read_ratio, thread_index); 99 | } 100 | 101 | run_workload_with_op_measurement(task, factory, (Workload **)workload_arr, nr_thread, nr_op, nr_thread * nr_op); 102 | 103 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 104 | delete workload_arr[thread_index]; 105 | } 106 | delete[] workload_arr; 107 | } 108 | 109 | void run_zipfian_workload_with_op_measurement(const char *task, ClientFactory *factory, long nr_entry, long key_size, long value_size, 110 | int nr_thread, double read_ratio, double zipfian_constant, long nr_op) { 111 | ZipfianWorkload **workload_arr = new ZipfianWorkload *[nr_thread]; 112 | printf("ZipfianWorkload: start initializing zipfian variables, might take a while\n"); 113 | ZipfianWorkload base_workload(key_size, value_size, nr_entry, nr_op, read_ratio, zipfian_constant, 0); 114 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 115 | workload_arr[thread_index] = base_workload.clone(thread_index); 116 | } 117 | 118 | run_workload_with_op_measurement(task, factory, (Workload **)workload_arr, nr_thread, nr_op, nr_thread * nr_op); 119 | 120 | for (int thread_index = 0; thread_index < nr_thread; ++thread_index) { 121 | delete workload_arr[thread_index]; 122 | } 123 | delete[] workload_arr; 124 | } 125 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/redis/init_redis.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "worker.h" 3 | #include "redis_client.h" 4 | 5 | enum { 6 | PARAM_KEY_SIZE = 1, 7 | PARAM_VALUE_SIZE, 8 | PARAM_NR_ENTRY, 9 | PARAM_NR_THREAD, 10 | PARAM_REDIS_ADDR, 11 | PARAM_REDIS_PORT, 12 | PARAM_ARGC 13 | }; 14 | 15 | int main(int argc, char *argv[]) { 16 | if (argc != PARAM_ARGC) { 17 | printf("Usage: %s \n", argv[0]); 18 | return EINVAL; 19 | } 20 | long key_size = atol(argv[PARAM_KEY_SIZE]); 21 | long value_size = atol(argv[PARAM_VALUE_SIZE]); 22 | long nr_entry = atol(argv[PARAM_NR_ENTRY]); 23 | int nr_thread = atol(argv[PARAM_NR_THREAD]); 24 | char *redis_addr = argv[PARAM_REDIS_ADDR]; 25 | int redis_port = atoi(argv[PARAM_REDIS_PORT]); 26 | 27 | RedisFactory factory(redis_addr, redis_port); 28 | 29 | run_init_workload_with_op_measurement("Initialization", &factory, nr_entry, key_size, value_size, nr_thread); 30 | } 31 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/redis/redis_client.cpp: -------------------------------------------------------------------------------- 1 | #include "redis_client.h" 2 | 3 | RedisClient::RedisClient(RedisFactory *factory, int id) 4 | : Client(id, factory), redis_context(nullptr), last_reply(nullptr) { 5 | this->redis_context = redisConnect(factory->redis_addr, factory->redis_port); 6 | if (this->redis_context == nullptr || this->redis_context->err) { 7 | if (this->redis_context) { 8 | fprintf(stderr, "RedisClient: redisConnect error %s\n", this->redis_context->errstr); 9 | } else { 10 | fprintf(stderr, "RedisClient: cannot allocate redis context\n"); 11 | } 12 | throw std::invalid_argument("failed to open redis_context"); 13 | } 14 | } 15 | 16 | RedisClient::~RedisClient() { 17 | if (this->last_reply != nullptr) 18 | freeReplyObject(this->last_reply); 19 | if (this->redis_context) 20 | redisFree(this->redis_context); 21 | } 22 | 23 | int RedisClient::do_set(char *key_buffer, char *value_buffer) { 24 | redisReply *reply = (redisReply *)redisCommand(this->redis_context, "SET %s %s", key_buffer, value_buffer); 25 | if (!reply) { 26 | fprintf(stderr, "RedisClient: SET error: %s\n", this->redis_context->errstr); 27 | throw std::invalid_argument("failed to SET"); 28 | } 29 | this->set_last_reply(reply); 30 | return 0; 31 | } 32 | 33 | int RedisClient::do_get(char *key_buffer, char **value) { 34 | redisReply *reply = (redisReply *)redisCommand(this->redis_context, "GET %s", key_buffer); 35 | if (!reply) { 36 | fprintf(stderr, "RedisClient: GET error: %s\n", this->redis_context->errstr); 37 | throw std::invalid_argument("failed to GET"); 38 | } 39 | *value = reply->str; 40 | this->set_last_reply(reply); 41 | return 0; 42 | } 43 | 44 | int RedisClient::reset() { 45 | throw std::invalid_argument("reset not implemented"); 46 | } 47 | 48 | void RedisClient::close() { 49 | if (this->last_reply) 50 | freeReplyObject(this->last_reply); 51 | this->last_reply = nullptr; 52 | if (this->redis_context) 53 | redisFree(this->redis_context); 54 | this->redis_context = nullptr; 55 | } 56 | 57 | void RedisClient::set_last_reply(redisReply *reply) { 58 | if (this->last_reply) 59 | freeReplyObject(this->last_reply); 60 | this->last_reply = reply; 61 | } 62 | 63 | RedisFactory::RedisFactory(const char *redis_addr, int redis_port) 64 | : redis_addr(redis_addr), redis_port(redis_port), client_id(0) { 65 | ; 66 | } 67 | 68 | RedisClient *RedisFactory::create_client() { 69 | RedisClient *client = new RedisClient(this, this->client_id++); 70 | return client; 71 | } 72 | 73 | void RedisFactory::destroy_client(Client *client) { 74 | RedisClient *redis_client = (RedisClient *) client; 75 | redis_client->close(); 76 | delete redis_client; 77 | } 78 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/redis/redis_client.h: -------------------------------------------------------------------------------- 1 | #ifndef YCSB_REDIS_CLIENT_H 2 | #define YCSB_REDIS_CLIENT_H 3 | 4 | #include 5 | #include "client.h" 6 | #include 7 | 8 | struct RedisFactory; 9 | 10 | struct RedisClient : public Client { 11 | redisContext *redis_context; 12 | redisReply *last_reply; 13 | 14 | RedisClient(RedisFactory *factory, int id); 15 | ~RedisClient(); 16 | int do_set(char *key_buffer, char *value_buffer) override; 17 | int do_get(char *key_buffer, char **value) override; 18 | int reset() override; 19 | void close() override; 20 | private: 21 | void set_last_reply(redisReply *reply); 22 | }; 23 | 24 | struct RedisFactory : public ClientFactory { 25 | const char *redis_addr; 26 | const int redis_port; 27 | std::atomic client_id; 28 | 29 | RedisFactory(const char *redis_addr, int redis_port); 30 | RedisClient *create_client() override; 31 | void destroy_client(Client *client) override; 32 | }; 33 | 34 | #endif //YCSB_REDIS_CLIENT_H 35 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/redis/run_redis.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "worker.h" 3 | #include "redis_client.h" 4 | 5 | enum { 6 | PARAM_KEY_SIZE = 1, 7 | PARAM_VALUE_SIZE, 8 | PARAM_NR_ENTRY, 9 | PARAM_NR_THREAD, 10 | PARAM_READ_RATIO, 11 | PARAM_WARM_UP_OP, 12 | PARAM_NR_OP, 13 | PARAM_REDIS_ADDR, 14 | PARAM_REDIS_PORT, 15 | PARAM_ARGC 16 | }; 17 | 18 | int main(int argc, char *argv[]) { 19 | if (argc != PARAM_ARGC) { 20 | printf("Usage: %s \n", argv[0]); 21 | return EINVAL; 22 | } 23 | long key_size = atol(argv[PARAM_KEY_SIZE]); 24 | long value_size = atol(argv[PARAM_VALUE_SIZE]); 25 | long nr_entry = atol(argv[PARAM_NR_ENTRY]); 26 | int nr_thread = atol(argv[PARAM_NR_THREAD]); 27 | double read_ratio = atof(argv[PARAM_READ_RATIO]); 28 | long nr_warm_up_op = atol(argv[PARAM_WARM_UP_OP]); 29 | long nr_op = atol(argv[PARAM_NR_OP]); 30 | char *redis_addr = argv[PARAM_REDIS_ADDR]; 31 | int redis_port = atoi(argv[PARAM_REDIS_PORT]); 32 | 33 | RedisFactory factory(redis_addr, redis_port); 34 | 35 | run_uniform_workload_with_op_measurement("Warm-Up", &factory, nr_entry, key_size, value_size, nr_thread, 36 | read_ratio, nr_warm_up_op); 37 | run_uniform_workload_with_op_measurement("Uniform-Workload", &factory, nr_entry, key_size, value_size, nr_thread, 38 | read_ratio, nr_op); 39 | } 40 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/wiredtiger/init_wt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "worker.h" 3 | #include "wt_client.h" 4 | 5 | enum { 6 | PARAM_KEY_SIZE = 1, 7 | PARAM_VALUE_SIZE, 8 | PARAM_NR_ENTRY, 9 | PARAM_ARGC 10 | }; 11 | 12 | int main(int argc, char *argv[]) { 13 | if (argc != PARAM_ARGC) { 14 | printf("Usage: %s \n", argv[0]); 15 | return EINVAL; 16 | } 17 | long key_size = atol(argv[PARAM_KEY_SIZE]); 18 | long value_size = atol(argv[PARAM_VALUE_SIZE]); 19 | long nr_entry = atol(argv[PARAM_NR_ENTRY]); 20 | 21 | WiredTigerFactory factory(nullptr, nullptr, nullptr, nullptr, nullptr, true, nullptr); 22 | 23 | factory.update_cursor_config(WiredTigerClient::cursor_bulk_config); 24 | run_init_workload_with_op_measurement("Initialization", &factory, nr_entry, key_size, value_size, 1); 25 | } 26 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/wiredtiger/run_wt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "worker.h" 3 | #include "wt_client.h" 4 | 5 | enum { 6 | PARAM_KEY_SIZE = 1, 7 | PARAM_VALUE_SIZE, 8 | PARAM_NR_ENTRY, 9 | PARAM_NR_THREAD, 10 | PARAM_READ_RATIO, 11 | PARAM_WARM_UP_OP, 12 | PARAM_NR_OP, 13 | PARAM_ARGC 14 | }; 15 | 16 | int main(int argc, char *argv[]) { 17 | if (argc != PARAM_ARGC) { 18 | printf("Usage: %s \n", argv[0]); 19 | return EINVAL; 20 | } 21 | long key_size = atol(argv[PARAM_KEY_SIZE]); 22 | long value_size = atol(argv[PARAM_VALUE_SIZE]); 23 | long nr_entry = atol(argv[PARAM_NR_ENTRY]); 24 | int nr_thread = atol(argv[PARAM_NR_THREAD]); 25 | double read_ratio = atof(argv[PARAM_READ_RATIO]); 26 | long nr_warm_up_op = atol(argv[PARAM_WARM_UP_OP]); 27 | long nr_op = atol(argv[PARAM_NR_OP]); 28 | 29 | WiredTigerFactory factory(nullptr, nullptr, nullptr, nullptr, nullptr, false, nullptr); 30 | 31 | factory.update_cursor_config(nullptr); 32 | run_uniform_workload_with_op_measurement("Warm-Up", &factory, nr_entry, key_size, value_size, nr_thread, 33 | read_ratio, nr_warm_up_op); 34 | run_uniform_workload_with_op_measurement("Uniform-Workload", &factory, nr_entry, key_size, value_size, nr_thread, 35 | read_ratio, nr_op); 36 | } 37 | -------------------------------------------------------------------------------- /ddp-artifacts/My-YCSB/wiredtiger/wt_client.h: -------------------------------------------------------------------------------- 1 | #ifndef YCSB_WT_CLIENT_H 2 | #define YCSB_WT_CLIENT_H 3 | 4 | #include "client.h" 5 | #include 6 | 7 | 8 | struct WiredTigerFactory; 9 | 10 | struct WiredTigerClient : public Client { 11 | WT_SESSION *session; 12 | WT_CURSOR *cursor; 13 | const char *session_config; 14 | const char *cursor_config; 15 | 16 | static const char *session_default_config; 17 | static const char *cursor_default_config; 18 | static const char *cursor_bulk_config; 19 | 20 | WiredTigerClient(WiredTigerFactory *factory, int id, const char *session_config, const char *cursor_config); 21 | ~WiredTigerClient(); 22 | int do_set(char *key_buffer, char *value_buffer) override; 23 | int do_get(char *key_buffer, char **value) override; 24 | int reset() override; 25 | void close() override; 26 | }; 27 | 28 | struct WiredTigerFactory : public ClientFactory { 29 | WT_CONNECTION *conn; 30 | const char *data_dir; 31 | const char *table_name; 32 | const char *conn_config; 33 | const char *session_config; 34 | const char *cursor_config; 35 | const char *create_table_config; 36 | std::atomic client_id; 37 | 38 | static const char *default_data_dir; 39 | static const char *default_table_name; 40 | static const char *conn_default_config; 41 | static const char *create_table_default_config; 42 | 43 | WiredTigerFactory(const char *data_dir, const char *table_name, const char *conn_config, 44 | const char *session_config, const char *cursor_config, bool new_table, 45 | const char *create_table_config); 46 | ~WiredTigerFactory(); 47 | void update_session_config(const char *new_session_config); 48 | void update_cursor_config(const char *new_cursor_config); 49 | WiredTigerClient *create_client() override; 50 | void destroy_client(Client *client) override; 51 | }; 52 | 53 | #endif //YCSB_WT_CLIENT_H 54 | -------------------------------------------------------------------------------- /ddp-artifacts/build.sh: -------------------------------------------------------------------------------- 1 | gcc -o db db.c db.h -lpthread -D_GNU_SOURCE 2 | -------------------------------------------------------------------------------- /ddp-artifacts/db.h: -------------------------------------------------------------------------------- 1 | #ifndef DB_H 2 | #define DB_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "db_types.h" 9 | 10 | // Node-level information 11 | #define INTERNAL 0 12 | #define LEAF 1 13 | 14 | // Database-level information 15 | #define DB_PATH "/dev/nvme0n1" 16 | #define LOAD_MODE 0 17 | #define RUN_MODE 1 18 | #define FILE_MASK ((ptr__t)1 << 63) 19 | 20 | size_t worker_num; 21 | size_t total_node; 22 | size_t *layer_cap; 23 | key__t max_key; 24 | int db; 25 | Node *cache; 26 | size_t cache_cap; 27 | 28 | typedef struct { 29 | size_t op_count; 30 | size_t index; 31 | int db_handler; 32 | size_t timer; 33 | } WorkerArg; 34 | 35 | int get_handler(int flag); 36 | 37 | ptr__t is_file_offset(ptr__t ptr) { 38 | return ptr & FILE_MASK; 39 | } 40 | 41 | ptr__t encode(ptr__t ptr) { 42 | return ptr | FILE_MASK; 43 | } 44 | 45 | ptr__t decode(ptr__t ptr) { 46 | return ptr & (~FILE_MASK); 47 | } 48 | 49 | int load(size_t layer_num); 50 | 51 | int run(size_t layer_num, size_t request_num, size_t thread_num); 52 | 53 | void *subtask(void *args); 54 | 55 | void build_cache(size_t layer_num); 56 | 57 | int get(key__t key, val__t val, int db_handler); 58 | 59 | ptr__t next_node(key__t key, Node *node); 60 | 61 | void read_node(ptr__t ptr, Node *node, int db_handler); 62 | 63 | void read_log(ptr__t ptr, Log *log, int db_handler); 64 | 65 | int retrieve_value(ptr__t ptr, val__t val, int db_handler); 66 | 67 | int prompt_help(); 68 | 69 | void initialize(size_t layer_num, int mode); 70 | 71 | void initialize_workers(WorkerArg *args, size_t total_op_count); 72 | 73 | void start_workers(pthread_t *tids, WorkerArg *args); 74 | 75 | void terminate_workers(pthread_t *tids, WorkerArg *args); 76 | 77 | int terminate(); 78 | 79 | int compare_nodes(Node *x, Node *y); 80 | 81 | void print_node(ptr__t ptr, Node *node); 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libbpf"] 2 | path = libbpf 3 | url = https://github.com/libbpf/libbpf.git 4 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Andrii Nakryiko 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/.lgtm.yml: -------------------------------------------------------------------------------- 1 | # vi: set ts=2 sw=2: 2 | extraction: 3 | cpp: 4 | prepare: 5 | packages: 6 | - libelf-dev 7 | - pkg-config 8 | after_prepare: 9 | # As the buildsystem detection by LGTM is performed _only_ during the 10 | # 'configure' phase, we need to trick LGTM we use a supported build 11 | # system (configure, meson, cmake, etc.). This way LGTM correctly detects 12 | # that our sources are in the src/ subfolder. 13 | - touch src/configure 14 | - chmod +x src/configure 15 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: bash 3 | dist: bionic 4 | services: 5 | - docker 6 | 7 | env: 8 | global: 9 | - PROJECT_NAME='libbpf' 10 | - AUTHOR_EMAIL="$(git log -1 --pretty=\"%aE\")" 11 | - REPO_ROOT="$TRAVIS_BUILD_DIR" 12 | - CI_ROOT="$REPO_ROOT/travis-ci" 13 | - VMTEST_ROOT="$CI_ROOT/vmtest" 14 | 15 | addons: 16 | apt: 17 | packages: 18 | - qemu-kvm 19 | - zstd 20 | - binutils-dev 21 | - elfutils 22 | - libcap-dev 23 | - libelf-dev 24 | - libdw-dev 25 | 26 | stages: 27 | # Run Coverity periodically instead of for each PR for following reasons: 28 | # 1) Coverity jobs are heavily rate-limited 29 | # 2) Due to security restrictions of encrypted environment variables 30 | # in Travis CI, pull requests made from forks can't access encrypted 31 | # env variables, making Coverity unusable 32 | # See: https://docs.travis-ci.com/user/pull-requests#pull-requests-and-security-restrictions 33 | - name: Coverity 34 | if: type = cron 35 | 36 | jobs: 37 | include: 38 | - stage: Builds & Tests 39 | name: Kernel LATEST + selftests 40 | language: bash 41 | env: KERNEL=LATEST 42 | script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1 43 | 44 | - name: Kernel 4.9.0 + selftests 45 | language: bash 46 | env: KERNEL=4.9.0 47 | script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1 48 | 49 | - name: Kernel 5.5.0 + selftests 50 | language: bash 51 | env: KERNEL=5.5.0 52 | script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1 53 | 54 | - name: Debian Build 55 | language: bash 56 | install: $CI_ROOT/managers/debian.sh SETUP 57 | script: $CI_ROOT/managers/debian.sh RUN || travis_terminate 1 58 | after_script: $CI_ROOT/managers/debian.sh CLEANUP 59 | 60 | - name: Debian Build (ASan+UBSan) 61 | language: bash 62 | install: $CI_ROOT/managers/debian.sh SETUP 63 | script: $CI_ROOT/managers/debian.sh RUN_ASAN || travis_terminate 1 64 | after_script: $CI_ROOT/managers/debian.sh CLEANUP 65 | 66 | - name: Debian Build (clang) 67 | language: bash 68 | install: $CI_ROOT/managers/debian.sh SETUP 69 | script: $CI_ROOT/managers/debian.sh RUN_CLANG || travis_terminate 1 70 | after_script: $CI_ROOT/managers/debian.sh CLEANUP 71 | 72 | - name: Debian Build (clang ASan+UBSan) 73 | language: bash 74 | install: $CI_ROOT/managers/debian.sh SETUP 75 | script: $CI_ROOT/managers/debian.sh RUN_CLANG_ASAN || travis_terminate 1 76 | after_script: $CI_ROOT/managers/debian.sh CLEANUP 77 | 78 | - name: Debian Build (gcc-8) 79 | language: bash 80 | install: $CI_ROOT/managers/debian.sh SETUP 81 | script: $CI_ROOT/managers/debian.sh RUN_GCC8 || travis_terminate 1 82 | after_script: $CI_ROOT/managers/debian.sh CLEANUP 83 | 84 | - name: Debian Build (gcc-8 ASan+UBSan) 85 | language: bash 86 | install: $CI_ROOT/managers/debian.sh SETUP 87 | script: $CI_ROOT/managers/debian.sh RUN_GCC8_ASAN || travis_terminate 1 88 | after_script: $CI_ROOT/managers/debian.sh CLEANUP 89 | 90 | - name: Ubuntu Bionic Build 91 | language: bash 92 | script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 93 | 94 | - name: Ubuntu Bionic Build (arm) 95 | arch: arm64 96 | language: bash 97 | script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 98 | 99 | - name: Ubuntu Bionic Build (s390x) 100 | arch: s390x 101 | language: bash 102 | script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 103 | 104 | - name: Ubuntu Bionic Build (ppc64le) 105 | arch: ppc64le 106 | language: bash 107 | script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 108 | 109 | - stage: Coverity 110 | language: bash 111 | env: 112 | # Coverity configuration 113 | # COVERITY_SCAN_TOKEN=xxx 114 | # Encrypted using `travis encrypt --repo libbpf/libbpf COVERITY_SCAN_TOKEN=xxx` 115 | - secure: "I9OsMRHbb82IUivDp+I+w/jEQFOJgBDAqYqf1ollqCM1QhocxMcS9bwIAgfPhdXi2hohV7sRrVMZstahY67FAvJLGxNopi4tAPDIAaIFxgO0yDxMhaTMx5xDfMwlIm2FOP/9gB9BQsd6M7CmoQZgXYwBIv7xd1ooxoQrh2rOK1YrRl7UQu3+c3zPTjDfIYZzR3bFttMqZ9/c4U0v8Ry5IFXrel3hCshndHA1TtttJrUSrILlZcmVc1ch7JIy6zCbCU/2lGv0B/7rWXfF8MT7O9jPtFOhJ1DEcd2zhw2n4j9YT3a8OhtnM61LA6ask632mwCOsxpFLTun7AzuR1Cb5mdPHsxhxnCHcXXARa2mJjem0QG1NhwxwJE8sbRDapojexxCvweYlEN40ofwMDSnj/qNt95XIcrk0tiIhGFx0gVNWvAdmZwx+N4mwGPMTAN0AEOFjpgI+ZdB89m+tL/CbEgE1flc8QxUxJhcp5OhH6yR0z9qYOp0nXIbHsIaCiRvt/7LqFRQfheifztWVz4mdQlCdKS9gcOQ09oKicPevKO1L0Ue3cb7Ug7jOpMs+cdh3XokJtUeYEr1NijMHT9+CTAhhO5RToWXIZRon719z3fwoUBNDREATwVFMlVxqSO/pbYgaKminigYbl785S89YYaZ6E5UvaKRHM6KHKMDszs=" 116 | - COVERITY_SCAN_PROJECT_NAME="libbpf" 117 | - COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}" 118 | - COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH" 119 | # Note: `make -C src/` as a BUILD_COMMAND will not work here 120 | - COVERITY_SCAN_BUILD_COMMAND_PREPEND="cd src/" 121 | - COVERITY_SCAN_BUILD_COMMAND="make" 122 | install: 123 | - sudo echo 'deb-src http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse' >>/etc/apt/sources.list 124 | - sudo apt-get update 125 | - sudo apt-get -y build-dep libelf-dev 126 | - sudo apt-get install -y libelf-dev pkg-config 127 | script: 128 | - scripts/coverity.sh || travis_terminate 1 129 | allow_failures: 130 | - env: KERNEL=x.x.x 131 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/BPF-CHECKPOINT-COMMIT: -------------------------------------------------------------------------------- 1 | 78031381ae9c88f4f914d66154f4745122149c58 2 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/CHECKPOINT-COMMIT: -------------------------------------------------------------------------------- 1 | 86ce322d21eb032ed8fdd294d0fb095d2debb430 2 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/LICENSE: -------------------------------------------------------------------------------- 1 | LGPL-2.1 OR BSD-2-Clause 2 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/LICENSE.BSD-2-Clause: -------------------------------------------------------------------------------- 1 | Valid-License-Identifier: BSD-2-Clause 2 | SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html 3 | Usage-Guide: 4 | To use the BSD 2-clause "Simplified" License put the following SPDX 5 | tag/value pair into a comment according to the placement guidelines in 6 | the licensing rules documentation: 7 | SPDX-License-Identifier: BSD-2-Clause 8 | License-Text: 9 | 10 | Copyright (c) . All rights reserved. 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions are met: 14 | 15 | 1. Redistributions of source code must retain the above copyright notice, 16 | this list of conditions and the following disclaimer. 17 | 18 | 2. Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/asm/barrier.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __ASM_BARRIER_H 3 | #define __ASM_BARRIER_H 4 | 5 | #include 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/compiler.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_COMPILER_H 4 | #define __LINUX_COMPILER_H 5 | 6 | #define likely(x) __builtin_expect(!!(x), 1) 7 | #define unlikely(x) __builtin_expect(!!(x), 0) 8 | 9 | #define READ_ONCE(x) (*(volatile typeof(x) *)&x) 10 | #define WRITE_ONCE(x, v) (*(volatile typeof(x) *)&x) = (v) 11 | 12 | #define barrier() asm volatile("" ::: "memory") 13 | 14 | #if defined(__x86_64__) 15 | 16 | # define smp_rmb() barrier() 17 | # define smp_wmb() barrier() 18 | # define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc") 19 | 20 | # define smp_store_release(p, v) \ 21 | do { \ 22 | barrier(); \ 23 | WRITE_ONCE(*p, v); \ 24 | } while (0) 25 | 26 | # define smp_load_acquire(p) \ 27 | ({ \ 28 | typeof(*p) ___p = READ_ONCE(*p); \ 29 | barrier(); \ 30 | ___p; \ 31 | }) 32 | 33 | #elif defined(__aarch64__) 34 | 35 | # define smp_rmb() asm volatile("dmb ishld" ::: "memory") 36 | # define smp_wmb() asm volatile("dmb ishst" ::: "memory") 37 | # define smp_mb() asm volatile("dmb ish" ::: "memory") 38 | 39 | #endif 40 | 41 | #ifndef smp_mb 42 | # define smp_mb() __sync_synchronize() 43 | #endif 44 | 45 | #ifndef smp_rmb 46 | # define smp_rmb() smp_mb() 47 | #endif 48 | 49 | #ifndef smp_wmb 50 | # define smp_wmb() smp_mb() 51 | #endif 52 | 53 | #ifndef smp_store_release 54 | # define smp_store_release(p, v) \ 55 | do { \ 56 | smp_mb(); \ 57 | WRITE_ONCE(*p, v); \ 58 | } while (0) 59 | #endif 60 | 61 | #ifndef smp_load_acquire 62 | # define smp_load_acquire(p) \ 63 | ({ \ 64 | typeof(*p) ___p = READ_ONCE(*p); \ 65 | smp_mb(); \ 66 | ___p; \ 67 | }) 68 | #endif 69 | 70 | #endif /* __LINUX_COMPILER_H */ 71 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/err.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_ERR_H 4 | #define __LINUX_ERR_H 5 | 6 | #include 7 | #include 8 | 9 | #define MAX_ERRNO 4095 10 | 11 | #define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) 12 | 13 | static inline void * ERR_PTR(long error_) 14 | { 15 | return (void *) error_; 16 | } 17 | 18 | static inline long PTR_ERR(const void *ptr) 19 | { 20 | return (long) ptr; 21 | } 22 | 23 | static inline bool IS_ERR(const void *ptr) 24 | { 25 | return IS_ERR_VALUE((unsigned long)ptr); 26 | } 27 | 28 | static inline bool IS_ERR_OR_NULL(const void *ptr) 29 | { 30 | return (!ptr) || IS_ERR_VALUE((unsigned long)ptr); 31 | } 32 | 33 | static inline long PTR_ERR_OR_ZERO(const void *ptr) 34 | { 35 | return IS_ERR(ptr) ? PTR_ERR(ptr) : 0; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/filter.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_FILTER_H 4 | #define __LINUX_FILTER_H 5 | 6 | #include 7 | 8 | #define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \ 9 | ((struct bpf_insn) { \ 10 | .code = CODE, \ 11 | .dst_reg = DST, \ 12 | .src_reg = SRC, \ 13 | .off = OFF, \ 14 | .imm = IMM }) 15 | 16 | #define BPF_ALU64_IMM(OP, DST, IMM) \ 17 | ((struct bpf_insn) { \ 18 | .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ 19 | .dst_reg = DST, \ 20 | .src_reg = 0, \ 21 | .off = 0, \ 22 | .imm = IMM }) 23 | 24 | #define BPF_MOV64_IMM(DST, IMM) \ 25 | ((struct bpf_insn) { \ 26 | .code = BPF_ALU64 | BPF_MOV | BPF_K, \ 27 | .dst_reg = DST, \ 28 | .src_reg = 0, \ 29 | .off = 0, \ 30 | .imm = IMM }) 31 | 32 | #define BPF_EXIT_INSN() \ 33 | ((struct bpf_insn) { \ 34 | .code = BPF_JMP | BPF_EXIT, \ 35 | .dst_reg = 0, \ 36 | .src_reg = 0, \ 37 | .off = 0, \ 38 | .imm = 0 }) 39 | 40 | #define BPF_EMIT_CALL(FUNC) \ 41 | ((struct bpf_insn) { \ 42 | .code = BPF_JMP | BPF_CALL, \ 43 | .dst_reg = 0, \ 44 | .src_reg = 0, \ 45 | .off = 0, \ 46 | .imm = ((FUNC) - BPF_FUNC_unspec) }) 47 | 48 | #define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \ 49 | ((struct bpf_insn) { \ 50 | .code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \ 51 | .dst_reg = DST, \ 52 | .src_reg = SRC, \ 53 | .off = OFF, \ 54 | .imm = 0 }) 55 | 56 | #define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ 57 | ((struct bpf_insn) { \ 58 | .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \ 59 | .dst_reg = DST, \ 60 | .src_reg = SRC, \ 61 | .off = OFF, \ 62 | .imm = 0 }) 63 | 64 | #define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ 65 | ((struct bpf_insn) { \ 66 | .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ 67 | .dst_reg = DST, \ 68 | .src_reg = 0, \ 69 | .off = OFF, \ 70 | .imm = IMM }) 71 | 72 | #define BPF_MOV64_REG(DST, SRC) \ 73 | ((struct bpf_insn) { \ 74 | .code = BPF_ALU64 | BPF_MOV | BPF_X, \ 75 | .dst_reg = DST, \ 76 | .src_reg = SRC, \ 77 | .off = 0, \ 78 | .imm = 0 }) 79 | 80 | #define BPF_MOV32_IMM(DST, IMM) \ 81 | ((struct bpf_insn) { \ 82 | .code = BPF_ALU | BPF_MOV | BPF_K, \ 83 | .dst_reg = DST, \ 84 | .src_reg = 0, \ 85 | .off = 0, \ 86 | .imm = IMM }) 87 | 88 | #define BPF_LD_IMM64_RAW_FULL(DST, SRC, OFF1, OFF2, IMM1, IMM2) \ 89 | ((struct bpf_insn) { \ 90 | .code = BPF_LD | BPF_DW | BPF_IMM, \ 91 | .dst_reg = DST, \ 92 | .src_reg = SRC, \ 93 | .off = OFF1, \ 94 | .imm = IMM1 }), \ 95 | ((struct bpf_insn) { \ 96 | .code = 0, \ 97 | .dst_reg = 0, \ 98 | .src_reg = 0, \ 99 | .off = OFF2, \ 100 | .imm = IMM2 }) 101 | 102 | #define BPF_LD_MAP_FD(DST, MAP_FD) \ 103 | BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_FD, 0, 0, \ 104 | MAP_FD, 0) 105 | 106 | #define BPF_LD_MAP_VALUE(DST, MAP_FD, VALUE_OFF) \ 107 | BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_VALUE, 0, 0, \ 108 | MAP_FD, VALUE_OFF) 109 | 110 | #define BPF_JMP_IMM(OP, DST, IMM, OFF) \ 111 | ((struct bpf_insn) { \ 112 | .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ 113 | .dst_reg = DST, \ 114 | .src_reg = 0, \ 115 | .off = OFF, \ 116 | .imm = IMM }) 117 | 118 | #define BPF_JMP32_IMM(OP, DST, IMM, OFF) \ 119 | ((struct bpf_insn) { \ 120 | .code = BPF_JMP32 | BPF_OP(OP) | BPF_K, \ 121 | .dst_reg = DST, \ 122 | .src_reg = 0, \ 123 | .off = OFF, \ 124 | .imm = IMM }) 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/kernel.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_KERNEL_H 4 | #define __LINUX_KERNEL_H 5 | 6 | #ifndef offsetof 7 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 8 | #endif 9 | 10 | #ifndef container_of 11 | #define container_of(ptr, type, member) ({ \ 12 | const typeof(((type *)0)->member) * __mptr = (ptr); \ 13 | (type *)((char *)__mptr - offsetof(type, member)); }) 14 | #endif 15 | 16 | #ifndef max 17 | #define max(x, y) ({ \ 18 | typeof(x) _max1 = (x); \ 19 | typeof(y) _max2 = (y); \ 20 | (void) (&_max1 == &_max2); \ 21 | _max1 > _max2 ? _max1 : _max2; }) 22 | #endif 23 | 24 | #ifndef min 25 | #define min(x, y) ({ \ 26 | typeof(x) _min1 = (x); \ 27 | typeof(y) _min2 = (y); \ 28 | (void) (&_min1 == &_min2); \ 29 | _min1 < _min2 ? _min1 : _min2; }) 30 | #endif 31 | 32 | #ifndef roundup 33 | #define roundup(x, y) ( \ 34 | { \ 35 | const typeof(y) __y = y; \ 36 | (((x) + (__y - 1)) / __y) * __y; \ 37 | } \ 38 | ) 39 | #endif 40 | 41 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 42 | #define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/list.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_LIST_H 4 | #define __LINUX_LIST_H 5 | 6 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 7 | #define LIST_HEAD(name) \ 8 | struct list_head name = LIST_HEAD_INIT(name) 9 | 10 | #define POISON_POINTER_DELTA 0 11 | #define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) 12 | #define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) 13 | 14 | 15 | static inline void INIT_LIST_HEAD(struct list_head *list) 16 | { 17 | list->next = list; 18 | list->prev = list; 19 | } 20 | 21 | static inline void __list_add(struct list_head *new, 22 | struct list_head *prev, 23 | struct list_head *next) 24 | { 25 | next->prev = new; 26 | new->next = next; 27 | new->prev = prev; 28 | prev->next = new; 29 | } 30 | 31 | /** 32 | * list_add - add a new entry 33 | * @new: new entry to be added 34 | * @head: list head to add it after 35 | * 36 | * Insert a new entry after the specified head. 37 | * This is good for implementing stacks. 38 | */ 39 | static inline void list_add(struct list_head *new, struct list_head *head) 40 | { 41 | __list_add(new, head, head->next); 42 | } 43 | 44 | /* 45 | * Delete a list entry by making the prev/next entries 46 | * point to each other. 47 | * 48 | * This is only for internal list manipulation where we know 49 | * the prev/next entries already! 50 | */ 51 | static inline void __list_del(struct list_head * prev, struct list_head * next) 52 | { 53 | next->prev = prev; 54 | prev->next = next; 55 | } 56 | 57 | /** 58 | * list_del - deletes entry from list. 59 | * @entry: the element to delete from the list. 60 | * Note: list_empty() on entry does not return true after this, the entry is 61 | * in an undefined state. 62 | */ 63 | static inline void __list_del_entry(struct list_head *entry) 64 | { 65 | __list_del(entry->prev, entry->next); 66 | } 67 | 68 | static inline void list_del(struct list_head *entry) 69 | { 70 | __list_del(entry->prev, entry->next); 71 | entry->next = LIST_POISON1; 72 | entry->prev = LIST_POISON2; 73 | } 74 | 75 | static inline int list_empty(const struct list_head *head) 76 | { 77 | return head->next == head; 78 | } 79 | 80 | #define list_entry(ptr, type, member) \ 81 | container_of(ptr, type, member) 82 | #define list_first_entry(ptr, type, member) \ 83 | list_entry((ptr)->next, type, member) 84 | #define list_next_entry(pos, member) \ 85 | list_entry((pos)->member.next, typeof(*(pos)), member) 86 | #define list_for_each_entry(pos, head, member) \ 87 | for (pos = list_first_entry(head, typeof(*pos), member); \ 88 | &pos->member != (head); \ 89 | pos = list_next_entry(pos, member)) 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/overflow.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_OVERFLOW_H 4 | #define __LINUX_OVERFLOW_H 5 | 6 | #define is_signed_type(type) (((type)(-1)) < (type)1) 7 | #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) 8 | #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) 9 | #define type_min(T) ((T)((T)-type_max(T)-(T)1)) 10 | 11 | #ifndef unlikely 12 | #define unlikely(x) __builtin_expect(!!(x), 0) 13 | #endif 14 | 15 | #ifdef __GNUC__ 16 | #define GCC_VERSION (__GNUC__ * 10000 \ 17 | + __GNUC_MINOR__ * 100 \ 18 | + __GNUC_PATCHLEVEL__) 19 | #if GCC_VERSION >= 50100 20 | #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 21 | #endif 22 | #endif 23 | 24 | #ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 25 | 26 | #define check_mul_overflow(a, b, d) ({ \ 27 | typeof(a) __a = (a); \ 28 | typeof(b) __b = (b); \ 29 | typeof(d) __d = (d); \ 30 | (void) (&__a == &__b); \ 31 | (void) (&__a == __d); \ 32 | __builtin_mul_overflow(__a, __b, __d); \ 33 | }) 34 | 35 | #else 36 | 37 | /* 38 | * If one of a or b is a compile-time constant, this avoids a division. 39 | */ 40 | #define __unsigned_mul_overflow(a, b, d) ({ \ 41 | typeof(a) __a = (a); \ 42 | typeof(b) __b = (b); \ 43 | typeof(d) __d = (d); \ 44 | (void) (&__a == &__b); \ 45 | (void) (&__a == __d); \ 46 | *__d = __a * __b; \ 47 | __builtin_constant_p(__b) ? \ 48 | __b > 0 && __a > type_max(typeof(__a)) / __b : \ 49 | __a > 0 && __b > type_max(typeof(__b)) / __a; \ 50 | }) 51 | 52 | /* 53 | * Signed multiplication is rather hard. gcc always follows C99, so 54 | * division is truncated towards 0. This means that we can write the 55 | * overflow check like this: 56 | * 57 | * (a > 0 && (b > MAX/a || b < MIN/a)) || 58 | * (a < -1 && (b > MIN/a || b < MAX/a) || 59 | * (a == -1 && b == MIN) 60 | * 61 | * The redundant casts of -1 are to silence an annoying -Wtype-limits 62 | * (included in -Wextra) warning: When the type is u8 or u16, the 63 | * __b_c_e in check_mul_overflow obviously selects 64 | * __unsigned_mul_overflow, but unfortunately gcc still parses this 65 | * code and warns about the limited range of __b. 66 | */ 67 | 68 | #define __signed_mul_overflow(a, b, d) ({ \ 69 | typeof(a) __a = (a); \ 70 | typeof(b) __b = (b); \ 71 | typeof(d) __d = (d); \ 72 | typeof(a) __tmax = type_max(typeof(a)); \ 73 | typeof(a) __tmin = type_min(typeof(a)); \ 74 | (void) (&__a == &__b); \ 75 | (void) (&__a == __d); \ 76 | *__d = (__u64)__a * (__u64)__b; \ 77 | (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \ 78 | (__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \ 79 | (__b == (typeof(__b))-1 && __a == __tmin); \ 80 | }) 81 | 82 | #define check_mul_overflow(a, b, d) \ 83 | __builtin_choose_expr(is_signed_type(typeof(a)), \ 84 | __signed_mul_overflow(a, b, d), \ 85 | __unsigned_mul_overflow(a, b, d)) 86 | 87 | 88 | #endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */ 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/ring_buffer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef _TOOLS_LINUX_RING_BUFFER_H_ 3 | #define _TOOLS_LINUX_RING_BUFFER_H_ 4 | 5 | #include 6 | 7 | static inline __u64 ring_buffer_read_head(struct perf_event_mmap_page *base) 8 | { 9 | return smp_load_acquire(&base->data_head); 10 | } 11 | 12 | static inline void ring_buffer_write_tail(struct perf_event_mmap_page *base, 13 | __u64 tail) 14 | { 15 | smp_store_release(&base->data_tail, tail); 16 | } 17 | 18 | #endif /* _TOOLS_LINUX_RING_BUFFER_H_ */ 19 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/linux/types.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __LINUX_TYPES_H 4 | #define __LINUX_TYPES_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #define __bitwise__ 14 | #define __bitwise __bitwise__ 15 | 16 | typedef __u16 __bitwise __le16; 17 | typedef __u16 __bitwise __be16; 18 | typedef __u32 __bitwise __le32; 19 | typedef __u32 __bitwise __be32; 20 | typedef __u64 __bitwise __le64; 21 | typedef __u64 __bitwise __be64; 22 | 23 | #ifndef __aligned_u64 24 | # define __aligned_u64 __u64 __attribute__((aligned(8))) 25 | #endif 26 | 27 | struct list_head { 28 | struct list_head *next, *prev; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/uapi/linux/bpf_common.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | #ifndef _UAPI__LINUX_BPF_COMMON_H__ 3 | #define _UAPI__LINUX_BPF_COMMON_H__ 4 | 5 | /* Instruction classes */ 6 | #define BPF_CLASS(code) ((code) & 0x07) 7 | #define BPF_LD 0x00 8 | #define BPF_LDX 0x01 9 | #define BPF_ST 0x02 10 | #define BPF_STX 0x03 11 | #define BPF_ALU 0x04 12 | #define BPF_JMP 0x05 13 | #define BPF_RET 0x06 14 | #define BPF_MISC 0x07 15 | 16 | /* ld/ldx fields */ 17 | #define BPF_SIZE(code) ((code) & 0x18) 18 | #define BPF_W 0x00 /* 32-bit */ 19 | #define BPF_H 0x08 /* 16-bit */ 20 | #define BPF_B 0x10 /* 8-bit */ 21 | /* eBPF BPF_DW 0x18 64-bit */ 22 | #define BPF_MODE(code) ((code) & 0xe0) 23 | #define BPF_IMM 0x00 24 | #define BPF_ABS 0x20 25 | #define BPF_IND 0x40 26 | #define BPF_MEM 0x60 27 | #define BPF_LEN 0x80 28 | #define BPF_MSH 0xa0 29 | 30 | /* alu/jmp fields */ 31 | #define BPF_OP(code) ((code) & 0xf0) 32 | #define BPF_ADD 0x00 33 | #define BPF_SUB 0x10 34 | #define BPF_MUL 0x20 35 | #define BPF_DIV 0x30 36 | #define BPF_OR 0x40 37 | #define BPF_AND 0x50 38 | #define BPF_LSH 0x60 39 | #define BPF_RSH 0x70 40 | #define BPF_NEG 0x80 41 | #define BPF_MOD 0x90 42 | #define BPF_XOR 0xa0 43 | 44 | #define BPF_JA 0x00 45 | #define BPF_JEQ 0x10 46 | #define BPF_JGT 0x20 47 | #define BPF_JGE 0x30 48 | #define BPF_JSET 0x40 49 | #define BPF_SRC(code) ((code) & 0x08) 50 | #define BPF_K 0x00 51 | #define BPF_X 0x08 52 | 53 | #ifndef BPF_MAXINSNS 54 | #define BPF_MAXINSNS 4096 55 | #endif 56 | 57 | #endif /* _UAPI__LINUX_BPF_COMMON_H__ */ 58 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/uapi/linux/btf.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* Copyright (c) 2018 Facebook */ 3 | #ifndef _UAPI__LINUX_BTF_H__ 4 | #define _UAPI__LINUX_BTF_H__ 5 | 6 | #include 7 | 8 | #define BTF_MAGIC 0xeB9F 9 | #define BTF_VERSION 1 10 | 11 | struct btf_header { 12 | __u16 magic; 13 | __u8 version; 14 | __u8 flags; 15 | __u32 hdr_len; 16 | 17 | /* All offsets are in bytes relative to the end of this header */ 18 | __u32 type_off; /* offset of type section */ 19 | __u32 type_len; /* length of type section */ 20 | __u32 str_off; /* offset of string section */ 21 | __u32 str_len; /* length of string section */ 22 | }; 23 | 24 | /* Max # of type identifier */ 25 | #define BTF_MAX_TYPE 0x000fffff 26 | /* Max offset into the string section */ 27 | #define BTF_MAX_NAME_OFFSET 0x00ffffff 28 | /* Max # of struct/union/enum members or func args */ 29 | #define BTF_MAX_VLEN 0xffff 30 | 31 | struct btf_type { 32 | __u32 name_off; 33 | /* "info" bits arrangement 34 | * bits 0-15: vlen (e.g. # of struct's members) 35 | * bits 16-23: unused 36 | * bits 24-27: kind (e.g. int, ptr, array...etc) 37 | * bits 28-30: unused 38 | * bit 31: kind_flag, currently used by 39 | * struct, union and fwd 40 | */ 41 | __u32 info; 42 | /* "size" is used by INT, ENUM, STRUCT, UNION and DATASEC. 43 | * "size" tells the size of the type it is describing. 44 | * 45 | * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, 46 | * FUNC, FUNC_PROTO and VAR. 47 | * "type" is a type_id referring to another type. 48 | */ 49 | union { 50 | __u32 size; 51 | __u32 type; 52 | }; 53 | }; 54 | 55 | #define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f) 56 | #define BTF_INFO_VLEN(info) ((info) & 0xffff) 57 | #define BTF_INFO_KFLAG(info) ((info) >> 31) 58 | 59 | #define BTF_KIND_UNKN 0 /* Unknown */ 60 | #define BTF_KIND_INT 1 /* Integer */ 61 | #define BTF_KIND_PTR 2 /* Pointer */ 62 | #define BTF_KIND_ARRAY 3 /* Array */ 63 | #define BTF_KIND_STRUCT 4 /* Struct */ 64 | #define BTF_KIND_UNION 5 /* Union */ 65 | #define BTF_KIND_ENUM 6 /* Enumeration */ 66 | #define BTF_KIND_FWD 7 /* Forward */ 67 | #define BTF_KIND_TYPEDEF 8 /* Typedef */ 68 | #define BTF_KIND_VOLATILE 9 /* Volatile */ 69 | #define BTF_KIND_CONST 10 /* Const */ 70 | #define BTF_KIND_RESTRICT 11 /* Restrict */ 71 | #define BTF_KIND_FUNC 12 /* Function */ 72 | #define BTF_KIND_FUNC_PROTO 13 /* Function Proto */ 73 | #define BTF_KIND_VAR 14 /* Variable */ 74 | #define BTF_KIND_DATASEC 15 /* Section */ 75 | #define BTF_KIND_MAX BTF_KIND_DATASEC 76 | #define NR_BTF_KINDS (BTF_KIND_MAX + 1) 77 | 78 | /* For some specific BTF_KIND, "struct btf_type" is immediately 79 | * followed by extra data. 80 | */ 81 | 82 | /* BTF_KIND_INT is followed by a u32 and the following 83 | * is the 32 bits arrangement: 84 | */ 85 | #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) 86 | #define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16) 87 | #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff) 88 | 89 | /* Attributes stored in the BTF_INT_ENCODING */ 90 | #define BTF_INT_SIGNED (1 << 0) 91 | #define BTF_INT_CHAR (1 << 1) 92 | #define BTF_INT_BOOL (1 << 2) 93 | 94 | /* BTF_KIND_ENUM is followed by multiple "struct btf_enum". 95 | * The exact number of btf_enum is stored in the vlen (of the 96 | * info in "struct btf_type"). 97 | */ 98 | struct btf_enum { 99 | __u32 name_off; 100 | __s32 val; 101 | }; 102 | 103 | /* BTF_KIND_ARRAY is followed by one "struct btf_array" */ 104 | struct btf_array { 105 | __u32 type; 106 | __u32 index_type; 107 | __u32 nelems; 108 | }; 109 | 110 | /* BTF_KIND_STRUCT and BTF_KIND_UNION are followed 111 | * by multiple "struct btf_member". The exact number 112 | * of btf_member is stored in the vlen (of the info in 113 | * "struct btf_type"). 114 | */ 115 | struct btf_member { 116 | __u32 name_off; 117 | __u32 type; 118 | /* If the type info kind_flag is set, the btf_member offset 119 | * contains both member bitfield size and bit offset. The 120 | * bitfield size is set for bitfield members. If the type 121 | * info kind_flag is not set, the offset contains only bit 122 | * offset. 123 | */ 124 | __u32 offset; 125 | }; 126 | 127 | /* If the struct/union type info kind_flag is set, the 128 | * following two macros are used to access bitfield_size 129 | * and bit_offset from btf_member.offset. 130 | */ 131 | #define BTF_MEMBER_BITFIELD_SIZE(val) ((val) >> 24) 132 | #define BTF_MEMBER_BIT_OFFSET(val) ((val) & 0xffffff) 133 | 134 | /* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param". 135 | * The exact number of btf_param is stored in the vlen (of the 136 | * info in "struct btf_type"). 137 | */ 138 | struct btf_param { 139 | __u32 name_off; 140 | __u32 type; 141 | }; 142 | 143 | enum { 144 | BTF_VAR_STATIC = 0, 145 | BTF_VAR_GLOBAL_ALLOCATED = 1, 146 | BTF_VAR_GLOBAL_EXTERN = 2, 147 | }; 148 | 149 | enum btf_func_linkage { 150 | BTF_FUNC_STATIC = 0, 151 | BTF_FUNC_GLOBAL = 1, 152 | BTF_FUNC_EXTERN = 2, 153 | }; 154 | 155 | /* BTF_KIND_VAR is followed by a single "struct btf_var" to describe 156 | * additional information related to the variable such as its linkage. 157 | */ 158 | struct btf_var { 159 | __u32 linkage; 160 | }; 161 | 162 | /* BTF_KIND_DATASEC is followed by multiple "struct btf_var_secinfo" 163 | * to describe all BTF_KIND_VAR types it contains along with it's 164 | * in-section offset as well as size. 165 | */ 166 | struct btf_var_secinfo { 167 | __u32 type; 168 | __u32 offset; 169 | __u32 size; 170 | }; 171 | 172 | #endif /* _UAPI__LINUX_BTF_H__ */ 173 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/include/uapi/linux/if_xdp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * if_xdp: XDP socket user-space interface 4 | * Copyright(c) 2018 Intel Corporation. 5 | * 6 | * Author(s): Björn Töpel 7 | * Magnus Karlsson 8 | */ 9 | 10 | #ifndef _LINUX_IF_XDP_H 11 | #define _LINUX_IF_XDP_H 12 | 13 | #include 14 | 15 | /* Options for the sxdp_flags field */ 16 | #define XDP_SHARED_UMEM (1 << 0) 17 | #define XDP_COPY (1 << 1) /* Force copy-mode */ 18 | #define XDP_ZEROCOPY (1 << 2) /* Force zero-copy mode */ 19 | /* If this option is set, the driver might go sleep and in that case 20 | * the XDP_RING_NEED_WAKEUP flag in the fill and/or Tx rings will be 21 | * set. If it is set, the application need to explicitly wake up the 22 | * driver with a poll() (Rx and Tx) or sendto() (Tx only). If you are 23 | * running the driver and the application on the same core, you should 24 | * use this option so that the kernel will yield to the user space 25 | * application. 26 | */ 27 | #define XDP_USE_NEED_WAKEUP (1 << 3) 28 | 29 | /* Flags for xsk_umem_config flags */ 30 | #define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0) 31 | 32 | struct sockaddr_xdp { 33 | __u16 sxdp_family; 34 | __u16 sxdp_flags; 35 | __u32 sxdp_ifindex; 36 | __u32 sxdp_queue_id; 37 | __u32 sxdp_shared_umem_fd; 38 | }; 39 | 40 | /* XDP_RING flags */ 41 | #define XDP_RING_NEED_WAKEUP (1 << 0) 42 | 43 | struct xdp_ring_offset { 44 | __u64 producer; 45 | __u64 consumer; 46 | __u64 desc; 47 | __u64 flags; 48 | }; 49 | 50 | struct xdp_mmap_offsets { 51 | struct xdp_ring_offset rx; 52 | struct xdp_ring_offset tx; 53 | struct xdp_ring_offset fr; /* Fill */ 54 | struct xdp_ring_offset cr; /* Completion */ 55 | }; 56 | 57 | /* XDP socket options */ 58 | #define XDP_MMAP_OFFSETS 1 59 | #define XDP_RX_RING 2 60 | #define XDP_TX_RING 3 61 | #define XDP_UMEM_REG 4 62 | #define XDP_UMEM_FILL_RING 5 63 | #define XDP_UMEM_COMPLETION_RING 6 64 | #define XDP_STATISTICS 7 65 | #define XDP_OPTIONS 8 66 | 67 | struct xdp_umem_reg { 68 | __u64 addr; /* Start of packet data area */ 69 | __u64 len; /* Length of packet data area */ 70 | __u32 chunk_size; 71 | __u32 headroom; 72 | __u32 flags; 73 | }; 74 | 75 | struct xdp_statistics { 76 | __u64 rx_dropped; /* Dropped for other reasons */ 77 | __u64 rx_invalid_descs; /* Dropped due to invalid descriptor */ 78 | __u64 tx_invalid_descs; /* Dropped due to invalid descriptor */ 79 | __u64 rx_ring_full; /* Dropped due to rx ring being full */ 80 | __u64 rx_fill_ring_empty_descs; /* Failed to retrieve item from fill ring */ 81 | __u64 tx_ring_empty_descs; /* Failed to retrieve item from tx ring */ 82 | }; 83 | 84 | struct xdp_options { 85 | __u32 flags; 86 | }; 87 | 88 | /* Flags for the flags field of struct xdp_options */ 89 | #define XDP_OPTIONS_ZEROCOPY (1 << 0) 90 | 91 | /* Pgoff for mmaping the rings */ 92 | #define XDP_PGOFF_RX_RING 0 93 | #define XDP_PGOFF_TX_RING 0x80000000 94 | #define XDP_UMEM_PGOFF_FILL_RING 0x100000000ULL 95 | #define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000ULL 96 | 97 | /* Masks for unaligned chunks mode */ 98 | #define XSK_UNALIGNED_BUF_OFFSET_SHIFT 48 99 | #define XSK_UNALIGNED_BUF_ADDR_MASK \ 100 | ((1ULL << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1) 101 | 102 | /* Rx/Tx descriptor */ 103 | struct xdp_desc { 104 | __u64 addr; 105 | __u32 len; 106 | __u32 options; 107 | }; 108 | 109 | /* UMEM descriptor is __u64 */ 110 | 111 | #endif /* _LINUX_IF_XDP_H */ 112 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/scripts/coverity.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Taken from: https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh 3 | # Local changes are annotated with "#[local]" 4 | 5 | set -e 6 | 7 | # Environment check 8 | echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m" 9 | [ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1 10 | [ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1 11 | [ -z "$COVERITY_SCAN_BRANCH_PATTERN" ] && echo "ERROR: COVERITY_SCAN_BRANCH_PATTERN must be set" && exit 1 12 | [ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1 13 | [ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1 14 | 15 | PLATFORM=`uname` 16 | #[local] Use /var/tmp for TOOL_ARCHIVE and TOOL_BASE, as on certain systems 17 | # /tmp is tmpfs and is sometimes too small to handle all necessary tooling 18 | TOOL_ARCHIVE=/var//tmp/cov-analysis-${PLATFORM}.tgz 19 | TOOL_URL=https://scan.coverity.com/download/${PLATFORM} 20 | TOOL_BASE=/var/tmp/coverity-scan-analysis 21 | UPLOAD_URL="https://scan.coverity.com/builds" 22 | SCAN_URL="https://scan.coverity.com" 23 | 24 | # Do not run on pull requests 25 | if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then 26 | echo -e "\033[33;1mINFO: Skipping Coverity Analysis: branch is a pull request.\033[0m" 27 | exit 0 28 | fi 29 | 30 | # Verify this branch should run 31 | IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_BRANCH_PATTERN\\z/ ? 1 : 0"` 32 | if [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then 33 | echo -e "\033[33;1mCoverity Scan configured to run on branch ${TRAVIS_BRANCH}\033[0m" 34 | else 35 | echo -e "\033[33;1mCoverity Scan NOT configured to run on branch ${TRAVIS_BRANCH}\033[0m" 36 | exit 1 37 | fi 38 | 39 | # Verify upload is permitted 40 | AUTH_RES=`curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted` 41 | if [ "$AUTH_RES" = "Access denied" ]; then 42 | echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m" 43 | exit 1 44 | else 45 | AUTH=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']"` 46 | if [ "$AUTH" = "true" ]; then 47 | echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m" 48 | else 49 | WHEN=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']"` 50 | echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m" 51 | exit 0 52 | fi 53 | fi 54 | 55 | if [ ! -d $TOOL_BASE ]; then 56 | # Download Coverity Scan Analysis Tool 57 | if [ ! -e $TOOL_ARCHIVE ]; then 58 | echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m" 59 | wget -nv -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" 60 | fi 61 | 62 | # Extract Coverity Scan Analysis Tool 63 | echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m" 64 | mkdir -p $TOOL_BASE 65 | pushd $TOOL_BASE 66 | tar xzf $TOOL_ARCHIVE 67 | popd 68 | fi 69 | 70 | TOOL_DIR=`find $TOOL_BASE -type d -name 'cov-analysis*'` 71 | export PATH=$TOOL_DIR/bin:$PATH 72 | 73 | # Build 74 | echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m" 75 | COV_BUILD_OPTIONS="" 76 | #COV_BUILD_OPTIONS="--return-emit-failures 8 --parse-error-threshold 85" 77 | RESULTS_DIR="cov-int" 78 | eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}" 79 | COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $COV_BUILD_OPTIONS $COVERITY_SCAN_BUILD_COMMAND 80 | cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt 2>&1 81 | 82 | # Upload results 83 | echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m" 84 | RESULTS_ARCHIVE=analysis-results.tgz 85 | tar czf $RESULTS_ARCHIVE $RESULTS_DIR 86 | SHA=`git rev-parse --short HEAD` 87 | 88 | echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m" 89 | response=$(curl \ 90 | --silent --write-out "\n%{http_code}\n" \ 91 | --form project=$COVERITY_SCAN_PROJECT_NAME \ 92 | --form token=$COVERITY_SCAN_TOKEN \ 93 | --form email=$COVERITY_SCAN_NOTIFICATION_EMAIL \ 94 | --form file=@$RESULTS_ARCHIVE \ 95 | --form version=$SHA \ 96 | --form description="Travis CI build" \ 97 | $UPLOAD_URL) 98 | status_code=$(echo "$response" | sed -n '$p') 99 | #[local] Coverity used to return 201 on success, but it's 200 now 100 | # See https://github.com/systemd/systemd/blob/master/tools/coverity.sh#L145 101 | if [ "$status_code" != "200" ]; then 102 | TEXT=$(echo "$response" | sed '$d') 103 | echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m" 104 | exit 1 105 | fi 106 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | /libbpf.pc 4 | /libbpf.so* 5 | /staticobjs 6 | /sharedobjs 7 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | 3 | ifeq ($(V),1) 4 | Q = 5 | msg = 6 | else 7 | Q = @ 8 | msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; 9 | endif 10 | 11 | LIBBPF_VERSION := $(shell \ 12 | grep -oE '^LIBBPF_([0-9.]+)' libbpf.map | \ 13 | sort -rV | head -n1 | cut -d'_' -f2) 14 | LIBBPF_MAJOR_VERSION := $(firstword $(subst ., ,$(LIBBPF_VERSION))) 15 | 16 | TOPDIR = .. 17 | 18 | INCLUDES := -I. -I$(TOPDIR)/include -I$(TOPDIR)/include/uapi 19 | ALL_CFLAGS := $(INCLUDES) 20 | 21 | SHARED_CFLAGS += -fPIC -fvisibility=hidden -DSHARED 22 | 23 | CFLAGS ?= -g -O2 -Werror -Wall 24 | ALL_CFLAGS += $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 25 | ALL_LDFLAGS += $(LDFLAGS) 26 | ifdef NO_PKG_CONFIG 27 | ALL_LDFLAGS += -lelf -lz 28 | else 29 | PKG_CONFIG ?= pkg-config 30 | ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf zlib) 31 | ALL_LDFLAGS += $(shell $(PKG_CONFIG) --libs libelf zlib) 32 | endif 33 | 34 | OBJDIR ?= . 35 | SHARED_OBJDIR := $(OBJDIR)/sharedobjs 36 | STATIC_OBJDIR := $(OBJDIR)/staticobjs 37 | OBJS := bpf.o btf.o libbpf.o libbpf_errno.o netlink.o \ 38 | nlattr.o str_error.o libbpf_probes.o bpf_prog_linfo.o xsk.o \ 39 | btf_dump.o hashmap.o ringbuf.o 40 | SHARED_OBJS := $(addprefix $(SHARED_OBJDIR)/,$(OBJS)) 41 | STATIC_OBJS := $(addprefix $(STATIC_OBJDIR)/,$(OBJS)) 42 | 43 | STATIC_LIBS := $(OBJDIR)/libbpf.a 44 | ifndef BUILD_STATIC_ONLY 45 | SHARED_LIBS := $(OBJDIR)/libbpf.so \ 46 | $(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION) \ 47 | $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION) 48 | VERSION_SCRIPT := libbpf.map 49 | endif 50 | 51 | HEADERS := bpf.h libbpf.h btf.h xsk.h libbpf_util.h \ 52 | bpf_helpers.h bpf_helper_defs.h bpf_tracing.h \ 53 | bpf_endian.h bpf_core_read.h libbpf_common.h 54 | UAPI_HEADERS := $(addprefix $(TOPDIR)/include/uapi/linux/,\ 55 | bpf.h bpf_common.h btf.h) 56 | 57 | PC_FILE := $(OBJDIR)/libbpf.pc 58 | 59 | INSTALL = install 60 | 61 | DESTDIR ?= 62 | 63 | ifeq ($(shell uname -m),x86_64) 64 | LIBSUBDIR := lib64 65 | else 66 | LIBSUBDIR := lib 67 | endif 68 | 69 | # By default let the pc file itself use ${prefix} in includedir/libdir so that 70 | # the prefix can be overridden at runtime (eg: --define-prefix) 71 | ifndef LIBDIR 72 | LIBDIR_PC := $$\{prefix\}/$(LIBSUBDIR) 73 | else 74 | LIBDIR_PC := $(LIBDIR) 75 | endif 76 | PREFIX ?= /usr 77 | LIBDIR ?= $(PREFIX)/$(LIBSUBDIR) 78 | INCLUDEDIR ?= $(PREFIX)/include 79 | UAPIDIR ?= $(PREFIX)/include 80 | 81 | TAGS_PROG := $(if $(shell which etags 2>/dev/null),etags,ctags) 82 | 83 | all: $(STATIC_LIBS) $(SHARED_LIBS) $(PC_FILE) 84 | 85 | $(OBJDIR)/libbpf.a: $(STATIC_OBJS) 86 | $(call msg,AR,$@) 87 | $(Q)$(AR) rcs $@ $^ 88 | 89 | $(OBJDIR)/libbpf.so: $(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION) 90 | $(Q)ln -sf $(^F) $@ 91 | 92 | $(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION): $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION) 93 | $(Q)ln -sf $(^F) $@ 94 | 95 | $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION): $(SHARED_OBJS) 96 | $(call msg,CC,$@) 97 | $(Q)$(CC) -shared -Wl,--version-script=$(VERSION_SCRIPT) \ 98 | -Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \ 99 | $^ $(ALL_LDFLAGS) -o $@ 100 | 101 | $(OBJDIR)/libbpf.pc: 102 | $(Q)sed -e "s|@PREFIX@|$(PREFIX)|" \ 103 | -e "s|@LIBDIR@|$(LIBDIR_PC)|" \ 104 | -e "s|@VERSION@|$(LIBBPF_VERSION)|" \ 105 | < libbpf.pc.template > $@ 106 | 107 | $(STATIC_OBJDIR) $(SHARED_OBJDIR): 108 | $(call msg,MKDIR,$@) 109 | $(Q)mkdir -p $@ 110 | 111 | $(STATIC_OBJDIR)/%.o: %.c | $(STATIC_OBJDIR) 112 | $(call msg,CC,$@) 113 | $(Q)$(CC) $(ALL_CFLAGS) $(CPPFLAGS) -c $< -o $@ 114 | 115 | $(SHARED_OBJDIR)/%.o: %.c | $(SHARED_OBJDIR) 116 | $(call msg,CC,$@) 117 | $(Q)$(CC) $(ALL_CFLAGS) $(SHARED_CFLAGS) $(CPPFLAGS) -c $< -o $@ 118 | 119 | define do_install 120 | $(call msg,INSTALL,$1) 121 | $(Q)if [ ! -d '$(DESTDIR)$2' ]; then \ 122 | $(INSTALL) -d -m 755 '$(DESTDIR)$2'; \ 123 | fi; 124 | $(Q)$(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR)$2' 125 | endef 126 | 127 | # Preserve symlinks at installation. 128 | define do_s_install 129 | $(call msg,INSTALL,$1) 130 | $(Q)if [ ! -d '$(DESTDIR)$2' ]; then \ 131 | $(INSTALL) -d -m 755 '$(DESTDIR)$2'; \ 132 | fi; 133 | $(Q)cp -fR $1 '$(DESTDIR)$2' 134 | endef 135 | 136 | install: all install_headers install_pkgconfig 137 | $(call do_s_install,$(STATIC_LIBS) $(SHARED_LIBS),$(LIBDIR)) 138 | 139 | install_headers: 140 | $(call do_install,$(HEADERS),$(INCLUDEDIR)/bpf,644) 141 | 142 | # UAPI headers can be installed by a different package so they're not installed 143 | # in by install rule. 144 | install_uapi_headers: 145 | $(call do_install,$(UAPI_HEADERS),$(UAPIDIR)/linux,644) 146 | 147 | install_pkgconfig: $(PC_FILE) 148 | $(call do_install,$(PC_FILE),$(LIBDIR)/pkgconfig,644) 149 | 150 | clean: 151 | $(call msg,CLEAN) 152 | $(Q)rm -rf *.o *.a *.so *.so.* *.pc $(SHARED_OBJDIR) $(STATIC_OBJDIR) 153 | 154 | .PHONY: cscope tags 155 | cscope: 156 | $(call msg,CSCOPE) 157 | $(Q)ls *.c *.h > cscope.files 158 | $(Q)cscope -b -q -f cscope.out 159 | 160 | tags: 161 | $(call msg,CTAGS) 162 | $(Q)rm -f TAGS tags 163 | $(Q)ls *.c *.h | xargs $(TAGS_PROG) -a 164 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/bpf_endian.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BPF_ENDIAN__ 3 | #define __BPF_ENDIAN__ 4 | 5 | /* 6 | * Isolate byte #n and put it into byte #m, for __u##b type. 7 | * E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64: 8 | * 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 9 | * 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000 10 | * 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 11 | * 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000 12 | */ 13 | #define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8)) 14 | 15 | #define ___bpf_swab16(x) ((__u16)( \ 16 | ___bpf_mvb(x, 16, 0, 1) | \ 17 | ___bpf_mvb(x, 16, 1, 0))) 18 | 19 | #define ___bpf_swab32(x) ((__u32)( \ 20 | ___bpf_mvb(x, 32, 0, 3) | \ 21 | ___bpf_mvb(x, 32, 1, 2) | \ 22 | ___bpf_mvb(x, 32, 2, 1) | \ 23 | ___bpf_mvb(x, 32, 3, 0))) 24 | 25 | #define ___bpf_swab64(x) ((__u64)( \ 26 | ___bpf_mvb(x, 64, 0, 7) | \ 27 | ___bpf_mvb(x, 64, 1, 6) | \ 28 | ___bpf_mvb(x, 64, 2, 5) | \ 29 | ___bpf_mvb(x, 64, 3, 4) | \ 30 | ___bpf_mvb(x, 64, 4, 3) | \ 31 | ___bpf_mvb(x, 64, 5, 2) | \ 32 | ___bpf_mvb(x, 64, 6, 1) | \ 33 | ___bpf_mvb(x, 64, 7, 0))) 34 | 35 | /* LLVM's BPF target selects the endianness of the CPU 36 | * it compiles on, or the user specifies (bpfel/bpfeb), 37 | * respectively. The used __BYTE_ORDER__ is defined by 38 | * the compiler, we cannot rely on __BYTE_ORDER from 39 | * libc headers, since it doesn't reflect the actual 40 | * requested byte order. 41 | * 42 | * Note, LLVM's BPF target has different __builtin_bswapX() 43 | * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE 44 | * in bpfel and bpfeb case, which means below, that we map 45 | * to cpu_to_be16(). We could use it unconditionally in BPF 46 | * case, but better not rely on it, so that this header here 47 | * can be used from application and BPF program side, which 48 | * use different targets. 49 | */ 50 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 51 | # define __bpf_ntohs(x) __builtin_bswap16(x) 52 | # define __bpf_htons(x) __builtin_bswap16(x) 53 | # define __bpf_constant_ntohs(x) ___bpf_swab16(x) 54 | # define __bpf_constant_htons(x) ___bpf_swab16(x) 55 | # define __bpf_ntohl(x) __builtin_bswap32(x) 56 | # define __bpf_htonl(x) __builtin_bswap32(x) 57 | # define __bpf_constant_ntohl(x) ___bpf_swab32(x) 58 | # define __bpf_constant_htonl(x) ___bpf_swab32(x) 59 | # define __bpf_be64_to_cpu(x) __builtin_bswap64(x) 60 | # define __bpf_cpu_to_be64(x) __builtin_bswap64(x) 61 | # define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x) 62 | # define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x) 63 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 64 | # define __bpf_ntohs(x) (x) 65 | # define __bpf_htons(x) (x) 66 | # define __bpf_constant_ntohs(x) (x) 67 | # define __bpf_constant_htons(x) (x) 68 | # define __bpf_ntohl(x) (x) 69 | # define __bpf_htonl(x) (x) 70 | # define __bpf_constant_ntohl(x) (x) 71 | # define __bpf_constant_htonl(x) (x) 72 | # define __bpf_be64_to_cpu(x) (x) 73 | # define __bpf_cpu_to_be64(x) (x) 74 | # define __bpf_constant_be64_to_cpu(x) (x) 75 | # define __bpf_constant_cpu_to_be64(x) (x) 76 | #else 77 | # error "Fix your compiler's __BYTE_ORDER__?!" 78 | #endif 79 | 80 | #define bpf_htons(x) \ 81 | (__builtin_constant_p(x) ? \ 82 | __bpf_constant_htons(x) : __bpf_htons(x)) 83 | #define bpf_ntohs(x) \ 84 | (__builtin_constant_p(x) ? \ 85 | __bpf_constant_ntohs(x) : __bpf_ntohs(x)) 86 | #define bpf_htonl(x) \ 87 | (__builtin_constant_p(x) ? \ 88 | __bpf_constant_htonl(x) : __bpf_htonl(x)) 89 | #define bpf_ntohl(x) \ 90 | (__builtin_constant_p(x) ? \ 91 | __bpf_constant_ntohl(x) : __bpf_ntohl(x)) 92 | #define bpf_cpu_to_be64(x) \ 93 | (__builtin_constant_p(x) ? \ 94 | __bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x)) 95 | #define bpf_be64_to_cpu(x) \ 96 | (__builtin_constant_p(x) ? \ 97 | __bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x)) 98 | 99 | #endif /* __BPF_ENDIAN__ */ 100 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/bpf_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BPF_HELPERS__ 3 | #define __BPF_HELPERS__ 4 | 5 | /* 6 | * Note that bpf programs need to include either 7 | * vmlinux.h (auto-generated from BTF) or linux/types.h 8 | * in advance since bpf_helper_defs.h uses such types 9 | * as __u64. 10 | */ 11 | #include "bpf_helper_defs.h" 12 | 13 | #define __uint(name, val) int (*name)[val] 14 | #define __type(name, val) typeof(val) *name 15 | #define __array(name, val) typeof(val) *name[] 16 | 17 | /* Helper macro to print out debug messages */ 18 | #define bpf_printk(fmt, ...) \ 19 | ({ \ 20 | char ____fmt[] = fmt; \ 21 | bpf_trace_printk(____fmt, sizeof(____fmt), \ 22 | ##__VA_ARGS__); \ 23 | }) 24 | 25 | /* 26 | * Helper macro to place programs, maps, license in 27 | * different sections in elf_bpf file. Section names 28 | * are interpreted by elf_bpf loader 29 | */ 30 | #define SEC(NAME) __attribute__((section(NAME), used)) 31 | 32 | #ifndef __always_inline 33 | #define __always_inline inline __attribute__((always_inline)) 34 | #endif 35 | #ifndef __noinline 36 | #define __noinline __attribute__((noinline)) 37 | #endif 38 | #ifndef __weak 39 | #define __weak __attribute__((weak)) 40 | #endif 41 | 42 | /* 43 | * Helper macro to manipulate data structures 44 | */ 45 | #ifndef offsetof 46 | #define offsetof(TYPE, MEMBER) ((unsigned long)&((TYPE *)0)->MEMBER) 47 | #endif 48 | #ifndef container_of 49 | #define container_of(ptr, type, member) \ 50 | ({ \ 51 | void *__mptr = (void *)(ptr); \ 52 | ((type *)(__mptr - offsetof(type, member))); \ 53 | }) 54 | #endif 55 | 56 | /* 57 | * Helper macro to throw a compilation error if __bpf_unreachable() gets 58 | * built into the resulting code. This works given BPF back end does not 59 | * implement __builtin_trap(). This is useful to assert that certain paths 60 | * of the program code are never used and hence eliminated by the compiler. 61 | * 62 | * For example, consider a switch statement that covers known cases used by 63 | * the program. __bpf_unreachable() can then reside in the default case. If 64 | * the program gets extended such that a case is not covered in the switch 65 | * statement, then it will throw a build error due to the default case not 66 | * being compiled out. 67 | */ 68 | #ifndef __bpf_unreachable 69 | # define __bpf_unreachable() __builtin_trap() 70 | #endif 71 | 72 | /* 73 | * Helper function to perform a tail call with a constant/immediate map slot. 74 | */ 75 | #if __clang_major__ >= 8 && defined(__bpf__) 76 | static __always_inline void 77 | bpf_tail_call_static(void *ctx, const void *map, const __u32 slot) 78 | { 79 | if (!__builtin_constant_p(slot)) 80 | __bpf_unreachable(); 81 | 82 | /* 83 | * Provide a hard guarantee that LLVM won't optimize setting r2 (map 84 | * pointer) and r3 (constant map index) from _different paths_ ending 85 | * up at the _same_ call insn as otherwise we won't be able to use the 86 | * jmpq/nopl retpoline-free patching by the x86-64 JIT in the kernel 87 | * given they mismatch. See also d2e4c1e6c294 ("bpf: Constant map key 88 | * tracking for prog array pokes") for details on verifier tracking. 89 | * 90 | * Note on clobber list: we need to stay in-line with BPF calling 91 | * convention, so even if we don't end up using r0, r4, r5, we need 92 | * to mark them as clobber so that LLVM doesn't end up using them 93 | * before / after the call. 94 | */ 95 | asm volatile("r1 = %[ctx]\n\t" 96 | "r2 = %[map]\n\t" 97 | "r3 = %[slot]\n\t" 98 | "call 12" 99 | :: [ctx]"r"(ctx), [map]"r"(map), [slot]"i"(slot) 100 | : "r0", "r1", "r2", "r3", "r4", "r5"); 101 | } 102 | #endif 103 | 104 | /* 105 | * Helper structure used by eBPF C program 106 | * to describe BPF map attributes to libbpf loader 107 | */ 108 | struct bpf_map_def { 109 | unsigned int type; 110 | unsigned int key_size; 111 | unsigned int value_size; 112 | unsigned int max_entries; 113 | unsigned int map_flags; 114 | }; 115 | 116 | enum libbpf_pin_type { 117 | LIBBPF_PIN_NONE, 118 | /* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */ 119 | LIBBPF_PIN_BY_NAME, 120 | }; 121 | 122 | enum libbpf_tristate { 123 | TRI_NO = 0, 124 | TRI_YES = 1, 125 | TRI_MODULE = 2, 126 | }; 127 | 128 | #define __kconfig __attribute__((section(".kconfig"))) 129 | #define __ksym __attribute__((section(".ksyms"))) 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/libbpf.pc.template: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | 3 | prefix=@PREFIX@ 4 | libdir=@LIBDIR@ 5 | includedir=${prefix}/include 6 | 7 | Name: libbpf 8 | Description: BPF library 9 | Version: @VERSION@ 10 | Libs: -L${libdir} -lbpf 11 | Requires.private: libelf zlib 12 | Cflags: -I${includedir} 13 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/libbpf_common.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | /* 4 | * Common user-facing libbpf helpers. 5 | * 6 | * Copyright (c) 2019 Facebook 7 | */ 8 | 9 | #ifndef __LIBBPF_LIBBPF_COMMON_H 10 | #define __LIBBPF_LIBBPF_COMMON_H 11 | 12 | #include 13 | 14 | #ifndef LIBBPF_API 15 | #define LIBBPF_API __attribute__((visibility("default"))) 16 | #endif 17 | 18 | #define LIBBPF_DEPRECATED(msg) __attribute__((deprecated(msg))) 19 | 20 | /* Helper macro to declare and initialize libbpf options struct 21 | * 22 | * This dance with uninitialized declaration, followed by memset to zero, 23 | * followed by assignment using compound literal syntax is done to preserve 24 | * ability to use a nice struct field initialization syntax and **hopefully** 25 | * have all the padding bytes initialized to zero. It's not guaranteed though, 26 | * when copying literal, that compiler won't copy garbage in literal's padding 27 | * bytes, but that's the best way I've found and it seems to work in practice. 28 | * 29 | * Macro declares opts struct of given type and name, zero-initializes, 30 | * including any extra padding, it with memset() and then assigns initial 31 | * values provided by users in struct initializer-syntax as varargs. 32 | */ 33 | #define DECLARE_LIBBPF_OPTS(TYPE, NAME, ...) \ 34 | struct TYPE NAME = ({ \ 35 | memset(&NAME, 0, sizeof(struct TYPE)); \ 36 | (struct TYPE) { \ 37 | .sz = sizeof(struct TYPE), \ 38 | __VA_ARGS__ \ 39 | }; \ 40 | }) 41 | 42 | #endif /* __LIBBPF_LIBBPF_COMMON_H */ 43 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/libbpf_errno.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | 3 | /* 4 | * Copyright (C) 2013-2015 Alexei Starovoitov 5 | * Copyright (C) 2015 Wang Nan 6 | * Copyright (C) 2015 Huawei Inc. 7 | * Copyright (C) 2017 Nicira, Inc. 8 | */ 9 | 10 | #undef _GNU_SOURCE 11 | #include 12 | #include 13 | 14 | #include "libbpf.h" 15 | 16 | /* make sure libbpf doesn't use kernel-only integer typedefs */ 17 | #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 18 | 19 | #define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START) 20 | #define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c) 21 | #define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START) 22 | 23 | static const char *libbpf_strerror_table[NR_ERRNO] = { 24 | [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf", 25 | [ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid", 26 | [ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost", 27 | [ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch", 28 | [ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf", 29 | [ERRCODE_OFFSET(RELOC)] = "Relocation failed", 30 | [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading", 31 | [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", 32 | [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", 33 | [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type", 34 | [ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message", 35 | [ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence", 36 | [ERRCODE_OFFSET(NLPARSE)] = "Incorrect netlink message parsing", 37 | }; 38 | 39 | int libbpf_strerror(int err, char *buf, size_t size) 40 | { 41 | if (!buf || !size) 42 | return -1; 43 | 44 | err = err > 0 ? err : -err; 45 | 46 | if (err < __LIBBPF_ERRNO__START) { 47 | int ret; 48 | 49 | ret = strerror_r(err, buf, size); 50 | buf[size - 1] = '\0'; 51 | return ret; 52 | } 53 | 54 | if (err < __LIBBPF_ERRNO__END) { 55 | const char *msg; 56 | 57 | msg = libbpf_strerror_table[ERRNO_OFFSET(err)]; 58 | snprintf(buf, size, "%s", msg); 59 | buf[size - 1] = '\0'; 60 | return 0; 61 | } 62 | 63 | snprintf(buf, size, "Unknown libbpf error %d", err); 64 | buf[size - 1] = '\0'; 65 | return -1; 66 | } 67 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/libbpf_util.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (c) 2019 Facebook */ 3 | 4 | #ifndef __LIBBPF_LIBBPF_UTIL_H 5 | #define __LIBBPF_LIBBPF_UTIL_H 6 | 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /* Use these barrier functions instead of smp_[rw]mb() when they are 14 | * used in a libbpf header file. That way they can be built into the 15 | * application that uses libbpf. 16 | */ 17 | #if defined(__i386__) || defined(__x86_64__) 18 | # define libbpf_smp_rmb() asm volatile("" : : : "memory") 19 | # define libbpf_smp_wmb() asm volatile("" : : : "memory") 20 | # define libbpf_smp_mb() \ 21 | asm volatile("lock; addl $0,-4(%%rsp)" : : : "memory", "cc") 22 | /* Hinders stores to be observed before older loads. */ 23 | # define libbpf_smp_rwmb() asm volatile("" : : : "memory") 24 | #elif defined(__aarch64__) 25 | # define libbpf_smp_rmb() asm volatile("dmb ishld" : : : "memory") 26 | # define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory") 27 | # define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory") 28 | # define libbpf_smp_rwmb() libbpf_smp_mb() 29 | #elif defined(__arm__) 30 | /* These are only valid for armv7 and above */ 31 | # define libbpf_smp_rmb() asm volatile("dmb ish" : : : "memory") 32 | # define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory") 33 | # define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory") 34 | # define libbpf_smp_rwmb() libbpf_smp_mb() 35 | #else 36 | /* Architecture missing native barrier functions. */ 37 | # define libbpf_smp_rmb() __sync_synchronize() 38 | # define libbpf_smp_wmb() __sync_synchronize() 39 | # define libbpf_smp_mb() __sync_synchronize() 40 | # define libbpf_smp_rwmb() __sync_synchronize() 41 | #endif 42 | 43 | #ifdef __cplusplus 44 | } /* extern "C" */ 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/nlattr.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | 3 | /* 4 | * NETLINK Netlink attributes 5 | * 6 | * Copyright (c) 2003-2013 Thomas Graf 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "nlattr.h" 14 | #include "libbpf_internal.h" 15 | 16 | static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = { 17 | [LIBBPF_NLA_U8] = sizeof(uint8_t), 18 | [LIBBPF_NLA_U16] = sizeof(uint16_t), 19 | [LIBBPF_NLA_U32] = sizeof(uint32_t), 20 | [LIBBPF_NLA_U64] = sizeof(uint64_t), 21 | [LIBBPF_NLA_STRING] = 1, 22 | [LIBBPF_NLA_FLAG] = 0, 23 | }; 24 | 25 | static struct nlattr *nla_next(const struct nlattr *nla, int *remaining) 26 | { 27 | int totlen = NLA_ALIGN(nla->nla_len); 28 | 29 | *remaining -= totlen; 30 | return (struct nlattr *) ((char *) nla + totlen); 31 | } 32 | 33 | static int nla_ok(const struct nlattr *nla, int remaining) 34 | { 35 | return remaining >= sizeof(*nla) && 36 | nla->nla_len >= sizeof(*nla) && 37 | nla->nla_len <= remaining; 38 | } 39 | 40 | static int nla_type(const struct nlattr *nla) 41 | { 42 | return nla->nla_type & NLA_TYPE_MASK; 43 | } 44 | 45 | static int validate_nla(struct nlattr *nla, int maxtype, 46 | struct libbpf_nla_policy *policy) 47 | { 48 | struct libbpf_nla_policy *pt; 49 | unsigned int minlen = 0; 50 | int type = nla_type(nla); 51 | 52 | if (type < 0 || type > maxtype) 53 | return 0; 54 | 55 | pt = &policy[type]; 56 | 57 | if (pt->type > LIBBPF_NLA_TYPE_MAX) 58 | return 0; 59 | 60 | if (pt->minlen) 61 | minlen = pt->minlen; 62 | else if (pt->type != LIBBPF_NLA_UNSPEC) 63 | minlen = nla_attr_minlen[pt->type]; 64 | 65 | if (libbpf_nla_len(nla) < minlen) 66 | return -1; 67 | 68 | if (pt->maxlen && libbpf_nla_len(nla) > pt->maxlen) 69 | return -1; 70 | 71 | if (pt->type == LIBBPF_NLA_STRING) { 72 | char *data = libbpf_nla_data(nla); 73 | 74 | if (data[libbpf_nla_len(nla) - 1] != '\0') 75 | return -1; 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | static inline int nlmsg_len(const struct nlmsghdr *nlh) 82 | { 83 | return nlh->nlmsg_len - NLMSG_HDRLEN; 84 | } 85 | 86 | /** 87 | * Create attribute index based on a stream of attributes. 88 | * @arg tb Index array to be filled (maxtype+1 elements). 89 | * @arg maxtype Maximum attribute type expected and accepted. 90 | * @arg head Head of attribute stream. 91 | * @arg len Length of attribute stream. 92 | * @arg policy Attribute validation policy. 93 | * 94 | * Iterates over the stream of attributes and stores a pointer to each 95 | * attribute in the index array using the attribute type as index to 96 | * the array. Attribute with a type greater than the maximum type 97 | * specified will be silently ignored in order to maintain backwards 98 | * compatibility. If \a policy is not NULL, the attribute will be 99 | * validated using the specified policy. 100 | * 101 | * @see nla_validate 102 | * @return 0 on success or a negative error code. 103 | */ 104 | int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, 105 | int len, struct libbpf_nla_policy *policy) 106 | { 107 | struct nlattr *nla; 108 | int rem, err; 109 | 110 | memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 111 | 112 | libbpf_nla_for_each_attr(nla, head, len, rem) { 113 | int type = nla_type(nla); 114 | 115 | if (type > maxtype) 116 | continue; 117 | 118 | if (policy) { 119 | err = validate_nla(nla, maxtype, policy); 120 | if (err < 0) 121 | goto errout; 122 | } 123 | 124 | if (tb[type]) 125 | pr_warn("Attribute of type %#x found multiple times in message, " 126 | "previous attribute is being ignored.\n", type); 127 | 128 | tb[type] = nla; 129 | } 130 | 131 | err = 0; 132 | errout: 133 | return err; 134 | } 135 | 136 | /** 137 | * Create attribute index based on nested attribute 138 | * @arg tb Index array to be filled (maxtype+1 elements). 139 | * @arg maxtype Maximum attribute type expected and accepted. 140 | * @arg nla Nested Attribute. 141 | * @arg policy Attribute validation policy. 142 | * 143 | * Feeds the stream of attributes nested into the specified attribute 144 | * to libbpf_nla_parse(). 145 | * 146 | * @see libbpf_nla_parse 147 | * @return 0 on success or a negative error code. 148 | */ 149 | int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype, 150 | struct nlattr *nla, 151 | struct libbpf_nla_policy *policy) 152 | { 153 | return libbpf_nla_parse(tb, maxtype, libbpf_nla_data(nla), 154 | libbpf_nla_len(nla), policy); 155 | } 156 | 157 | /* dump netlink extended ack error message */ 158 | int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh) 159 | { 160 | struct libbpf_nla_policy extack_policy[NLMSGERR_ATTR_MAX + 1] = { 161 | [NLMSGERR_ATTR_MSG] = { .type = LIBBPF_NLA_STRING }, 162 | [NLMSGERR_ATTR_OFFS] = { .type = LIBBPF_NLA_U32 }, 163 | }; 164 | struct nlattr *tb[NLMSGERR_ATTR_MAX + 1], *attr; 165 | struct nlmsgerr *err; 166 | char *errmsg = NULL; 167 | int hlen, alen; 168 | 169 | /* no TLVs, nothing to do here */ 170 | if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) 171 | return 0; 172 | 173 | err = (struct nlmsgerr *)NLMSG_DATA(nlh); 174 | hlen = sizeof(*err); 175 | 176 | /* if NLM_F_CAPPED is set then the inner err msg was capped */ 177 | if (!(nlh->nlmsg_flags & NLM_F_CAPPED)) 178 | hlen += nlmsg_len(&err->msg); 179 | 180 | attr = (struct nlattr *) ((void *) err + hlen); 181 | alen = nlh->nlmsg_len - hlen; 182 | 183 | if (libbpf_nla_parse(tb, NLMSGERR_ATTR_MAX, attr, alen, 184 | extack_policy) != 0) { 185 | pr_warn("Failed to parse extended error attributes\n"); 186 | return 0; 187 | } 188 | 189 | if (tb[NLMSGERR_ATTR_MSG]) 190 | errmsg = (char *) libbpf_nla_data(tb[NLMSGERR_ATTR_MSG]); 191 | 192 | pr_warn("Kernel error message: %s\n", errmsg); 193 | 194 | return 0; 195 | } 196 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/nlattr.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | /* 4 | * NETLINK Netlink attributes 5 | * 6 | * Copyright (c) 2003-2013 Thomas Graf 7 | */ 8 | 9 | #ifndef __LIBBPF_NLATTR_H 10 | #define __LIBBPF_NLATTR_H 11 | 12 | #include 13 | #include 14 | /* avoid multiple definition of netlink features */ 15 | #define __LINUX_NETLINK_H 16 | 17 | /** 18 | * Standard attribute types to specify validation policy 19 | */ 20 | enum { 21 | LIBBPF_NLA_UNSPEC, /**< Unspecified type, binary data chunk */ 22 | LIBBPF_NLA_U8, /**< 8 bit integer */ 23 | LIBBPF_NLA_U16, /**< 16 bit integer */ 24 | LIBBPF_NLA_U32, /**< 32 bit integer */ 25 | LIBBPF_NLA_U64, /**< 64 bit integer */ 26 | LIBBPF_NLA_STRING, /**< NUL terminated character string */ 27 | LIBBPF_NLA_FLAG, /**< Flag */ 28 | LIBBPF_NLA_MSECS, /**< Micro seconds (64bit) */ 29 | LIBBPF_NLA_NESTED, /**< Nested attributes */ 30 | __LIBBPF_NLA_TYPE_MAX, 31 | }; 32 | 33 | #define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1) 34 | 35 | /** 36 | * @ingroup attr 37 | * Attribute validation policy. 38 | * 39 | * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. 40 | */ 41 | struct libbpf_nla_policy { 42 | /** Type of attribute or LIBBPF_NLA_UNSPEC */ 43 | uint16_t type; 44 | 45 | /** Minimal length of payload required */ 46 | uint16_t minlen; 47 | 48 | /** Maximal length of payload allowed */ 49 | uint16_t maxlen; 50 | }; 51 | 52 | /** 53 | * @ingroup attr 54 | * Iterate over a stream of attributes 55 | * @arg pos loop counter, set to current attribute 56 | * @arg head head of attribute stream 57 | * @arg len length of attribute stream 58 | * @arg rem initialized to len, holds bytes currently remaining in stream 59 | */ 60 | #define libbpf_nla_for_each_attr(pos, head, len, rem) \ 61 | for (pos = head, rem = len; \ 62 | nla_ok(pos, rem); \ 63 | pos = nla_next(pos, &(rem))) 64 | 65 | /** 66 | * libbpf_nla_data - head of payload 67 | * @nla: netlink attribute 68 | */ 69 | static inline void *libbpf_nla_data(const struct nlattr *nla) 70 | { 71 | return (char *) nla + NLA_HDRLEN; 72 | } 73 | 74 | static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla) 75 | { 76 | return *(uint8_t *)libbpf_nla_data(nla); 77 | } 78 | 79 | static inline uint32_t libbpf_nla_getattr_u32(const struct nlattr *nla) 80 | { 81 | return *(uint32_t *)libbpf_nla_data(nla); 82 | } 83 | 84 | static inline const char *libbpf_nla_getattr_str(const struct nlattr *nla) 85 | { 86 | return (const char *)libbpf_nla_data(nla); 87 | } 88 | 89 | /** 90 | * libbpf_nla_len - length of payload 91 | * @nla: netlink attribute 92 | */ 93 | static inline int libbpf_nla_len(const struct nlattr *nla) 94 | { 95 | return nla->nla_len - NLA_HDRLEN; 96 | } 97 | 98 | int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, 99 | int len, struct libbpf_nla_policy *policy); 100 | int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype, 101 | struct nlattr *nla, 102 | struct libbpf_nla_policy *policy); 103 | 104 | int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh); 105 | 106 | #endif /* __LIBBPF_NLATTR_H */ 107 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/str_error.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | #undef _GNU_SOURCE 3 | #include 4 | #include 5 | #include "str_error.h" 6 | 7 | /* make sure libbpf doesn't use kernel-only integer typedefs */ 8 | #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 9 | 10 | /* 11 | * Wrapper to allow for building in non-GNU systems such as Alpine Linux's musl 12 | * libc, while checking strerror_r() return to avoid having to check this in 13 | * all places calling it. 14 | */ 15 | char *libbpf_strerror_r(int err, char *dst, int len) 16 | { 17 | int ret = strerror_r(err < 0 ? -err : err, dst, len); 18 | if (ret) 19 | snprintf(dst, len, "ERROR: strerror_r(%d)=%d", err, ret); 20 | return dst; 21 | } 22 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/src/str_error.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __LIBBPF_STR_ERROR_H 3 | #define __LIBBPF_STR_ERROR_H 4 | 5 | char *libbpf_strerror_r(int err, char *dst, int len); 6 | #endif /* __LIBBPF_STR_ERROR_H */ 7 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/managers/debian.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP}) 4 | DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}" 5 | CONT_NAME="${CONT_NAME:-libbpf-debian-$DEBIAN_RELEASE}" 6 | ENV_VARS="${ENV_VARS:-}" 7 | DOCKER_RUN="${DOCKER_RUN:-docker run}" 8 | REPO_ROOT="${REPO_ROOT:-$PWD}" 9 | ADDITIONAL_DEPS=(clang pkg-config gcc-8) 10 | CFLAGS="-g -O2 -Werror -Wall" 11 | 12 | function info() { 13 | echo -e "\033[33;1m$1\033[0m" 14 | } 15 | 16 | function error() { 17 | echo -e "\033[31;1m$1\033[0m" 18 | } 19 | 20 | function docker_exec() { 21 | docker exec $ENV_VARS -it $CONT_NAME "$@" 22 | } 23 | 24 | set -e 25 | 26 | source "$(dirname $0)/travis_wait.bash" 27 | 28 | for phase in "${PHASES[@]}"; do 29 | case $phase in 30 | SETUP) 31 | info "Setup phase" 32 | info "Using Debian $DEBIAN_RELEASE" 33 | 34 | sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce 35 | docker --version 36 | 37 | docker pull debian:$DEBIAN_RELEASE 38 | info "Starting container $CONT_NAME" 39 | $DOCKER_RUN -v $REPO_ROOT:/build:rw \ 40 | -w /build --privileged=true --name $CONT_NAME \ 41 | -dit --net=host debian:$DEBIAN_RELEASE /bin/bash 42 | docker_exec bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list" 43 | docker_exec apt-get -y update 44 | docker_exec apt-get -y build-dep libelf-dev 45 | docker_exec apt-get -y install libelf-dev 46 | docker_exec apt-get -y install "${ADDITIONAL_DEPS[@]}" 47 | ;; 48 | RUN|RUN_CLANG|RUN_GCC8|RUN_ASAN|RUN_CLANG_ASAN|RUN_GCC8_ASAN) 49 | if [[ "$phase" = *"CLANG"* ]]; then 50 | ENV_VARS="-e CC=clang -e CXX=clang++" 51 | CC="clang" 52 | elif [[ "$phase" = *"GCC8"* ]]; then 53 | ENV_VARS="-e CC=gcc-8 -e CXX=g++-8" 54 | CC="gcc-8" 55 | else 56 | CFLAGS="${CFLAGS} -Wno-stringop-truncation" 57 | fi 58 | if [[ "$phase" = *"ASAN"* ]]; then 59 | CFLAGS="${CFLAGS} -fsanitize=address,undefined" 60 | fi 61 | docker_exec mkdir build install 62 | docker_exec ${CC:-cc} --version 63 | info "build" 64 | docker_exec make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build 65 | info "ldd build/libbpf.so:" 66 | docker_exec ldd build/libbpf.so 67 | if ! docker_exec ldd build/libbpf.so | grep -q libelf; then 68 | error "No reference to libelf.so in libbpf.so!" 69 | exit 1 70 | fi 71 | info "install" 72 | docker_exec make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install 73 | docker_exec rm -rf build install 74 | ;; 75 | CLEANUP) 76 | info "Cleanup phase" 77 | docker stop $CONT_NAME 78 | docker rm -f $CONT_NAME 79 | ;; 80 | *) 81 | echo >&2 "Unknown phase '$phase'" 82 | exit 1 83 | esac 84 | done 85 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/managers/travis_wait.bash: -------------------------------------------------------------------------------- 1 | # This was borrowed from https://github.com/travis-ci/travis-build/tree/master/lib/travis/build/bash 2 | # to get around https://github.com/travis-ci/travis-ci/issues/9979. It should probably be removed 3 | # as soon as Travis CI has started to provide an easy way to export the functions to bash scripts. 4 | 5 | travis_jigger() { 6 | local cmd_pid="${1}" 7 | shift 8 | local timeout="${1}" 9 | shift 10 | local count=0 11 | 12 | echo -e "\\n" 13 | 14 | while [[ "${count}" -lt "${timeout}" ]]; do 15 | count="$((count + 1))" 16 | echo -ne "Still running (${count} of ${timeout}): ${*}\\r" 17 | sleep 60 18 | done 19 | 20 | echo -e "\\n${ANSI_RED}Timeout (${timeout} minutes) reached. Terminating \"${*}\"${ANSI_RESET}\\n" 21 | kill -9 "${cmd_pid}" 22 | } 23 | 24 | travis_wait() { 25 | local timeout="${1}" 26 | 27 | if [[ "${timeout}" =~ ^[0-9]+$ ]]; then 28 | shift 29 | else 30 | timeout=20 31 | fi 32 | 33 | local cmd=("${@}") 34 | local log_file="travis_wait_${$}.log" 35 | 36 | "${cmd[@]}" &>"${log_file}" & 37 | local cmd_pid="${!}" 38 | 39 | travis_jigger "${!}" "${timeout}" "${cmd[@]}" & 40 | local jigger_pid="${!}" 41 | local result 42 | 43 | { 44 | set +e 45 | wait "${cmd_pid}" 2>/dev/null 46 | result="${?}" 47 | ps -p"${jigger_pid}" &>/dev/null && kill "${jigger_pid}" 48 | set -e 49 | } 50 | 51 | if [[ "${result}" -eq 0 ]]; then 52 | echo -e "\\n${ANSI_GREEN}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}" 53 | else 54 | echo -e "\\n${ANSI_RED}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}" 55 | fi 56 | 57 | echo -e "\\n${ANSI_GREEN}Log:${ANSI_RESET}\\n" 58 | cat "${log_file}" 59 | 60 | return "${result}" 61 | } 62 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/managers/ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -x 4 | 5 | RELEASE="bionic" 6 | 7 | echo "deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse" >>/etc/apt/sources.list 8 | 9 | apt-get update 10 | apt-get -y build-dep libelf-dev 11 | apt-get install -y libelf-dev pkg-config 12 | 13 | source "$(dirname $0)/travis_wait.bash" 14 | 15 | cd $REPO_ROOT 16 | 17 | CFLAGS="-g -O2 -Werror -Wall -fsanitize=address,undefined" 18 | mkdir build install 19 | cc --version 20 | make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build 21 | ldd build/libbpf.so 22 | if ! ldd build/libbpf.so | grep -q libelf; then 23 | echo "FAIL: No reference to libelf.so in libbpf.so!" 24 | exit 1 25 | fi 26 | make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install 27 | rm -rf build install 28 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/build_pahole.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | source $(cd $(dirname $0) && pwd)/helpers.sh 6 | 7 | travis_fold start build_pahole "Building pahole" 8 | 9 | CWD=$(pwd) 10 | REPO_PATH=$1 11 | PAHOLE_ORIGIN=https://git.kernel.org/pub/scm/devel/pahole/pahole.git 12 | 13 | mkdir -p ${REPO_PATH} 14 | cd ${REPO_PATH} 15 | git init 16 | git remote add origin ${PAHOLE_ORIGIN} 17 | git fetch origin 18 | git checkout master 19 | 20 | mkdir -p build 21 | cd build 22 | cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -D__LIB=lib .. 23 | make -j$((4*$(nproc))) all 24 | sudo make install 25 | 26 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:/usr/local/lib 27 | ldd $(which pahole) 28 | pahole --version 29 | 30 | travis_fold end build_pahole 31 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/build_selftests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | source $(cd $(dirname $0) && pwd)/helpers.sh 6 | 7 | travis_fold start prepare_selftests "Building selftests" 8 | 9 | LLVM_VER=12 10 | LIBBPF_PATH="${REPO_ROOT}" 11 | REPO_PATH="travis-ci/vmtest/bpf-next" 12 | 13 | PREPARE_SELFTESTS_SCRIPT=${VMTEST_ROOT}/prepare_selftests-${KERNEL}.sh 14 | if [ -f "${PREPARE_SELFTESTS_SCRIPT}" ]; then 15 | (cd "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" && ${PREPARE_SELFTESTS_SCRIPT}) 16 | fi 17 | 18 | if [[ "${KERNEL}" = 'LATEST' ]]; then 19 | VMLINUX_H= 20 | else 21 | VMLINUX_H=${VMTEST_ROOT}/vmlinux.h 22 | fi 23 | 24 | make \ 25 | CLANG=clang-${LLVM_VER} \ 26 | LLC=llc-${LLVM_VER} \ 27 | LLVM_STRIP=llvm-strip-${LLVM_VER} \ 28 | VMLINUX_BTF="${VMLINUX_BTF}" \ 29 | VMLINUX_H=${VMLINUX_H} \ 30 | -C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \ 31 | -j $((2*$(nproc))) 32 | mkdir ${LIBBPF_PATH}/selftests 33 | cp -R "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \ 34 | ${LIBBPF_PATH}/selftests 35 | cd ${LIBBPF_PATH} 36 | rm selftests/bpf/.gitignore 37 | git add selftests 38 | 39 | git add "${VMTEST_ROOT}/configs/blacklist" 40 | 41 | travis_fold end prepare_selftests 42 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/checkout_latest_kernel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | source $(cd $(dirname $0) && pwd)/helpers.sh 6 | 7 | CWD=$(pwd) 8 | LIBBPF_PATH=$(pwd) 9 | REPO_PATH=$1 10 | 11 | BPF_NEXT_ORIGIN=https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git 12 | LINUX_SHA=$(cat ${LIBBPF_PATH}/CHECKPOINT-COMMIT) 13 | SNAPSHOT_URL=https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/snapshot/bpf-next-${LINUX_SHA}.tar.gz 14 | 15 | echo REPO_PATH = ${REPO_PATH} 16 | echo LINUX_SHA = ${LINUX_SHA} 17 | 18 | if [ ! -d "${REPO_PATH}" ]; then 19 | echo 20 | travis_fold start pull_kernel_srcs "Fetching kernel sources" 21 | 22 | mkdir -p $(dirname "${REPO_PATH}") 23 | cd $(dirname "${REPO_PATH}") 24 | # attempt to fetch desired bpf-next repo snapshot 25 | if wget ${SNAPSHOT_URL} && tar xf bpf-next-${LINUX_SHA}.tar.gz ; then 26 | mv bpf-next-${LINUX_SHA} $(basename ${REPO_PATH}) 27 | else 28 | # but fallback to git fetch approach if that fails 29 | mkdir -p $(basename ${REPO_PATH}) 30 | cd $(basename ${REPO_PATH}) 31 | git init 32 | git remote add bpf-next ${BPF_NEXT_ORIGIN} 33 | # try shallow clone first 34 | git fetch --depth 32 bpf-next 35 | # check if desired SHA exists 36 | if ! git cat-file -e ${LINUX_SHA}^{commit} ; then 37 | # if not, fetch all of bpf-next; slow and painful 38 | git fetch bpf-next 39 | fi 40 | git reset --hard ${LINUX_SHA} 41 | fi 42 | 43 | travis_fold end pull_kernel_srcs 44 | fi 45 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/configs/INDEX: -------------------------------------------------------------------------------- 1 | INDEX https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/INDEX 2 | libbpf-vmtest-rootfs-2020.09.27.tar.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/libbpf-vmtest-rootfs-2020.09.27.tar.zst 3 | vmlinux-4.9.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-4.9.0.zst 4 | vmlinux-5.5.0-rc6.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0-rc6.zst 5 | vmlinux-5.5.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0.zst 6 | vmlinuz-5.5.0-rc6 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0-rc6 7 | vmlinuz-5.5.0 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0 8 | vmlinuz-4.9.0 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-4.9.0 9 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0: -------------------------------------------------------------------------------- 1 | # PERMANENTLY DISABLED 2 | align # verifier output format changed 3 | atomics # new atomic operations (v5.12+) 4 | bpf_iter # bpf_iter support is missing 5 | bpf_obj_id # bpf_link support missing for GET_OBJ_INFO, GET_FD_BY_ID, etc 6 | bpf_tcp_ca # STRUCT_OPS is missing 7 | btf_map_in_map # inner map leak fixed in 5.8 8 | btf_skc_cls_ingress # v5.10+ functionality 9 | cg_storage_multi # v5.9+ functionality 10 | cgroup_attach_multi # BPF_F_REPLACE_PROG missing 11 | cgroup_link # LINK_CREATE is missing 12 | cgroup_skb_sk_lookup # bpf_sk_lookup_tcp() helper is missing 13 | cls_redirect # bpf_csum_level() helper is missing 14 | connect_force_port # cgroup/get{peer,sock}name{4,6} support is missing 15 | d_path # v5.10+ feature 16 | enable_stats # BPF_ENABLE_STATS support is missing 17 | fentry_fexit # bpf_prog_test_tracing missing 18 | fentry_test # bpf_prog_test_tracing missing 19 | fexit_bpf2bpf # freplace is missing 20 | fexit_test # bpf_prog_test_tracing missing 21 | flow_dissector # bpf_link-based flow dissector is in 5.8+ 22 | flow_dissector_reattach 23 | get_stack_raw_tp # exercising BPF verifier bug causing infinite loop 24 | hash_large_key # v5.11+ 25 | ima # v5.11+ 26 | kfree_skb # 32-bit pointer arith in test_pkt_access 27 | ksyms # __start_BTF has different name 28 | link_pinning # bpf_link is missing 29 | load_bytes_relative # new functionality in 5.8 30 | map_init # per-CPU LRU missing 31 | map_ptr # test uses BPF_MAP_TYPE_RINGBUF, added in 5.8 32 | metadata # v5.10+ 33 | mmap # 5.5 kernel is too permissive with re-mmaping 34 | modify_return # fmod_ret support is missing 35 | module_attach # module BTF support missing (v5.11+) 36 | ns_current_pid_tgid # bpf_get_ns_current_pid_tgid() helper is missing 37 | pe_preserve_elems # v5.10+ 38 | perf_branches # bpf_read_branch_records() helper is missing 39 | pkt_access # 32-bit pointer arith in test_pkt_access 40 | probe_read_user_str # kernel bug with garbage bytes at the end 41 | prog_run_xattr # 32-bit pointer arith in test_pkt_access 42 | raw_tp_test_run # v5.10+ 43 | ringbuf # BPF_MAP_TYPE_RINGBUF is supported in 5.8+ 44 | 45 | # bug in verifier w/ tracking references 46 | #reference_tracking/classifier/sk_lookup_success 47 | reference_tracking 48 | 49 | select_reuseport # UDP support is missing 50 | send_signal # bpf_send_signal_thread() helper is missing 51 | sk_assign # bpf_sk_assign helper missing 52 | skb_helpers # helpers added in 5.8+ 53 | sk_storage_tracing # missing bpf_sk_storage_get() helper 54 | snprintf_btf # v5.10+ 55 | sock_fields # v5.10+ 56 | sockmap_basic # uses new socket fields, 5.8+ 57 | sockmap_listen # no listen socket supportin SOCKMAP 58 | sockopt_sk 59 | sk_lookup # v5.9+ 60 | skb_ctx # ctx_{size, }_{in, out} in BPF_PROG_TEST_RUN is missing 61 | tcp_hdr_options # v5.10+, new TCP header options feature in BPF 62 | tcpbpf_user # LINK_CREATE is missing 63 | test_bpffs # v5.10+, new CONFIG_BPF_PRELOAD=y and CONFIG_BPF_PRELOAD_UMG=y|m 64 | test_bprm_opts # v5.11+ 65 | test_global_funcs # kernel doesn't support BTF linkage=global on FUNCs 66 | test_local_storage # v5.10+ feature 67 | test_lsm # no BPF_LSM support 68 | test_overhead # no fmod_ret support 69 | test_profiler # needs verifier logic improvements from v5.10+ 70 | test_skb_pkt_end # v5.11+ 71 | trace_ext # v5.10+ 72 | udp_limit # no cgroup/sock_release BPF program type (5.9+) 73 | varlen # verifier bug fixed in later kernels 74 | vmlinux # hrtimer_nanosleep() signature changed incompatibly 75 | xdp_adjust_tail # new XDP functionality added in 5.8 76 | xdp_attach # IFLA_XDP_EXPECTED_FD support is missing 77 | xdp_bpf2bpf # freplace is missing 78 | xdp_cpumap_attach # v5.9+ 79 | xdp_devmap_attach # new feature in 5.8 80 | xdp_link # v5.9+ 81 | 82 | # SUBTESTS FAILING (block entire test until blocking subtests works properly) 83 | btf # "size check test", "func (Non zero vlen)" 84 | tailcalls # tailcall_bpf2bpf_1, tailcall_bpf2bpf_2, tailcall_bpf2bpf_3 85 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/configs/blacklist/BLACKLIST-latest: -------------------------------------------------------------------------------- 1 | # TEMPORARY 2 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/configs/whitelist/WHITELIST-4.9.0: -------------------------------------------------------------------------------- 1 | btf_dump 2 | core_retro 3 | cpu_mask 4 | hashmap 5 | perf_buffer 6 | section_names 7 | 8 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/helpers.sh: -------------------------------------------------------------------------------- 1 | # $1 - start or end 2 | # $2 - fold identifier, no spaces 3 | # $3 - fold section description 4 | travis_fold() { 5 | local YELLOW='\033[1;33m' 6 | local NOCOLOR='\033[0m' 7 | echo travis_fold:$1:$2 8 | if [ ! -z "${3:-}" ]; then 9 | echo -e "${YELLOW}$3${NOCOLOR}" 10 | fi 11 | echo 12 | } 13 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/mkrootfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is based on drgn script for generating Arch Linux bootstrap 4 | # images. 5 | # https://github.com/osandov/drgn/blob/master/scripts/vmtest/mkrootfs.sh 6 | 7 | set -euo pipefail 8 | 9 | usage () { 10 | USAGE_STRING="usage: $0 [NAME] 11 | $0 -h 12 | 13 | Build an Arch Linux root filesystem image for testing libbpf in a virtual 14 | machine. 15 | 16 | The image is generated as a zstd-compressed tarball. 17 | 18 | This must be run as root, as most of the installation is done in a chroot. 19 | 20 | Arguments: 21 | NAME name of generated image file (default: 22 | libbpf-vmtest-rootfs-\$DATE.tar.zst) 23 | 24 | Options: 25 | -h display this help message and exit" 26 | 27 | case "$1" in 28 | out) 29 | echo "$USAGE_STRING" 30 | exit 0 31 | ;; 32 | err) 33 | echo "$USAGE_STRING" >&2 34 | exit 1 35 | ;; 36 | esac 37 | } 38 | 39 | while getopts "h" OPT; do 40 | case "$OPT" in 41 | h) 42 | usage out 43 | ;; 44 | *) 45 | usage err 46 | ;; 47 | esac 48 | done 49 | if [[ $OPTIND -eq $# ]]; then 50 | NAME="${!OPTIND}" 51 | elif [[ $OPTIND -gt $# ]]; then 52 | NAME="libbpf-vmtest-rootfs-$(date +%Y.%m.%d).tar.zst" 53 | else 54 | usage err 55 | fi 56 | 57 | pacman_conf= 58 | root= 59 | trap 'rm -rf "$pacman_conf" "$root"' EXIT 60 | pacman_conf="$(mktemp -p "$PWD")" 61 | cat > "$pacman_conf" << "EOF" 62 | [options] 63 | Architecture = x86_64 64 | CheckSpace 65 | SigLevel = Required DatabaseOptional 66 | [core] 67 | Include = /etc/pacman.d/mirrorlist 68 | [extra] 69 | Include = /etc/pacman.d/mirrorlist 70 | [community] 71 | Include = /etc/pacman.d/mirrorlist 72 | EOF 73 | root="$(mktemp -d -p "$PWD")" 74 | 75 | packages=( 76 | busybox 77 | # libbpf dependencies. 78 | libelf 79 | zlib 80 | # selftests test_progs dependencies. 81 | binutils 82 | elfutils 83 | glibc 84 | iproute2 85 | # selftests test_verifier dependencies. 86 | libcap 87 | ) 88 | 89 | pacstrap -C "$pacman_conf" -cGM "$root" "${packages[@]}" 90 | 91 | # Remove unnecessary files from the chroot. 92 | 93 | # We don't need the pacman databases anymore. 94 | rm -rf "$root/var/lib/pacman/sync/" 95 | # We don't need D, Fortran, or Go. 96 | rm -f "$root/usr/lib/libgdruntime."* \ 97 | "$root/usr/lib/libgphobos."* \ 98 | "$root/usr/lib/libgfortran."* \ 99 | "$root/usr/lib/libgo."* 100 | # We don't need any documentation. 101 | rm -rf "$root/usr/share/{doc,help,man,texinfo}" 102 | 103 | chroot "${root}" /bin/busybox --install 104 | 105 | cat > "$root/etc/inittab" << "EOF" 106 | ::sysinit:/etc/init.d/rcS 107 | ::ctrlaltdel:/sbin/reboot 108 | ::shutdown:/sbin/swapoff -a 109 | ::shutdown:/bin/umount -a -r 110 | ::restart:/sbin/init 111 | EOF 112 | chmod 644 "$root/etc/inittab" 113 | 114 | mkdir -m 755 "$root/etc/init.d" "$root/etc/rcS.d" 115 | cat > "$root/etc/rcS.d/S10-mount" << "EOF" 116 | #!/bin/sh 117 | 118 | set -eux 119 | 120 | /bin/mount proc /proc -t proc 121 | 122 | # Mount devtmpfs if not mounted 123 | if [[ -z $(/bin/mount -l -t devtmpfs) ]]; then 124 | /bin/mount devtmpfs /dev -t devtmpfs 125 | fi 126 | 127 | /bin/mount sysfs /sys -t sysfs 128 | /bin/mount bpffs /sys/fs/bpf -t bpf 129 | /bin/mount debugfs /sys/kernel/debug -t debugfs 130 | 131 | echo 'Listing currently mounted file systems' 132 | /bin/mount 133 | EOF 134 | chmod 755 "$root/etc/rcS.d/S10-mount" 135 | 136 | cat > "$root/etc/rcS.d/S40-network" << "EOF" 137 | #!/bin/sh 138 | 139 | set -eux 140 | 141 | ip link set lo up 142 | EOF 143 | chmod 755 "$root/etc/rcS.d/S40-network" 144 | 145 | cat > "$root/etc/init.d/rcS" << "EOF" 146 | #!/bin/sh 147 | 148 | set -eux 149 | 150 | for path in /etc/rcS.d/S*; do 151 | [ -x "$path" ] && "$path" 152 | done 153 | EOF 154 | chmod 755 "$root/etc/init.d/rcS" 155 | 156 | chmod 755 "$root" 157 | tar -C "$root" -c . | zstd -T0 -19 -o "$NAME" 158 | chmod 644 "$NAME" 159 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/prepare_selftests-4.9.0.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | printf "all:\n\ttouch bpf_testmod.ko\n\nclean:\n" > bpf_testmod/Makefile 4 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/prepare_selftests-5.5.0.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | printf "all:\n\ttouch bpf_testmod.ko\n\nclean:\n" > bpf_testmod/Makefile 4 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/prepare_selftests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | source $(cd $(dirname $0) && pwd)/helpers.sh 6 | 7 | REPO_PATH=$1 8 | 9 | ${VMTEST_ROOT}/checkout_latest_kernel.sh ${REPO_PATH} 10 | cd ${REPO_PATH} 11 | 12 | if [[ "${KERNEL}" = 'LATEST' ]]; then 13 | travis_fold start build_kernel "Kernel build" 14 | 15 | cp ${VMTEST_ROOT}/configs/latest.config .config 16 | make -j $((4*$(nproc))) olddefconfig all 17 | 18 | travis_fold end build_kernel 19 | fi 20 | 21 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/run_selftests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | source $(cd $(dirname $0) && pwd)/helpers.sh 6 | 7 | test_progs() { 8 | if [[ "${KERNEL}" != '4.9.0' ]]; then 9 | travis_fold start test_progs "Testing test_progs" 10 | ./test_progs ${BLACKLIST:+-b$BLACKLIST} ${WHITELIST:+-t$WHITELIST} 11 | travis_fold end test_progs 12 | fi 13 | 14 | travis_fold start test_progs-no_alu32 "Testing test_progs-no_alu32" 15 | ./test_progs-no_alu32 ${BLACKLIST:+-b$BLACKLIST} ${WHITELIST:+-t$WHITELIST} 16 | travis_fold end test_progs-no_alu32 17 | } 18 | 19 | test_maps() { 20 | travis_fold start test_maps "Testing test_maps" 21 | ./test_maps 22 | travis_fold end test_maps 23 | } 24 | 25 | test_verifier() { 26 | travis_fold start test_verifier "Testing test_verifier" 27 | ./test_verifier 28 | travis_fold end test_verifier 29 | } 30 | 31 | travis_fold end vm_init 32 | 33 | configs_path='libbpf/travis-ci/vmtest/configs' 34 | blacklist_path="$configs_path/blacklist/BLACKLIST-${KERNEL}" 35 | if [[ -s "${blacklist_path}" ]]; then 36 | BLACKLIST=$(cat "${blacklist_path}" | cut -d'#' -f1 | tr -s '[:space:]' ',') 37 | fi 38 | 39 | whitelist_path="$configs_path/whitelist/WHITELIST-${KERNEL}" 40 | if [[ -s "${whitelist_path}" ]]; then 41 | WHITELIST=$(cat "${whitelist_path}" | cut -d'#' -f1 | tr -s '[:space:]' ',') 42 | fi 43 | 44 | cd libbpf/selftests/bpf 45 | 46 | test_progs 47 | 48 | if [[ "${KERNEL}" == 'latest' ]]; then 49 | #test_maps 50 | test_verifier 51 | fi 52 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/libbpf/travis-ci/vmtest/run_vmtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | source $(cd $(dirname $0) && pwd)/helpers.sh 6 | 7 | VMTEST_SETUPCMD="PROJECT_NAME=${PROJECT_NAME} ./${PROJECT_NAME}/travis-ci/vmtest/run_selftests.sh" 8 | 9 | echo "KERNEL: $KERNEL" 10 | echo 11 | 12 | # Build latest pahole 13 | ${VMTEST_ROOT}/build_pahole.sh travis-ci/vmtest/pahole 14 | 15 | travis_fold start install_clang "Installing Clang/LLVM" 16 | 17 | # Install required packages 18 | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 19 | echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" | sudo tee -a /etc/apt/sources.list 20 | sudo apt-get update 21 | sudo apt-get -y install clang-12 lld-12 llvm-12 22 | sudo apt-get -y install python-docutils # for rst2man 23 | 24 | travis_fold end install_clang 25 | 26 | # Build selftests (and latest kernel, if necessary) 27 | KERNEL="${KERNEL}" ${VMTEST_ROOT}/prepare_selftests.sh travis-ci/vmtest/bpf-next 28 | 29 | # Escape whitespace characters. 30 | setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}") 31 | 32 | sudo adduser "${USER}" kvm 33 | 34 | if [[ "${KERNEL}" = 'LATEST' ]]; then 35 | sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -b travis-ci/vmtest/bpf-next -o -d ~ -s "${setup_cmd}" ~/root.img; 36 | else 37 | sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -k "${KERNEL}*" -o -d ~ -s "${setup_cmd}" ~/root.img; 38 | fi 39 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/.gitignore: -------------------------------------------------------------------------------- 1 | /.output 2 | /bootstrap 3 | /minimal 4 | /uprobe 5 | /kprobe 6 | /fentry 7 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | OUTPUT := .output 3 | CLANG ?= clang 4 | LLVM_STRIP ?= llvm-strip 5 | BPFTOOL ?= $(abspath ../tools/bpftool) 6 | LIBBPF_SRC := $(abspath ../libbpf/src) 7 | LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) 8 | # Use our own libbpf API headers and Linux UAPI headers distributed with 9 | # libbpf to avoid dependency on system-wide headers, which could be missing or 10 | # outdated 11 | INCLUDES := -I$(OUTPUT) -I../libbpf/include/uapi 12 | CFLAGS := -g -Wall 13 | ARCH := $(shell uname -m | sed 's/x86_64/x86/') 14 | 15 | APPS = minimal bootstrap uprobe kprobe fentry 16 | 17 | # Get Clang's default includes on this system. We'll explicitly add these dirs 18 | # to the includes list when compiling with `-target bpf` because otherwise some 19 | # architecture-specific dirs will be "missing" on some architectures/distros - 20 | # headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h, 21 | # sys/cdefs.h etc. might be missing. 22 | # 23 | # Use '-idirafter': Don't interfere with include mechanics except where the 24 | # build would have failed anyways. 25 | CLANG_BPF_SYS_INCLUDES = $(shell $(CLANG) -v -E - &1 \ 26 | | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') 27 | 28 | ifeq ($(V),1) 29 | Q = 30 | msg = 31 | else 32 | Q = @ 33 | msg = @printf ' %-8s %s%s\n' \ 34 | "$(1)" \ 35 | "$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \ 36 | "$(if $(3), $(3))"; 37 | MAKEFLAGS += --no-print-directory 38 | endif 39 | 40 | .PHONY: all 41 | all: $(APPS) 42 | 43 | .PHONY: clean 44 | clean: 45 | $(call msg,CLEAN) 46 | $(Q)rm -rf $(OUTPUT) $(APPS) 47 | 48 | $(OUTPUT) $(OUTPUT)/libbpf: 49 | $(call msg,MKDIR,$@) 50 | $(Q)mkdir -p $@ 51 | 52 | # Build libbpf 53 | $(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf 54 | $(call msg,LIB,$@) 55 | $(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \ 56 | OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \ 57 | INCLUDEDIR= LIBDIR= UAPIDIR= \ 58 | install 59 | 60 | # Build BPF code 61 | $(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) vmlinux.h | $(OUTPUT) 62 | $(call msg,BPF,$@) 63 | $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) -c $(filter %.c,$^) -o $@ 64 | $(Q)$(LLVM_STRIP) -g $@ # strip useless DWARF info 65 | 66 | # Generate BPF skeletons 67 | $(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) 68 | $(call msg,GEN-SKEL,$@) 69 | $(Q)$(BPFTOOL) gen skeleton $< > $@ 70 | 71 | # Build user-space code 72 | $(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h 73 | 74 | $(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) 75 | $(call msg,CC,$@) 76 | $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ 77 | 78 | # Build application binary 79 | $(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) 80 | $(call msg,BINARY,$@) 81 | $(Q)$(CC) $(CFLAGS) $^ -lelf -lz -o $@ 82 | 83 | # delete failed targets 84 | .DELETE_ON_ERROR: 85 | 86 | # keep intermediate (.skel.h, .bpf.o, etc) targets 87 | .SECONDARY: 88 | 89 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/bootstrap.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 | /* Copyright (c) 2020 Facebook */ 3 | #include "vmlinux.h" 4 | #include 5 | #include 6 | #include 7 | #include "bootstrap.h" 8 | 9 | char LICENSE[] SEC("license") = "Dual BSD/GPL"; 10 | 11 | struct { 12 | __uint(type, BPF_MAP_TYPE_HASH); 13 | __uint(max_entries, 8192); 14 | __type(key, pid_t); 15 | __type(value, u64); 16 | } exec_start SEC(".maps"); 17 | 18 | struct { 19 | __uint(type, BPF_MAP_TYPE_RINGBUF); 20 | __uint(max_entries, 256 * 1024); 21 | } rb SEC(".maps"); 22 | 23 | const volatile unsigned long long min_duration_ns = 0; 24 | 25 | SEC("tp/sched/sched_process_exec") 26 | int handle_exec(struct trace_event_raw_sched_process_exec *ctx) 27 | { 28 | struct task_struct *task; 29 | unsigned fname_off; 30 | struct event *e; 31 | pid_t pid; 32 | u64 ts; 33 | 34 | /* remember time exec() was executed for this PID */ 35 | pid = bpf_get_current_pid_tgid() >> 32; 36 | ts = bpf_ktime_get_ns(); 37 | bpf_map_update_elem(&exec_start, &pid, &ts, BPF_ANY); 38 | 39 | /* don't emit exec events when minimum duration is specified */ 40 | if (min_duration_ns) 41 | return 0; 42 | 43 | /* reserve sample from BPF ringbuf */ 44 | e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); 45 | if (!e) 46 | return 0; 47 | 48 | /* fill out the sample with data */ 49 | task = (struct task_struct *)bpf_get_current_task(); 50 | 51 | e->exit_event = false; 52 | e->pid = pid; 53 | e->ppid = BPF_CORE_READ(task, real_parent, tgid); 54 | bpf_get_current_comm(&e->comm, sizeof(e->comm)); 55 | 56 | fname_off = ctx->__data_loc_filename & 0xFFFF; 57 | bpf_probe_read_str(&e->filename, sizeof(e->filename), (void *)ctx + fname_off); 58 | 59 | /* successfully submit it to user-space for post-processing */ 60 | bpf_ringbuf_submit(e, 0); 61 | return 0; 62 | } 63 | 64 | SEC("tp/sched/sched_process_exit") 65 | int handle_exit(struct trace_event_raw_sched_process_template* ctx) 66 | { 67 | struct task_struct *task; 68 | struct event *e; 69 | pid_t pid, tid; 70 | u64 id, ts, *start_ts, duration_ns = 0; 71 | 72 | /* get PID and TID of exiting thread/process */ 73 | id = bpf_get_current_pid_tgid(); 74 | pid = id >> 32; 75 | tid = (u32)id; 76 | 77 | /* ignore thread exits */ 78 | if (pid != tid) 79 | return 0; 80 | 81 | /* if we recorded start of the process, calculate lifetime duration */ 82 | start_ts = bpf_map_lookup_elem(&exec_start, &pid); 83 | if (start_ts) 84 | duration_ns = bpf_ktime_get_ns() - *start_ts; 85 | else if (min_duration_ns) 86 | return 0; 87 | bpf_map_delete_elem(&exec_start, &pid); 88 | 89 | /* if process didn't live long enough, return early */ 90 | if (min_duration_ns && duration_ns < min_duration_ns) 91 | return 0; 92 | 93 | /* reserve sample from BPF ringbuf */ 94 | e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); 95 | if (!e) 96 | return 0; 97 | 98 | /* fill out the sample with data */ 99 | task = (struct task_struct *)bpf_get_current_task(); 100 | 101 | e->exit_event = true; 102 | e->duration_ns = duration_ns; 103 | e->pid = pid; 104 | e->ppid = BPF_CORE_READ(task, real_parent, tgid); 105 | e->exit_code = (BPF_CORE_READ(task, exit_code) >> 8) & 0xff; 106 | bpf_get_current_comm(&e->comm, sizeof(e->comm)); 107 | 108 | /* send data to user-space for post-processing */ 109 | bpf_ringbuf_submit(e, 0); 110 | return 0; 111 | } 112 | 113 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/bootstrap.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | /* Copyright (c) 2020 Facebook */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "bootstrap.h" 10 | #include "bootstrap.skel.h" 11 | 12 | static struct env { 13 | bool verbose; 14 | long min_duration_ms; 15 | } env; 16 | 17 | const char *argp_program_version = "bootstrap 0.0"; 18 | const char *argp_program_bug_address = ""; 19 | const char argp_program_doc[] = 20 | "BPF bootstrap demo application.\n" 21 | "\n" 22 | "It traces process start and exits and shows associated \n" 23 | "information (filename, process duration, PID and PPID, etc).\n" 24 | "\n" 25 | "USAGE: ./bootstrap [-d ] [-v]\n"; 26 | 27 | static const struct argp_option opts[] = { 28 | { "verbose", 'v', NULL, 0, "Verbose debug output" }, 29 | { "duration", 'd', "DURATION-MS", 0, "Minimum process duration (ms) to report" }, 30 | {}, 31 | }; 32 | 33 | static error_t parse_arg(int key, char *arg, struct argp_state *state) 34 | { 35 | switch (key) { 36 | case 'v': 37 | env.verbose = true; 38 | break; 39 | case 'd': 40 | errno = 0; 41 | env.min_duration_ms = strtol(arg, NULL, 10); 42 | if (errno || env.min_duration_ms <= 0) { 43 | fprintf(stderr, "Invalid duration: %s\n", arg); 44 | argp_usage(state); 45 | } 46 | break; 47 | case ARGP_KEY_ARG: 48 | argp_usage(state); 49 | break; 50 | default: 51 | return ARGP_ERR_UNKNOWN; 52 | } 53 | return 0; 54 | } 55 | 56 | static const struct argp argp = { 57 | .options = opts, 58 | .parser = parse_arg, 59 | .doc = argp_program_doc, 60 | }; 61 | 62 | static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) 63 | { 64 | if (level == LIBBPF_DEBUG && !env.verbose) 65 | return 0; 66 | return vfprintf(stderr, format, args); 67 | } 68 | 69 | static void bump_memlock_rlimit(void) 70 | { 71 | struct rlimit rlim_new = { 72 | .rlim_cur = RLIM_INFINITY, 73 | .rlim_max = RLIM_INFINITY, 74 | }; 75 | 76 | if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { 77 | fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); 78 | exit(1); 79 | } 80 | } 81 | 82 | static volatile bool exiting = false; 83 | 84 | static void sig_handler(int sig) 85 | { 86 | exiting = true; 87 | } 88 | 89 | static int handle_event(void *ctx, void *data, size_t data_sz) 90 | { 91 | const struct event *e = data; 92 | struct tm *tm; 93 | char ts[32]; 94 | time_t t; 95 | 96 | time(&t); 97 | tm = localtime(&t); 98 | strftime(ts, sizeof(ts), "%H:%M:%S", tm); 99 | 100 | if (e->exit_event) { 101 | printf("%-8s %-5s %-16s %-7d %-7d [%u]", 102 | ts, "EXIT", e->comm, e->pid, e->ppid, e->exit_code); 103 | if (e->duration_ns) 104 | printf(" (%llums)", e->duration_ns / 1000000); 105 | printf("\n"); 106 | } else { 107 | printf("%-8s %-5s %-16s %-7d %-7d %s\n", 108 | ts, "EXEC", e->comm, e->pid, e->ppid, e->filename); 109 | } 110 | 111 | return 0; 112 | } 113 | 114 | int main(int argc, char **argv) 115 | { 116 | struct ring_buffer *rb = NULL; 117 | struct bootstrap_bpf *skel; 118 | int err; 119 | 120 | /* Parse command line arguments */ 121 | err = argp_parse(&argp, argc, argv, 0, NULL, NULL); 122 | if (err) 123 | return err; 124 | 125 | /* Set up libbpf errors and debug info callback */ 126 | libbpf_set_print(libbpf_print_fn); 127 | 128 | /* Bump RLIMIT_MEMLOCK to create BPF maps */ 129 | bump_memlock_rlimit(); 130 | 131 | /* Cleaner handling of Ctrl-C */ 132 | signal(SIGINT, sig_handler); 133 | signal(SIGTERM, sig_handler); 134 | 135 | /* Load and verify BPF application */ 136 | skel = bootstrap_bpf__open(); 137 | if (!skel) { 138 | fprintf(stderr, "Failed to open and load BPF skeleton\n"); 139 | return 1; 140 | } 141 | 142 | /* Parameterize BPF code with minimum duration parameter */ 143 | skel->rodata->min_duration_ns = env.min_duration_ms * 1000000ULL; 144 | 145 | /* Load & verify BPF programs */ 146 | err = bootstrap_bpf__load(skel); 147 | if (err) { 148 | fprintf(stderr, "Failed to load and verify BPF skeleton\n"); 149 | goto cleanup; 150 | } 151 | 152 | /* Attach tracepoints */ 153 | err = bootstrap_bpf__attach(skel); 154 | if (err) { 155 | fprintf(stderr, "Failed to attach BPF skeleton\n"); 156 | goto cleanup; 157 | } 158 | 159 | /* Set up ring buffer polling */ 160 | rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL); 161 | if (!rb) { 162 | err = -1; 163 | fprintf(stderr, "Failed to create ring buffer\n"); 164 | goto cleanup; 165 | } 166 | 167 | /* Process events */ 168 | printf("%-8s %-5s %-16s %-7s %-7s %s\n", 169 | "TIME", "EVENT", "COMM", "PID", "PPID", "FILENAME/EXIT CODE"); 170 | while (!exiting) { 171 | err = ring_buffer__poll(rb, 100 /* timeout, ms */); 172 | /* Ctrl-C will cause -EINTR */ 173 | if (err == -EINTR) { 174 | err = 0; 175 | break; 176 | } 177 | if (err < 0) { 178 | printf("Error polling perf buffer: %d\n", err); 179 | break; 180 | } 181 | } 182 | 183 | cleanup: 184 | /* Clean up */ 185 | ring_buffer__free(rb); 186 | bootstrap_bpf__destroy(skel); 187 | 188 | return err < 0 ? -err : 0; 189 | } 190 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/bootstrap.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (c) 2020 Facebook */ 3 | #ifndef __BOOTSTRAP_H 4 | #define __BOOTSTRAP_H 5 | 6 | #define TASK_COMM_LEN 16 7 | #define MAX_FILENAME_LEN 127 8 | 9 | struct event { 10 | int pid; 11 | int ppid; 12 | unsigned exit_code; 13 | unsigned long long duration_ns; 14 | char comm[TASK_COMM_LEN]; 15 | char filename[MAX_FILENAME_LEN]; 16 | bool exit_event; 17 | }; 18 | 19 | #endif /* __BOOTSTRAP_H */ 20 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/fentry.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 | /* Copyright (c) 2021 Sartura */ 3 | #include "vmlinux.h" 4 | #include 5 | #include 6 | 7 | char LICENSE[] SEC("license") = "Dual BSD/GPL"; 8 | 9 | SEC("fentry/do_unlinkat") 10 | int BPF_PROG(do_unlinkat, int dfd, struct filename *name) 11 | { 12 | const char *filename = name->name; 13 | pid_t pid; 14 | 15 | pid = bpf_get_current_pid_tgid(); 16 | 17 | bpf_printk("fentry: pid = %d, filename = %s\n", pid, filename); 18 | return 0; 19 | } 20 | 21 | SEC("fexit/do_unlinkat") 22 | int BPF_PROG(do_unlinkat_exit, int dfd, struct filename *name, long ret) 23 | { 24 | pid_t pid; 25 | 26 | pid = bpf_get_current_pid_tgid(); 27 | 28 | bpf_printk("fexit: pid = %d, filename = %s, ret = %ld\n", pid, name->name, ret); 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/fentry.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | /* Copyright (c) 2021 Sartura 3 | * Based on minimal.c by Facebook */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "fentry.skel.h" 13 | 14 | static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) 15 | { 16 | return vfprintf(stderr, format, args); 17 | } 18 | 19 | static void bump_memlock_rlimit(void) 20 | { 21 | struct rlimit rlim_new = { 22 | .rlim_cur = RLIM_INFINITY, 23 | .rlim_max = RLIM_INFINITY, 24 | }; 25 | 26 | if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { 27 | fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); 28 | exit(1); 29 | } 30 | } 31 | 32 | static volatile sig_atomic_t stop; 33 | 34 | void sig_int(int signo) 35 | { 36 | stop = 1; 37 | } 38 | 39 | int main(int argc, char **argv) 40 | { 41 | struct fentry_bpf *skel; 42 | int err; 43 | 44 | /* Set up libbpf errors and debug info callback */ 45 | libbpf_set_print(libbpf_print_fn); 46 | 47 | /* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */ 48 | bump_memlock_rlimit(); 49 | 50 | /* Open load and verify BPF application */ 51 | skel = fentry_bpf__open_and_load(); 52 | if (!skel) { 53 | fprintf(stderr, "Failed to open BPF skeleton\n"); 54 | return 1; 55 | } 56 | 57 | /* Attach tracepoint handler */ 58 | err = fentry_bpf__attach(skel); 59 | if (err) { 60 | fprintf(stderr, "Failed to attach BPF skeleton\n"); 61 | goto cleanup; 62 | } 63 | 64 | if (signal(SIGINT, sig_int) == SIG_ERR) { 65 | fprintf(stderr, "can't set signal handler: %s\n", strerror(errno)); 66 | goto cleanup; 67 | } 68 | 69 | printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe`" 70 | "to see output of the BPF programs.\n"); 71 | 72 | while (!stop) { 73 | fprintf(stderr, "."); 74 | sleep(1); 75 | } 76 | 77 | cleanup: 78 | fentry_bpf__destroy(skel); 79 | return -err; 80 | } 81 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/kprobe.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 | /* Copyright (c) 2021 Sartura */ 3 | #include "vmlinux.h" 4 | #include 5 | #include 6 | #include 7 | 8 | char LICENSE[] SEC("license") = "Dual BSD/GPL"; 9 | 10 | SEC("kprobe/do_unlinkat") 11 | int BPF_KPROBE(do_unlinkat, int dfd, struct filename *name) 12 | { 13 | const char *filename = BPF_CORE_READ(name, name); 14 | pid_t pid; 15 | 16 | pid = bpf_get_current_pid_tgid(); 17 | 18 | bpf_printk("KPROBE ENTRY pid = %d, filename = %s\n", pid, filename); 19 | return 0; 20 | } 21 | 22 | SEC("kretprobe/do_unlinkat") 23 | int BPF_KRETPROBE(do_open_execat_exit, long ret) 24 | { 25 | bpf_printk("KPROBE EXIT: ret = %ld\n", ret); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/kprobe.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | /* Copyright (c) 2021 Sartura 3 | * Based on minimal.c by Facebook */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "kprobe.skel.h" 13 | 14 | static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) 15 | { 16 | return vfprintf(stderr, format, args); 17 | } 18 | 19 | static void bump_memlock_rlimit(void) 20 | { 21 | struct rlimit rlim_new = { 22 | .rlim_cur = RLIM_INFINITY, 23 | .rlim_max = RLIM_INFINITY, 24 | }; 25 | 26 | if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { 27 | fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); 28 | exit(1); 29 | } 30 | } 31 | 32 | static volatile sig_atomic_t stop; 33 | 34 | static void sig_int(int signo) 35 | { 36 | stop = 1; 37 | } 38 | 39 | int main(int argc, char **argv) 40 | { 41 | struct kprobe_bpf *skel; 42 | int err; 43 | 44 | /* Set up libbpf errors and debug info callback */ 45 | libbpf_set_print(libbpf_print_fn); 46 | 47 | /* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */ 48 | bump_memlock_rlimit(); 49 | 50 | /* Open load and verify BPF application */ 51 | skel = kprobe_bpf__open_and_load(); 52 | if (!skel) { 53 | fprintf(stderr, "Failed to open BPF skeleton\n"); 54 | return 1; 55 | } 56 | 57 | /* Attach tracepoint handler */ 58 | err = kprobe_bpf__attach(skel); 59 | if (err) { 60 | fprintf(stderr, "Failed to attach BPF skeleton\n"); 61 | goto cleanup; 62 | } 63 | 64 | if (signal(SIGINT, sig_int) == SIG_ERR) { 65 | fprintf(stderr, "can't set signal handler: %s\n", strerror(errno)); 66 | goto cleanup; 67 | } 68 | 69 | printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe`" 70 | "to see output of the BPF programs.\n"); 71 | 72 | while (!stop) { 73 | fprintf(stderr, "."); 74 | sleep(1); 75 | } 76 | 77 | cleanup: 78 | kprobe_bpf__destroy(skel); 79 | return -err; 80 | } 81 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/minimal.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 | /* Copyright (c) 2020 Facebook */ 3 | #include 4 | #include 5 | 6 | char LICENSE[] SEC("license") = "Dual BSD/GPL"; 7 | 8 | int my_pid = 0; 9 | 10 | SEC("ddp") 11 | int handle_tp(int ctx) 12 | { 13 | 14 | return 220; 15 | } 16 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/minimal.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | /* Copyright (c) 2020 Facebook */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "minimal.skel.h" 8 | 9 | static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) 10 | { 11 | return vfprintf(stderr, format, args); 12 | } 13 | 14 | static void bump_memlock_rlimit(void) 15 | { 16 | struct rlimit rlim_new = { 17 | .rlim_cur = RLIM_INFINITY, 18 | .rlim_max = RLIM_INFINITY, 19 | }; 20 | 21 | if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { 22 | fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); 23 | exit(1); 24 | } 25 | } 26 | 27 | int main(int argc, char **argv) 28 | { 29 | struct minimal_bpf *skel; 30 | int err; 31 | 32 | /* Set up libbpf errors and debug info callback */ 33 | libbpf_set_print(libbpf_print_fn); 34 | 35 | /* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */ 36 | bump_memlock_rlimit(); 37 | 38 | /* Open BPF application */ 39 | skel = minimal_bpf__open(); 40 | if (!skel) { 41 | fprintf(stderr, "Failed to open BPF skeleton\n"); 42 | return 1; 43 | } 44 | 45 | /* ensure BPF program only handles write() syscalls from our process */ 46 | skel->bss->my_pid = getpid(); 47 | 48 | /* Load & verify BPF programs */ 49 | err = minimal_bpf__load(skel); 50 | if (err) { 51 | fprintf(stderr, "Failed to load and verify BPF skeleton\n"); 52 | goto cleanup; 53 | } 54 | 55 | /* Attach tracepoint handler */ 56 | err = minimal_bpf__attach(skel); 57 | if (err) { 58 | fprintf(stderr, "Failed to attach BPF skeleton\n"); 59 | goto cleanup; 60 | } 61 | 62 | printf("Successfully started!\n"); 63 | 64 | /* 65 | for (;;) { 66 | fprintf(stderr, "."); 67 | sleep(1); 68 | } 69 | */ 70 | 71 | cleanup: 72 | minimal_bpf__destroy(skel); 73 | return -err; 74 | } 75 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/uprobe.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 | /* Copyright (c) 2020 Facebook */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | char LICENSE[] SEC("license") = "Dual BSD/GPL"; 9 | 10 | SEC("uprobe/func") 11 | int BPF_KPROBE(uprobe, int a, int b) 12 | { 13 | bpf_printk("UPROBE ENTRY: a = %d, b = %d\n", a, b); 14 | return 0; 15 | } 16 | 17 | SEC("uretprobe/func") 18 | int BPF_KRETPROBE(uretprobe, int ret) 19 | { 20 | bpf_printk("UPROBE EXIT: return = %d\n", ret); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/uprobe.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | /* Copyright (c) 2020 Facebook */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "uprobe.skel.h" 9 | 10 | static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) 11 | { 12 | return vfprintf(stderr, format, args); 13 | } 14 | 15 | static void bump_memlock_rlimit(void) 16 | { 17 | struct rlimit rlim_new = { 18 | .rlim_cur = RLIM_INFINITY, 19 | .rlim_max = RLIM_INFINITY, 20 | }; 21 | 22 | if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { 23 | fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); 24 | exit(1); 25 | } 26 | } 27 | 28 | /* Find process's base load address. We use /proc/self/maps for that, 29 | * searching for the first executable (r-xp) memory mapping: 30 | * 31 | * 5574fd254000-5574fd258000 r-xp 00002000 fd:01 668759 /usr/bin/cat 32 | * ^^^^^^^^^^^^ ^^^^^^^^ 33 | * 34 | * Subtracting that region's offset (4th column) from its absolute start 35 | * memory address (1st column) gives us the process's base load address. 36 | */ 37 | static long get_base_addr() { 38 | size_t start, offset; 39 | char buf[256]; 40 | FILE *f; 41 | 42 | f = fopen("/proc/self/maps", "r"); 43 | if (!f) 44 | return -errno; 45 | 46 | while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n", &start, buf, &offset) == 3) { 47 | if (strcmp(buf, "r-xp") == 0) { 48 | fclose(f); 49 | return start - offset; 50 | } 51 | } 52 | 53 | fclose(f); 54 | return -1; 55 | } 56 | 57 | /* It's a global function to make sure compiler doesn't inline it. */ 58 | int uprobed_function(int a, int b) 59 | { 60 | return a + b; 61 | } 62 | 63 | int main(int argc, char **argv) 64 | { 65 | struct uprobe_bpf *skel; 66 | long base_addr, uprobe_offset; 67 | int err, i; 68 | 69 | /* Set up libbpf errors and debug info callback */ 70 | libbpf_set_print(libbpf_print_fn); 71 | 72 | /* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */ 73 | bump_memlock_rlimit(); 74 | 75 | /* Load and verify BPF application */ 76 | skel = uprobe_bpf__open_and_load(); 77 | if (!skel) { 78 | fprintf(stderr, "Failed to open and load BPF skeleton\n"); 79 | return 1; 80 | } 81 | 82 | base_addr = get_base_addr(); 83 | if (base_addr < 0) { 84 | fprintf(stderr, "Failed to determine process's load address\n"); 85 | err = base_addr; 86 | goto cleanup; 87 | } 88 | 89 | /* uprobe/uretprobe expects relative offset of the function to attach 90 | * to. This offset is relateve to the process's base load address. So 91 | * easy way to do this is to take an absolute address of the desired 92 | * function and substract base load address from it. If we were to 93 | * parse ELF to calculate this function, we'd need to add .text 94 | * section offset and function's offset within .text ELF section. 95 | */ 96 | uprobe_offset = (long)&uprobed_function - base_addr; 97 | 98 | /* Attach tracepoint handler */ 99 | skel->links.uprobe = bpf_program__attach_uprobe(skel->progs.uprobe, 100 | false /* not uretprobe */, 101 | 0 /* self pid */, 102 | "/proc/self/exe", 103 | uprobe_offset); 104 | err = libbpf_get_error(skel->links.uprobe); 105 | if (err) { 106 | fprintf(stderr, "Failed to attach uprobe: %d\n", err); 107 | goto cleanup; 108 | } 109 | 110 | /* we can also attach uprobe/uretprobe to any existing or future 111 | * processes that use the same binary executable; to do that we need 112 | * to specify -1 as PID, as we do here 113 | */ 114 | skel->links.uretprobe = bpf_program__attach_uprobe(skel->progs.uretprobe, 115 | true /* uretprobe */, 116 | -1 /* any pid */, 117 | "/proc/self/exe", 118 | uprobe_offset); 119 | err = libbpf_get_error(skel->links.uretprobe); 120 | if (err) { 121 | fprintf(stderr, "Failed to attach uprobe: %d\n", err); 122 | goto cleanup; 123 | } 124 | 125 | printf("Successfully started!\n"); 126 | 127 | for (i = 0; ; i++) { 128 | /* trigger our BPF programs */ 129 | fprintf(stderr, "."); 130 | uprobed_function(i, i + 1); 131 | sleep(1); 132 | } 133 | 134 | cleanup: 135 | uprobe_bpf__destroy(skel); 136 | return -err; 137 | } 138 | -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/src/vmlinux.h: -------------------------------------------------------------------------------- 1 | vmlinux_508.h -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/tools/bpftool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrp-project/BPF-KV/d4ea37c2266586b3ebfdd9351d501f27477ae2bc/ddp-artifacts/libbpf-boot/tools/bpftool -------------------------------------------------------------------------------- /ddp-artifacts/libbpf-boot/tools/gen_vmlinux_h.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | $(dirname "$0")/bpftool btf dump file ${1:-/sys/kernel/btf/vmlinux} format c 4 | -------------------------------------------------------------------------------- /ddp-artifacts/nnbuild.sh: -------------------------------------------------------------------------------- 1 | gcc -g -o nndb nndb.c nndb.h -lpthread -D_GNU_SOURCE 2 | -------------------------------------------------------------------------------- /ddp-artifacts/nndb.h: -------------------------------------------------------------------------------- 1 | #ifndef DB_H 2 | #define DB_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Data-level information 10 | typedef unsigned long meta__t; 11 | typedef unsigned long key__t; 12 | typedef unsigned char val__t[64]; 13 | typedef unsigned long ptr__t; 14 | 15 | #define META_SIZE sizeof(meta__t) 16 | #define KEY_SIZE sizeof(key__t) 17 | #define VAL_SIZE sizeof(val__t) 18 | #define PTR_SIZE sizeof(ptr__t) 19 | #define BLK_SIZE 512 20 | #define BLK_SIZE_LOG 9 21 | 22 | // Node-level information 23 | #define INTERNAL 0 24 | #define LEAF 1 25 | 26 | #define NODE_CAPACITY ((BLK_SIZE - 2 * META_SIZE) / (KEY_SIZE + PTR_SIZE)) 27 | #define LOG_CAPACITY ((BLK_SIZE) / (VAL_SIZE)) 28 | #define FANOUT NODE_CAPACITY 29 | 30 | typedef struct _Node { 31 | meta__t num; 32 | meta__t type; 33 | key__t key[NODE_CAPACITY]; 34 | ptr__t ptr[NODE_CAPACITY]; 35 | } Node; 36 | 37 | typedef struct _Log { 38 | val__t val[LOG_CAPACITY]; 39 | } Log; 40 | 41 | // Database-level information 42 | #define DB_PATH "/dev/treenvme0" 43 | #define LOG_PATH "/dev/nvme0n1" 44 | #define LOAD_MODE 0 45 | #define RUN_MODE 1 46 | #define FILE_MASK ((ptr__t)1 << 63) 47 | 48 | size_t worker_num; 49 | size_t total_node; 50 | size_t *layer_cap; 51 | key__t max_key; 52 | int db; 53 | int logfn; 54 | Node *cache; 55 | size_t cache_cap; 56 | 57 | typedef struct { 58 | size_t op_count; 59 | size_t index; 60 | int db_handler; 61 | size_t timer; 62 | int log_handler; 63 | } WorkerArg; 64 | 65 | int get_handler(int flag); 66 | int get_log_handler(int flag); 67 | 68 | ptr__t is_file_offset(ptr__t ptr) { 69 | return ptr & FILE_MASK; 70 | } 71 | 72 | ptr__t encode(ptr__t ptr) { 73 | return ptr | FILE_MASK; 74 | } 75 | 76 | ptr__t decode(ptr__t ptr) { 77 | return ptr & (~FILE_MASK); 78 | } 79 | 80 | int load(size_t layer_num); 81 | 82 | int run(size_t layer_num, size_t request_num, size_t thread_num); 83 | 84 | void *subtask(void *args); 85 | 86 | void build_cache(size_t layer_num); 87 | 88 | int get(key__t key, val__t val, int db_handler, int log_handler); 89 | 90 | ptr__t next_node(key__t key, Node *node); 91 | 92 | void read_node(ptr__t ptr, Node *node, int db_handler); 93 | 94 | void read_log(ptr__t ptr, Log *log, int db_handler); 95 | 96 | int retrieve_value(ptr__t ptr, val__t val, int db_handler); 97 | 98 | int prompt_help(); 99 | 100 | void initialize(size_t layer_num, int mode); 101 | 102 | void initialize_workers(WorkerArg *args, size_t total_op_count); 103 | 104 | void start_workers(pthread_t *tids, WorkerArg *args); 105 | 106 | void terminate_workers(pthread_t *tids, WorkerArg *args); 107 | 108 | int terminate(); 109 | 110 | int compare_nodes(Node *x, Node *y); 111 | 112 | void print_node(ptr__t ptr, Node *node); 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /ddp-artifacts/nnnbuild.sh: -------------------------------------------------------------------------------- 1 | gcc -g -o nnndb nnndb.c nnndb.h -lpthread -D_GNU_SOURCE 2 | -------------------------------------------------------------------------------- /ddp-artifacts/nnndb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrp-project/BPF-KV/d4ea37c2266586b3ebfdd9351d501f27477ae2bc/ddp-artifacts/nnndb -------------------------------------------------------------------------------- /ddp-artifacts/nnndb.h: -------------------------------------------------------------------------------- 1 | #ifndef DB_H 2 | #define DB_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Data-level information 10 | typedef unsigned long meta__t; 11 | typedef unsigned long key__t; 12 | typedef unsigned char val__t[64]; 13 | typedef unsigned long ptr__t; 14 | 15 | #define META_SIZE sizeof(meta__t) 16 | #define KEY_SIZE sizeof(key__t) 17 | #define VAL_SIZE sizeof(val__t) 18 | #define PTR_SIZE sizeof(ptr__t) 19 | #define BLK_SIZE 512 20 | #define BLK_SIZE_LOG 9 21 | 22 | // Node-level information 23 | #define INTERNAL 0 24 | #define LEAF 1 25 | 26 | #define NODE_CAPACITY ((BLK_SIZE - 2 * META_SIZE) / (KEY_SIZE + PTR_SIZE)) 27 | #define LOG_CAPACITY ((BLK_SIZE) / (VAL_SIZE)) 28 | #define FANOUT NODE_CAPACITY 29 | 30 | typedef struct _Node { 31 | meta__t num; 32 | meta__t type; 33 | key__t key[NODE_CAPACITY]; 34 | ptr__t ptr[NODE_CAPACITY]; 35 | } Node; 36 | 37 | typedef struct _Log { 38 | val__t val[LOG_CAPACITY]; 39 | } Log; 40 | 41 | // Database-level information 42 | #define DB_PATH "/dev/treenvme0" 43 | #define LOG_PATH "/dev/nvme0n1" 44 | #define LOAD_MODE 0 45 | #define RUN_MODE 1 46 | #define FILE_MASK ((ptr__t)1 << 63) 47 | 48 | size_t worker_num; 49 | size_t total_node; 50 | size_t *layer_cap; 51 | key__t max_key; 52 | int db; 53 | int logfn; 54 | Node *cache; 55 | size_t cache_cap; 56 | 57 | typedef struct { 58 | size_t op_count; 59 | size_t index; 60 | int db_handler; 61 | size_t timer; 62 | int log_handler; 63 | } WorkerArg; 64 | 65 | int get_handler(int flag); 66 | int get_log_handler(int flag); 67 | 68 | ptr__t is_file_offset(ptr__t ptr) { 69 | return ptr & FILE_MASK; 70 | } 71 | 72 | ptr__t encode(ptr__t ptr) { 73 | return ptr | FILE_MASK; 74 | } 75 | 76 | ptr__t decode(ptr__t ptr) { 77 | return ptr & (~FILE_MASK); 78 | } 79 | 80 | int load(size_t layer_num); 81 | 82 | int run(size_t layer_num, size_t request_num, size_t thread_num); 83 | 84 | void *subtask(void *args); 85 | 86 | void build_cache(size_t layer_num); 87 | 88 | int get(key__t key, val__t val, int db_handler, int log_handler); 89 | 90 | ptr__t next_node(key__t key, Node *node); 91 | 92 | void read_node(ptr__t ptr, Node *node, int db_handler); 93 | 94 | void read_log(ptr__t ptr, Log *log, int db_handler); 95 | 96 | int retrieve_value(ptr__t ptr, val__t val, int db_handler); 97 | 98 | int prompt_help(); 99 | 100 | void initialize(size_t layer_num, int mode); 101 | 102 | void initialize_workers(WorkerArg *args, size_t total_op_count); 103 | 104 | void start_workers(pthread_t *tids, WorkerArg *args); 105 | 106 | void terminate_workers(pthread_t *tids, WorkerArg *args); 107 | 108 | int terminate(); 109 | 110 | int compare_nodes(Node *x, Node *y); 111 | 112 | void print_node(ptr__t ptr, Node *node); 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /ddp-artifacts/scripts/setup.sh: -------------------------------------------------------------------------------- 1 | # disable hyper threading 2 | echo off > /sys/devices/system/cpu/smt/control 3 | # set to performance mode 4 | for CPUID in {0..5} 5 | do 6 | cd /sys/devices/system/cpu/cpu$CPUID/ 7 | cd cpufreq/ 8 | echo "performance" > scaling_governor 9 | echo $(cat cpuinfo_max_freq) > scaling_max_freq 10 | echo $(cat cpuinfo_max_freq) > scaling_min_freq 11 | cd ../cpuidle 12 | cd state0 13 | echo 0 > disable 14 | cd .. 15 | for STATE in {1..3} 16 | do 17 | cd state$STATE 18 | echo 1 > disable 19 | cd .. 20 | done 21 | done 22 | cd /sys/devices/system/cpu/intel_pstate 23 | echo 1 > no_turbo 24 | echo 100 > max_perf_pct 25 | echo 100 > min_perf_pct 26 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/.gitignore: -------------------------------------------------------------------------------- 1 | *.ll 2 | *.o 3 | *.insn 4 | *.out 5 | a.out 6 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/Makefile: -------------------------------------------------------------------------------- 1 | LLC ?= llc 2 | CLANG ?= clang 3 | CC ?= gcc 4 | 5 | BPF_CFLAGS ?= -I$(LIBBPF_DIR)/build/usr/ 6 | 7 | all: drop.o drop2.o droptree.o 8 | 9 | %.o: %.c 10 | $(CLANG) -S \ 11 | -target bpf \ 12 | -D __BPF_TRACING__ \ 13 | $(BPF_CFLAGS) \ 14 | -Wall \ 15 | -Wno-unused-value \ 16 | -Wno-pointer-sign \ 17 | -Wno-compare-distinct-pointer-types \ 18 | -Werror \ 19 | -O2 -emit-llvm -c -g -o ${@:.o=.ll} $< 20 | $(LLC) -march=bpf -filetype=obj -o $@ ${@:.o=.ll} 21 | 22 | clean: 23 | rm -rf *.o 24 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/bpf_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BPF_HELPERS__ 3 | #define __BPF_HELPERS__ 4 | 5 | #include "bpf_helper_defs.h" 6 | 7 | #define __uint(name, val) int (*name)[val] 8 | #define __type(name, val) typeof(val) *name 9 | 10 | /* Helper macro to print out debug messages */ 11 | #define bpf_printk(fmt, ...) \ 12 | ({ \ 13 | char ____fmt[] = fmt; \ 14 | bpf_trace_printk(____fmt, sizeof(____fmt), \ 15 | ##__VA_ARGS__); \ 16 | }) 17 | 18 | /* 19 | * Helper macro to place programs, maps, license in 20 | * different sections in elf_bpf file. Section names 21 | * are interpreted by elf_bpf loader 22 | */ 23 | #define SEC(NAME) __attribute__((section(NAME), used)) 24 | 25 | #ifndef __always_inline 26 | #define __always_inline __attribute__((always_inline)) 27 | #endif 28 | #ifndef __weak 29 | #define __weak __attribute__((weak)) 30 | #endif 31 | 32 | /* 33 | * Helper structure used by eBPF C program 34 | * to describe BPF map attributes to libbpf loader 35 | */ 36 | struct bpf_map_def { 37 | unsigned int type; 38 | unsigned int key_size; 39 | unsigned int value_size; 40 | unsigned int max_entries; 41 | unsigned int map_flags; 42 | }; 43 | 44 | enum libbpf_pin_type { 45 | LIBBPF_PIN_NONE, 46 | /* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */ 47 | LIBBPF_PIN_BY_NAME, 48 | }; 49 | 50 | enum libbpf_tristate { 51 | TRI_NO = 0, 52 | TRI_YES = 1, 53 | TRI_MODULE = 2, 54 | }; 55 | 56 | #define __kconfig __attribute__((section(".kconfig"))) 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/bpf_util.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (c) 2019 Facebook */ 3 | 4 | #ifndef __LIBBPF_LIBBPF_UTIL_H 5 | #define __LIBBPF_LIBBPF_UTIL_H 6 | 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /* Use these barrier functions instead of smp_[rw]mb() when they are 14 | * used in a libbpf header file. That way they can be built into the 15 | * application that uses libbpf. 16 | */ 17 | #if defined(__i386__) || defined(__x86_64__) 18 | # define libbpf_smp_rmb() asm volatile("" : : : "memory") 19 | # define libbpf_smp_wmb() asm volatile("" : : : "memory") 20 | # define libbpf_smp_mb() \ 21 | asm volatile("lock; addl $0,-4(%%rsp)" : : : "memory", "cc") 22 | /* Hinders stores to be observed before older loads. */ 23 | # define libbpf_smp_rwmb() asm volatile("" : : : "memory") 24 | #elif defined(__aarch64__) 25 | # define libbpf_smp_rmb() asm volatile("dmb ishld" : : : "memory") 26 | # define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory") 27 | # define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory") 28 | # define libbpf_smp_rwmb() libbpf_smp_mb() 29 | #elif defined(__arm__) 30 | /* These are only valid for armv7 and above */ 31 | # define libbpf_smp_rmb() asm volatile("dmb ish" : : : "memory") 32 | # define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory") 33 | # define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory") 34 | # define libbpf_smp_rwmb() libbpf_smp_mb() 35 | #else 36 | /* Architecture missing native barrier functions. */ 37 | # define libbpf_smp_rmb() __sync_synchronize() 38 | # define libbpf_smp_wmb() __sync_synchronize() 39 | # define libbpf_smp_mb() __sync_synchronize() 40 | # define libbpf_smp_rwmb() __sync_synchronize() 41 | #endif 42 | 43 | #ifdef __cplusplus 44 | } /* extern "C" */ 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/bye.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // test ir decoder 3 | // 4 | // Copyright (C) 2018 Sean Young 5 | 6 | // A lirc chardev is a device representing a consumer IR (cir) device which 7 | // can receive infrared signals from remote control and/or transmit IR. 8 | // 9 | // IR is sent as a series of pulses and space somewhat like morse code. The 10 | // BPF program can decode this into scancodes so that rc-core can translate 11 | // this into input key codes using the rc keymap. 12 | // 13 | // This test works by sending IR over rc-loopback, so the IR is processed by 14 | // BPF and then decoded into scancodes. The lirc chardev must be the one 15 | // associated with rc-loopback, see the output of ir-keytable(1). 16 | // 17 | // The following CONFIG options must be enabled for the test to succeed: 18 | // CONFIG_RC_CORE=y 19 | // CONFIG_BPF_RAWIR_EVENT=y 20 | // CONFIG_RC_LOOPBACK=y 21 | 22 | // Steps: 23 | // 1. Open the /dev/lircN device for rc-loopback (given on command line) 24 | // 2. Attach bpf_lirc_mode2 program which decodes some IR. 25 | // 3. Send some IR to the same IR device; since it is loopback, this will 26 | // end up in the bpf program 27 | // 4. bpf program should decode IR and report keycode 28 | // 5. We can read keycode from same /dev/lirc device 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "bpf_util.h" 45 | #include 46 | #include 47 | #include 48 | 49 | int main(int argc, char **argv) 50 | { 51 | struct bpf_object *obj; 52 | int ret, lircfd, progfd, inputfd; 53 | 54 | lircfd = open("/dev/treenvme0", O_RDWR | O_NONBLOCK); 55 | ret = bpf_prog_detach2(progfd, lircfd, BPF_DDP); 56 | if (ret) { 57 | printf("bpf_prog_detach2: returned %m\n"); 58 | return 1; 59 | } 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/bye.sh: -------------------------------------------------------------------------------- 1 | clang bye.c -lbpf 2 | LD_PRELOAD="../libbpf-boot/libbpf/src/libbpf.so.0" ./a.out 3 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/ddp_loader: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrp-project/BPF-KV/d4ea37c2266586b3ebfdd9351d501f27477ae2bc/ddp-artifacts/tdp/ddp_loader -------------------------------------------------------------------------------- /ddp-artifacts/tdp/ddp_loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | int bpf(int cmd, union bpf_attr * attr, unsigned int size); 14 | void load_and_attach_ddp(const char* prog_path, const char* dev_path, const char* pin_path); 15 | int get_ddp(const char* pin_path); 16 | void detach_ddp(int prog_fd, const char* dev_path); 17 | 18 | int bpf(int cmd, union bpf_attr * attr, unsigned int size){ 19 | return syscall(__NR_bpf, cmd, attr, size); 20 | } 21 | 22 | //load ddp, attach, and pin ddp program 23 | void load_and_attach_ddp(const char* prog_path, const char* dev_path, const char* pin_path){ 24 | struct stat st; 25 | void *insns; 26 | union bpf_attr load_attr; 27 | union bpf_attr attach_attr; 28 | union bpf_attr pin_attr; 29 | int prog_fd; 30 | int dev_fd; 31 | int ret; 32 | 33 | prog_fd = open(prog_path, O_RDONLY); 34 | dev_fd = open(dev_path, O_RDONLY); 35 | fstat(prog_fd, &st); 36 | insns = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, prog_fd, 0); 37 | close(prog_fd); 38 | 39 | memset(&load_attr, 0, sizeof(load_attr)); 40 | memset(&attach_attr, 0, sizeof(attach_attr)); 41 | memset(&pin_attr, 0, sizeof(pin_attr)); 42 | load_attr.prog_type = BPF_PROG_TYPE_DDP; 43 | load_attr.insns = (__u64) insns; 44 | load_attr.insn_cnt = st.st_size / sizeof(struct bpf_insn); 45 | load_attr.license = (__u64) "GPL"; 46 | 47 | prog_fd = bpf(BPF_PROG_LOAD, &load_attr, sizeof(load_attr)); 48 | printf("Prog Load FD: %d\n", prog_fd); 49 | 50 | attach_attr.target_fd = (__u32) dev_fd; 51 | attach_attr.attach_bpf_fd = (__u32) prog_fd; 52 | attach_attr.attach_type = (__u32) BPF_DDP; 53 | 54 | ret = bpf(BPF_PROG_ATTACH, &attach_attr, sizeof(attach_attr)); 55 | printf("Prog Attach FD: %d\n", ret); 56 | 57 | pin_attr.pathname = (__aligned_u64) pin_path; 58 | pin_attr.bpf_fd = (__u32) prog_fd; 59 | 60 | ret = bpf(BPF_OBJ_PIN, &pin_attr, sizeof(pin_attr)); 61 | printf("Prog Pin FD: %d\n", ret); 62 | 63 | munmap(insns, st.st_size); 64 | close(prog_fd); 65 | close(dev_fd); 66 | 67 | } 68 | 69 | //get pinned ddp program 70 | int get_ddp(const char* pin_path){ 71 | union bpf_attr get_attr; 72 | int prog_fd; 73 | 74 | memset(&get_attr, 0, sizeof(get_attr)); 75 | get_attr.pathname = (__aligned_u64) pin_path; 76 | get_attr.file_flags = O_RDWR; 77 | 78 | prog_fd = bpf(BPF_OBJ_GET, &get_attr, sizeof(get_attr)); 79 | printf("Prog Get FD: %d\n", prog_fd); 80 | return prog_fd; 81 | } 82 | 83 | //detaches ddp program 84 | void detach_ddp(int prog_fd, const char* dev_path){ 85 | union bpf_attr detach_attr; 86 | int dev_fd = open(dev_path, O_RDONLY); 87 | int ret; 88 | 89 | memset(&detach_attr, 0, sizeof(detach_attr)); 90 | detach_attr.target_fd = (__u32) dev_fd; 91 | detach_attr.attach_bpf_fd = (__u32) prog_fd; 92 | detach_attr.attach_type = (__u32) BPF_DDP; 93 | 94 | ret = bpf(BPF_PROG_DETACH, &detach_attr, sizeof(detach_attr)); 95 | printf("Prog Detach FD: %d\n", ret); 96 | } 97 | 98 | int main(int argc, char** argv){ 99 | const char* prog_path; 100 | const char* dev_path; 101 | const char* pin_path; 102 | int prog_fd; 103 | int attach = 0; 104 | int c; 105 | 106 | //check for suite_name argument if provided 107 | while ((c = getopt (argc, argv, "ab:d:p:")) != -1){ 108 | switch(c) { 109 | case 'a' : attach = 1; 110 | break; 111 | case 'b': prog_path = optarg; 112 | break; 113 | case 'd': dev_path = optarg; 114 | break; 115 | case 'p': pin_path = optarg; 116 | break; 117 | default: printf("optopt: %c\n", optopt); 118 | 119 | } 120 | } 121 | 122 | if (attach){ 123 | load_and_attach_ddp(prog_path, dev_path, pin_path); 124 | } 125 | else{ 126 | prog_fd = get_ddp(pin_path); 127 | detach_ddp(prog_fd, dev_path); 128 | } 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/ddp_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | __attribute__((section("ddp_test"), used)) 5 | int ddp_prog(char* buffer){ 6 | return 3; 7 | } 8 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/drop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | SEC("ddp_pass") 5 | int ddp_pass_func(char *ctx) 6 | { 7 | return 20; 8 | } 9 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/drop2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "simplekvspec.h" 4 | 5 | #ifndef memcpy 6 | #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) 7 | #endif 8 | 9 | struct halfnode { 10 | unsigned long num; 11 | unsigned long type; 12 | unsigned long key[31]; 13 | }; 14 | 15 | SEC("ddp_pass") 16 | unsigned long ddp_pass_func(struct ddp_key dk) 17 | { 18 | unsigned long i = 0; 19 | unsigned long key = dk.key; 20 | // struct halfnode hn; 21 | // memcpy(&hn, dk.data, sizeof(struct halfnode)); 22 | struct halfnode *hn = (struct halfnode *)dk.data; 23 | unsigned long f = hn->type == 1 ? 32 : 0; 24 | 25 | #pragma unroll 26 | for (i = 0; i < 31; i++) { 27 | if (key < hn->key[i]) { 28 | return i - 1 + f; 29 | } 30 | } 31 | return hn->num - 1 + f; 32 | } 33 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/drop3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "simplekvspec.h" 4 | 5 | #ifndef memcpy 6 | #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) 7 | #endif 8 | 9 | struct halfnode { 10 | unsigned long num; 11 | unsigned long type; 12 | unsigned long key[31]; 13 | }; 14 | 15 | struct restnode { 16 | unsigned long val[31]; 17 | }; 18 | 19 | SEC("ddp_next") 20 | unsigned long ddp_pass_func(struct ddp_key dk) 21 | { 22 | //unsigned long i = 0; 23 | //unsigned long key = dk.key; 24 | struct restnode hn; 25 | memcpy(&hn, dk.data[sizeof(struct halfnode)], sizeof(struct restnode)); 26 | return hn.val[dk.result]; 27 | } 28 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/droptree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "simplekvspec.h" 4 | 5 | #ifndef memcpy 6 | #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) 7 | #endif 8 | 9 | struct halfnode { 10 | unsigned long num; 11 | unsigned long type; 12 | unsigned long key[31]; 13 | }; 14 | 15 | SEC("ddp_pass") 16 | unsigned long ddp_pass_func(struct ddp_key dk) 17 | { 18 | unsigned long i = 0; 19 | unsigned long key = dk.key; 20 | // struct halfnode hn; 21 | // memcpy(&hn, dk.data, sizeof(struct halfnode)); 22 | struct halfnode *hn = (struct halfnode *)dk.data; 23 | 24 | if (key == 4444) 25 | { 26 | unsigned long len = 5; 27 | return len; 28 | } 29 | else { 30 | unsigned long f = hn->type == 1 ? 32 : 0; 31 | 32 | #pragma unroll 33 | for (i = 0; i < 31; i++) { 34 | if (key < hn->key[i]) { 35 | return i - 1 + f; 36 | } 37 | } 38 | return hn->num - 1 + f; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/run.sh: -------------------------------------------------------------------------------- 1 | clang test.c -lbpf 2 | LD_PRELOAD="/home/simplekv/libbpf-boot/libbpf/src/libbpf.so.0" ./a.out 3 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/run2.sh: -------------------------------------------------------------------------------- 1 | clang test2.c -lbpf 2 | LD_PRELOAD="../libbpf-boot/libbpf/src/libbpf.so.0" ./a.out 3 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/run3.sh: -------------------------------------------------------------------------------- 1 | clang test3.c -lbpf 2 | LD_PRELOAD="/home/simplekv/libbpf-boot/libbpf/src/libbpf.so.0" ./a.out 3 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/runtree.sh: -------------------------------------------------------------------------------- 1 | clang testree.c -lbpf 2 | LD_PRELOAD="../libbpf-boot/libbpf/src/libbpf.so.0" ./a.out 3 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/simplekvspec.h: -------------------------------------------------------------------------------- 1 | #ifndef SKV_H 2 | #define SKV_H 3 | 4 | #include "../db_types.h" 5 | 6 | // Node-level information 7 | #define INTERNAL 0 8 | #define LEAF 1 9 | 10 | #define FILE_MASK ((ptr__t)1 << 63) 11 | 12 | #ifndef memcpy 13 | #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) 14 | #endif 15 | 16 | static __inline ptr__t encode(ptr__t ptr) { 17 | return ptr | FILE_MASK; 18 | } 19 | 20 | static __inline ptr__t decode(ptr__t ptr) { 21 | return ptr & (~FILE_MASK); 22 | } 23 | 24 | // struct 25 | struct ddp_key{ 26 | unsigned char data[512]; 27 | unsigned long key; 28 | }; 29 | 30 | #ifdef VERBOSE 31 | #define dbg_print(...) bpf_printk(__VA_ARGS__) 32 | 33 | static __inline void print_query(struct Query *q) { 34 | dbg_print("struct Query {\n"); 35 | 36 | dbg_print("\tfound = %ld\n", q->found); 37 | dbg_print("\treached_leaf = %ld\n", q->state_flags & REACHED_LEAF); 38 | dbg_print("\tkey = %ld\n", q->key); 39 | dbg_print("\tvalue = %s\n", q->value); 40 | dbg_print("\tvalue_ptr = %ld\n", q->value_ptr); 41 | 42 | dbg_print("}\n"); 43 | } 44 | 45 | static __inline void print_node(Node *node) { 46 | dbg_print("struct Node {\n"); 47 | 48 | dbg_print("\tnum = %ld\n", node->num); 49 | dbg_print("\ttype = %ld\n", node->type); 50 | dbg_print("\tkey[0] = %ld\n", node->key[0]); 51 | dbg_print("\tkey[30] = %ld\n", node->key[NODE_CAPACITY - 1]); 52 | dbg_print("\tptr[0] = 0x%lx\n", node->ptr[0]); 53 | dbg_print("\tptr[30] = 0x%lx\n", node->ptr[NODE_CAPACITY - 1]); 54 | 55 | dbg_print("}\n"); 56 | } 57 | #else 58 | #define dbg_print(...) 59 | #endif 60 | 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/test.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // test ir decoder 3 | // 4 | // Copyright (C) 2018 Sean Young 5 | 6 | // A lirc chardev is a device representing a consumer IR (cir) device which 7 | // can receive infrared signals from remote control and/or transmit IR. 8 | // 9 | // IR is sent as a series of pulses and space somewhat like morse code. The 10 | // BPF program can decode this into scancodes so that rc-core can translate 11 | // this into input key codes using the rc keymap. 12 | // 13 | // This test works by sending IR over rc-loopback, so the IR is processed by 14 | // BPF and then decoded into scancodes. The lirc chardev must be the one 15 | // associated with rc-loopback, see the output of ir-keytable(1). 16 | // 17 | // The following CONFIG options must be enabled for the test to succeed: 18 | // CONFIG_RC_CORE=y 19 | // CONFIG_BPF_RAWIR_EVENT=y 20 | // CONFIG_RC_LOOPBACK=y 21 | 22 | // Steps: 23 | // 1. Open the /dev/lircN device for rc-loopback (given on command line) 24 | // 2. Attach bpf_lirc_mode2 program which decodes some IR. 25 | // 3. Send some IR to the same IR device; since it is loopback, this will 26 | // end up in the bpf program 27 | // 4. bpf program should decode IR and report keycode 28 | // 5. We can read keycode from same /dev/lirc device 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "bpf_util.h" 45 | #include 46 | #include 47 | #include 48 | 49 | int main(int argc, char **argv) 50 | { 51 | struct bpf_object *obj; 52 | int ret, lircfd, progfd, inputfd; 53 | int testir1 = 0x1dead; 54 | int testir2 = 0x20101; 55 | unsigned int prog_ids[10], prog_flags[10], prog_cnt; 56 | 57 | /* 58 | if (argc != 3) { 59 | printf("Usage: %s /dev/lircN /dev/input/eventM\n", argv[0]); 60 | return 2; 61 | } 62 | */ 63 | 64 | ret = bpf_prog_load("drop.o", 65 | BPF_PROG_TYPE_DDP, &obj, &progfd); 66 | if (ret) { 67 | printf("Failed to load bpf program\n"); 68 | return 1; 69 | } 70 | 71 | /* 72 | lircfd = open(argv[1], O_RDWR | O_NONBLOCK); 73 | if (lircfd == -1) { 74 | printf("failed to open lirc device %s: %m\n", argv[1]); 75 | return 1; 76 | } 77 | 78 | ret = bpf_prog_detach2(progfd, lircfd, BPF_LIRC_MODE2); 79 | if (ret != -1 || errno != ENOENT) { 80 | printf("bpf_prog_detach2 not attached should fail: %m\n"); 81 | return 1; 82 | } 83 | 84 | inputfd = open(argv[2], O_RDONLY | O_NONBLOCK); 85 | if (inputfd == -1) { 86 | printf("failed to open input device %s: %m\n", argv[1]); 87 | return 1; 88 | } 89 | 90 | prog_cnt = 10; 91 | ret = bpf_prog_query(lircfd, BPF_LIRC_MODE2, 0, prog_flags, prog_ids, 92 | &prog_cnt); 93 | if (ret) { 94 | printf("Failed to query bpf programs on lirc device: %m\n"); 95 | return 1; 96 | } 97 | 98 | if (prog_cnt != 0) { 99 | printf("Expected nothing to be attached\n"); 100 | return 1; 101 | } 102 | */ 103 | 104 | ret = bpf_prog_attach(progfd, lircfd, BPF_DDP, 0); 105 | if (ret) { 106 | printf("Failed to attach bpf to lirc device: %m\n"); 107 | return 1; 108 | } 109 | 110 | /* Write raw IR */ 111 | ret = write(lircfd, &testir1, sizeof(testir1)); 112 | if (ret != sizeof(testir1)) { 113 | printf("Failed to send test IR message: %m\n"); 114 | return 1; 115 | } 116 | 117 | struct pollfd pfd = { .fd = inputfd, .events = POLLIN }; 118 | struct input_event event; 119 | 120 | for (;;) { 121 | poll(&pfd, 1, 100); 122 | 123 | /* Read decoded IR */ 124 | ret = read(inputfd, &event, sizeof(event)); 125 | if (ret != sizeof(event)) { 126 | printf("Failed to read decoded IR: %m\n"); 127 | return 1; 128 | } 129 | 130 | if (event.type == EV_MSC && event.code == MSC_SCAN && 131 | event.value == 0xdead) { 132 | break; 133 | } 134 | } 135 | 136 | /* Write raw IR */ 137 | ret = write(lircfd, &testir2, sizeof(testir2)); 138 | if (ret != sizeof(testir2)) { 139 | printf("Failed to send test IR message: %m\n"); 140 | return 1; 141 | } 142 | 143 | for (;;) { 144 | poll(&pfd, 1, 100); 145 | 146 | /* Read decoded IR */ 147 | ret = read(inputfd, &event, sizeof(event)); 148 | if (ret != sizeof(event)) { 149 | printf("Failed to read decoded IR: %m\n"); 150 | return 1; 151 | } 152 | 153 | if (event.type == EV_REL && event.code == REL_Y && 154 | event.value == 1 ) { 155 | break; 156 | } 157 | } 158 | 159 | prog_cnt = 10; 160 | ret = bpf_prog_query(lircfd, BPF_LIRC_MODE2, 0, prog_flags, prog_ids, 161 | &prog_cnt); 162 | if (ret) { 163 | printf("Failed to query bpf programs on lirc device: %m\n"); 164 | return 1; 165 | } 166 | 167 | if (prog_cnt != 1) { 168 | printf("Expected one program to be attached\n"); 169 | return 1; 170 | } 171 | 172 | /* Let's try detaching it now it is actually attached */ 173 | ret = bpf_prog_detach2(progfd, lircfd, BPF_LIRC_MODE2); 174 | if (ret) { 175 | printf("bpf_prog_detach2: returned %m\n"); 176 | return 1; 177 | } 178 | 179 | return 0; 180 | } 181 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/test2.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // test ir decoder 3 | // 4 | // Copyright (C) 2018 Sean Young 5 | 6 | // A lirc chardev is a device representing a consumer IR (cir) device which 7 | // can receive infrared signals from remote control and/or transmit IR. 8 | // 9 | // IR is sent as a series of pulses and space somewhat like morse code. The 10 | // BPF program can decode this into scancodes so that rc-core can translate 11 | // this into input key codes using the rc keymap. 12 | // 13 | // This test works by sending IR over rc-loopback, so the IR is processed by 14 | // BPF and then decoded into scancodes. The lirc chardev must be the one 15 | // associated with rc-loopback, see the output of ir-keytable(1). 16 | // 17 | // The following CONFIG options must be enabled for the test to succeed: 18 | // CONFIG_RC_CORE=y 19 | // CONFIG_BPF_RAWIR_EVENT=y 20 | // CONFIG_RC_LOOPBACK=y 21 | 22 | // Steps: 23 | // 1. Open the /dev/lircN device for rc-loopback (given on command line) 24 | // 2. Attach bpf_lirc_mode2 program which decodes some IR. 25 | // 3. Send some IR to the same IR device; since it is loopback, this will 26 | // end up in the bpf program 27 | // 4. bpf program should decode IR and report keycode 28 | // 5. We can read keycode from same /dev/lirc device 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "bpf_util.h" 45 | #include 46 | #include 47 | #include 48 | 49 | int main(int argc, char **argv) 50 | { 51 | struct bpf_object *obj; 52 | int ret, lircfd, progfd, inputfd; 53 | int testir1 = 0x1dead; 54 | int testir2 = 0x20101; 55 | unsigned int prog_ids[10], prog_flags[10], prog_cnt; 56 | 57 | /* 58 | if (argc != 3) { 59 | printf("Usage: %s /dev/lircN /dev/input/eventM\n", argv[0]); 60 | return 2; 61 | } 62 | */ 63 | 64 | ret = bpf_prog_load("drop2.o", 65 | BPF_PROG_TYPE_DDP, &obj, &progfd); 66 | if (ret) { 67 | printf("Failed to load bpf program\n"); 68 | return 1; 69 | } 70 | 71 | lircfd = open("/dev/treenvme0", O_RDWR | O_NONBLOCK); 72 | ret = bpf_prog_attach(progfd, lircfd, BPF_DDP, 0); 73 | if (ret) { 74 | printf("Failed to attach bpf to lirc device: %m\n"); 75 | return 1; 76 | } 77 | 78 | //ret = bpf_prog_detach2(progfd, lircfd, BPF_DDP); 79 | if (ret) { 80 | printf("bpf_prog_detach2: returned %m\n"); 81 | return 1; 82 | } 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/test3.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // test ir decoder 3 | // 4 | // Copyright (C) 2018 Sean Young 5 | 6 | // A lirc chardev is a device representing a consumer IR (cir) device which 7 | // can receive infrared signals from remote control and/or transmit IR. 8 | // 9 | // IR is sent as a series of pulses and space somewhat like morse code. The 10 | // BPF program can decode this into scancodes so that rc-core can translate 11 | // this into input key codes using the rc keymap. 12 | // 13 | // This test works by sending IR over rc-loopback, so the IR is processed by 14 | // BPF and then decoded into scancodes. The lirc chardev must be the one 15 | // associated with rc-loopback, see the output of ir-keytable(1). 16 | // 17 | // The following CONFIG options must be enabled for the test to succeed: 18 | // CONFIG_RC_CORE=y 19 | // CONFIG_BPF_RAWIR_EVENT=y 20 | // CONFIG_RC_LOOPBACK=y 21 | 22 | // Steps: 23 | // 1. Open the /dev/lircN device for rc-loopback (given on command line) 24 | // 2. Attach bpf_lirc_mode2 program which decodes some IR. 25 | // 3. Send some IR to the same IR device; since it is loopback, this will 26 | // end up in the bpf program 27 | // 4. bpf program should decode IR and report keycode 28 | // 5. We can read keycode from same /dev/lirc device 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "bpf_util.h" 45 | #include 46 | #include 47 | #include 48 | 49 | int main(int argc, char **argv) 50 | { 51 | struct bpf_object *obj; 52 | int ret, lircfd, progfd, inputfd; 53 | int testir1 = 0x1dead; 54 | int testir2 = 0x20101; 55 | unsigned int prog_ids[10], prog_flags[10], prog_cnt; 56 | 57 | /* 58 | if (argc != 3) { 59 | printf("Usage: %s /dev/lircN /dev/input/eventM\n", argv[0]); 60 | return 2; 61 | } 62 | */ 63 | 64 | ret = bpf_prog_load("drop3.o", 65 | BPF_PROG_TYPE_DDP, &obj, &progfd); 66 | if (ret) { 67 | printf("Failed to load bpf program\n"); 68 | return 1; 69 | } 70 | 71 | lircfd = open("/dev/treenvme0", O_RDWR | O_NONBLOCK); 72 | ret = bpf_prog_attach(progfd, lircfd, BPF_DDP, 0); 73 | if (ret) { 74 | printf("Failed to attach bpf to lirc device: %m\n"); 75 | return 1; 76 | } 77 | 78 | ret = bpf_prog_attach(progfd, lircfd, BPF_DDP_NEXT, 0); 79 | if (ret) { 80 | printf("Failed to attach bpf to lirc device: %m\n"); 81 | return 1; 82 | } 83 | //ret = bpf_prog_detach2(progfd, lircfd, BPF_DDP); 84 | if (ret) { 85 | printf("bpf_prog_detach2: returned %m\n"); 86 | return 1; 87 | } 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /ddp-artifacts/tdp/testree.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // test ir decoder 3 | // 4 | // Copyright (C) 2018 Sean Young 5 | 6 | // A lirc chardev is a device representing a consumer IR (cir) device which 7 | // can receive infrared signals from remote control and/or transmit IR. 8 | // 9 | // IR is sent as a series of pulses and space somewhat like morse code. The 10 | // BPF program can decode this into scancodes so that rc-core can translate 11 | // this into input key codes using the rc keymap. 12 | // 13 | // This test works by sending IR over rc-loopback, so the IR is processed by 14 | // BPF and then decoded into scancodes. The lirc chardev must be the one 15 | // associated with rc-loopback, see the output of ir-keytable(1). 16 | // 17 | // The following CONFIG options must be enabled for the test to succeed: 18 | // CONFIG_RC_CORE=y 19 | // CONFIG_BPF_RAWIR_EVENT=y 20 | // CONFIG_RC_LOOPBACK=y 21 | 22 | // Steps: 23 | // 1. Open the /dev/lircN device for rc-loopback (given on command line) 24 | // 2. Attach bpf_lirc_mode2 program which decodes some IR. 25 | // 3. Send some IR to the same IR device; since it is loopback, this will 26 | // end up in the bpf program 27 | // 4. bpf program should decode IR and report keycode 28 | // 5. We can read keycode from same /dev/lirc device 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "bpf_util.h" 45 | #include 46 | #include 47 | #include 48 | 49 | int main(int argc, char **argv) 50 | { 51 | struct bpf_object *obj; 52 | int ret, lircfd, progfd, inputfd; 53 | int testir1 = 0x1dead; 54 | int testir2 = 0x20101; 55 | unsigned int prog_ids[10], prog_flags[10], prog_cnt; 56 | 57 | /* 58 | if (argc != 3) { 59 | printf("Usage: %s /dev/lircN /dev/input/eventM\n", argv[0]); 60 | return 2; 61 | } 62 | */ 63 | 64 | ret = bpf_prog_load("droptree.o", 65 | BPF_PROG_TYPE_DDP, &obj, &progfd); 66 | if (ret) { 67 | printf("Failed to load bpf program\n"); 68 | return 1; 69 | } 70 | 71 | lircfd = open("/dev/treenvme0", O_RDWR | O_NONBLOCK); 72 | ret = bpf_prog_attach(progfd, lircfd, BPF_DDP, 0); 73 | if (ret) { 74 | printf("Failed to attach bpf to lirc device: %m\n"); 75 | return 1; 76 | } 77 | 78 | //ret = bpf_prog_detach2(progfd, lircfd, BPF_DDP); 79 | if (ret) { 80 | printf("bpf_prog_detach2: returned %m\n"); 81 | return 1; 82 | } 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /ddp-artifacts/trace/cmd.sh: -------------------------------------------------------------------------------- 1 | sudo trace-cmd record -p function_graph -g nvme_irq 2 | -------------------------------------------------------------------------------- /get.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "get.h" 7 | #include "parse.h" 8 | #include "db_types.h" 9 | #include "helpers.h" 10 | #include "simplekv.h" 11 | 12 | 13 | int do_get_cmd(int argc, char *argv[], struct ArgState *as) { 14 | struct GetArgs ga = { 15 | .database_layers = as->layers, 16 | .threads = 1, 17 | .requests = 500 18 | }; 19 | parse_get_opts(argc, argv, &ga); 20 | 21 | /* Load BPF program */ 22 | int bpf_fd = -1; 23 | if (ga.xrp) { 24 | bpf_fd = load_bpf_program("xrp-bpf/get.o"); 25 | } 26 | 27 | if (ga.key_set) { 28 | return lookup_single_key(as->filename, ga.key, ga.xrp, bpf_fd); 29 | } 30 | 31 | return run(as->filename, as->layers, ga.requests, ga.threads, ga.xrp, bpf_fd, ga.cache_level); 32 | } 33 | 34 | 35 | 36 | int lookup_single_key(char *filename, long key, int use_xrp, int bpf_fd) { 37 | /* Lookup Single Key */ 38 | char *value = grab_value(filename, key, use_xrp, bpf_fd, ROOT_NODE_OFFSET); 39 | printf("Key: %ld\n", key); 40 | if (value == NULL) { 41 | printf("Value not found\n"); 42 | return 1; 43 | } 44 | char *nospace = value; 45 | while (*nospace != '\0' && isspace((int) *nospace)) { 46 | ++nospace; 47 | } 48 | printf("Value %s\n", nospace); 49 | free(value); 50 | return 0; 51 | } 52 | 53 | char *grab_value(char *file_name, unsigned long const key, int use_xrp, int bpf_fd, ptr__t index_offset) { 54 | char *const retval = malloc(sizeof(val__t) + 1); 55 | if (retval == NULL) { 56 | perror("malloc"); 57 | exit(1); 58 | } 59 | /* Ensure we have a null at the end of the string */ 60 | retval[sizeof(val__t)] = '\0'; 61 | 62 | /* Open the database */ 63 | int flags = O_RDONLY; 64 | if (use_xrp) { 65 | flags = flags | O_DIRECT; 66 | } 67 | int db_fd = open(file_name, flags); 68 | if (db_fd < 0) { 69 | perror("failed to open database"); 70 | exit(1); 71 | } 72 | 73 | struct Query query = new_query(key); 74 | if (use_xrp) { 75 | long ret = lookup_bpf(db_fd, bpf_fd, &query, index_offset); 76 | 77 | if (ret < 0) { 78 | printf("reached leaf? %ld\n", query.state_flags); 79 | fprintf(stderr, "read xrp failed with code %d\n", errno); 80 | fprintf(stderr, "%s\n", strerror(errno)); 81 | exit(errno); 82 | } 83 | if (query.found == 0) { 84 | printf("reached leaf? %ld\n", query.state_flags); 85 | printf("result not found\n"); 86 | exit(1); 87 | } 88 | } else { 89 | if (lookup_key_userspace(db_fd, &query, index_offset)) { 90 | free(retval); 91 | close(db_fd); 92 | return NULL; 93 | } 94 | /* Traverse b+ tree index in db to find value and verify the key exists in leaf node */ 95 | } 96 | memcpy(retval, query.value, sizeof(query.value)); 97 | close(db_fd); 98 | return retval; 99 | } 100 | 101 | /** 102 | * Traverses the B+ tree index and retrieves the value associated with 103 | * [key] from the heap, if [key] is in the database. 104 | * @param file_name 105 | * @param key 106 | * @param index_offset Offset into the B+tree index to begin the traversal inside the index 107 | * if caching is used. 108 | * @return null terminated string containing the value on disk, or NULL if key not found 109 | */ 110 | 111 | long lookup_key_userspace(int db_fd, struct Query *query, ptr__t index_offset) { 112 | /* Traverse b+ tree index in db to find value and verify the key exists in leaf node */ 113 | Node node = { 0 }; 114 | if (get_leaf_containing(db_fd, query->key, &node, index_offset) != 0 || !key_exists(query->key, &node)) { 115 | query->found = 0; 116 | return -1; 117 | } 118 | read_value_the_hard_way(db_fd, (char *) query->value, nxt_node(query->key, &node)); 119 | query->found = 1; 120 | return 0; 121 | } 122 | 123 | /* Function using the same bit fiddling that we use in the BPF function */ 124 | void read_value_the_hard_way(int fd, char *retval, ptr__t ptr) { 125 | /* Aligned buffer for O_DIRECT read */ 126 | char *buf = (char *) aligned_alloca(BLK_SIZE, BLK_SIZE); 127 | 128 | /* Base of the block containing our value */ 129 | ptr__t base = decode(ptr) & ~(BLK_SIZE - 1); 130 | checked_pread(fd, buf, BLK_SIZE, (long) base); 131 | ptr__t offset = decode(ptr) & (BLK_SIZE - 1); 132 | memcpy(retval, buf + offset, sizeof(val__t)); 133 | } 134 | -------------------------------------------------------------------------------- /get.h: -------------------------------------------------------------------------------- 1 | #ifndef _GET_H_ 2 | #define _GET_H_ 3 | 4 | #include "db_types.h" 5 | 6 | struct ArgState; 7 | 8 | int do_get_cmd(int argc, char *argv[], struct ArgState *as); 9 | 10 | int lookup_single_key(char *filename, long key, int use_xrp, int bpf_fd); 11 | 12 | char *grab_value(char *file_name, unsigned long key, int use_xrp, int bpf_fd, ptr__t index_offset); 13 | 14 | long lookup_key_userspace(int db_fd, struct Query *query, ptr__t index_offset); 15 | 16 | void read_value_the_hard_way(int fd, char *retval, ptr__t ptr); 17 | 18 | #endif /* _GET_H_ */ -------------------------------------------------------------------------------- /helpers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "helpers.h" 7 | 8 | /** 9 | * Get the leaf node that MAY contain [key]. 10 | * 11 | * Note: It is up to the caller to verify that the node actually contains [key]. 12 | * If it does not, then [key] does not exist in the database. 13 | * 14 | * @param database_fd - File descriptor for open database file 15 | * @param key 16 | * @param *node - Pointer to Node that will be populated on success 17 | * @return 0 on success (node retrieved), -1 on error 18 | */ 19 | int _get_leaf_containing(int database_fd, key__t key, Node *node, ptr__t index_offset, ptr__t *node_offset) { 20 | Node *const tmp_node = (Node *) aligned_alloca(BLK_SIZE, sizeof(Node)); 21 | long bytes_read = pread(database_fd, tmp_node, sizeof(Node), (long) index_offset); 22 | if (bytes_read != sizeof(Node)) { 23 | return -1; 24 | } 25 | ptr__t ptr = nxt_node(key, tmp_node); 26 | while (tmp_node->type != LEAF) { 27 | bytes_read = pread(database_fd, tmp_node, sizeof(Node), (long) decode(ptr)); 28 | if (bytes_read != sizeof(Node)) { 29 | return -1; 30 | } 31 | *node_offset = ptr; 32 | ptr = nxt_node(key, tmp_node); 33 | } 34 | *node = *tmp_node; 35 | return 0; 36 | } 37 | 38 | int get_leaf_containing(int database_fd, key__t key, Node *node, ptr__t index_offset) { 39 | ptr__t x = 0; 40 | return _get_leaf_containing(database_fd, key, node, index_offset, &x); 41 | } 42 | 43 | long lookup_bpf(int db_fd, int bpf_fd, struct Query *query, ptr__t index_offset) { 44 | /* Set up buffers and query */ 45 | char *buf = (char *) aligned_alloca(0x1000, 0x1000); 46 | char *scratch = (char *) aligned_alloca(0x1000, SCRATCH_SIZE); 47 | memset(buf, 0, 0x1000); 48 | memset(scratch, 0, 0x1000); 49 | 50 | struct ScatterGatherQuery *sgq = (struct ScatterGatherQuery *) scratch; 51 | sgq->keys[0] = query->key; 52 | sgq->n_keys = 1; 53 | 54 | /* Syscall to invoke BPF function that we loaded out-of-band previously */ 55 | long ret = syscall(SYS_READ_XRP, db_fd, buf, BLK_SIZE, index_offset, bpf_fd, scratch); 56 | 57 | struct MaybeValue *maybe_v = &sgq->values[0]; 58 | query->found = (long) maybe_v->found; 59 | if (query->found) { 60 | memcpy(query->value, maybe_v->value, sizeof(val__t)); 61 | } 62 | 63 | return ret; 64 | } 65 | 66 | /* Helper function that terminates the program is pread fails */ 67 | void checked_pread(int fd, void *buf, size_t size, long offset) { 68 | ssize_t bytes_read = pread(fd, buf, size, offset); 69 | if (bytes_read < 0) { 70 | perror("checked_pread: "); 71 | exit(1); 72 | } 73 | if ((size_t) bytes_read != size) { 74 | fprintf(stderr, "partial read %ld bytes of Node\n", bytes_read); 75 | exit(1); 76 | } 77 | } 78 | 79 | /** 80 | * Finds the file offset for the next node to traverse to in the B+ tree 81 | * @param key 82 | * @param node 83 | * @return B+ tree encoded byte offset into the db file 84 | */ 85 | ptr__t nxt_node(unsigned long key, Node *node) { 86 | for (size_t i = 1; i < NODE_CAPACITY; ++i) { 87 | if (key < node->key[i]) { 88 | return node->ptr[i - 1]; 89 | } 90 | } 91 | /* Key wasn't smaller than any of node->key[x], so take the last ptr */ 92 | return node->ptr[NODE_CAPACITY - 1]; 93 | } 94 | 95 | /** 96 | * Verifies that [key] exists in the leaf [node] 97 | * @param key 98 | * @param node 99 | * @return 1 if [key] exists, else 0 100 | */ 101 | int key_exists(unsigned long const key, Node const *node) { 102 | for (unsigned int i = 0; i < NODE_CAPACITY; ++i) { 103 | if (node->key[i] == key) { 104 | return 1; 105 | } 106 | } 107 | return 0; 108 | } 109 | 110 | int compare_nodes(Node *x, Node *y) { 111 | if (x->type != y->type) { 112 | printf("type differs %lu %lu\n", x->type, y->type); 113 | return 0; 114 | } 115 | for (size_t i = 0; i < NODE_CAPACITY; i++) 116 | if (x->key[i] != y->key[i] || x->ptr[i] != y->ptr[i]) { 117 | printf("bucket %lu differs x.key %lu y.key %lu x.ptr %lu y.ptr %lu\n", 118 | i, x->key[i], y->key[i], x->ptr[i], y->ptr[i]); 119 | return 0; 120 | } 121 | return 1; 122 | } 123 | 124 | long calculate_max_key(unsigned int layers) { 125 | long result = 1; 126 | for (unsigned int i = 0; i < layers; ++i) { 127 | result *= FANOUT; 128 | } 129 | /* Subtract one due to zero indexing of keys */ 130 | return result - 1; 131 | } 132 | 133 | int load_bpf_program(char *path) { 134 | struct bpf_object *obj; 135 | int ret, progfd; 136 | 137 | ret = bpf_prog_load(path, BPF_PROG_TYPE_XRP, &obj, &progfd); 138 | if (ret) { 139 | printf("Failed to load bpf program\n"); 140 | exit(1); 141 | } 142 | 143 | return progfd; 144 | } 145 | -------------------------------------------------------------------------------- /helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef HELPERS_H 2 | #define HELPERS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "db_types.h" 18 | 19 | #define SYS_READ_XRP 445 20 | 21 | #define NS_PER_SEC 1000000000 22 | #define US_PER_NS 1000 23 | 24 | #define aligned_alloca(align, size) (((uintptr_t) alloca((size) + (align) - 1) + ((align) - 1)) & ~ (uintptr_t) ((align) - 1)); 25 | 26 | long lookup_bpf(int db_fd, int bpf_fd, struct Query *query, ptr__t index_offset); 27 | 28 | void checked_pread(int fd, void *buf, size_t size, long offset); 29 | 30 | ptr__t nxt_node(unsigned long key, Node *node); 31 | 32 | int key_exists(unsigned long key, Node const *node); 33 | 34 | int _get_leaf_containing(int database_fd, key__t key, Node *node, ptr__t index_offset, ptr__t *node_offset); 35 | int get_leaf_containing(int database_fd, key__t key, Node *node, ptr__t index_offset); 36 | 37 | static inline long strtol_or_exit(char *str, char *fail_msg) { 38 | char *endptr = NULL; 39 | errno = 0; 40 | long result = strtol(str, &endptr, 10); 41 | if ((endptr != NULL && *endptr != '\0') || errno != 0) { 42 | fprintf(stderr, "%s", fail_msg); 43 | exit(1); 44 | } 45 | return result; 46 | } 47 | 48 | static inline unsigned long strtoul_or_exit(char *str, char *fail_msg) { 49 | char *endptr = NULL; 50 | errno = 0; 51 | unsigned long result = strtoul(str, &endptr, 10); 52 | if ((endptr != NULL && *endptr != '\0') || errno != 0) { 53 | fprintf(stderr, "%s", fail_msg); 54 | exit(1); 55 | } 56 | return result; 57 | } 58 | 59 | int compare_nodes(Node *x, Node *y); 60 | 61 | long calculate_max_key(unsigned int layers); 62 | 63 | int load_bpf_program(char *path); 64 | 65 | #define BUG_ON(condition) \ 66 | do { \ 67 | if (condition) \ 68 | abort(); \ 69 | } while (0) 70 | 71 | #endif /* HELPERS_H */ -------------------------------------------------------------------------------- /parse.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARSE_H_ 2 | #define _PARSE_H_ 3 | 4 | #include 5 | 6 | #define CACHE_ARG_KEY 1337 7 | #define RANGE_SUM_KEY 9999 8 | 9 | struct ArgState { 10 | /* Required Args */ 11 | char *filename; 12 | int layers; 13 | 14 | int subcommand_retval; 15 | }; 16 | 17 | struct GetArgs { 18 | long key; 19 | 20 | /* Flags */ 21 | int key_set; 22 | int xrp; 23 | 24 | int threads; 25 | int requests; 26 | size_t cache_level; 27 | size_t database_layers; 28 | }; 29 | 30 | struct RangeArgs { 31 | int dump_flag; 32 | int xrp; 33 | unsigned long range_begin; 34 | unsigned long range_end; 35 | long requests; 36 | long range_size; 37 | 38 | int agg_op; 39 | }; 40 | 41 | static inline struct ArgState default_argstate(void) { 42 | struct ArgState as = { 0 }; 43 | return as; 44 | } 45 | 46 | struct Range { 47 | unsigned long begin; 48 | unsigned long end; 49 | }; 50 | 51 | int run_subcommand(struct argp_state *state, char *cmd_name, int(*subcommand)(int argc, char* argv[], struct ArgState*)); 52 | 53 | 54 | 55 | int parse_range(struct Range *range, char *range_str); 56 | 57 | void parse_range_opts(int argc, char *argv[], struct RangeArgs *range_args); 58 | 59 | void parse_get_opts(int argc, char *argv[], struct GetArgs *get_args); 60 | 61 | void parse_create_opts(int argc, char *argv[]); 62 | 63 | #endif /* _PARSE_H_ */ -------------------------------------------------------------------------------- /range.h: -------------------------------------------------------------------------------- 1 | #ifndef _RANGE_H 2 | #define _RANGE_H 3 | 4 | #include "db_types.h" 5 | 6 | struct ArgState; 7 | 8 | int do_range_cmd(int argc, char *argv[], struct ArgState*); 9 | 10 | int submit_range_query(struct RangeQuery *query, int db_fd, int use_xrp, int bpf_fd); 11 | 12 | int iter_print(int idx, Node *node, void *state); 13 | 14 | typedef int(*key_iter_action)(int idx, Node *node, void *state); 15 | 16 | int iterate_keys(char *filename, int levels, key__t start_key, key__t end_key, 17 | key_iter_action fn, void *fn_state); 18 | 19 | #endif /* _RANGE_H */ -------------------------------------------------------------------------------- /simplekv.h: -------------------------------------------------------------------------------- 1 | #ifndef OLIVER_DB_H 2 | #define OLIVER_DB_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "db_types.h" 12 | 13 | // Database-level information 14 | #define LOAD_MODE 0 15 | #define RUN_MODE 1 16 | 17 | #define CREATE_CMD "create" 18 | #define RANGE_CMD "range" 19 | #define GET_CMD "get" 20 | 21 | extern size_t worker_num; 22 | extern size_t total_node; 23 | extern size_t *layer_cap; 24 | extern key__t max_key; 25 | extern Node *cache; 26 | extern size_t cache_cap; 27 | 28 | typedef struct { 29 | size_t op_count; 30 | size_t index; 31 | int db_handler; 32 | size_t timer; 33 | int use_xrp; 34 | int bpf_fd; 35 | size_t *latency_arr; 36 | } WorkerArg; 37 | 38 | int get_handler(char *db_path, int flag); 39 | 40 | int run(char *db_path, size_t layer_num, size_t request_num, size_t thread_num, int use_xrp, int bpf_fd, size_t cache_level); 41 | 42 | void *subtask(void *args); 43 | 44 | void build_cache(int db_fd, size_t layer_num, size_t cache_level); 45 | 46 | void read_node(ptr__t ptr, Node *node, int db_handler); 47 | 48 | void read_log(ptr__t ptr, Log *log, int db_handler); 49 | 50 | int initialize(size_t layer_num, int mode, char *db_path); 51 | 52 | void initialize_workers(WorkerArg *args, size_t total_op_count, char *db_path, int use_xrp, int bpf_fd); 53 | 54 | void start_workers(pthread_t *tids, WorkerArg *args); 55 | 56 | void terminate_workers(pthread_t *tids, WorkerArg *args); 57 | 58 | int terminate(void); 59 | 60 | int compare_nodes(Node *x, Node *y); 61 | 62 | void print_node(ptr__t ptr, Node *node); 63 | 64 | void free_globals(void); 65 | 66 | #endif /* OLIVER_DB_H */ -------------------------------------------------------------------------------- /xrp-bpf/.gitignore: -------------------------------------------------------------------------------- 1 | *.ll 2 | *.o 3 | *.insn 4 | *.out 5 | a.out 6 | -------------------------------------------------------------------------------- /xrp-bpf/Makefile: -------------------------------------------------------------------------------- 1 | LLC ?= llc 2 | CLANG ?= clang 3 | CC ?= gcc 4 | 5 | BPF_CFLAGS ?= -I$(LIBBPF_DIR)/build/usr/ 6 | 7 | all: get.o range.o 8 | 9 | 10 | get.o: get.c simplekvspec.h ../db_types.h 11 | 12 | range.o: range.c simplekvspec.h ../db_types.h 13 | 14 | 15 | %.o: %.c 16 | $(CLANG) -S \ 17 | -target bpf \ 18 | -D __BPF_TRACING__ \ 19 | $(BPF_CFLAGS) \ 20 | -Wall \ 21 | -Wno-unused-value \ 22 | -Wno-pointer-sign \ 23 | -Wno-compare-distinct-pointer-types \ 24 | -Werror \ 25 | -O2 -emit-llvm -c -g -o ${@:.o=.ll} $< 26 | $(LLC) -march=bpf -filetype=obj -o $@ ${@:.o=.ll} 27 | 28 | 29 | .PHONY: clean 30 | clean: 31 | rm -rf *.o 32 | -------------------------------------------------------------------------------- /xrp-bpf/get.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BPF program for simple-kv 3 | * 4 | * Author: etm2131@columbia.edu 5 | */ 6 | #include 7 | #include 8 | #include "simplekvspec.h" 9 | 10 | #ifndef NULL 11 | #define NULL 0 12 | #endif 13 | 14 | char LICENSE[] SEC("license") = "GPL"; 15 | 16 | static __inline int key_exists(unsigned long const key, Node *node) { 17 | /* Safety: NULL is never passed for node, but mr. verifier doesn't know that */ 18 | dbg_print("simplekv-bpf: key_exists entered\n"); 19 | if (node == NULL) 20 | return -1; 21 | for (int i = 0; i < NODE_CAPACITY; ++i) { 22 | if (node->key[i] == key) { 23 | return 1; 24 | } 25 | } 26 | return 0; 27 | } 28 | 29 | static __inline ptr__t nxt_node(unsigned long key, Node *node) { 30 | /* Safety: NULL is never passed for node, but mr. verifier doesn't know that */ 31 | dbg_print("simplekv-bpf: nxt_node entered\n"); 32 | if (node == NULL) 33 | return -1; 34 | for (int i = 1; i < NODE_CAPACITY; ++i) { 35 | if (key < node->key[i]) { 36 | return node->ptr[i - 1]; 37 | } 38 | } 39 | /* Key wasn't smaller than any of node->key[x], so take the last ptr */ 40 | return node->ptr[NODE_CAPACITY - 1]; 41 | } 42 | 43 | /* State flags */ 44 | #define AT_VALUE 1 45 | 46 | static __inline void set_context_next_index(struct bpf_xrp *context, struct ScatterGatherQuery *query) { 47 | query->current_index += 1; 48 | query->state_flags = 0; 49 | if (query->current_index >= query->n_keys || query->current_index >= SG_KEYS) { 50 | context->done = 1; 51 | context->next_addr[0] = 0; 52 | context->size[0] = 0; 53 | } else { 54 | context->next_addr[0] = query->root_pointer; 55 | context->size[0] = BLK_SIZE; 56 | } 57 | } 58 | 59 | /* Mask to prevent out of bounds memory access */ 60 | #define EBPF_CONTEXT_MASK SG_KEYS - 1 61 | 62 | SEC("oliver_agg") 63 | unsigned int oliver_agg_func(struct bpf_xrp *context) { 64 | struct ScatterGatherQuery *query = (struct ScatterGatherQuery*) context->scratch; 65 | Node *node = (Node *) context->data; 66 | int *curr_idx = &query->current_index; 67 | 68 | /* Three cases: 69 | * 70 | * 1. We've found the log offset in the previous iteration and are 71 | * now reading the value into the query result. If there are more 72 | * keys to process, start again at the node. 73 | * 74 | * 2. We've found a leaf node and need to a) verify the key exists and 2) 75 | * get the log offset and make one more resubmission to read the value. 76 | * If the keys is missing, but there are more keys to process, start again 77 | * at the root. 78 | * 79 | * 3. We're in an internal node and need to keep traversing the B+ tree 80 | */ 81 | 82 | /* Case 1: read value into query result */ 83 | dbg_print("simplekv-bpf: entered\n"); 84 | if (query->state_flags & AT_VALUE) { 85 | dbg_print("simplekv-bpf: case 1 - value found\n"); 86 | 87 | ptr__t offset = query->value_ptr & (BLK_SIZE - 1); 88 | struct MaybeValue *mv = &query->values[*curr_idx & EBPF_CONTEXT_MASK]; 89 | mv->found = 1; 90 | memcpy(mv->value, context->data + offset, sizeof(val__t)); 91 | 92 | set_context_next_index(context, query); 93 | return 0; 94 | } 95 | 96 | /* Case 2: verify key & submit read for block containing value */ 97 | if (node->type == LEAF) { 98 | dbg_print("simplekv-bpf: case 2 - verify key & get last block\n"); 99 | 100 | query->state_flags = REACHED_LEAF; 101 | if (!key_exists(query->keys[*curr_idx & EBPF_CONTEXT_MASK], node)) { 102 | dbg_print("simplekv-bpf: key doesn't exist\n"); 103 | 104 | /* Skip this key */ 105 | query->values[*curr_idx & EBPF_CONTEXT_MASK].found = 0; 106 | set_context_next_index(context, query); 107 | return 0; 108 | } 109 | query->state_flags = AT_VALUE; 110 | query->value_ptr = decode(nxt_node(query->keys[*curr_idx & EBPF_CONTEXT_MASK], node)); 111 | /* Need to submit a request for base of the block containing our offset */ 112 | ptr__t base = query->value_ptr & ~(BLK_SIZE - 1); 113 | context->next_addr[0] = base; 114 | context->size[0] = BLK_SIZE; 115 | return 0; 116 | } 117 | 118 | /* Case 3: at an internal node, keep going */ 119 | dbg_print("simplekv-bpf: case 3 - internal node\n"); 120 | context->next_addr[0] = decode(nxt_node(query->keys[*curr_idx & EBPF_CONTEXT_MASK], node)); 121 | context->size[0] = BLK_SIZE; 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /xrp-bpf/simplekvspec.h: -------------------------------------------------------------------------------- 1 | #ifndef SKV_H 2 | #define SKV_H 3 | 4 | #include "../db_types.h" 5 | 6 | // Node-level information 7 | #define INTERNAL 0 8 | #define LEAF 1 9 | 10 | #define FILE_MASK ((ptr__t)1 << 63) 11 | 12 | #ifndef memcpy 13 | #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) 14 | #endif 15 | 16 | // struct 17 | struct ddp_key{ 18 | unsigned char data[512]; 19 | unsigned long key; 20 | }; 21 | 22 | #ifdef VERBOSE 23 | #define dbg_print(...) bpf_printk(__VA_ARGS__) 24 | 25 | static __inline void print_query(struct Query *q) { 26 | dbg_print("struct Query {\n"); 27 | 28 | dbg_print("\tfound = %ld\n", q->found); 29 | dbg_print("\treached_leaf = %ld\n", q->state_flags & REACHED_LEAF); 30 | dbg_print("\tkey = %ld\n", q->key); 31 | dbg_print("\tvalue = %s\n", q->value); 32 | dbg_print("\tvalue_ptr = %ld\n", q->value_ptr); 33 | 34 | dbg_print("}\n"); 35 | } 36 | 37 | static __inline void print_node(Node *node) { 38 | dbg_print("struct Node {\n"); 39 | 40 | dbg_print("\tnum = %ld\n", node->num); 41 | dbg_print("\ttype = %ld\n", node->type); 42 | dbg_print("\tkey[0] = %ld\n", node->key[0]); 43 | dbg_print("\tkey[30] = %ld\n", node->key[NODE_CAPACITY - 1]); 44 | dbg_print("\tptr[0] = 0x%lx\n", node->ptr[0]); 45 | dbg_print("\tptr[30] = 0x%lx\n", node->ptr[NODE_CAPACITY - 1]); 46 | 47 | dbg_print("}\n"); 48 | } 49 | #else 50 | #define dbg_print(...) 51 | #endif 52 | 53 | 54 | 55 | #endif 56 | --------------------------------------------------------------------------------