From 00c57b6900fb0f3d9ed10127258a9fb2b0b7e124 Mon Sep 17 00:00:00 2001 From: Leonardo Di Donato Date: Tue, 7 Jun 2022 15:30:00 +0200 Subject: [PATCH 1/5] docs: insert instructions about the debug build Signed-off-by: Leonardo Di Donato --- README.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.txt b/README.txt index a4b9cea..dd8ef5a 100644 --- a/README.txt +++ b/README.txt @@ -127,6 +127,14 @@ BUILD xmake -b bpf + In case you want to compile in debug mode: + + xmake f -m debug + + You will be able to read from the trace_pipe the logs of the BPF programs + and you will obtain the logs of libbpf into the stderr only if you compile + in debug mode. + TEST To run the test suite you can do this: From 8e91a1f2948b8c316b3ca9508982b55623d4ff04 Mon Sep 17 00:00:00 2001 From: Leonardo Di Donato Date: Tue, 7 Jun 2022 15:30:37 +0200 Subject: [PATCH 2/5] update: output libbpf logs only in debug mode Signed-off-by: Leonardo Di Donato --- traffico.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/traffico.c b/traffico.c index 2fd2c95..ae3cf03 100644 --- a/traffico.c +++ b/traffico.c @@ -197,7 +197,11 @@ void sig_handler(int signo) static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { +#ifndef NDEBUG return print_log(g_config.err_stream, level == LIBBPF_DEBUG && g_config.verbose, false, format, args); +#else + return 0; +#endif } int await(struct bpf_tc_hook hook, struct bpf_tc_opts opts) From df45c45e9a3d750d49225f816fb0ff7a2b8ef18c Mon Sep 17 00:00:00 2001 From: Leonardo Di Donato Date: Tue, 7 Jun 2022 15:31:42 +0200 Subject: [PATCH 3/5] new(.devcontainer): install gdb and tree Signed-off-by: Leonardo Di Donato --- .devcontainer/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 7538e63..9a06f9d 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,12 +1,10 @@ FROM docker.io/archlinux:latest RUN pacman -Syy --noconfirm -RUN pacman -S --noconfirm nodejs clang llvm gcc linux-headers bpf unzip docker vi vim +RUN pacman -S --noconfirm nodejs clang llvm gcc linux-headers bpf unzip docker vi vim gdb tree RUN pacman -S --noconfirm --needed git base-devel - - # user setup WORKDIR /tmp RUN useradd -m -r -u 1000 vscode -s /bin/bash From f3da7ce8abad526465741678325eaf6e4eaa7980 Mon Sep 17 00:00:00 2001 From: Leonardo Di Donato Date: Tue, 7 Jun 2022 15:32:12 +0200 Subject: [PATCH 4/5] build: simplify the output path for BPF artifacts Signed-off-by: Leonardo Di Donato --- bpf/block_ip.bpf.c | 1 - bpf/block_port.bpf.c | 3 +-- bpf/block_private_ipv4.bpf.c | 2 +- bpf/xmake.lua | 6 +++--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/bpf/block_ip.bpf.c b/bpf/block_ip.bpf.c index 0ee18f8..1542b42 100644 --- a/bpf/block_ip.bpf.c +++ b/bpf/block_ip.bpf.c @@ -5,7 +5,6 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -// TODO > make this easy to configure via config struct const volatile __u32 input = 0; // address to block (host byte order) SEC("tc") diff --git a/bpf/block_port.bpf.c b/bpf/block_port.bpf.c index e51bb7c..9b45b20 100644 --- a/bpf/block_port.bpf.c +++ b/bpf/block_port.bpf.c @@ -5,8 +5,7 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -// TODO > make this easy to configure via config struct -const volatile __u32 input = 0; +const volatile __u16 input = 0; // port to block SEC("tc") int block_port(struct __sk_buff *skb) diff --git a/bpf/block_private_ipv4.bpf.c b/bpf/block_private_ipv4.bpf.c index 0d07b30..bc66565 100644 --- a/bpf/block_private_ipv4.bpf.c +++ b/bpf/block_private_ipv4.bpf.c @@ -53,7 +53,7 @@ int block_private_ipv4(struct __sk_buff *skb) struct iphdr *ip_header = data + l3_offset; const int l4_offset = l3_offset + sizeof(*ip_header); - + if (data + l4_offset > data_end) { bpf_printk("classifier: [iph] size lenght check hit: continue"); diff --git a/bpf/xmake.lua b/bpf/xmake.lua index 0379913..de67952 100644 --- a/bpf/xmake.lua +++ b/bpf/xmake.lua @@ -8,7 +8,7 @@ rule("bpf") set_extensions(".bpf.c") on_config(function (target) assert(is_host("linux"), 'rule("bpf"): only supported on linux!') - local headerdir = path.join(target:autogendir(), "rules", "bpf") + local headerdir = path.join(target:autogendir()) if not os.isdir(headerdir) then os.mkdir(headerdir) end @@ -21,8 +21,8 @@ rule("bpf") bpftool = filecfg.bpftool end - local headerfile = path.join(target:autogendir(), "rules", "bpf", (path.filename(sourcefile):gsub("%.bpf%.c", ".skel.h"))) - local objectfile = path.join(target:autogendir(), "rules", "bpf", (path.filename(sourcefile):gsub("%.bpf%.c", ".bpf.o"))) + local headerfile = path.join(target:autogendir(), (path.filename(sourcefile):gsub("%.bpf%.c", ".skel.h"))) + local objectfile = path.join(target:autogendir(), (path.filename(sourcefile):gsub("%.bpf%.c", ".bpf.o"))) local targetarch if target:is_arch("x86_64", "i386") then targetarch = "__TARGET_ARCH_x86" From 37ebb23df7373ad608a4dcb5253f829b6556f495 Mon Sep 17 00:00:00 2001 From: Leonardo Di Donato Date: Tue, 7 Jun 2022 15:33:40 +0200 Subject: [PATCH 5/5] SAVEPOINT: 2022-06-07 @ 15:33:40 --- api/api.$progname.h.in | 32 ++++++++++++++++++++++++-------- api/api.h.in | 14 +++++--------- api/xmake.lua | 6 +++--- traffico.c | 5 ++++- xmake/modules/api.lua | 33 +++++++++++++++++++++++++++++---- 5 files changed, 65 insertions(+), 25 deletions(-) diff --git a/api/api.$progname.h.in b/api/api.$progname.h.in index f0260bd..a55f20a 100644 --- a/api/api.$progname.h.in +++ b/api/api.$progname.h.in @@ -1,6 +1,8 @@ #include "${PROGNAME}.skel.h" -int ${OPERATION}${PROGNAME}(struct config *conf, after_attach_fn_t cb, bpf_obj_fn_t obj_cb) +#define ${PROGNAME}_has_rodata ${PROGNAME_WITH_RODATA} + +int ${OPERATION}${PROGNAME}(struct config *conf, after_attach_fn_t cb, const void* rodata) { int err; char buf[100]; @@ -15,14 +17,28 @@ int ${OPERATION}${PROGNAME}(struct config *conf, after_attach_fn_t cb, bpf_obj_f return 1; } - if (obj_cb) { - err = obj_cb(obj); - if (err) - { - fprintf(stderr, "traffico: fail calling obj callback\n"); - goto destroy_${PROGNAME}; - } + // Set read-only data +#if ${PROGNAME}_has_rodata + struct bpf_map *m = bpf_object__find_map_by_name(obj->obj, ".rodata"); + if (!m || !bpf_map__is_internal(m)) + { + log_err(conf, "fail: finding the .rodata map\n"); + return 1; + } + const char *m_name = bpf_map__name(m); + size_t m_size = bpf_map__value_size(m); + log_out(conf, "done: finding the %s map (size %d)\n", m_name, m_size); + err = bpf_map__set_initial_value(m, rodata, m_size); + if (err) + { + free(m); + log_err(conf, "fail: setting the %s map\n", m_name); + return 1; } + log_out(conf, "done: setting the %s map\n", m_name); +#else + log_out(conf, "done: moving on: no .rodata map\n"); +#endif err = ${PROGNAME}_bpf__load(obj); if (err) diff --git a/api/api.h.in b/api/api.h.in index 0cd158c..07be114 100644 --- a/api/api.h.in +++ b/api/api.h.in @@ -31,11 +31,9 @@ struct config FILE *out_stream; }; -typedef int (*bpf_obj_fn_t)(void *obj); - typedef int (*after_attach_fn_t)(struct bpf_tc_hook hook, struct bpf_tc_opts opts); -typedef int (*attach_fn_t)(struct config *conf, after_attach_fn_t cb, bpf_obj_fn_t obj_cb); +typedef int (*attach_fn_t)(struct config *conf, after_attach_fn_t cb, const void* rodata); /// logging int print_log(FILE *f, bool verbosity, bool prefix, const char *fmt, va_list argptr) @@ -78,7 +76,7 @@ int exit_after_attach(struct bpf_tc_hook hook, struct bpf_tc_opts opts) } /// non-existing programs -int ${OPERATION}0(struct config *conf, after_attach_fn_t cb, bpf_obj_fn_t obj_cb) +int ${OPERATION}0(struct config *conf, after_attach_fn_t cb, const void *rodata) { return 1; } @@ -88,15 +86,13 @@ ${API} /// dispatch attach_fn_t attach_fn[NUM_PROGRAMS] = { ${PROGRAMS_OPS_AS_SYMBOLS} }; -int attach(struct config *conf, after_attach_fn_t cb, bpf_obj_fn_t obj_cb) +int attach(struct config *conf, after_attach_fn_t cb, const void* rodata) { attach_fn_t fn = attach_fn[conf->program]; if (fn) { - return fn(conf, cb, obj_cb); + return fn(conf, cb, rodata); } - return ${OPERATION}0(conf, cb, obj_cb); + return ${OPERATION}0(conf, cb, NULL); } - - #endif // TRAFFICO_API_H \ No newline at end of file diff --git a/api/xmake.lua b/api/xmake.lua index dd43351..5e5b69a 100644 --- a/api/xmake.lua +++ b/api/xmake.lua @@ -8,7 +8,7 @@ includes("xmake/repos.lua") add_rules("mode.release", "mode.debug") -- target to generate API components for every BPF program -target("every.api") +target("every-api") set_kind("headeronly") includes("../bpf") add_deps("bpf") @@ -23,10 +23,10 @@ target("every.api") -- target to generate the API target("api") set_kind("headeronly") - add_deps("every.api") + add_deps("every-api") on_config(function(target) import("xmake.modules.api", { rootdir = os.projectdir() }) - api(target, "every.api", true) + api(target, "every-api", true) import("actions.config.configfiles", { alias = "gen_configfiles", rootdir = os.programdir() }) gen_configfiles() diff --git a/traffico.c b/traffico.c index ae3cf03..7382919 100644 --- a/traffico.c +++ b/traffico.c @@ -244,5 +244,8 @@ int main(int argc, char **argv) // Execute log_info("prog: %s\n", g_programs_name[g_config.program]); - return attach(&g_config, &await, NULL); + __u32 input = 16843010; + __u8 *val = malloc(4); + memcpy(val, &input, 4); // memset(val, 1, 4); + return attach(&g_config, &await, val); } diff --git a/xmake/modules/api.lua b/xmake/modules/api.lua index ae817f8..807165d 100644 --- a/xmake/modules/api.lua +++ b/xmake/modules/api.lua @@ -1,4 +1,5 @@ import("core.project.project") +import("lib.detect.check_cxsnippets") -- get sourcefiles function _get_programs(target_name) @@ -17,6 +18,10 @@ function gen(target, source_target) if not target then raise("could not configure target") end + local source_gendir = path.absolute(project.target(source_target):autogendir()) + if not source_gendir then + raise("could not obtain the autogendir of the source target") + end target:set("configdir", target:autogendir()) @@ -30,7 +35,22 @@ function gen(target, source_target) local tempconf = path.join(os.tmpdir(), confname) os.tryrm(tempconf) os.cp(configfile_template_path, tempconf) - target:add("configfiles", tempconf, { variables = { PROGNAME = progname, OPERATION = "attach__" } }) + + local skelpath = path.join(source_gendir, progname .. ".skel.h") + local has_rodata = check_cxsnippets("void test() {&((struct " .. progname .. "_bpf*)0)->rodata;}", {includes = skelpath}) and 1 or 0 + if has_rodata == 1 then + utils.dump( + check_cxsnippets('void test() {printf("%ld", sizeof(&((struct ' .. progname .. '_bpf*)0)->rodata));}', {includes = skelpath}) + ) + end + + target:add("configfiles", tempconf, { + variables = { + PROGNAME = progname, + OPERATION = "attach__", + PROGNAME_WITH_RODATA = has_rodata + } + }) end end @@ -51,18 +71,23 @@ function main(target, components_target, banner) local op = vars[1].variables.OPERATION v["OPERATION"] = op - + + local descr = '" - ' local programs = {} table.insert(programs, "0") - for _, v in ipairs(vars) do + for i, v in ipairs(vars) do table.insert(programs, v.variables.PROGNAME) + descr = descr .. v.variables.PROGNAME .. (v.variables.PROGNAME_WITH_RODATA == 1 and ' [input]' or '') + if i ~= #vars then + descr = descr .. '\\n - ' + end end table.sort(programs) v["PROGRAMS_AS_SYMBOLS"] = 'program_' .. table.concat(programs, ", program_") v["PROGRAMS_AS_STRINGS"] = '"' .. table.concat(programs, '", "') .. '"' v["PROGRAMS_OPS_AS_SYMBOLS"] = op .. table.concat(programs, ', ' .. op) table.remove(programs, 1) - v["PROGRAMS_DESCRIPTION"] = '" - ' .. table.concat(programs, '\\n - ') .. '"' + v["PROGRAMS_DESCRIPTION"] = descr .. '"' local content = "" for i, c in ipairs(components) do