From 02ccbfc1526276ca935a691392e56a47ebf9f117 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Mon, 21 Mar 2022 12:47:56 +0100 Subject: [PATCH 01/14] AF_XDP-interaction: Move function xsk_btf__init_xdp_hint Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/lib_xsk_extend.c | 106 ++++++++++++++-------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/AF_XDP-interaction/lib_xsk_extend.c b/AF_XDP-interaction/lib_xsk_extend.c index 7221af9..ba2a8c8 100644 --- a/AF_XDP-interaction/lib_xsk_extend.c +++ b/AF_XDP-interaction/lib_xsk_extend.c @@ -67,59 +67,6 @@ static bool __xsk_equal_fn(const void *k1, const void *k2, void *ctx) return k1 == k2; } -int xsk_btf__init_xdp_hint(struct btf *btf_obj, - const char *xdp_hints_name, - struct xsk_btf_info **xbi) -{ - const struct btf_member *m; - const struct btf_type *t; - unsigned short vlen; - int i, id, ret = 0; - - if (!xbi) - return -EINVAL; - - /* Require XDP-hints are defined as a struct */ - id = btf__find_by_name_kind(btf_obj, xdp_hints_name, BTF_KIND_STRUCT); - if (id < 0) { - ret = id; - goto error_btf; - } - - t = btf__type_by_id(btf_obj, id); - - *xbi = malloc(sizeof(**xbi)); - if (!*xbi) { - ret = -ENOMEM; - goto error_btf; - } - - hashmap__init(&(*xbi)->map, __xsk_hash_fn, __xsk_equal_fn, NULL); - - /* Validate no BTF field is a bitfield */ - m = btf_members(t); - vlen = BTF_INFO_VLEN(t->info); - for (i = 0; i < vlen; i++, m++) { - if (BTF_MEMBER_BITFIELD_SIZE(m->offset)) { - ret = -ENOTSUP; - goto error_entry; - } - } - - (*xbi)->btf = btf_obj; - (*xbi)->type = t; - (*xbi)->btf_type_id = id; - - return ret; - -error_entry: - __xsk_btf_free_hash(*xbi); - free(*xbi); - -error_btf: - return ret; -} - static int __xsk_btf_field_entry(struct xsk_btf_info *xbi, const char *field, struct xsk_btf_member *entry) { @@ -219,3 +166,56 @@ int xsk_btf__read_field(void **dest, size_t size, const char *field, xsk_btf__read(dest, size, entry, xbi,addr); return 0; } + +int xsk_btf__init_xdp_hint(struct btf *btf_obj, + const char *xdp_hints_name, + struct xsk_btf_info **xbi) +{ + const struct btf_member *m; + const struct btf_type *t; + unsigned short vlen; + int i, id, ret = 0; + + if (!xbi) + return -EINVAL; + + /* Require XDP-hints are defined as a struct */ + id = btf__find_by_name_kind(btf_obj, xdp_hints_name, BTF_KIND_STRUCT); + if (id < 0) { + ret = id; + goto error_btf; + } + + t = btf__type_by_id(btf_obj, id); + + *xbi = malloc(sizeof(**xbi)); + if (!*xbi) { + ret = -ENOMEM; + goto error_btf; + } + + hashmap__init(&(*xbi)->map, __xsk_hash_fn, __xsk_equal_fn, NULL); + + /* Validate no BTF field is a bitfield */ + m = btf_members(t); + vlen = BTF_INFO_VLEN(t->info); + for (i = 0; i < vlen; i++, m++) { + if (BTF_MEMBER_BITFIELD_SIZE(m->offset)) { + ret = -ENOTSUP; + goto error_entry; + } + } + + (*xbi)->btf = btf_obj; + (*xbi)->type = t; + (*xbi)->btf_type_id = id; + + return ret; + +error_entry: + __xsk_btf_free_hash(*xbi); + free(*xbi); + +error_btf: + return ret; +} From f9095c5cafe0fcd1917d646458dd854e207dfde3 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Mon, 21 Mar 2022 13:24:26 +0100 Subject: [PATCH 02/14] AF_XDP-interaction: lib_xsk_extend: Validate 'btf_id' member MUST exist Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/lib_xsk_extend.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/AF_XDP-interaction/lib_xsk_extend.c b/AF_XDP-interaction/lib_xsk_extend.c index ba2a8c8..d28e539 100644 --- a/AF_XDP-interaction/lib_xsk_extend.c +++ b/AF_XDP-interaction/lib_xsk_extend.c @@ -171,10 +171,11 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, const char *xdp_hints_name, struct xsk_btf_info **xbi) { + struct xsk_btf_member btf_id; const struct btf_member *m; const struct btf_type *t; unsigned short vlen; - int i, id, ret = 0; + int i, id, err = 0; if (!xbi) return -EINVAL; @@ -182,7 +183,7 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, /* Require XDP-hints are defined as a struct */ id = btf__find_by_name_kind(btf_obj, xdp_hints_name, BTF_KIND_STRUCT); if (id < 0) { - ret = id; + err = id; goto error_btf; } @@ -190,7 +191,7 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, *xbi = malloc(sizeof(**xbi)); if (!*xbi) { - ret = -ENOMEM; + err = -ENOMEM; goto error_btf; } @@ -201,7 +202,7 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, vlen = BTF_INFO_VLEN(t->info); for (i = 0; i < vlen; i++, m++) { if (BTF_MEMBER_BITFIELD_SIZE(m->offset)) { - ret = -ENOTSUP; + err = -ENOTSUP; goto error_entry; } } @@ -210,12 +211,19 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, (*xbi)->type = t; (*xbi)->btf_type_id = id; - return ret; + /* Validate 'btf_id' member MUST exist */ + err = __xsk_btf_field_entry((*xbi), "btf_id", &btf_id); + if (err) + goto error_entry; + + /* TODO: Validate 'btf_id' member is last member */ + + return 0; error_entry: __xsk_btf_free_hash(*xbi); free(*xbi); error_btf: - return ret; + return err; } From 2b3fcf932de2d817e14ed21fb1962080b008a349 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Mon, 21 Mar 2022 15:10:46 +0100 Subject: [PATCH 03/14] AF_XDP-interaction: Add btf_unit_test Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/Makefile | 1 + AF_XDP-interaction/btf_unit_test.c | 51 +++++++++++++++++++++++++++++ AF_XDP-interaction/lib_xsk_extend.c | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 AF_XDP-interaction/btf_unit_test.c diff --git a/AF_XDP-interaction/Makefile b/AF_XDP-interaction/Makefile index 74fe7d8..07a27bb 100644 --- a/AF_XDP-interaction/Makefile +++ b/AF_XDP-interaction/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) USER_TARGETS := af_xdp_user +USER_TARGETS += btf_unit_test BPF_TARGETS := af_xdp_kern # Define C-code objects USER_TARGETS needs diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c new file mode 100644 index 0000000..cdfada4 --- /dev/null +++ b/AF_XDP-interaction/btf_unit_test.c @@ -0,0 +1,51 @@ +/* Code exercising BTF userspace decoding */ + +#include +#include +#include + +#include + +#include +#include + +#include /* provided by libbpf */ + +#include "lib_xsk_extend.h" + +/* Exit return codes - can be used by scripts looking at exit code */ +#define EXIT_OK 0 /* == EXIT_SUCCESS (stdlib.h) man exit(3) */ +#define EXIT_FAIL 1 /* == EXIT_FAILURE (stdlib.h) man exit(3) */ +#define EXIT_FAIL_OPTION 2 +#define EXIT_FAIL_XDP 3 +#define EXIT_FAIL_BPF 4 +#define EXIT_FAIL_BTF 5 + +struct bpf_object *load_bpf_object() { + struct bpf_object *obj; + char buf[100]; + int err; + + obj = bpf_object__open_file("af_xdp_kern.o", NULL); + err = libbpf_get_error(obj); + if (err) { + libbpf_strerror(err, buf, sizeof(buf)); + printf("Error opening file: %s\n", buf); + return NULL; + } + return obj; +} + +int main(int argc, char **argv) +{ + struct bpf_object *bpf_obj; + // int err = 0; + + bpf_obj = load_bpf_object(); + if (!bpf_obj) + return EXIT_FAIL_BPF; + + return EXIT_OK; +} + + diff --git a/AF_XDP-interaction/lib_xsk_extend.c b/AF_XDP-interaction/lib_xsk_extend.c index d28e539..ec86a76 100644 --- a/AF_XDP-interaction/lib_xsk_extend.c +++ b/AF_XDP-interaction/lib_xsk_extend.c @@ -216,7 +216,7 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, if (err) goto error_entry; - /* TODO: Validate 'btf_id' member is last member */ + /* TODO: Validate 'btf_id' is last member */ return 0; From 7715df83eeabea3a36fc6180b31e1b38cc6eb0eb Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Thu, 24 Mar 2022 12:25:07 +0100 Subject: [PATCH 04/14] AF_XDP-interaction: Add BTF decoding code to btf_unit_test Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 90 +++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index cdfada4..5878188 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -13,6 +13,8 @@ #include "lib_xsk_extend.h" +static int verbose = 1; + /* Exit return codes - can be used by scripts looking at exit code */ #define EXIT_OK 0 /* == EXIT_SUCCESS (stdlib.h) man exit(3) */ #define EXIT_FAIL 1 /* == EXIT_FAILURE (stdlib.h) man exit(3) */ @@ -36,15 +38,101 @@ struct bpf_object *load_bpf_object() { return obj; } +/** + * BTF setup XDP-hints + * ------------------- + * Setup the data structures for accessing the XDP-hints provided by + * kernel side BPF-prog via decoding BTF-info provided in BPF + * ELF-object file. + */ + +/* This struct BTF mirrors kernel-side struct xdp_hints_rx_time */ +struct xdp_hints_rx_time { + __u32 btf_type_id; /* cached xsk_btf__btf_type_id(xbi) */ + struct xsk_btf_info *xbi; + struct xsk_btf_member rx_ktime; + struct xsk_btf_member xdp_rx_cpu; +} xdp_hints_rx_time = { 0 }; + +/* This struct BTF mirrors kernel-side struct xdp_hints_mark */ +struct xdp_hints_mark { + __u32 btf_type_id; /* cached xsk_btf__btf_type_id(xbi) */ + struct xsk_btf_info *xbi; + struct xsk_btf_member mark; +} xdp_hints_mark = { 0 }; + +struct xsk_btf_info *setup_btf_info(struct btf *btf, + const char *struct_name) +{ + struct xsk_btf_info *xbi = NULL; + int err; + + err = xsk_btf__init_xdp_hint(btf, struct_name, &xbi); + if (err) { + fprintf(stderr, "WARN(%d): Cannot BTF find struct:%s\n", + err, struct_name); + return NULL; + } + + if (!xsk_btf__has_field("btf_id", xbi)) { + fprintf(stderr, "ERR: %s doesn't contain member btf_id\n", + struct_name); + xsk_btf__free_xdp_hint(xbi); + return NULL; + } + + if (verbose) + printf("Setup BTF based XDP hints for struct: %s\n", + struct_name); + + return xbi; +} + +int init_btf_info_via_bpf_object(struct bpf_object *bpf_obj) +{ + struct btf *btf = bpf_object__btf(bpf_obj); + struct xsk_btf_info *xbi; + + xbi = setup_btf_info(btf, "xdp_hints_rx_time"); + if (xbi) { + /* Lookup info on required member "rx_ktime" */ + if (!xsk_btf__field_member("rx_ktime", xbi, + &xdp_hints_rx_time.rx_ktime)) + return -EBADSLT; + if (!xsk_btf__field_member("xdp_rx_cpu", xbi, + &xdp_hints_rx_time.xdp_rx_cpu)) + return -EBADSLT; + xdp_hints_rx_time.btf_type_id = xsk_btf__btf_type_id(xbi); + xdp_hints_rx_time.xbi = xbi; + } + + xbi = setup_btf_info(btf, "xdp_hints_mark"); + if (xbi) { + if (!xsk_btf__field_member("mark", xbi, &xdp_hints_mark.mark)) + return -EBADSLT; + xdp_hints_mark.btf_type_id = xsk_btf__btf_type_id(xbi); + xdp_hints_mark.xbi = xbi; + } + + return 0; +} + int main(int argc, char **argv) { struct bpf_object *bpf_obj; - // int err = 0; + int err = 0; bpf_obj = load_bpf_object(); if (!bpf_obj) return EXIT_FAIL_BPF; + err = init_btf_info_via_bpf_object(bpf_obj); + if (err) { + if (verbose) + printf("ERR(%d): Failed loading BTF info", err); + return EXIT_FAIL_BTF; + } + return EXIT_OK; } From 871378bd4da716ceb292cf4c4d34a329bfa88ac8 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 25 Mar 2022 14:17:23 +0100 Subject: [PATCH 05/14] AF_XDP-interaction: lib_xsk_extend: Validate 'btf_id' is last member Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/lib_xsk_extend.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/AF_XDP-interaction/lib_xsk_extend.c b/AF_XDP-interaction/lib_xsk_extend.c index ec86a76..237833b 100644 --- a/AF_XDP-interaction/lib_xsk_extend.c +++ b/AF_XDP-interaction/lib_xsk_extend.c @@ -171,10 +171,11 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, const char *xdp_hints_name, struct xsk_btf_info **xbi) { - struct xsk_btf_member btf_id; + struct xsk_btf_member btf_id_member; const struct btf_member *m; const struct btf_type *t; unsigned short vlen; + __u32 member_end; int i, id, err = 0; if (!xbi) @@ -212,18 +213,23 @@ int xsk_btf__init_xdp_hint(struct btf *btf_obj, (*xbi)->btf_type_id = id; /* Validate 'btf_id' member MUST exist */ - err = __xsk_btf_field_entry((*xbi), "btf_id", &btf_id); + err = __xsk_btf_field_entry((*xbi), "btf_id", &btf_id_member); if (err) goto error_entry; - /* TODO: Validate 'btf_id' is last member */ + /* Validate 'btf_id' is last member */ + member_end = btf_id_member.offset + btf_id_member.size; + if (t->size != member_end) { + /* Situation can happen if compiler adds struct padding */ + err = -EOVERFLOW; + goto error_entry; + } return 0; error_entry: __xsk_btf_free_hash(*xbi); free(*xbi); - error_btf: return err; } From a0e2c9198314e086c5315237a8459e1b1f9060b7 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Tue, 5 Apr 2022 10:35:34 +0200 Subject: [PATCH 06/14] AF_XDP-interaction: lib user don't need to check for btf_id Now that lib side of xsk_btf__init_xdp_hint check for a valid btf_id variable, then users of the call doesn't need to check for the existance of a btf_id member. Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/af_xdp_user.c | 9 +-------- AF_XDP-interaction/btf_unit_test.c | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/AF_XDP-interaction/af_xdp_user.c b/AF_XDP-interaction/af_xdp_user.c index b69b608..492e82d 100644 --- a/AF_XDP-interaction/af_xdp_user.c +++ b/AF_XDP-interaction/af_xdp_user.c @@ -143,18 +143,11 @@ struct xsk_btf_info *setup_btf_info(struct btf *btf, err = xsk_btf__init_xdp_hint(btf, struct_name, &xbi); if (err) { - fprintf(stderr, "WARN(%d): Cannot BTF find struct:%s\n", + fprintf(stderr, "WARN(%d): Cannot BTF locate valid struct:%s\n", err, struct_name); return NULL; } - if (!xsk_btf__has_field("btf_id", xbi)) { - fprintf(stderr, "ERR: %s doesn't contain member btf_id\n", - struct_name); - xsk_btf__free_xdp_hint(xbi); - return NULL; - } - if (debug_meta) printf("Setup BTF based XDP hints for struct: %s\n", struct_name); diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index 5878188..c5445e2 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -69,18 +69,11 @@ struct xsk_btf_info *setup_btf_info(struct btf *btf, err = xsk_btf__init_xdp_hint(btf, struct_name, &xbi); if (err) { - fprintf(stderr, "WARN(%d): Cannot BTF find struct:%s\n", + fprintf(stderr, "WARN(%d): Cannot BTF locate valid struct:%s\n", err, struct_name); return NULL; } - if (!xsk_btf__has_field("btf_id", xbi)) { - fprintf(stderr, "ERR: %s doesn't contain member btf_id\n", - struct_name); - xsk_btf__free_xdp_hint(xbi); - return NULL; - } - if (verbose) printf("Setup BTF based XDP hints for struct: %s\n", struct_name); From 20916547db98c39cdb628bc622a805f9392f2592 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 08:33:40 +0200 Subject: [PATCH 07/14] AF_XDP-interaction: Add BPF object/code for unit test Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/Makefile | 1 + AF_XDP-interaction/btf_unit_test.c | 2 - AF_XDP-interaction/btf_unit_test_bpf.c | 73 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 AF_XDP-interaction/btf_unit_test_bpf.c diff --git a/AF_XDP-interaction/Makefile b/AF_XDP-interaction/Makefile index 07a27bb..e752306 100644 --- a/AF_XDP-interaction/Makefile +++ b/AF_XDP-interaction/Makefile @@ -3,6 +3,7 @@ USER_TARGETS := af_xdp_user USER_TARGETS += btf_unit_test BPF_TARGETS := af_xdp_kern +BPF_TARGETS += btf_unit_test_bpf # Define C-code objects USER_TARGETS needs USER_TARGETS_OBJS := common_params.o common_user_bpf_xdp.o diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index c5445e2..76c9fb6 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -128,5 +128,3 @@ int main(int argc, char **argv) return EXIT_OK; } - - diff --git a/AF_XDP-interaction/btf_unit_test_bpf.c b/AF_XDP-interaction/btf_unit_test_bpf.c new file mode 100644 index 0000000..7d214aa --- /dev/null +++ b/AF_XDP-interaction/btf_unit_test_bpf.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include + +#include /* bpf_core_type_id_local */ + +/* + * The xdp_hints_xxx struct's are stored in the XDP 'data_meta' area, + * which is located just in-front-of the raw packet payload data. + * + * Explaining the struct attribute's: + * ---------------------------------- + * The struct must be 4 byte aligned (kernel requirement), which here + * is enforced by the struct __attribute__((aligned(4))). + * + * To avoid any C-struct padding attribute "packed" is used. + * + * NOTICE: Do NOT define __attribute__((preserve_access_index)) here, + * as libbpf will try to find a matching kernel data-structure, + * e.g. it will cause BPF-prog loading step to fail (with invalid func + * unknown#195896080 which is 0xbad2310 in hex for "bad relo"). + */ + +struct xdp_hints_fail001 { + __u64 hash64; + __u32 btf_id; + __u32 pad; /* Pad that breaks btf_id as last member */ +} __attribute__((aligned(4))) __attribute__((packed)); + +/* Notice struct is without attribute "packed", thus (64-bit) C-compiler will + * add padding. This will cause btf_id to NOT be the last member (which is a + * requirement). + */ +struct xdp_hints_fail002 { + __u64 hash64; + __u32 btf_id; +} __attribute__((aligned(4))) /* not packed */; + + +SEC("xdp") +int xdp_prog_fail001(struct xdp_md *ctx) +{ + struct xdp_hints_fail001 *meta; + void *data; + int err; + + err = bpf_xdp_adjust_meta(ctx, -(int)sizeof(*meta)); + if (err) + return XDP_ABORTED; + + data = (void *)(unsigned long)ctx->data; + meta = (void *)(unsigned long)ctx->data_meta; + if (meta + 1 > data) /* Verify meta area is accessible */ + return XDP_ABORTED; + + meta->btf_id = bpf_core_type_id_local(struct xdp_hints_fail001); + meta->hash64 = 0x4142434445464748; + + return XDP_PASS; +} + +SEC("xdp") +int xdp_prog_fail002(struct xdp_md *ctx) +{ + struct xdp_hints_fail002 f002; + f002.btf_id = bpf_core_type_id_local(struct xdp_hints_fail002); + if (f002.btf_id == 0) + return XDP_ABORTED; + + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL"; From 1f15e94296a7bafe8c1a37981eb3384911e322ef Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 10:12:50 +0200 Subject: [PATCH 08/14] btf_unit_test: Refactor load_bpf_object to take filename Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index 76c9fb6..16f88b8 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -23,12 +23,12 @@ static int verbose = 1; #define EXIT_FAIL_BPF 4 #define EXIT_FAIL_BTF 5 -struct bpf_object *load_bpf_object() { +struct bpf_object *load_bpf_object(const char *filename) { struct bpf_object *obj; char buf[100]; int err; - obj = bpf_object__open_file("af_xdp_kern.o", NULL); + obj = bpf_object__open_file(filename, NULL); err = libbpf_get_error(obj); if (err) { libbpf_strerror(err, buf, sizeof(buf)); @@ -110,12 +110,14 @@ int init_btf_info_via_bpf_object(struct bpf_object *bpf_obj) return 0; } + + int main(int argc, char **argv) { struct bpf_object *bpf_obj; int err = 0; - bpf_obj = load_bpf_object(); + bpf_obj = load_bpf_object("af_xdp_kern.o"); if (!bpf_obj) return EXIT_FAIL_BPF; From 9ed0567cf38e1c7fd43dc7d8f08f324c4d0eab8f Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 10:15:05 +0200 Subject: [PATCH 09/14] btf_unit_test: Load BPF-object file btf_unit_test_bpf.o Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index 16f88b8..73d20dc 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -128,5 +128,10 @@ int main(int argc, char **argv) return EXIT_FAIL_BTF; } + bpf_obj = load_bpf_object("btf_unit_test_bpf.o"); + if (!bpf_obj) + return EXIT_FAIL_BPF; + + return EXIT_OK; } From 8b2494f0c0841269f542f558c004a8428eb30882 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 10:34:16 +0200 Subject: [PATCH 10/14] btf_unit_test: Remember to free memory It is a bad habit to rely on process exit to free memory. Add proper memory free operations. Using checker command: valgrind --leak-check=yes ./btf_unit_test Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index 73d20dc..b954e4c 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -98,6 +98,7 @@ int init_btf_info_via_bpf_object(struct bpf_object *bpf_obj) xdp_hints_rx_time.btf_type_id = xsk_btf__btf_type_id(xbi); xdp_hints_rx_time.xbi = xbi; } + // xsk_btf__free_xdp_hint(xbi); xbi = setup_btf_info(btf, "xdp_hints_mark"); if (xbi) { @@ -127,10 +128,15 @@ int main(int argc, char **argv) printf("ERR(%d): Failed loading BTF info", err); return EXIT_FAIL_BTF; } + /* Teardown structs and memory again */ + xsk_btf__free_xdp_hint(xdp_hints_rx_time.xbi); + xsk_btf__free_xdp_hint(xdp_hints_mark.xbi); + bpf_object__close(bpf_obj); bpf_obj = load_bpf_object("btf_unit_test_bpf.o"); if (!bpf_obj) return EXIT_FAIL_BPF; + bpf_object__close(bpf_obj); return EXIT_OK; From f14a20a15de1ae2df8327300270bc33b81473cfe Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 10:41:27 +0200 Subject: [PATCH 11/14] btf_unit_test: Prepare partition of tests Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index b954e4c..d1726e7 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -98,7 +98,7 @@ int init_btf_info_via_bpf_object(struct bpf_object *bpf_obj) xdp_hints_rx_time.btf_type_id = xsk_btf__btf_type_id(xbi); xdp_hints_rx_time.xbi = xbi; } - // xsk_btf__free_xdp_hint(xbi); + /* Remember to cleanup later: xsk_btf__free_xdp_hint(xbi); */ xbi = setup_btf_info(btf, "xdp_hints_mark"); if (xbi) { @@ -111,9 +111,7 @@ int init_btf_info_via_bpf_object(struct bpf_object *bpf_obj) return 0; } - - -int main(int argc, char **argv) +int test01_normal() { struct bpf_object *bpf_obj; int err = 0; @@ -133,6 +131,18 @@ int main(int argc, char **argv) xsk_btf__free_xdp_hint(xdp_hints_mark.xbi); bpf_object__close(bpf_obj); + return EXIT_OK; +} + +int main(int argc, char **argv) +{ + struct bpf_object *bpf_obj; + int err; + + err = test01_normal(); + if (err != EXIT_OK) + return err; + bpf_obj = load_bpf_object("btf_unit_test_bpf.o"); if (!bpf_obj) return EXIT_FAIL_BPF; From 7409814e44550e1ec6454de05703aa87c13a2f70 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 10:43:55 +0200 Subject: [PATCH 12/14] btf_unit_test: Fix small leak If init_btf_info_via_bpf_object() fails, then we should release bpf_object. Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index d1726e7..b04bcec 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -124,6 +124,7 @@ int test01_normal() if (err) { if (verbose) printf("ERR(%d): Failed loading BTF info", err); + bpf_object__close(bpf_obj); return EXIT_FAIL_BTF; } /* Teardown structs and memory again */ From 1e4e033c3ada70c8a5d694c48d47a70a5ccfe4f8 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 11:29:47 +0200 Subject: [PATCH 13/14] btf_unit_test: Add test02_should_fail Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 76 ++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index b04bcec..4419448 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -62,21 +62,30 @@ struct xdp_hints_mark { } xdp_hints_mark = { 0 }; struct xsk_btf_info *setup_btf_info(struct btf *btf, - const char *struct_name) + const char *struct_name, + int *errval) { struct xsk_btf_info *xbi = NULL; int err; err = xsk_btf__init_xdp_hint(btf, struct_name, &xbi); if (err) { - fprintf(stderr, "WARN(%d): Cannot BTF locate valid struct:%s\n", - err, struct_name); + if (errval) { + /* Expect caller to handle err detection */ + *errval = err; + } else { + fprintf(stderr, + "WARN(%d): Cannot BTF locate valid struct:%s\n", + err, struct_name); + } return NULL; } - if (verbose) - printf("Setup BTF based XDP hints for struct: %s\n", - struct_name); + if (verbose) { + int btf_id = xsk_btf__btf_type_id(xbi); + printf("Setup BTF based XDP hints for (btf_id:%d) struct: %s\n", + btf_id, struct_name); + } return xbi; } @@ -86,7 +95,7 @@ int init_btf_info_via_bpf_object(struct bpf_object *bpf_obj) struct btf *btf = bpf_object__btf(bpf_obj); struct xsk_btf_info *xbi; - xbi = setup_btf_info(btf, "xdp_hints_rx_time"); + xbi = setup_btf_info(btf, "xdp_hints_rx_time", NULL); if (xbi) { /* Lookup info on required member "rx_ktime" */ if (!xsk_btf__field_member("rx_ktime", xbi, @@ -100,7 +109,7 @@ int init_btf_info_via_bpf_object(struct bpf_object *bpf_obj) } /* Remember to cleanup later: xsk_btf__free_xdp_hint(xbi); */ - xbi = setup_btf_info(btf, "xdp_hints_mark"); + xbi = setup_btf_info(btf, "xdp_hints_mark", NULL); if (xbi) { if (!xsk_btf__field_member("mark", xbi, &xdp_hints_mark.mark)) return -EBADSLT; @@ -135,20 +144,57 @@ int test01_normal() return EXIT_OK; } -int main(int argc, char **argv) +int test02_should_fail() { struct bpf_object *bpf_obj; - int err; - - err = test01_normal(); - if (err != EXIT_OK) - return err; + struct xsk_btf_info *xbi; + struct btf *btf; + int errval = 0; + int ret = EXIT_OK; + const char *xdp_hint_name = "xdp_hints_fail001"; bpf_obj = load_bpf_object("btf_unit_test_bpf.o"); if (!bpf_obj) return EXIT_FAIL_BPF; - bpf_object__close(bpf_obj); + btf = bpf_object__btf(bpf_obj); + + xbi = setup_btf_info(btf, xdp_hint_name, &errval); + if (xbi) { + /* Unexpected success - as hints layout should be invalid */ + printf(" - Unexpected success in test that should fail\n"); + xsk_btf__free_xdp_hint(xbi); + ret = EXIT_FAIL_BPF; + goto out; + } + if (errval != -EOVERFLOW) { + /* Expecting failure with EOVERFLOW as btf_id not last member */ + printf("Unexpect FAIL - with errno:%d\n", errval); + ret = EXIT_FAIL_BTF; + goto out; + } + if (verbose) { + printf("SUCCESS - " + "detect btf_id not last member in struct %s\n", + xdp_hint_name); + } + +out: + bpf_object__close(bpf_obj); + return ret; +} + +int main(int argc, char **argv) +{ + int err; + + err = test01_normal(); + if (err) + return err; + + err = test02_should_fail(); + if (err) + return err; return EXIT_OK; } From 18908873a7f48483ed8bab2d949e8760cff30810 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 22 Apr 2022 12:21:35 +0200 Subject: [PATCH 14/14] refactor code test02_should_fail Introduce helper to make is easier to test two struct variations with the same invalid btf_id struct location. Signed-off-by: Jesper Dangaard Brouer --- AF_XDP-interaction/btf_unit_test.c | 40 ++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/AF_XDP-interaction/btf_unit_test.c b/AF_XDP-interaction/btf_unit_test.c index 4419448..85919cb 100644 --- a/AF_XDP-interaction/btf_unit_test.c +++ b/AF_XDP-interaction/btf_unit_test.c @@ -144,20 +144,12 @@ int test01_normal() return EXIT_OK; } -int test02_should_fail() +int helper_expect_invalid_btf_id(struct btf *btf, + const char *xdp_hint_name) { - struct bpf_object *bpf_obj; struct xsk_btf_info *xbi; - struct btf *btf; - int errval = 0; int ret = EXIT_OK; - const char *xdp_hint_name = "xdp_hints_fail001"; - - bpf_obj = load_bpf_object("btf_unit_test_bpf.o"); - if (!bpf_obj) - return EXIT_FAIL_BPF; - - btf = bpf_object__btf(bpf_obj); + int errval = 0; xbi = setup_btf_info(btf, xdp_hint_name, &errval); if (xbi) { @@ -179,6 +171,32 @@ int test02_should_fail() xdp_hint_name); } +out: + return ret; +} + +int test02_should_fail() +{ + const char *xdp_hint01 = "xdp_hints_fail001"; + const char *xdp_hint02 = "xdp_hints_fail002"; + struct bpf_object *bpf_obj; + int ret = EXIT_OK; + struct btf *btf; + + bpf_obj = load_bpf_object("btf_unit_test_bpf.o"); + if (!bpf_obj) + return EXIT_FAIL_BPF; + + btf = bpf_object__btf(bpf_obj); + + ret = helper_expect_invalid_btf_id(btf, xdp_hint01); + if (ret) + goto out; + + ret = helper_expect_invalid_btf_id(btf, xdp_hint02); + if (ret) + goto out; + out: bpf_object__close(bpf_obj); return ret;