diff --git a/core/Readme.md b/core/Readme.md index 0d25c2cf..707a8d2c 100644 --- a/core/Readme.md +++ b/core/Readme.md @@ -8,12 +8,24 @@ To start with, a simple constraint would be "range constraint", meaning a regist One opinion, one benefit of designing the raw constraint from is that our runtime-check system will not depend heavily on the current linux verifier and will be portable to other verifiers. +## Future work + +Rewrite Normalization. Plain the IR. + +Just store the allocated position in value. Not track users. No references. + +All VRs are changed to Real Registers. + ## Bugs ### SplitBB operation may not work properly if it's at the top of a BB +Resolved. + ### Coalesce has some bugs +Found root cause: you may not directly remove instructions like r1 = r1. + ## Errors Reproduce: `ringbuf.c` enable coalesce will cause some error in CG diff --git a/core/aux/kern_utils.c b/core/aux/kern_utils.c index 13ea743c..c1851201 100644 --- a/core/aux/kern_utils.c +++ b/core/aux/kern_utils.c @@ -82,6 +82,10 @@ static int apply_pass_opt(struct bpf_ir_env *env, const char *opt) } } } + if (!found_pass) { + PRINT_LOG_ERROR(env, "Pass %s not found\n", pass_name); + return -EINVAL; + } return 0; } @@ -97,6 +101,8 @@ static int apply_global_opt(struct bpf_ir_env *env, const char *opt) env->opts.print_mode = BPF_IR_PRINT_DUMP; } else if (strcmp(opt, "print_detail") == 0) { env->opts.print_mode = BPF_IR_PRINT_DETAIL; + } else if (strcmp(opt, "no_prog_check") == 0) { + env->opts.disable_prog_check = true; } else if (strcmp(opt, "print_bpf_detail") == 0) { env->opts.print_mode = BPF_IR_PRINT_BPF_DETAIL; } else if (strncmp(opt, "verbose=", 8) == 0) { @@ -128,6 +134,9 @@ static int apply_global_opt(struct bpf_ir_env *env, const char *opt) // Check if a builtin pass is enabled (by cfg) bool bpf_ir_builtin_pass_enabled(struct bpf_ir_env *env, const char *pass_name) { + if (!env) { + return false; + } for (size_t i = 0; i < env->opts.builtin_pass_cfg_num; ++i) { if (strcmp(env->opts.builtin_pass_cfg[i].name, pass_name) == 0) { diff --git a/core/aux/prog_check.c b/core/aux/prog_check.c index bdf6dbde..b6d0a01e 100644 --- a/core/aux/prog_check.c +++ b/core/aux/prog_check.c @@ -390,75 +390,6 @@ static void check_phi(struct bpf_ir_env *env, struct ir_function *fun) } } -static void bpf_ir_fix_bb_succ(struct bpf_ir_env *env, struct ir_function *fun) -{ - struct ir_basic_block **pos; - array_for(pos, fun->all_bbs) - { - struct ir_basic_block *bb = *pos; - struct ir_insn *insn = bpf_ir_get_last_insn(bb); - if (insn && bpf_ir_is_cond_jmp(insn)) { - // Conditional jmp - if (bb->succs.num_elem != 2) { - print_ir_insn_err(env, insn, - "Jump instruction"); - RAISE_ERROR( - "Conditional jmp with != 2 successors"); - } - struct ir_basic_block **s1 = array_get( - &bb->succs, 0, struct ir_basic_block *); - struct ir_basic_block **s2 = array_get( - &bb->succs, 1, struct ir_basic_block *); - *s1 = insn->bb1; - *s2 = insn->bb2; - } - } -} - -static void add_reach(struct bpf_ir_env *env, struct ir_function *fun, - struct ir_basic_block *bb) -{ - if (bb->_visited) { - return; - } - bb->_visited = 1; - bpf_ir_array_push(env, &fun->reachable_bbs, &bb); - - struct ir_basic_block **succ; - bool first = false; - array_for(succ, bb->succs) - { - if (!first && bb->succs.num_elem > 1) { - first = true; - // Check if visited - if ((*succ)->_visited) { - RAISE_ERROR("Loop BB detected"); - } - } - add_reach(env, fun, *succ); - } -} - -static void gen_reachable_bbs(struct bpf_ir_env *env, struct ir_function *fun) -{ - bpf_ir_clean_visited(fun); - bpf_ir_array_clear(env, &fun->reachable_bbs); - add_reach(env, fun, fun->entry); -} - -static void gen_end_bbs(struct bpf_ir_env *env, struct ir_function *fun) -{ - struct ir_basic_block **pos; - bpf_ir_array_clear(env, &fun->end_bbs); - array_for(pos, fun->reachable_bbs) - { - struct ir_basic_block *bb = *pos; - if (bb->succs.num_elem == 0) { - bpf_ir_array_push(env, &fun->end_bbs, &bb); - } - } -} - // Interface Implementation static void check_err_and_print(struct bpf_ir_env *env, struct ir_function *fun) @@ -477,17 +408,6 @@ static void check_err_and_print(struct bpf_ir_env *env, struct ir_function *fun) // Check that the program is valid and able to be compiled void bpf_ir_prog_check(struct bpf_ir_env *env, struct ir_function *fun) { - print_ir_err_init(fun); - - bpf_ir_fix_bb_succ(env, fun); - CHECK_DUMP(); - - bpf_ir_clean_metadata_all(fun); - gen_reachable_bbs(env, fun); - CHECK_DUMP(); - gen_end_bbs(env, fun); - CHECK_DUMP(); - check_insn(env, fun); CHECK_DUMP(); diff --git a/core/bpf_ir.c b/core/bpf_ir.c index c55582a4..d1ebf9d5 100644 --- a/core/bpf_ir.c +++ b/core/bpf_ir.c @@ -264,6 +264,20 @@ static int compare_num(const void *a, const void *b) return 0; } +static bool is_raw_insn_breakpoint(u8 code) +{ + // exit, jmp (not call) is breakpoint + if (BPF_CLASS(code) == BPF_JMP || BPF_CLASS(code) == BPF_JMP32) { + if (BPF_OP(code) != BPF_CALL) { + return true; + } else { + // call is not a breakpoint + return false; + } + } + return false; +} + // Add current_pos --> entrance_pos in bb_entrances static void add_entrance_info(struct bpf_ir_env *env, const struct bpf_insn *insns, @@ -283,11 +297,16 @@ static void add_entrance_info(struct bpf_ir_env *env, // New entrance struct array preds; INIT_ARRAY(&preds, size_t); - size_t last_pos = entrance_pos - 1; - u8 code = insns[last_pos].code; - if (!(BPF_OP(code) == BPF_JA || BPF_OP(code) == BPF_EXIT)) { - // BPF_EXIT - bpf_ir_array_push_unique(env, &preds, &last_pos); + if (entrance_pos >= 1) { + size_t last_pos = entrance_pos - 1; + u8 code = insns[last_pos].code; + if (!is_raw_insn_breakpoint(code)) { // Error! + // Breaking point + // rx = ... + // BB Entrance + // ==> Add preds + bpf_ir_array_push_unique(env, &preds, &last_pos); + } } bpf_ir_array_push_unique(env, &preds, ¤t_pos); struct bb_entrance_info new_bb; @@ -1462,27 +1481,146 @@ static void init_function(struct bpf_ir_env *env, struct ir_function *fun, } } -static void run_single_pass(struct bpf_ir_env *env, struct ir_function *fun, - const struct function_pass *pass, void *param) +static void bpf_ir_fix_bb_succ(struct bpf_ir_env *env, struct ir_function *fun) +{ + struct ir_basic_block **pos; + array_for(pos, fun->all_bbs) + { + struct ir_basic_block *bb = *pos; + struct ir_insn *insn = bpf_ir_get_last_insn(bb); + if (insn && bpf_ir_is_cond_jmp(insn)) { + // Conditional jmp + if (bb->succs.num_elem != 2) { + print_ir_insn_err(env, insn, + "Jump instruction"); + RAISE_ERROR( + "Conditional jmp with != 2 successors"); + } + struct ir_basic_block **s1 = array_get( + &bb->succs, 0, struct ir_basic_block *); + struct ir_basic_block **s2 = array_get( + &bb->succs, 1, struct ir_basic_block *); + *s1 = insn->bb1; + *s2 = insn->bb2; + } + } +} + +static void add_reach(struct bpf_ir_env *env, struct ir_function *fun, + struct ir_basic_block *bb) +{ + if (bb->_visited) { + return; + } + // bb->_visited = 1; + // bpf_ir_array_push(env, &fun->reachable_bbs, &bb); + struct array todo; + INIT_ARRAY(&todo, struct ir_basic_block *); + + // struct ir_basic_block **succ; + // bool first = false; + // array_for(succ, bb->succs) + // { + // if (!first && bb->succs.num_elem > 1) { + // first = true; + // // Check if visited + // if ((*succ)->_visited) { + // RAISE_ERROR("Loop BB detected"); + // } + // } + // add_reach(env, fun, *succ); + // } + + // First Test sanity ... TODO! + + struct ir_basic_block *cur_bb = bb; + + while (1) { + cur_bb->_visited = 1; + bpf_ir_array_push(env, &fun->reachable_bbs, &cur_bb); + if (cur_bb->succs.num_elem == 0) { + break; + } + + struct ir_basic_block **succ1 = + bpf_ir_array_get_void(&cur_bb->succs, 0); + if ((*succ1)->_visited) { + break; + } + if (cur_bb->succs.num_elem == 1) { + } else if (cur_bb->succs.num_elem == 2) { + struct ir_basic_block **succ2 = + bpf_ir_array_get_void(&cur_bb->succs, 1); + bpf_ir_array_push(env, &todo, succ2); + } else { + CRITICAL("Not possible: BB with >2 succs"); + } + cur_bb = *succ1; + } + + struct ir_basic_block **pos; + array_for(pos, todo) + { + add_reach(env, fun, *pos); + } + + bpf_ir_array_free(&todo); +} + +static void gen_reachable_bbs(struct bpf_ir_env *env, struct ir_function *fun) +{ + bpf_ir_clean_visited(fun); + bpf_ir_array_clear(env, &fun->reachable_bbs); + add_reach(env, fun, fun->entry); +} + +static void gen_end_bbs(struct bpf_ir_env *env, struct ir_function *fun) +{ + struct ir_basic_block **pos; + bpf_ir_array_clear(env, &fun->end_bbs); + array_for(pos, fun->reachable_bbs) + { + struct ir_basic_block *bb = *pos; + if (bb->succs.num_elem == 0) { + bpf_ir_array_push(env, &fun->end_bbs, &bb); + } + } +} + +static void bpf_ir_pass_postprocess(struct bpf_ir_env *env, + struct ir_function *fun) { - bpf_ir_prog_check(env, fun); + bpf_ir_fix_bb_succ(env, fun); + CHECK_ERR(); + bpf_ir_clean_metadata_all(fun); + gen_reachable_bbs(env, fun); CHECK_ERR(); + gen_end_bbs(env, fun); + CHECK_ERR(); + if (!env->opts.disable_prog_check) { + bpf_ir_prog_check(env, fun); + } +} +static void run_single_pass(struct bpf_ir_env *env, struct ir_function *fun, + const struct function_pass *pass, void *param) +{ PRINT_LOG_DEBUG(env, "\x1B[32m------ Running Pass: %s ------\x1B[0m\n", pass->name); pass->pass(env, fun, param); CHECK_ERR(); // Validate the IR - bpf_ir_prog_check(env, fun); + bpf_ir_pass_postprocess(env, fun); CHECK_ERR(); print_ir_prog(env, fun); CHECK_ERR(); } -static void run_passes(struct bpf_ir_env *env, struct ir_function *fun) +void bpf_ir_run(struct bpf_ir_env *env, struct ir_function *fun) { + u64 starttime = get_cur_time_ns(); for (size_t i = 0; i < sizeof(pre_passes) / sizeof(pre_passes[0]); ++i) { bool has_override = false; @@ -1554,6 +1692,8 @@ static void run_passes(struct bpf_ir_env *env, struct ir_function *fun) } CHECK_ERR(); } + + env->run_time += get_cur_time_ns() - starttime; } static void print_bpf_insn_simple(struct bpf_ir_env *env, @@ -1617,6 +1757,7 @@ static void print_bpf_prog(struct bpf_ir_env *env, const struct bpf_insn *insns, struct ir_function *bpf_ir_lift(struct bpf_ir_env *env, const struct bpf_insn *insns, size_t len) { + u64 starttime = get_cur_time_ns(); struct bb_info info; gen_bb(env, &info, insns, len); CHECK_ERR(NULL); @@ -1638,10 +1779,12 @@ struct ir_function *bpf_ir_lift(struct bpf_ir_env *env, SAFE_MALLOC_RET_NULL(fun, sizeof(struct ir_function)); init_function(env, fun, &trans_env); + env->lift_time += get_cur_time_ns() - starttime; + return fun; } -void bpf_ir_run(struct bpf_ir_env *env) +void bpf_ir_autorun(struct bpf_ir_env *env) { env->executed = true; const struct bpf_insn *insns = env->insns; @@ -1649,19 +1792,19 @@ void bpf_ir_run(struct bpf_ir_env *env) struct ir_function *fun = bpf_ir_lift(env, insns, len); CHECK_ERR(); - bpf_ir_prog_check(env, fun); + bpf_ir_pass_postprocess(env, fun); CHECK_ERR(); print_ir_prog(env, fun); PRINT_LOG_DEBUG(env, "Starting IR Passes...\n"); // Start IR manipulation - run_passes(env, fun); + bpf_ir_run(env, fun); CHECK_ERR(); // End IR manipulation PRINT_LOG_DEBUG(env, "IR Passes Ended!\n"); - bpf_ir_code_gen(env, fun); + bpf_ir_compile(env, fun); CHECK_ERR(); // Got the bpf bytecode @@ -1689,6 +1832,7 @@ struct bpf_ir_opts bpf_ir_default_opts(void) opts.force = false; opts.verbose = 1; opts.max_iteration = 10; + opts.disable_prog_check = false; return opts; } @@ -1705,6 +1849,11 @@ struct bpf_ir_env *bpf_ir_init_env(struct bpf_ir_opts opts, env->verifier_err = -1; env->executed = false; env->venv = NULL; + env->verifier_log_end_pos = 0; + env->prog_type = 0; // Unspecified + env->lift_time = 0; + env->cg_time = 0; + env->run_time = 0; return env; } diff --git a/core/epasstool/epasstool.c b/core/epasstool/epasstool.c index 583fe35d..c90d74af 100644 --- a/core/epasstool/epasstool.c +++ b/core/epasstool/epasstool.c @@ -42,6 +42,8 @@ int main(int argc, char **argv) MODE_PRINT_LOG, } mode = MODE_NONE; struct user_opts uopts; + uopts.gopt[0] = 0; + uopts.popt[0] = 0; static struct option long_options[] = { { "mode", required_argument, NULL, 'm' }, { "gopt", required_argument, NULL, 0 }, diff --git a/core/epasstool/read.c b/core/epasstool/read.c index d8399793..6e6768a8 100644 --- a/core/epasstool/read.c +++ b/core/epasstool/read.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only #include "bpf/libbpf.h" #include "epasstool.h" +#include "linux/bpf_ir.h" +#include int read(struct user_opts uopts) { @@ -27,12 +29,19 @@ int read(struct user_opts uopts) return err; } enable_builtin(env); - bpf_ir_run(env); + u64 starttime = get_cur_time_ns(); + bpf_ir_autorun(env); + u64 tot = get_cur_time_ns() - starttime; if (env->err) { return env->err; } + printf("ePass finished in %lluns\n", tot); + printf("lift %lluns\trun %lluns\tcompile %lluns\tsum %lluns\n", + env->lift_time, env->run_time, env->cg_time, + env->lift_time + env->run_time + env->cg_time); + bpf_ir_free_opts(env); bpf_ir_free_env(env); bpf_object__close(obj); diff --git a/core/epasstool/readload.c b/core/epasstool/readload.c index 8d9e5e5c..969442c0 100644 --- a/core/epasstool/readload.c +++ b/core/epasstool/readload.c @@ -35,7 +35,7 @@ int readload(struct user_opts uopts) return err; } enable_builtin(env); - bpf_ir_run(env); + bpf_ir_autorun(env); struct libbpf_prog_handler_opts handler_opts; handler_opts.sz = sizeof(handler_opts); @@ -47,7 +47,11 @@ int readload(struct user_opts uopts) bpf_program__expected_attach_type(prog), &handler_opts); bpf_object__close(obj); +#ifdef EPASS_LIBBPF + obj = bpf_object__open(uopts.prog, 0, NULL, NULL); +#else obj = bpf_object__open(uopts.prog); +#endif bpf_object__load(obj); bpf_ir_free_opts(env); bpf_ir_free_env(env); diff --git a/core/epasstool/readlog.c b/core/epasstool/readlog.c index 737a91e0..5b62bd14 100644 --- a/core/epasstool/readlog.c +++ b/core/epasstool/readlog.c @@ -40,7 +40,7 @@ int readlog(struct user_opts uopts) return err; } enable_builtin(env); - bpf_ir_run(env); + bpf_ir_autorun(env); if (env->err) { return env->err; } diff --git a/core/include/linux/bpf_ir.h b/core/include/linux/bpf_ir.h index 770ea365..984cbfff 100644 --- a/core/include/linux/bpf_ir.h +++ b/core/include/linux/bpf_ir.h @@ -14,6 +14,7 @@ #include #include +#include typedef __s8 s8; typedef __u8 u8; @@ -58,6 +59,8 @@ struct bpf_ir_opts { // Verbose level int verbose; + bool disable_prog_check; + u32 max_iteration; enum { @@ -80,12 +83,6 @@ struct bpf_ir_env { // Internal error code int err; - // Verifier error - int verifier_err; - - // Whether executed, used in verifier - bool executed; - // Number of instructions size_t insn_cnt; @@ -97,6 +94,27 @@ struct bpf_ir_env { struct bpf_ir_opts opts; + // Stats + + u64 lift_time; + u64 run_time; + u64 cg_time; + + // Verifier information + + // Whether executed, used in verifier + bool executed; + + // Verifier error + int verifier_err; + + // Verifier log end pos in ubuf + u64 verifier_log_end_pos; + + // Prog type + // May not be specified in user space + enum bpf_prog_type prog_type; + // Verifier env void *venv; }; @@ -238,6 +256,8 @@ void free_proto(void *ptr); int parse_int(const char *str, int *val); +u64 get_cur_time_ns(void); + #define SAFE_MALLOC(dst, size) \ { \ if (size > 10000000) { \ @@ -619,7 +639,7 @@ struct ssa_transform_env { struct ir_basic_block *bpf_ir_init_bb_raw(void); // Main interface -void bpf_ir_run(struct bpf_ir_env *env); +void bpf_ir_autorun(struct bpf_ir_env *env); void bpf_ir_print_bpf_insn(struct bpf_ir_env *env, const struct bpf_insn *insn); @@ -1228,11 +1248,16 @@ struct builtin_pass_cfg { /* Passes End */ +struct ir_function *bpf_ir_lift(struct bpf_ir_env *env, + const struct bpf_insn *insns, size_t len); + +void bpf_ir_run(struct bpf_ir_env *env, struct ir_function *fun); + /* Code Gen Start */ void bpf_ir_init_insn_cg(struct bpf_ir_env *env, struct ir_insn *insn); -void bpf_ir_code_gen(struct bpf_ir_env *env, struct ir_function *fun); +void bpf_ir_compile(struct bpf_ir_env *env, struct ir_function *fun); void bpf_ir_free_insn_cg(struct ir_insn *insn); diff --git a/core/ir_code_gen.c b/core/ir_code_gen.c index dce05146..58d32cfc 100644 --- a/core/ir_code_gen.c +++ b/core/ir_code_gen.c @@ -1202,6 +1202,11 @@ static struct ir_insn *normalize_load_const(struct bpf_ir_env *env, return new_insn; } +static void bpf_ir_erase_insn_cg_shallow(struct ir_insn *insn) +{ + list_del(&insn->list_ptr); +} + static void normalize_assign(struct bpf_ir_env *env, struct ir_function *fun, struct ir_insn *insn) { @@ -1242,7 +1247,9 @@ static void normalize_assign(struct bpf_ir_env *env, struct ir_function *fun, if (tdst == REG && t0 == REG) { if (allocated_reg_insn(dst_insn) == allocated_reg(*v0)) { // The same, erase this instruction - erase_same_reg_assign(env, fun, insn); + // erase_same_reg_assign(env, fun, insn); + // Needs garbage collection for instructions + bpf_ir_erase_insn_cg_shallow(insn); } } } @@ -1300,6 +1307,9 @@ static void normalize_alu(struct bpf_ir_env *env, struct ir_function *fun, // ==> // reg1 = reg2 // reg1 = add reg1 reg3 + PRINT_LOG_DEBUG(env, "v0:"); + print_ir_insn(env, v0->data.insn_d); + PRINT_LOG_DEBUG(env, "\n"); struct ir_insn *new_insn = bpf_ir_create_assign_insn_cg( env, insn, *v0, INSERT_FRONT); // DBGASSERT(dst_insn == @@ -2147,6 +2157,9 @@ static void check_insn_operand_cg(struct bpf_ir_env *env, struct ir_insn *insn) static void prog_check_cg(struct bpf_ir_env *env, struct ir_function *fun) { + if (env->opts.disable_prog_check) { + return; + } // CG IR check // Available to run while dst is maintained @@ -2951,10 +2964,18 @@ static void spill_array(struct bpf_ir_env *env, struct ir_function *fun) } } +// static void vreg_to_rreg(struct bpf_ir_env *env, struct ir_function *fun) +// { +// // Change all virtual registers to real registers +// // Make sure the VRs are all allocated +// // TODO +// } + // Interface Implementation -void bpf_ir_code_gen(struct bpf_ir_env *env, struct ir_function *fun) +void bpf_ir_compile(struct bpf_ir_env *env, struct ir_function *fun) { + u64 starttime = get_cur_time_ns(); // Init CG, start code generation init_cg(env, fun); CHECK_ERR(); @@ -3090,8 +3111,8 @@ void bpf_ir_code_gen(struct bpf_ir_env *env, struct ir_function *fun) normalize(env, fun); CHECK_ERR(); print_ir_prog_cg_alloc(env, fun, "Normalization"); - prog_check_cg(env, fun); - CHECK_ERR(); + // prog_check_cg(env, fun); + // CHECK_ERR(); replace_builtin_const(env, fun); CHECK_ERR(); @@ -3113,6 +3134,7 @@ void bpf_ir_code_gen(struct bpf_ir_env *env, struct ir_function *fun) // Free CG resources free_cg_res(fun); + env->cg_time += get_cur_time_ns() - starttime; } void bpf_ir_init_insn_cg(struct bpf_ir_env *env, struct ir_insn *insn) diff --git a/core/ir_helper.c b/core/ir_helper.c index 91d3e83f..bb866be9 100644 --- a/core/ir_helper.c +++ b/core/ir_helper.c @@ -729,7 +729,6 @@ void print_ir_bb_err(struct bpf_ir_env *env, struct ir_basic_block *bb) void bpf_ir_reset_env(struct bpf_ir_env *env) { - env->log_pos = 0; env->venv = NULL; env->err = 0; env->verifier_err = 0; diff --git a/core/lii.c b/core/lii.c index cdfbc5e4..64276fd0 100644 --- a/core/lii.c +++ b/core/lii.c @@ -20,6 +20,11 @@ int parse_int(const char *str, int *val) return kstrtoint(str, 10, val); } +u64 get_cur_time_ns(void) +{ + return ktime_get_ns(); +} + #else void *malloc_proto(size_t size) @@ -46,4 +51,11 @@ int parse_int(const char *str, int *val) return 0; } +u64 get_cur_time_ns(void) +{ + struct timespec t = { 0, 0 }; + clock_gettime(CLOCK_MONOTONIC, &t); + return 1e9 * t.tv_sec + t.tv_nsec; +} + #endif diff --git a/core/passes/add_counter_pass.c b/core/passes/add_counter_pass.c index 88d6c105..1cc8b11e 100644 --- a/core/passes/add_counter_pass.c +++ b/core/passes/add_counter_pass.c @@ -100,21 +100,61 @@ void add_counter(struct bpf_ir_env *env, struct ir_function *fun, void *param) bpf_ir_array_free(&critical_bbs); } +struct bpf_ir_counter_opt { + int counter_limit; + bool accurate; +}; + +#define GET_OPT(p, src) \ + while (*src && *src != ' ') { \ + *p = *src; \ + p++; \ + src++; \ + } \ + *p = '\0'; + +#define NEXT_OPT(src) \ + if (*src) { \ + src++; \ + } else { \ + break; \ + } + static int load_param(const char *opt, void **param) { - int res = 0; - int err = parse_int(opt, &res); - if (err) { - return err; + struct bpf_ir_counter_opt res; + res.counter_limit = 1000000; + res.accurate = false; + + char mopt[30] = { 0 }; + const char *src = opt; + while (*src) { + char *p = mopt; + GET_OPT(p, src); + + if (strcmp(mopt, "accurate") == 0) { + res.accurate = true; + } + + if (strncmp(mopt, "limit=", 6) == 0) { + res.accurate = true; + int err = parse_int(mopt + 6, &res.counter_limit); + if (err) { + return err; + } + } + + NEXT_OPT(src); } - if (res > 1000000) { + + if (res.counter_limit > 1000000) { // Could be configurable return -EINVAL; } - *param = malloc_proto(sizeof(int)); + *param = malloc_proto(sizeof(struct bpf_ir_counter_opt)); if (!*param) { return -ENOMEM; } - *(int *)(*param) = res; + *(struct bpf_ir_counter_opt *)(*param) = res; return 0; } diff --git a/core/passes/msan.c b/core/passes/msan.c index ae5dfdd9..c7eb6992 100644 --- a/core/passes/msan.c +++ b/core/passes/msan.c @@ -17,6 +17,130 @@ static u8 vr_type_to_size(enum ir_vr_type type) } } +static void modify_loadraw(struct bpf_ir_env *env, struct ir_function *fun, + struct ir_insn *arr, struct ir_insn *insn) +{ + // Non-sp memory access + // loadraw size addr(sp-32) + // ==> + // x = r10 - addr + struct ir_basic_block *bb = insn->parent_bb; + + struct ir_value v = bpf_ir_value_stack_ptr(fun); + v.raw_stack = true; + struct ir_insn *s1 = + bpf_ir_create_bin_insn(env, insn, v, insn->addr_val.value, + IR_INSN_SUB, IR_ALU_64, INSERT_FRONT); + struct ir_insn *b1 = bpf_ir_create_bin_insn( + env, s1, bpf_ir_value_insn(s1), bpf_ir_value_const32(8), + IR_INSN_DIV, IR_ALU_64, INSERT_BACK); + struct ir_insn *b2 = bpf_ir_create_bin_insn( + env, b1, bpf_ir_value_insn(b1), bpf_ir_value_const32(1), + IR_INSN_SUB, IR_ALU_64, INSERT_BACK); + struct ir_insn *s3 = bpf_ir_create_bin_insn( + env, b2, bpf_ir_value_insn(s1), bpf_ir_value_const32(8), + IR_INSN_MOD, IR_ALU_64, INSERT_BACK); + + struct ir_insn *b1ptr = bpf_ir_create_getelemptr_insn( + env, s3, arr, bpf_ir_value_insn(b1), INSERT_BACK); + struct ir_insn *b1c = bpf_ir_create_loadraw_insn( + env, b1ptr, IR_VR_TYPE_8, + bpf_ir_addr_val(bpf_ir_value_insn(b1ptr), 0), INSERT_BACK); + struct ir_insn *b2ptr = bpf_ir_create_getelemptr_insn( + env, b1c, arr, bpf_ir_value_insn(b2), INSERT_BACK); + struct ir_insn *b2c = bpf_ir_create_loadraw_insn( + env, b2ptr, IR_VR_TYPE_8, + bpf_ir_addr_val(bpf_ir_value_insn(b2ptr), 0), INSERT_BACK); + + // Memory layout: ... sp-16 b1 b2 sp-32 ... + struct ir_insn *comp1 = bpf_ir_create_bin_insn( + env, b2c, bpf_ir_value_insn(b1c), bpf_ir_value_const32(8), + IR_INSN_LSH, IR_ALU_64, INSERT_BACK); + struct ir_insn *comp2 = bpf_ir_create_bin_insn( + env, comp1, bpf_ir_value_insn(comp1), bpf_ir_value_insn(b2c), + IR_INSN_ADD, IR_ALU_64, INSERT_BACK); + int masking_val = (1 << vr_type_to_size(insn->vr_type)) - 1; + // off = pos%8 + 9 - size + struct ir_insn *off = bpf_ir_create_bin_insn( + env, comp2, bpf_ir_value_insn(s3), + bpf_ir_value_const32(9 - vr_type_to_size(insn->vr_type)), + IR_INSN_ADD, IR_ALU_64, INSERT_BACK); + struct ir_insn *comp3 = bpf_ir_create_bin_insn( + env, off, bpf_ir_value_insn(comp2), bpf_ir_value_insn(off), + IR_INSN_RSH, IR_ALU_64, INSERT_BACK); + // res = comp3 & masking + struct ir_insn *res1 = + bpf_ir_create_bin_insn(env, comp3, bpf_ir_value_insn(comp3), + bpf_ir_value_const32(masking_val), + IR_INSN_AND, IR_ALU_64, INSERT_BACK); + + struct ir_basic_block *new_bb = + bpf_ir_split_bb(env, fun, res1, INSERT_BACK); + struct ir_basic_block *err_bb = bpf_ir_create_bb(env, fun); + bpf_ir_create_throw_insn_bb(env, err_bb, INSERT_BACK); + bpf_ir_create_jbin_insn(env, res1, bpf_ir_value_insn(res1), + bpf_ir_value_const32(masking_val), new_bb, + err_bb, IR_INSN_JNE, IR_ALU_64, INSERT_BACK); + // Manually connect BBs + bpf_ir_connect_bb(env, bb, err_bb); +} + +static void modify_storeraw(struct bpf_ir_env *env, struct ir_insn *arr, + struct ir_insn *insn) +{ + PRINT_LOG_DEBUG(env, "Found a stack pointer store at off %d\n", + insn->addr_val.offset); + struct ir_value s1 = + bpf_ir_value_const32_rawoff(-insn->addr_val.offset); + s1.type = IR_VALUE_CONSTANT_RAWOFF_REV; + + struct ir_insn *b1 = + bpf_ir_create_bin_insn(env, insn, s1, bpf_ir_value_const32(8), + IR_INSN_DIV, IR_ALU_64, INSERT_BACK); + struct ir_insn *b2 = bpf_ir_create_bin_insn( + env, b1, bpf_ir_value_insn(b1), bpf_ir_value_const32(1), + IR_INSN_SUB, IR_ALU_64, INSERT_BACK); + struct ir_insn *s3 = + bpf_ir_create_bin_insn(env, b2, s1, bpf_ir_value_const32(8), + IR_INSN_MOD, IR_ALU_64, INSERT_BACK); + + struct ir_insn *b1ptr = bpf_ir_create_getelemptr_insn( + env, s3, arr, bpf_ir_value_insn(b1), INSERT_BACK); + struct ir_insn *b1c = bpf_ir_create_loadraw_insn( + env, b1ptr, IR_VR_TYPE_8, + bpf_ir_addr_val(bpf_ir_value_insn(b1ptr), 0), INSERT_BACK); + struct ir_insn *b2ptr = bpf_ir_create_getelemptr_insn( + env, b1c, arr, bpf_ir_value_insn(b2), INSERT_BACK); + struct ir_insn *b2c = bpf_ir_create_loadraw_insn( + env, b2ptr, IR_VR_TYPE_8, + bpf_ir_addr_val(bpf_ir_value_insn(b2ptr), 0), INSERT_BACK); + + // Memory layout: ... sp-16 b1 b2 sp-32 ... + struct ir_insn *comp1 = bpf_ir_create_bin_insn( + env, b2c, bpf_ir_value_insn(b1c), bpf_ir_value_const32(8), + IR_INSN_LSH, IR_ALU_64, INSERT_BACK); + struct ir_insn *comp2 = bpf_ir_create_bin_insn( + env, comp1, bpf_ir_value_insn(comp1), bpf_ir_value_insn(b2c), + IR_INSN_ADD, IR_ALU_64, INSERT_BACK); + int masking_val = (1 << vr_type_to_size(insn->vr_type)) - 1; + // off = pos%8 + 9 - size + struct ir_insn *off = bpf_ir_create_bin_insn( + env, comp2, bpf_ir_value_insn(s3), + bpf_ir_value_const32(9 - vr_type_to_size(insn->vr_type)), + IR_INSN_ADD, IR_ALU_64, INSERT_BACK); + struct ir_insn *comp3 = bpf_ir_create_bin_insn( + env, off, bpf_ir_value_const32(masking_val), + bpf_ir_value_insn(off), IR_INSN_LSH, IR_ALU_64, INSERT_BACK); + // res = comp3 | comp2 + struct ir_insn *res1 = bpf_ir_create_bin_insn( + env, comp3, bpf_ir_value_insn(comp3), bpf_ir_value_insn(comp2), + IR_INSN_OR, IR_ALU_64, INSERT_BACK); + bpf_ir_create_storeraw_insn(env, res1, IR_VR_TYPE_16, + bpf_ir_addr_val(bpf_ir_value_insn(b2ptr), + 0), + bpf_ir_value_insn(res1), INSERT_BACK); +} + void msan(struct bpf_ir_env *env, struct ir_function *fun, void *param) { // Add the 64B mapping space @@ -53,159 +177,23 @@ void msan(struct bpf_ir_env *env, struct ir_function *fun, void *param) struct ir_insn *insn = *pos2; if (insn->addr_val.value.type == IR_VALUE_INSN && insn->addr_val.value.data.insn_d == fun->sp) { - PRINT_LOG_DEBUG( - env, "Found a stack pointer store at off %d\n", - insn->addr_val.offset); - struct ir_value s1 = bpf_ir_value_const32_rawoff( - -insn->addr_val.offset); - s1.type = IR_VALUE_CONSTANT_RAWOFF_REV; - - struct ir_insn *b1 = bpf_ir_create_bin_insn( - env, insn, s1, bpf_ir_value_const32(8), - IR_INSN_DIV, IR_ALU_64, INSERT_BACK); - struct ir_insn *b2 = bpf_ir_create_bin_insn( - env, b1, bpf_ir_value_insn(b1), - bpf_ir_value_const32(1), IR_INSN_SUB, IR_ALU_64, - INSERT_BACK); - struct ir_insn *s3 = bpf_ir_create_bin_insn( - env, b2, s1, bpf_ir_value_const32(8), - IR_INSN_MOD, IR_ALU_64, INSERT_BACK); - - struct ir_insn *b1ptr = bpf_ir_create_getelemptr_insn( - env, s3, arr, bpf_ir_value_insn(b1), - INSERT_BACK); - struct ir_insn *b1c = bpf_ir_create_loadraw_insn( - env, b1ptr, IR_VR_TYPE_8, - bpf_ir_addr_val(bpf_ir_value_insn(b1ptr), 0), - INSERT_BACK); - struct ir_insn *b2ptr = bpf_ir_create_getelemptr_insn( - env, b1c, arr, bpf_ir_value_insn(b2), - INSERT_BACK); - struct ir_insn *b2c = bpf_ir_create_loadraw_insn( - env, b2ptr, IR_VR_TYPE_8, - bpf_ir_addr_val(bpf_ir_value_insn(b2ptr), 0), - INSERT_BACK); - - // Memory layout: ... sp-16 b1 b2 sp-32 ... - struct ir_insn *comp1 = bpf_ir_create_bin_insn( - env, b2c, bpf_ir_value_insn(b1c), - bpf_ir_value_const32(8), IR_INSN_LSH, IR_ALU_64, - INSERT_BACK); - struct ir_insn *comp2 = bpf_ir_create_bin_insn( - env, comp1, bpf_ir_value_insn(comp1), - bpf_ir_value_insn(b2c), IR_INSN_ADD, IR_ALU_64, - INSERT_BACK); - int masking_val = - (1 << vr_type_to_size(insn->vr_type)) - 1; - // off = pos%8 + 9 - size - struct ir_insn *off = bpf_ir_create_bin_insn( - env, comp2, bpf_ir_value_insn(s3), - bpf_ir_value_const32( - 9 - vr_type_to_size(insn->vr_type)), - IR_INSN_ADD, IR_ALU_64, INSERT_BACK); - struct ir_insn *comp3 = bpf_ir_create_bin_insn( - env, off, bpf_ir_value_const32(masking_val), - bpf_ir_value_insn(off), IR_INSN_LSH, IR_ALU_64, - INSERT_BACK); - // res = comp3 | comp2 - struct ir_insn *res1 = bpf_ir_create_bin_insn( - env, comp3, bpf_ir_value_insn(comp3), - bpf_ir_value_insn(comp2), IR_INSN_OR, IR_ALU_64, - INSERT_BACK); - bpf_ir_create_storeraw_insn( - env, res1, IR_VR_TYPE_16, - bpf_ir_addr_val(bpf_ir_value_insn(b2ptr), 0), - bpf_ir_value_insn(res1), INSERT_BACK); + modify_storeraw(env, arr, insn); } } array_for(pos2, loadraw_insns) { struct ir_insn *insn = *pos2; - struct ir_basic_block *bb = insn->parent_bb; - if (bpf_ir_get_last_insn(bb) == insn) { - PRINT_LOG_WARNING(env, "Last insn is a loadraw insn\n"); - continue; - } + // struct ir_basic_block *bb = insn->parent_bb; + // if (bpf_ir_get_last_insn(bb) == insn) { + // PRINT_LOG_WARNING(env, "Last insn is a loadraw insn\n"); + // continue; + // } if (insn->addr_val.value.type == IR_VALUE_INSN && insn->addr_val.value.data.insn_d == fun->sp) { // Sp memory access } else if (insn->addr_val.value.type == IR_VALUE_INSN) { - // Non-sp memory access - // loadraw size addr(sp-32) - // ==> - // x = r10 - addr - struct ir_value v = bpf_ir_value_stack_ptr(fun); - v.raw_stack = true; - struct ir_insn *s1 = bpf_ir_create_bin_insn( - env, insn, v, insn->addr_val.value, IR_INSN_SUB, - IR_ALU_64, INSERT_FRONT); - struct ir_insn *b1 = bpf_ir_create_bin_insn( - env, s1, bpf_ir_value_insn(s1), - bpf_ir_value_const32(8), IR_INSN_DIV, IR_ALU_64, - INSERT_BACK); - struct ir_insn *b2 = bpf_ir_create_bin_insn( - env, b1, bpf_ir_value_insn(b1), - bpf_ir_value_const32(1), IR_INSN_SUB, IR_ALU_64, - INSERT_BACK); - struct ir_insn *s3 = bpf_ir_create_bin_insn( - env, b2, bpf_ir_value_insn(s1), - bpf_ir_value_const32(8), IR_INSN_MOD, IR_ALU_64, - INSERT_BACK); - - struct ir_insn *b1ptr = bpf_ir_create_getelemptr_insn( - env, s3, arr, bpf_ir_value_insn(b1), - INSERT_BACK); - struct ir_insn *b1c = bpf_ir_create_loadraw_insn( - env, b1ptr, IR_VR_TYPE_8, - bpf_ir_addr_val(bpf_ir_value_insn(b1ptr), 0), - INSERT_BACK); - struct ir_insn *b2ptr = bpf_ir_create_getelemptr_insn( - env, b1c, arr, bpf_ir_value_insn(b2), - INSERT_BACK); - struct ir_insn *b2c = bpf_ir_create_loadraw_insn( - env, b2ptr, IR_VR_TYPE_8, - bpf_ir_addr_val(bpf_ir_value_insn(b2ptr), 0), - INSERT_BACK); - - // Memory layout: ... sp-16 b1 b2 sp-32 ... - struct ir_insn *comp1 = bpf_ir_create_bin_insn( - env, b2c, bpf_ir_value_insn(b1c), - bpf_ir_value_const32(8), IR_INSN_LSH, IR_ALU_64, - INSERT_BACK); - struct ir_insn *comp2 = bpf_ir_create_bin_insn( - env, comp1, bpf_ir_value_insn(comp1), - bpf_ir_value_insn(b2c), IR_INSN_ADD, IR_ALU_64, - INSERT_BACK); - int masking_val = - (1 << vr_type_to_size(insn->vr_type)) - 1; - // off = pos%8 + 9 - size - struct ir_insn *off = bpf_ir_create_bin_insn( - env, comp2, bpf_ir_value_insn(s3), - bpf_ir_value_const32( - 9 - vr_type_to_size(insn->vr_type)), - IR_INSN_ADD, IR_ALU_64, INSERT_BACK); - struct ir_insn *comp3 = bpf_ir_create_bin_insn( - env, off, bpf_ir_value_insn(comp2), - bpf_ir_value_insn(off), IR_INSN_RSH, IR_ALU_64, - INSERT_BACK); - // res = comp3 & masking - struct ir_insn *res1 = bpf_ir_create_bin_insn( - env, comp3, bpf_ir_value_insn(comp3), - bpf_ir_value_const32(masking_val), IR_INSN_AND, - IR_ALU_64, INSERT_BACK); - - struct ir_basic_block *new_bb = - bpf_ir_split_bb(env, fun, res1, INSERT_BACK); - struct ir_basic_block *err_bb = - bpf_ir_create_bb(env, fun); - bpf_ir_create_throw_insn_bb(env, err_bb, INSERT_BACK); - bpf_ir_create_jbin_insn( - env, res1, bpf_ir_value_insn(res1), - bpf_ir_value_const32(masking_val), new_bb, - err_bb, IR_INSN_JNE, IR_ALU_64, INSERT_BACK); - // Manually connect BBs - bpf_ir_connect_bb(env, bb, err_bb); + modify_loadraw(env, fun, arr, insn); } } diff --git a/core/tests/complex.c b/core/tests/complex.c new file mode 100644 index 00000000..7e9be0a2 --- /dev/null +++ b/core/tests/complex.c @@ -0,0 +1,63 @@ +/** + A complex eBPF program that the verifier cannot verify. + + https://stackoverflow.com/questions/70841631/bpf-verifier-says-program-exceeds-1m-instruction + + */ + +#include +#include + +struct server_name { + char server_name[256]; + __u16 length; +}; + +#define MAX_SERVER_NAME_LENGTH 253 +#define HEADER_LEN 6 + +SEC("xdp") +int prog(struct xdp_md *ctx) +{ + char *data_end = (char *)(long)ctx->data_end; + char *data = (char *)(long)ctx->data; + int host_header_found = 0; + + for (__u16 i = 0; i <= 512 - HEADER_LEN; i++) { + host_header_found = 0; + + if (data_end < data + HEADER_LEN) { + goto end; + } + + // Elf loader does not allow NULL terminated strings, so have to check each char manually + if (data[0] == 'H' && data[1] == 'o' && data[2] == 's' && + data[3] == 't' && data[4] == ':' && data[5] == ' ') { + host_header_found = 1; + data += HEADER_LEN; + break; + } + + data++; + } + + if (host_header_found) { + struct server_name sn = { "a", 0 }; + + for (__u16 j = 0; j < MAX_SERVER_NAME_LENGTH; j++) { + if (data_end < data + 1) { + goto end; + } + + if (*data == '\r') { + break; + } + + sn.server_name[j] = *data++; + sn.length++; + } + } + +end: + return XDP_PASS; +} diff --git a/core/tests/lsm.c b/core/tests/lsm.c new file mode 100644 index 00000000..347c6fac --- /dev/null +++ b/core/tests/lsm.c @@ -0,0 +1,20 @@ +#include "vmlinux.h" +#include +#include + +char LICENSE[] SEC("license") = "GPL"; + +#define EPERM 1 + +SEC("lsm/bpf") +int BPF_PROG(prog, int cmd, union bpf_attr *attr, unsigned int size, int ret) +{ + /* ret is the return value from the previous BPF program + * or 0 if it's the first hook. + */ + if (ret != 0) + return ret; + + bpf_printk("LSM: block bpf() worked"); + return -EPERM; +} diff --git a/core/tests/uninit1.c b/core/tests/uninit1.c index ba9f668e..e1666737 100644 --- a/core/tests/uninit1.c +++ b/core/tests/uninit1.c @@ -11,7 +11,7 @@ int prog(void *ctx) } a[5] = 0; if (a[id]) { - bpf_printk("aba\n"); + bpf_printk("%p\n", &a[id]); } return 0; } diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 00000000..54c68d3d --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,6 @@ +output/ +env/ +*.pdf +evalout/ +env.py +__pycache__/ diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 00000000..5930156f --- /dev/null +++ b/test/Makefile @@ -0,0 +1,141 @@ +output/progs_libbpf_minimal.bpf.o: ./progs/libbpf/minimal.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_minimal.bpf.ll: ./progs/libbpf/minimal.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_task_iter.bpf.o: ./progs/libbpf/task_iter.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_task_iter.bpf.ll: ./progs/libbpf/task_iter.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_ksyscall.bpf.o: ./progs/libbpf/ksyscall.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_ksyscall.bpf.ll: ./progs/libbpf/ksyscall.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_uprobe.bpf.o: ./progs/libbpf/uprobe.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_uprobe.bpf.ll: ./progs/libbpf/uprobe.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_lsm.bpf.o: ./progs/libbpf/lsm.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_lsm.bpf.ll: ./progs/libbpf/lsm.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_kprobe.bpf.o: ./progs/libbpf/kprobe.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_kprobe.bpf.ll: ./progs/libbpf/kprobe.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_bootstrap.bpf.o: ./progs/libbpf/bootstrap.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_bootstrap.bpf.ll: ./progs/libbpf/bootstrap.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_minimal_legacy.bpf.o: ./progs/libbpf/minimal_legacy.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_minimal_legacy.bpf.ll: ./progs/libbpf/minimal_legacy.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_profile.bpf.o: ./progs/libbpf/profile.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_profile.bpf.ll: ./progs/libbpf/profile.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_sockfilter.bpf.o: ./progs/libbpf/sockfilter.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_sockfilter.bpf.ll: ./progs/libbpf/sockfilter.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_fentry.bpf.o: ./progs/libbpf/fentry.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_fentry.bpf.ll: ./progs/libbpf/fentry.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_libbpf_minimal_ns.bpf.o: ./progs/libbpf/minimal_ns.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_libbpf_minimal_ns.bpf.ll: ./progs/libbpf/minimal_ns.bpf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_ringbuf.o: ./progs/ringbuf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_ringbuf.ll: ./progs/ringbuf.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_map1.o: ./progs/map1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_map1.ll: ./progs/map1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_simple2.o: ./progs/simple2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_simple2.ll: ./progs/simple2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_loop3.o: ./progs/loop3.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_loop3.ll: ./progs/loop3.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_mem2.o: ./progs/mem2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_mem2.ll: ./progs/mem2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_mem1.o: ./progs/mem1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_mem1.ll: ./progs/mem1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_loop1.o: ./progs/loop1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_loop1.ll: ./progs/loop1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_str.o: ./progs/str.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_str.ll: ./progs/str.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_simple1.o: ./progs/simple1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_simple1.ll: ./progs/simple1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_test_asm.o: ./progs/test_asm.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_test_asm.ll: ./progs/test_asm.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_empty.o: ./progs/empty.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_empty.ll: ./progs/empty.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_loop2.o: ./progs/loop2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_loop2.ll: ./progs/loop2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_alu64.o: ./progs/alu64.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_alu64.ll: ./progs/alu64.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/progs_mask.o: ./progs/mask.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/progs_mask.ll: ./progs/mask.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_counter_complex.o: ./evaluation/counter/complex.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_counter_complex.ll: ./evaluation/counter/complex.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_counter_loop3.o: ./evaluation/counter/loop3.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_counter_loop3.ll: ./evaluation/counter/loop3.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_counter_loop1.o: ./evaluation/counter/loop1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_counter_loop1.ll: ./evaluation/counter/loop1.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_counter_loop4.o: ./evaluation/counter/loop4.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_counter_loop4.ll: ./evaluation/counter/loop4.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_counter_loop2.o: ./evaluation/counter/loop2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_counter_loop2.ll: ./evaluation/counter/loop2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_counter_complex2.o: ./evaluation/counter/complex2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_counter_complex2.ll: ./evaluation/counter/complex2.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_compile_speed_speed_20.o: ./evaluation/compile_speed/speed_20.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_compile_speed_speed_20.ll: ./evaluation/compile_speed/speed_20.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_compile_speed_speed_100.o: ./evaluation/compile_speed/speed_100.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_compile_speed_speed_100.ll: ./evaluation/compile_speed/speed_100.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +output/evaluation_compile_speed_speed_50.o: ./evaluation/compile_speed/speed_50.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $< -o $@ +output/evaluation_compile_speed_speed_50.ll: ./evaluation/compile_speed/speed_50.c + clang -O2 -I./progs -I/usr/include/x86_64-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c $< -o $@ +all:output/evaluation_compile_speed_speed_50.o output/evaluation_compile_speed_speed_50.ll output/evaluation_compile_speed_speed_100.o output/evaluation_compile_speed_speed_100.ll output/evaluation_compile_speed_speed_20.o output/evaluation_compile_speed_speed_20.ll output/evaluation_counter_complex2.o output/evaluation_counter_complex2.ll output/evaluation_counter_loop2.o output/evaluation_counter_loop2.ll output/evaluation_counter_loop4.o output/evaluation_counter_loop4.ll output/evaluation_counter_loop1.o output/evaluation_counter_loop1.ll output/evaluation_counter_loop3.o output/evaluation_counter_loop3.ll output/evaluation_counter_complex.o output/evaluation_counter_complex.ll output/progs_mask.o output/progs_mask.ll output/progs_alu64.o output/progs_alu64.ll output/progs_loop2.o output/progs_loop2.ll output/progs_empty.o output/progs_empty.ll output/progs_test_asm.o output/progs_test_asm.ll output/progs_simple1.o output/progs_simple1.ll output/progs_str.o output/progs_str.ll output/progs_loop1.o output/progs_loop1.ll output/progs_mem1.o output/progs_mem1.ll output/progs_mem2.o output/progs_mem2.ll output/progs_loop3.o output/progs_loop3.ll output/progs_simple2.o output/progs_simple2.ll output/progs_map1.o output/progs_map1.ll output/progs_ringbuf.o output/progs_ringbuf.ll output/progs_libbpf_minimal_ns.bpf.o output/progs_libbpf_minimal_ns.bpf.ll output/progs_libbpf_fentry.bpf.o output/progs_libbpf_fentry.bpf.ll output/progs_libbpf_sockfilter.bpf.o output/progs_libbpf_sockfilter.bpf.ll output/progs_libbpf_profile.bpf.o output/progs_libbpf_profile.bpf.ll output/progs_libbpf_minimal_legacy.bpf.o output/progs_libbpf_minimal_legacy.bpf.ll output/progs_libbpf_bootstrap.bpf.o output/progs_libbpf_bootstrap.bpf.ll output/progs_libbpf_kprobe.bpf.o output/progs_libbpf_kprobe.bpf.ll output/progs_libbpf_lsm.bpf.o output/progs_libbpf_lsm.bpf.ll output/progs_libbpf_uprobe.bpf.o output/progs_libbpf_uprobe.bpf.ll output/progs_libbpf_ksyscall.bpf.o output/progs_libbpf_ksyscall.bpf.ll output/progs_libbpf_task_iter.bpf.o output/progs_libbpf_task_iter.bpf.ll output/progs_libbpf_minimal.bpf.o output/progs_libbpf_minimal.bpf.ll diff --git a/test/env.example.py b/test/env.example.py new file mode 100644 index 00000000..a3f2d558 --- /dev/null +++ b/test/env.example.py @@ -0,0 +1,2 @@ +CARD = "enp0s3" +EXPERIMENT_TIMES = 1 \ No newline at end of file diff --git a/test/evaluate.py b/test/evaluate.py index a955700d..f5c93841 100644 --- a/test/evaluate.py +++ b/test/evaluate.py @@ -5,8 +5,345 @@ """ import os +import subprocess +import re +import matplotlib.pyplot as plt +import matplotlib +import numpy as np +import requests +from pathlib import Path +import env +import time + +EXPERIMENT_TIMES = env.EXPERIMENT_TIMES +CARD = env.CARD + +urls = [ + "https://www.google.com", + "https://1.1.1.1", + "https://208.67.222.222", + "https://www.github.com", + "https://www.wikipedia.org", +] + + +def check_connectivity(url): + try: + requests.get(url, timeout=0.1) + except: + print(f"Connection failed for {url}") + def init(): print("init...") - os.system("sudo /sbin/sysctl -w kernel.bpf_stats_enabled=1") + os.system("./gen_tests.sh") + os.system("make all -j$(nproc)") + + +def measure_cmd_time_avg(cmd: str): + times = [] + cmds = cmd.split(" ") + + for _ in range(EXPERIMENT_TIMES): + process = subprocess.Popen( + ["./time"] + cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + out, _ = process.communicate() + rec = re.compile(r"Real Time: (.*?) nanoseconds") + times.append(int(rec.findall(out.decode())[0])) + + return sum(times) / len(times) / 1000000 + + +def measure_epass_time_avg(prog, sec, gopt="", popt=""): + tot_times = [] + lift_times = [] + run_times = [] + compile_times = [] + + for _ in range(EXPERIMENT_TIMES): + process = subprocess.Popen( + [ + "epass", + "-m", + "read", + "-p", + prog, + "-s", + sec, + "--gopt", + gopt, + "--popt", + popt, + ], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + out, _ = process.communicate() + rec = re.compile( + r"ePass finished in (.*?)ns\nlift (.*?)ns\trun (.*?)ns\tcompile (.*?)ns" + ) + (tott, liftt, runt, compilet) = rec.findall(out.decode())[0] + tot_times.append(int(tott)) + lift_times.append(int(liftt)) + run_times.append(int(runt)) + compile_times.append(int(compilet)) + + mean_tot = sum(tot_times) / len(tot_times) / 1000000 + mean_lift = sum(lift_times) / len(lift_times) / 1000000 + mean_run = sum(run_times) / len(run_times) / 1000000 + mean_compile = sum(compile_times) / len(compile_times) / 1000000 + return mean_tot, mean_lift, mean_run, mean_compile + + +def load_prog_epass(prog, gopt="", popt=""): + bname = Path(prog).stem + # bpftool prog load {prog} /sys/fs/bpf/{bname} epass {gopt} {popt} + ret = os.system( + f'sudo bpftool prog load {prog} /sys/fs/bpf/{bname} epass "{gopt}" "{popt}"' + ) + return ret + + +def load_prog_no_epass(prog): + bname = Path(prog).stem + ret = os.system(f"sudo bpftool prog load {prog} /sys/fs/bpf/{bname}") + return ret + + +def attach_prog(): + os.system(f"sudo bpftool net attach xdp name prog dev {CARD}") + + +def test_network(): + for _ in range(10): + for u in urls: + check_connectivity(u) + + +def collect_info(): + cmds = "sudo bpftool prog show name prog" + process = subprocess.Popen( + cmds.split(" "), stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + out, _ = process.communicate() + out = out.decode() + rec = re.compile(r"run_time_ns (.*?) run_cnt (.*?)\s") + res = rec.findall(out)[0] + tot = int(res[0]) + cnt = int(res[1]) + return tot / cnt, cnt + + +def dettach_prog(): + os.system(f"sudo bpftool net detach xdp dev {CARD}") + + +def remove_prog(prog): + bname = Path(prog).stem + os.system(f"sudo rm -f /sys/fs/bpf/{bname}") + +def evaluate_compile_speed(): + llc_time_20 = measure_cmd_time_avg( + "llc -march=bpf output/evaluation_compile_speed_speed_20.ll -o /dev/null" + ) + (epass_tot_20o, epass_lift_20o, epass_run_20o, epass_compile_20o) = ( + measure_epass_time_avg( + "output/evaluation_compile_speed_speed_20.o", "prog", "no_prog_check" + ) + ) + epass_other_20o = epass_tot_20o - epass_lift_20o - epass_run_20o - epass_compile_20o + (epass_tot_20, epass_lift_20, epass_run_20, epass_compile_20) = ( + measure_epass_time_avg("output/evaluation_compile_speed_speed_20.o", "prog") + ) + epass_other_20 = epass_tot_20 - epass_lift_20 - epass_run_20 - epass_compile_20 + + llc_time_50 = measure_cmd_time_avg( + "llc -march=bpf output/evaluation_compile_speed_speed_50.ll -o /dev/null" + ) + (epass_tot_50o, epass_lift_50o, epass_run_50o, epass_compile_50o) = ( + measure_epass_time_avg( + "output/evaluation_compile_speed_speed_50.o", "prog", "no_prog_check" + ) + ) + epass_other_50o = epass_tot_50o - epass_lift_50o - epass_run_50o - epass_compile_50o + (epass_tot_50, epass_lift_50, epass_run_50, epass_compile_50) = ( + measure_epass_time_avg("output/evaluation_compile_speed_speed_50.o", "prog") + ) + epass_other_50 = epass_tot_50 - epass_lift_50 - epass_run_50 - epass_compile_50 + + llc_time_100 = measure_cmd_time_avg( + "llc -march=bpf output/evaluation_compile_speed_speed_100.ll -o /dev/null" + ) + (epass_tot_100o, epass_lift_100o, epass_run_100o, epass_compile_100o) = ( + measure_epass_time_avg( + "output/evaluation_compile_speed_speed_100.o", "prog", "no_prog_check" + ) + ) + epass_other_100o = ( + epass_tot_100o - epass_lift_100o - epass_run_100o - epass_compile_100o + ) + (epass_tot_100, epass_lift_100, epass_run_100, epass_compile_100) = ( + measure_epass_time_avg("output/evaluation_compile_speed_speed_100.o", "prog") + ) + epass_other_100 = epass_tot_100 - epass_lift_100 - epass_run_100 - epass_compile_100 + + categories = ["speed_20", "speed_50", "speed_100"] + group3 = [llc_time_20, llc_time_50, llc_time_100] + + # Bar width + bar_width = 0.25 + + # x positions for each group of bars + x = np.arange(len(categories)) + x1 = x - bar_width - 0.02 + x2 = x + x3 = x + bar_width + 0.02 + + x1region1 = [epass_compile_20o, epass_compile_50o, epass_compile_100o] + x1region2 = [epass_lift_20o, epass_lift_50o, epass_lift_100o] + x1region3 = [epass_run_20o, epass_run_50o, epass_run_100o] + x1region4 = [epass_other_20o, epass_other_50o, epass_other_100o] + + x2region1 = [epass_compile_20, epass_compile_50, epass_compile_100] + x2region2 = [epass_lift_20, epass_lift_50, epass_lift_100] + x2region3 = [epass_run_20, epass_run_50, epass_run_100] + x2region4 = [epass_other_20, epass_other_50, epass_other_100] + + color1 = (0.2, 0.6, 0.9, 0.8) + color2 = (0.2, 0.8, 0.6, 0.8) + color3 = (1.0, 0.6, 0.2, 0.8) + color4 = (0, 0, 0, 0.1) + color5 = (0.6, 0.3, 0.8, 0.8) + + # Plotting + plt.bar(x1, x1region1, width=bar_width, label="Compile", color=color1) + plt.bar( + x1, x1region2, width=bar_width, bottom=x1region1, label="Lift", color=color2 + ) + plt.bar( + x1, + x1region3, + width=bar_width, + bottom=np.array(x1region1) + np.array(x1region2), + label="Run", + color=color3, + ) + plt.bar( + x1, + x1region4, + width=bar_width, + bottom=np.array(x1region1) + np.array(x1region2) + np.array(x1region3), + label="Other", + color=color4, + ) + + plt.bar(x2, x2region1, width=bar_width, color=color1) + plt.bar(x2, x2region2, width=bar_width, bottom=x2region1, color=color2) + plt.bar( + x2, + x2region3, + width=bar_width, + bottom=np.array(x2region1) + np.array(x2region2), + color=color3, + ) + plt.bar( + x2, + x2region4, + width=bar_width, + bottom=np.array(x2region1) + np.array(x2region2) + np.array(x2region3), + color=color4, + ) + + plt.bar(x3, group3, width=bar_width, label="llc", color=color5) + + # Adding labels and title + # plt.xlabel("Tests") + plt.ylabel("Time (ms)") + # plt.title("") + plt.xticks(x, categories) + plt.legend(fontsize=8) + + # Show plot + # plt.show() + fig = matplotlib.pyplot.gcf() + fig.set_size_inches(3, 2) + plt.tight_layout() + fig.savefig("evalout/compile_speed.pdf", dpi=200) + + +def evaluate_counter_pass_single(prog_name): + prog = f"output/{prog_name}.o" + remove_prog(prog) + load_prog_no_epass(prog) + attach_prog() + print(f"test {prog_name}...") + test_network() + (avg1, cnt) = collect_info() + print(avg1, cnt) + dettach_prog() + remove_prog(prog) + time.sleep(1) + print(f"test {prog_name} with add_counter...") + load_prog_epass(prog, popt="add_counter") + attach_prog() + test_network() + (avg2, cnt) = collect_info() + print(avg2, cnt) + dettach_prog() + remove_prog(prog) + return avg1, avg2 + + +def evaluate_counter_pass(): + (l1, l1c) = evaluate_counter_pass_single("evaluation_counter_loop3") + print(l1, l1c) + time.sleep(1) + (l2, l2c) = evaluate_counter_pass_single("evaluation_counter_loop4") + print(l2, l2c) + + categories = ["counter_1", "counter_2"] + group1 = [l1, l2] + group2 = [l1c, l2c] + # group3 = [4, 6, 0] + + # Bar width + bar_width = 0.25 + + # x positions for each group of bars + x = np.arange(len(categories)) + x1 = x - bar_width/2 + x2 = x + bar_width/2 + # x3 = x + bar_width + + # Plotting + plt.bar(x1, group1, width=bar_width, label="Group 1") + plt.bar(x2, group2, width=bar_width, label="Group 2") + # plt.bar(x3, group3, width=bar_width, label='Group 3') + + # Adding labels and title + plt.ylabel("Time (ns)") + # plt.title("") + plt.xticks(x, categories) + plt.legend(fontsize=8) + + # Show plot + # plt.show() + fig = matplotlib.pyplot.gcf() + fig.set_size_inches(3, 2) + plt.tight_layout() + fig.savefig("evalout/add_counter.pdf", dpi=200) + + +if __name__ == "__main__": + import sys + + arg = sys.argv[1] + os.system("sudo /sbin/sysctl -w kernel.bpf_stats_enabled=1") + if arg == "init": + init() + if arg == "speed": + evaluate_compile_speed() + if arg == "counter": + evaluate_counter_pass() diff --git a/test/evaluation/compile_speed/speed_100.c b/test/evaluation/compile_speed/speed_100.c new file mode 100644 index 00000000..a9d24545 --- /dev/null +++ b/test/evaluation/compile_speed/speed_100.c @@ -0,0 +1,465 @@ +#include +#include + +struct server_name { + char server_name[256]; + __u16 length; +}; + +SEC("xdp") +int prog(struct xdp_md *ctx) { + __u64 t = bpf_ktime_get_ns(); + char xx[] = "asfdsf"; + for (__u64 i = 0; i < t; ++i) { + bpf_trace_printk(xx, i); + } + t = bpf_ktime_get_ns(); + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + char *data_end = (char *)(long)ctx->data_end; + char *data = (char *)(long)ctx->data; + int host_header_found = 0; + + for (__u16 i = 0; i <= 512; i++) { + host_header_found = 0; + + if (data_end < data + 6) { + return 0; + } + + // Elf loader does not allow NULL terminated strings, so have to check each char manually + if (data[0] == 'H' && data[1] == 'o' && data[2] == 's' && data[3] == 't' && + data[4] == ':' && data[5] == ' ') { + host_header_found = 1; + data += 3; + break; + } + + data++; + } + + if (host_header_found) { + struct server_name sn = {"a", 0}; + + for (__u16 j = 0; j < 11; j++) { + if (data_end < data + 1) { + return 0; + } + + if (*data == '\r') { + break; + } + + sn.server_name[j] = *data++; + sn.length++; + } + } + if (host_header_found) { + struct server_name sn = {"a", 0}; + + for (__u16 j = 0; j < 11; j++) { + if (data_end < data + 1) { + return 0; + } + + if (*data == '\r') { + break; + } + + sn.server_name[j] = *data++; + sn.length++; + } + } + return 0; +} + +char _license[] SEC("license") = "GPL"; diff --git a/test/evaluation/compile_speed/speed_20.c b/test/evaluation/compile_speed/speed_20.c new file mode 100644 index 00000000..9f2f54e4 --- /dev/null +++ b/test/evaluation/compile_speed/speed_20.c @@ -0,0 +1,107 @@ +#include +#include + +struct server_name { + char server_name[256]; + __u16 length; +}; + +SEC("xdp") +int prog(struct xdp_md *ctx) { + __u64 t = bpf_ktime_get_ns(); + char xx[] = "asfdsf"; + for (__u64 i = 0; i < t; ++i) { + bpf_trace_printk(xx, i); + } + t = bpf_ktime_get_ns(); + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + char *data_end = (char *)(long)ctx->data_end; + char *data = (char *)(long)ctx->data; + int host_header_found = 0; + + for (__u16 i = 0; i <= 512; i++) { + host_header_found = 0; + + if (data_end < data + 6) { + return 0; + } + + // Elf loader does not allow NULL terminated strings, so have to check each char manually + if (data[0] == 'H' && data[1] == 'o' && data[2] == 's' && data[3] == 't' && + data[4] == ':' && data[5] == ' ') { + host_header_found = 1; + data += 3; + break; + } + + data++; + } + + if (host_header_found) { + struct server_name sn = {"a", 0}; + + for (__u16 j = 0; j < 11; j++) { + if (data_end < data + 1) { + return 0; + } + + if (*data == '\r') { + break; + } + + sn.server_name[j] = *data++; + sn.length++; + } + } + if (host_header_found) { + struct server_name sn = {"a", 0}; + + for (__u16 j = 0; j < 11; j++) { + if (data_end < data + 1) { + return 0; + } + + if (*data == '\r') { + break; + } + + sn.server_name[j] = *data++; + sn.length++; + } + } + return 0; +} + +char _license[] SEC("license") = "GPL"; diff --git a/test/evaluation/compile_speed/speed_50.c b/test/evaluation/compile_speed/speed_50.c new file mode 100644 index 00000000..469ecdb2 --- /dev/null +++ b/test/evaluation/compile_speed/speed_50.c @@ -0,0 +1,163 @@ +#include +#include + +struct server_name { + char server_name[256]; + __u16 length; +}; + +SEC("xdp") +int prog(struct xdp_md *ctx) { + __u64 t = bpf_ktime_get_ns(); + char xx[] = "asfdsf"; + for (__u64 i = 0; i < t; ++i) { + bpf_trace_printk(xx, i); + } + t = bpf_ktime_get_ns(); + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < t; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk(xx, x); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + for (__u64 i = 0; i < 10; ++i) { + int x = bpf_ktime_get_ns(); + bpf_trace_printk("vdnvd", x - t); + bpf_trace_printk("fasas", 2, x + i); + } + + char *data_end = (char *)(long)ctx->data_end; + char *data = (char *)(long)ctx->data; + int host_header_found = 0; + + for (__u16 i = 0; i <= 512; i++) { + host_header_found = 0; + + if (data_end < data + 6) { + return 0; + } + + // Elf loader does not allow NULL terminated strings, so have to check each char manually + if (data[0] == 'H' && data[1] == 'o' && data[2] == 's' && data[3] == 't' && + data[4] == ':' && data[5] == ' ') { + host_header_found = 1; + data += 3; + break; + } + + data++; + } + + if (host_header_found) { + struct server_name sn = {"a", 0}; + + for (__u16 j = 0; j < 11; j++) { + if (data_end < data + 1) { + return 0; + } + + if (*data == '\r') { + break; + } + + sn.server_name[j] = *data++; + sn.length++; + } + } + if (host_header_found) { + struct server_name sn = {"a", 0}; + + for (__u16 j = 0; j < 11; j++) { + if (data_end < data + 1) { + return 0; + } + + if (*data == '\r') { + break; + } + + sn.server_name[j] = *data++; + sn.length++; + } + } + return 0; +} + +char _license[] SEC("license") = "GPL"; diff --git a/test/evaluation/counter/complex.c b/test/evaluation/counter/complex.c index 635968c4..1f40653f 100644 --- a/test/evaluation/counter/complex.c +++ b/test/evaluation/counter/complex.c @@ -17,7 +17,7 @@ struct server_name { #define HEADER_LEN 6 SEC("xdp") -int collect_ips_prog(struct xdp_md *ctx) { +int prog(struct xdp_md *ctx) { char *data_end = (char *)(long)ctx->data_end; char *data = (char *)(long)ctx->data; int host_header_found = 0; diff --git a/test/evaluation/counter/complex2.c b/test/evaluation/counter/complex2.c index 53c14788..0bf47bab 100644 --- a/test/evaluation/counter/complex2.c +++ b/test/evaluation/counter/complex2.c @@ -4,16 +4,33 @@ https://stackoverflow.com/questions/78603028/bpf-program-is-too-large-processed-1000001-insn */ +#include +#include + +#define MAX_BUF_LEN 1000 + +SEC("xdp") +int prog(void *ctx) +{ + char fmts[100] = "helhlo hhh world"; + char msgs[100] = {0}; + int i = 0; + char *fmt = fmts; + char *msg = msgs; + while (i < MAX_BUF_LEN) { + if (*fmt == '\0') + break; + if (*fmt == 'h') { + fmt++; + i++; + continue; + } -while (i < MAX_BUF_LEN) { - if (*fmt == '\0') - break; - if (*fmt == 'h') { - fmt++; i++; - continue; + *msg++ = *fmt++; } - i++; - *msg++ = *fmt++; + return XDP_PASS; } + +char _license[] SEC("license") = "GPL"; diff --git a/test/evaluation/counter/loop3.c b/test/evaluation/counter/loop3.c index d3765521..d8dc444e 100644 --- a/test/evaluation/counter/loop3.c +++ b/test/evaluation/counter/loop3.c @@ -4,13 +4,12 @@ SEC("xdp") int prog(void *ctx) { - for (__u64 i = 0; i < 500; ++i) { - bpf_ktime_get_ns(); + for (__u64 i = 0; i < 100; ++i) { + __u64 k = bpf_ktime_get_ns() % 100; + k = k/10 + k/3 + k/7 - i; + bpf_printk("%llu", k); } return XDP_PASS; } -char _license[] SEC("license") = "GPL"; - -// Plain avg: 14260 ns -// Add counter: 18303 ns +char _license[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/test/evaluation/counter/loop4.c b/test/evaluation/counter/loop4.c new file mode 100644 index 00000000..ae51580b --- /dev/null +++ b/test/evaluation/counter/loop4.c @@ -0,0 +1,20 @@ +#include +#include + +SEC("xdp") +int prog(void *ctx) +{ + int tot = 0; + __u64 t = bpf_ktime_get_ns() % 10; + if (t < 1 || t > 5){ + return XDP_PASS; + } + for (__u64 i = 0; i < t; ++i) { + __u64 tmp = bpf_ktime_get_ns() % 7; + tot += tmp; + } + bpf_printk("%d", tot); + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL"; diff --git a/test/gen_tests.sh b/test/gen_tests.sh index 5f0aa1c6..240a29df 100755 --- a/test/gen_tests.sh +++ b/test/gen_tests.sh @@ -1,13 +1,19 @@ #!/bin/bash -bpftool btf dump file /sys/kernel/btf/vmlinux format c > progs/vmlinux.h +# bpftool btf dump file /sys/kernel/btf/vmlinux format c > progs/vmlinux.h mkdir -p output -files=$(find . -iname '*.c') +files=$(find . -iname '*.c' -not -path "./env/*") + +rm Makefile +all_objs="" for file in $files; do - base_name=$(basename $file) - clang -O2 -I/usr/include/$(uname -m)-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c $file -o output/$base_name.o - #clang -O0 -I/usr/include/$(uname -m)-linux-gnu -target bpf -g -c $file -o output/$base_name.nop.o + base_name=$(echo $file | sed -r 's/\.c//g' | sed -r 's/\.\///g' | tr '/' '_') + printf "output/$base_name.o: $file\n\tclang -O2 -I./progs -I/usr/include/$(uname -m)-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -c \$< -o \$@\n" >> Makefile + printf "output/$base_name.ll: $file\n\tclang -O2 -I./progs -I/usr/include/$(uname -m)-linux-gnu -D__TARGET_ARCH_x86 -target bpf -g -emit-llvm -S -c \$< -o \$@\n" >> Makefile + all_objs="output/$base_name.o output/$base_name.ll "$all_objs done + +echo "all:$all_objs" >> Makefile diff --git a/test/requirements.txt b/test/requirements.txt new file mode 100644 index 00000000..ed2c5ea5 --- /dev/null +++ b/test/requirements.txt @@ -0,0 +1,3 @@ +requests +matplotlib +numpy \ No newline at end of file diff --git a/test/test.ipynb b/test/test.ipynb new file mode 100644 index 00000000..2ec059f6 --- /dev/null +++ b/test/test.ipynb @@ -0,0 +1,76 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAHHCAYAAACRAnNyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA8yUlEQVR4nO3dfXyP9f////trs/NT5nzJzMmYk4gkKymnEfGOlVSMVEzIybeUMmVO56QTG3q/nZZ0gnfJp5KTpZTISZFzNsmsITYss7bn7w8/r7eXDRvjdZjb9XJ5Xep4Hs/jOB7HscNl9x3H8zheNmOMEQAAgAW5OLsAAACASyGoAAAAyyKoAAAAyyKoAAAAyyKoAAAAyyKoAAAAyyKoAAAAyyKoAAAAyyKoAAAAyyKoAMVY8+bN1bx5c2eXcV2EhITo4YcfdnYZt6w5c+bIZrMpOTnZ2aWgmCOooNhKSkpS//79VaNGDXl7e8vb21vh4eGKjo7Wr7/+6uzyLCUkJEQ2m83+8fT0VPXq1TVs2DD99ddfN7SWP//8U0OHDlXNmjXl7e0tHx8fNWzYUKNHj9aJEyduaC3nbd++XTExMQX+pRwTE+NwPC/+pKamXt+CgWKkhLMLAK6HL774Qo899phKlCih7t2764477pCLi4t27typxYsXKyEhQUlJSapcubKzS7WM+vXra8iQIZKkM2fOaOPGjZo6daq+/fZbrV+//obUsGHDBrVr106nTp3Sk08+qYYNG0qSfv75Z40bN05r1qzR8uXLb0gtF9q+fbtGjRql5s2bKyQkpMDLJSQkyNfXN097YGBg0RUHFHMEFRQ7+/bt0+OPP67KlStr5cqVqlChgsP88ePHKz4+Xi4ul7+gePr0afn4+FzPUi0lODhYTz75pH36mWeeka+vr+Li4rRnzx5Vr179mrdxuWN64sQJde7cWa6urtq8ebNq1qzpMD82NlbvvffeNddQGGfOnJG7u/tVL9+lSxeVLl26CCsCbj3c+kGxM2HCBJ0+fVqzZ8/OE1IkqUSJEhowYIAqVapkb+vZs6d8fX21b98+tWvXTn5+furevbukc79chwwZokqVKsnDw0NhYWGKi4vThV88npycLJvNpjlz5uTZns1mU0xMjH36/G2BnTt3KjIyUv7+/goKCtLAgQN15syZPMu///77atiwoby8vFSqVCk9/vjjOnjwYJ5+M2fOVNWqVeXl5aXGjRvru+++K8xhy1f58uUlnTtm5/3666/q2bOnQkND5enpqfLly6tXr146duyYw7Ln93P79u164oknVLJkSd17772X3NaMGTN06NAhTZ48OU9IkaRy5cppxIgRedq///57NW7cWJ6engoNDdW8efMc5v/1118aOnSo6tatK19fX/n7++uhhx7SL7/84tAvMTFRNptNCxcu1IgRIxQcHCxvb2+9/fbb6tq1qyTpgQcesN++SUxMvPzBK4AePXrI09NTO3bscGhv06aNSpYsqZSUlKvah48//lijRo1ScHCw/Pz81KVLF6WnpysrK0uDBg1S2bJl5evrq6ioKGVlZTmsw2azqX///vrggw8UFhYmT09PNWzYUGvWrCnQPn355Ze677775OPjIz8/P7Vv316//fbbNRwl3Oq4ooJi54svvlC1atV09913F2q5f/75R23atNG9996ruLg4eXt7yxijjh07avXq1erdu7fq16+vr7/+WsOGDdOhQ4c0ZcqUq64zMjJSISEhGjt2rNatW6e3335bx48fd/hFGxsbq9dee02RkZF65plndOTIEb3zzjtq1qyZNm/ebL+F8J///EfPPfecmjZtqkGDBmn//v3q2LGjSpUq5RDILic7O1tHjx6VdO5KwubNmzV58mQ1a9ZMVapUsff75ptvtH//fkVFRal8+fL67bffNHPmTP32229at26dbDabw3q7du2q6tWra8yYMQ7h7mKff/65vLy81KVLl4IeQu3du1ddunRR79691aNHD82aNUs9e/ZUw4YNVbt2bUnS/v379d///lddu3ZVlSpV9Oeff2rGjBm6//77tX37dlWsWNFhnW+++abc3d01dOhQZWVlqXXr1howYIDefvttvfLKK6pVq5Yk2f97OfmN7ylRooT95/bWW29p1apV6tGjh3788Ue5urpqxowZWr58uebPn2+vrbD7MHbsWHl5eenll1/W3r179c4778jNzU0uLi46fvy4YmJitG7dOs2ZM0dVqlTR66+/7rD8t99+q48++kgDBgyQh4eH4uPj1bZtW61fv1516tS55P7Onz9fPXr0UJs2bTR+/HhlZmYqISFB9957rzZv3lyo22aAnQGKkfT0dCPJdOrUKc+848ePmyNHjtg/mZmZ9nk9evQwkszLL7/ssMx///tfI8mMHj3aob1Lly7GZrOZvXv3GmOMSUpKMpLM7Nmz82xXkhk5cqR9euTIkUaS6dixo0O/fv36GUnml19+McYYk5ycbFxdXU1sbKxDv61bt5oSJUrY28+ePWvKli1r6tevb7Kysuz9Zs6caSSZ+++//xJH638qV65sJOX5REREmKNHjzr0vfC4nffhhx8aSWbNmjV59rNbt25X3L4xxpQsWdLccccdBep7Yc0XbjMtLc14eHiYIUOG2NvOnDljcnJyHJZNSkoyHh4e5o033rC3rV692kgyoaGhefbxk08+MZLM6tWrC1Tb+X3P7xMWFubQ9+uvv7afY/v37ze+vr55zt/C7kOdOnXM2bNn7e3dunUzNpvNPPTQQw7ruOeee0zlypUd2s7X+fPPP9vbDhw4YDw9PU3nzp3tbbNnzzaSTFJSkjHGmJMnT5rAwEDTp08fh/WlpqaagICAPO1AQXHrB8VKRkaGJOU7gLF58+YqU6aM/TNt2rQ8ffr27esw/X//939ydXXVgAEDHNqHDBkiY4y+/PLLq641OjraYfqFF16wb1OSFi9erNzcXEVGRuro0aP2T/ny5VW9enWtXr1a0rmBpmlpaXr++ecdxlP07NlTAQEBBa7n7rvv1jfffKNvvvlGX3zxhWJjY/Xbb7+pY8eO+vvvv+39vLy87P9/5swZHT16VE2aNJEkbdq0Kc96n3/++QJtPyMjQ35+fgWuV5LCw8N133332afLlCmjsLAw7d+/397m4eFhH4+Uk5OjY8eOydfXV2FhYfnW26NHD4d9vBaLFi2yH9Pzn9mzZzv0ad26tZ577jm98cYb+te//iVPT0/NmDHDoU9h9+Hpp5+Wm5ubffruu++WMUa9evVy6Hf33Xfr4MGD+ueffxza77nnHvtAZkm6/fbb9cgjj+jrr79WTk5Ovvv6zTff6MSJE+rWrZvD+erq6qq7777bfr4ChcWtHxQr53/RnTp1Ks+8GTNm6OTJk/rzzz8dBo2eV6JECd12220ObQcOHFDFihXz/AI9f9n/wIEDV13rxYNTq1atKhcXF/sjsHv27JEx5pKDWM//Ijpfw8X93NzcFBoaWuB6SpcurZYtW9qn27dvr7CwMHXp0kX//ve/7UHqr7/+0qhRo7Rw4UKlpaU5rCM9PT3Pei+8bXQ5/v7+OnnyZIHrlc79Ar1YyZIldfz4cft0bm6u3nrrLcXHxyspKcnhF21QUNBV11sQzZo1K9Bg2ri4OH322WfasmWLFixYoLJlyzrML+w+XHxczgfWi28DBgQEKDc3V+np6Q7rye+cq1GjhjIzM3XkyBH72KUL7dmzR5L04IMP5ruP/v7++bYDV0JQQbESEBCgChUqaNu2bXnmnR+zcql3YVz4V2thXTwu47xL/fVZkHXk5ubKZrPpyy+/lKura57++V01KmotWrSQJK1Zs8YeVCIjI/XDDz9o2LBhql+/vnx9fZWbm6u2bdsqNzc3zzoKenWiZs2a2rJli86ePVvgJ23yOy6SHMbCjBkzRq+99pp69eqlN998U6VKlZKLi4sGDRp0TfUWpc2bN9tD39atW9WtWzeH+YXdh0sdl4Icr6t1vo758+fnG2QuHJANFAZnDoqd9u3b69///rfWr1+vxo0bX9O6KleurBUrVujkyZMOV1V27txpny+d+yteUp4Xkl3uisuePXsc/nrfu3evcnNz7QMOq1atKmOMqlSpoho1aly2xvPru/Cv2ezsbCUlJemOO+4owJ7m7/wtgfNXqI4fP66VK1dq1KhRDgMwz/81fS06dOigH3/8UYsWLcrzi/pafPrpp3rggQf0n//8x6H9xIkTBX50+FJBtCicPn1aUVFRCg8PV9OmTTVhwgR17txZd911l71PUexDYeT389y9e7e8vb1VpkyZfJepWrWqJKls2bIOV+aAa8UYFRQ7/+///T95e3urV69e+vPPP/PML8xfj+3atVNOTo7effddh/YpU6bIZrPpoYceknTusnbp0qXzPMIZHx9/yXVfPEbmnXfekST7Ov/1r3/J1dVVo0aNylOzMcb+OHCjRo1UpkwZTZ8+XWfPnrX3mTNnzjW/yXXp0qWSZA875/8iv7ieqVOnXtN2pHNjWSpUqKAhQ4Zo9+7deeanpaVp9OjRhV6vq6trnno/+eQTHTp0qMDrOP/ul+vxZtyXXnpJv//+u+bOnavJkycrJCREPXr0cHhsuCj2oTB+/PFHh7EvBw8e1GeffabWrVtf8qpMmzZt5O/vrzFjxig7OzvP/CNHjlyXWlH8cUUFxU716tW1YMECdevWTWFhYfY30xpjlJSUpAULFsjFxSXPeJT8dOjQQQ888IBeffVVJScn64477tDy5cv12WefadCgQfa/IqVzL0gbN26cnnnmGTVq1Ehr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Xbu2fv75Z0VFRSkgIEADBgy45vXbbDZVqFBBZcuWLdIv3UPRcHNz40oKAOCynBpUfvjhBz3yyCNq3/7cm/pCQkL04Ycfav369UW6HVdXV34hAgBwE3LqYNqmTZtq5cqV2r17tyTpl19+0ffff6+HHnoo3/5ZWVn2L7q78AvvAABA8eTUKyovv/yyMjIyVLNmTbm6uionJ0exsbHq3r17vv3Hjh2rUaNG3eAqAThNTICzKyi8mHRnVwAUK069ovLxxx/rgw8+0IIFC7Rp0ybNnTtXcXFxmjt3br79hw8frvT0dPvn4MGDN7hiAABwIzn1isqwYcP08ssv6/HHH5ck1a1bVwcOHNDYsWPVo0ePPP09PDzk4eFxo8sEAABO4tQrKpmZmXJxcSzB1dVVubm5TqoIAABYiVOvqHTo0EGxsbG6/fbbVbt2bW3evFmTJ09Wr169nFkWAACwCKcGlXfeeUevvfaa+vXrp7S0NFWsWFHPPfecXn/9dWeWBQAALMKpQcXPz09Tp07V1KlTnVkGAACwqGL7pYQAAODmR1ABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWRVABAACWVcLZBQC4MUJeXubsEgot2dPZFQBFLCbA2RUUXky6UzfPFRUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZTg8qhw4d0pNPPqmgoCB5eXmpbt26+vnnn51dFgAAsIASztz48ePHFRERoQceeEBffvmlypQpoz179qhkyZLOLAsA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2LEKCAiwfypVqnQDKwQAADeaJYJK//799cUXX2j16tW67bbbLtlv+PDhSk9Pt38OHjx4A6sEAAA3mlNv/Rhj9MILL2jJkiVKTExUlSpVLtvfw8NDHh4eN6g6AADgbE4NKtHR0VqwYIE+++wz+fn5KTU1VZIUEBAgLy8vZ5YGAAAswKm3fhISEpSenq7mzZurQoUK9s9HH33kzLIAAIBFOP3WDwAAwKVYYjAtAABAfggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsiwRVKZNm6aQkBB5enrq7rvv1vr1651dEgAAsACnB5WPPvpIgwcP1siRI7Vp0ybdcccdatOmjdLS0pxdGgAAcDKnB5XJkyerT58+ioqKUnh4uKZPny5vb2/NmjXL2aUBAAAnc2pQOXv2rDZu3KiWLVva21xcXNSyZUv9+OOPTqwMAABYQQlnbvzo0aPKyclRuXLlHNrLlSunnTt35umflZWlrKws+3R6erokKSMj47rUl5uVeV3Wez1l2IyzSyi86/TzgyPO5xuE8/mGuBnPZ4lz+n+rPLdOY658PJwaVApr7NixGjVqVJ72SpUqOaEaawpwdgFXY9xNWTVugJvyzOB8xmXclGfHdTynT548qYCAy6/fqUGldOnScnV11Z9//unQ/ueff6p8+fJ5+g8fPlyDBw+2T+fm5uqvv/5SUFCQbDbbda/3VpWR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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "# Sample data\n", + "categories = ['Category 1', 'Category 2', 'Category 3']\n", + "group1 = [5, 7, 9]\n", + "group2 = [6, 8, 7]\n", + "# group3 = [4, 6, 8]\n", + "\n", + "# Bar width\n", + "bar_width = 0.25\n", + "\n", + "# x positions for each group of bars\n", + "x = np.arange(len(categories))\n", + "x1 = x - bar_width/2\n", + "x2 = x + bar_width/2\n", + "# x3 = x + bar_width\n", + "\n", + "# Plotting\n", + "plt.bar(x1, group1, width=bar_width, label='Group 1')\n", + "plt.bar(x2, group2, width=bar_width, label='Group 2')\n", + "# plt.bar(x3, group3, width=bar_width, label='Group 3')\n", + "\n", + "# Adding labels and title\n", + "plt.xlabel('Categories')\n", + "plt.ylabel('Values')\n", + "plt.title('Grouped Bar Chart Example')\n", + "plt.xticks(x, categories)\n", + "plt.legend()\n", + "\n", + "# Show plot\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/test/time b/test/time new file mode 100755 index 00000000..6204154b --- /dev/null +++ b/test/time @@ -0,0 +1,3 @@ +#!/bin/bash + +ts=$(date +%s%N) ; $@ ; tt=$((($(date +%s%N) - $ts))) ; echo "Real Time: $tt nanoseconds" diff --git a/tools/startvm.sh b/tools/startvm.sh new file mode 100755 index 00000000..88516fd5 --- /dev/null +++ b/tools/startvm.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +KERNEL_PATH=/home/linsy/Projects/ebpf/ePass-kernel + +DRIVE_PATH=/home/linsy/Projects/ebpf/vm/vm/ebpf.qcow2 + +# First enable bridge virbr0 + +qemu-system-x86_64 -enable-kvm -drive file=${DRIVE_PATH},format=qcow2 -kernel ${KERNEL_PATH}/arch/x86_64/boot/bzImage -append "root=/dev/sda1" --nographic -netdev bridge,id=net0,br=virbr0 -device virtio-net-pci,netdev=net0 -cpu host -smp $(nproc) -m 8G & + +#qemu-system-x86_64 -enable-kvm -drive file=${DRIVE_PATH},format=qcow2 -kernel ${KERNEL_PATH}/arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0" --nographic -netdev bridge,id=net0,br=virbr0 -device virtio-net-pci,netdev=net0 -cpu host -smp $(nproc) -m 8G