Skip to content

Commit 0568735

Browse files
iamkafaiAlexei Starovoitov
authored andcommitted
bpf: Refactor and bug fix in test_func_type in test_btf.c
1) bpf_load_program_xattr() is absorbing the EBIG error which makes testing this case impossible. It is replaced with a direct syscall(__NR_bpf, BPF_PROG_LOAD,...). 2) The test_func_type() is renamed to test_info_raw() to prepare for the new line_info test in the next patch. 3) The bpf_obj_get_info_by_fd() testing for func_info is refactored to test_get_finfo(). A new test_get_linfo() will be added in the next patch for testing line_info purpose. 4) The test->func_info_cnt is checked instead of a static value "2". 5) Remove unnecessary "\n" in error message. 6) Adding back info_raw_test_num to the cmd arg such that a specific test case can be tested, like all other existing tests. 7) Fix a bug in handling expected_prog_load_failure. A test could pass even if prog_fd != -1 while expected_prog_load_failure is true. 8) The min rec_size check should be < 8 instead of < 4. Fixes: 4798c4b ("tools/bpf: extends test_btf to test load/retrieve func_type info") Signed-off-by: Martin KaFai Lau <kafai@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent ee491d8 commit 0568735

File tree

1 file changed

+125
-86
lines changed

1 file changed

+125
-86
lines changed

tools/testing/selftests/bpf/test_btf.c

Lines changed: 125 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/err.h>
77
#include <linux/kernel.h>
88
#include <linux/filter.h>
9+
#include <linux/unistd.h>
910
#include <bpf/bpf.h>
1011
#include <sys/resource.h>
1112
#include <libelf.h>
@@ -114,12 +115,13 @@ static struct args {
114115
unsigned int raw_test_num;
115116
unsigned int file_test_num;
116117
unsigned int get_info_test_num;
118+
unsigned int info_raw_test_num;
117119
bool raw_test;
118120
bool file_test;
119121
bool get_info_test;
120122
bool pprint_test;
121123
bool always_log;
122-
bool func_type_test;
124+
bool info_raw_test;
123125
} args;
124126

125127
static char btf_log_buf[BTF_LOG_BUF_SIZE];
@@ -3051,7 +3053,7 @@ static int test_pprint(void)
30513053
return err;
30523054
}
30533055

3054-
static struct btf_func_type_test {
3056+
static struct prog_info_raw_test {
30553057
const char *descr;
30563058
const char *str_sec;
30573059
__u32 raw_types[MAX_NR_RAW_TYPES];
@@ -3062,7 +3064,7 @@ static struct btf_func_type_test {
30623064
__u32 func_info_rec_size;
30633065
__u32 func_info_cnt;
30643066
bool expected_prog_load_failure;
3065-
} func_type_test[] = {
3067+
} info_raw_tests[] = {
30663068
{
30673069
.descr = "func_type (main func + one sub)",
30683070
.raw_types = {
@@ -3198,90 +3200,44 @@ static size_t probe_prog_length(const struct bpf_insn *fp)
31983200
return len + 1;
31993201
}
32003202

3201-
static int do_test_func_type(int test_num)
3203+
static int test_get_finfo(const struct prog_info_raw_test *test,
3204+
int prog_fd)
32023205
{
3203-
const struct btf_func_type_test *test = &func_type_test[test_num];
3204-
unsigned int raw_btf_size, info_len, rec_size;
3205-
int i, btf_fd = -1, prog_fd = -1, err = 0;
3206-
struct bpf_load_program_attr attr = {};
3207-
void *raw_btf, *func_info = NULL;
32083206
struct bpf_prog_info info = {};
32093207
struct bpf_func_info *finfo;
3210-
3211-
fprintf(stderr, "%s......", test->descr);
3212-
raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
3213-
test->str_sec, test->str_sec_size,
3214-
&raw_btf_size);
3215-
3216-
if (!raw_btf)
3217-
return -1;
3218-
3219-
*btf_log_buf = '\0';
3220-
btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
3221-
btf_log_buf, BTF_LOG_BUF_SIZE,
3222-
args.always_log);
3223-
free(raw_btf);
3224-
3225-
if (CHECK(btf_fd == -1, "invalid btf_fd errno:%d", errno)) {
3226-
err = -1;
3227-
goto done;
3228-
}
3229-
3230-
if (*btf_log_buf && args.always_log)
3231-
fprintf(stderr, "\n%s", btf_log_buf);
3232-
3233-
attr.prog_type = test->prog_type;
3234-
attr.insns = test->insns;
3235-
attr.insns_cnt = probe_prog_length(attr.insns);
3236-
attr.license = "GPL";
3237-
attr.prog_btf_fd = btf_fd;
3238-
attr.func_info_rec_size = test->func_info_rec_size;
3239-
attr.func_info_cnt = test->func_info_cnt;
3240-
attr.func_info = test->func_info;
3241-
3242-
*btf_log_buf = '\0';
3243-
prog_fd = bpf_load_program_xattr(&attr, btf_log_buf,
3244-
BTF_LOG_BUF_SIZE);
3245-
if (test->expected_prog_load_failure && prog_fd == -1) {
3246-
err = 0;
3247-
goto done;
3248-
}
3249-
if (CHECK(prog_fd == -1, "invalid prog_id errno:%d", errno)) {
3250-
fprintf(stderr, "%s\n", btf_log_buf);
3251-
err = -1;
3252-
goto done;
3253-
}
3208+
__u32 info_len, rec_size, i;
3209+
void *func_info = NULL;
3210+
int err;
32543211

32553212
/* get necessary lens */
32563213
info_len = sizeof(struct bpf_prog_info);
32573214
err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
32583215
if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
32593216
fprintf(stderr, "%s\n", btf_log_buf);
3260-
err = -1;
3261-
goto done;
3217+
return -1;
32623218
}
3263-
if (CHECK(info.func_info_cnt != 2,
3264-
"incorrect info.func_info_cnt (1st) %d\n",
3219+
if (CHECK(info.func_info_cnt != test->func_info_cnt,
3220+
"incorrect info.func_info_cnt (1st) %d",
32653221
info.func_info_cnt)) {
3266-
err = -1;
3267-
goto done;
3222+
return -1;
32683223
}
3224+
32693225
rec_size = info.func_info_rec_size;
3270-
if (CHECK(rec_size < 4,
3271-
"incorrect info.func_info_rec_size (1st) %d\n", rec_size)) {
3272-
err = -1;
3273-
goto done;
3226+
if (CHECK(rec_size < 8,
3227+
"incorrect info.func_info_rec_size (1st) %d", rec_size)) {
3228+
return -1;
32743229
}
32753230

3231+
if (!info.func_info_cnt)
3232+
return 0;
3233+
32763234
func_info = malloc(info.func_info_cnt * rec_size);
3277-
if (CHECK(!func_info, "out of memory")) {
3278-
err = -1;
3279-
goto done;
3280-
}
3235+
if (CHECK(!func_info, "out of memory"))
3236+
return -1;
32813237

32823238
/* reset info to only retrieve func_info related data */
32833239
memset(&info, 0, sizeof(info));
3284-
info.func_info_cnt = 2;
3240+
info.func_info_cnt = test->func_info_cnt;
32853241
info.func_info_rec_size = rec_size;
32863242
info.func_info = ptr_to_u64(func_info);
32873243
err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
@@ -3290,14 +3246,14 @@ static int do_test_func_type(int test_num)
32903246
err = -1;
32913247
goto done;
32923248
}
3293-
if (CHECK(info.func_info_cnt != 2,
3294-
"incorrect info.func_info_cnt (2nd) %d\n",
3249+
if (CHECK(info.func_info_cnt != test->func_info_cnt,
3250+
"incorrect info.func_info_cnt (2nd) %d",
32953251
info.func_info_cnt)) {
32963252
err = -1;
32973253
goto done;
32983254
}
3299-
if (CHECK(info.func_info_rec_size != rec_size,
3300-
"incorrect info.func_info_rec_size (2nd) %d\n",
3255+
if (CHECK(info.func_info_rec_size < 8,
3256+
"incorrect info.func_info_rec_size (2nd) %d",
33013257
info.func_info_rec_size)) {
33023258
err = -1;
33033259
goto done;
@@ -3310,7 +3266,7 @@ static int do_test_func_type(int test_num)
33103266
}
33113267

33123268
finfo = func_info;
3313-
for (i = 0; i < 2; i++) {
3269+
for (i = 0; i < test->func_info_cnt; i++) {
33143270
if (CHECK(finfo->type_id != test->func_info[i][1],
33153271
"incorrect func_type %u expected %u",
33163272
finfo->type_id, test->func_info[i][1])) {
@@ -3320,41 +3276,114 @@ static int do_test_func_type(int test_num)
33203276
finfo = (void *)finfo + rec_size;
33213277
}
33223278

3279+
err = 0;
3280+
3281+
done:
3282+
free(func_info);
3283+
return err;
3284+
}
3285+
3286+
static int do_test_info_raw(unsigned int test_num)
3287+
{
3288+
const struct prog_info_raw_test *test = &info_raw_tests[test_num - 1];
3289+
int btf_fd = -1, prog_fd = -1, err = 0;
3290+
unsigned int raw_btf_size;
3291+
union bpf_attr attr = {};
3292+
void *raw_btf;
3293+
3294+
fprintf(stderr, "BTF prog info raw test[%u] (%s): ", test_num, test->descr);
3295+
raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
3296+
test->str_sec, test->str_sec_size,
3297+
&raw_btf_size);
3298+
3299+
if (!raw_btf)
3300+
return -1;
3301+
3302+
*btf_log_buf = '\0';
3303+
btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
3304+
btf_log_buf, BTF_LOG_BUF_SIZE,
3305+
args.always_log);
3306+
free(raw_btf);
3307+
3308+
if (CHECK(btf_fd == -1, "invalid btf_fd errno:%d", errno)) {
3309+
err = -1;
3310+
goto done;
3311+
}
3312+
3313+
if (*btf_log_buf && args.always_log)
3314+
fprintf(stderr, "\n%s", btf_log_buf);
3315+
*btf_log_buf = '\0';
3316+
3317+
attr.prog_type = test->prog_type;
3318+
attr.insns = ptr_to_u64(test->insns);
3319+
attr.insn_cnt = probe_prog_length(test->insns);
3320+
attr.license = ptr_to_u64("GPL");
3321+
attr.prog_btf_fd = btf_fd;
3322+
attr.func_info_rec_size = test->func_info_rec_size;
3323+
attr.func_info_cnt = test->func_info_cnt;
3324+
attr.func_info = ptr_to_u64(test->func_info);
3325+
attr.log_buf = ptr_to_u64(btf_log_buf);
3326+
attr.log_size = BTF_LOG_BUF_SIZE;
3327+
attr.log_level = 1;
3328+
3329+
prog_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
3330+
err = ((prog_fd == -1) != test->expected_prog_load_failure);
3331+
if (CHECK(err, "prog_fd:%d expected_prog_load_failure:%u errno:%d",
3332+
prog_fd, test->expected_prog_load_failure, errno)) {
3333+
err = -1;
3334+
goto done;
3335+
}
3336+
3337+
if (prog_fd == -1)
3338+
goto done;
3339+
3340+
err = test_get_finfo(test, prog_fd);
3341+
if (err)
3342+
goto done;
3343+
33233344
done:
3345+
if (!err)
3346+
fprintf(stderr, "OK");
3347+
33243348
if (*btf_log_buf && (err || args.always_log))
33253349
fprintf(stderr, "\n%s", btf_log_buf);
33263350

33273351
if (btf_fd != -1)
33283352
close(btf_fd);
33293353
if (prog_fd != -1)
33303354
close(prog_fd);
3331-
free(func_info);
3355+
33323356
return err;
33333357
}
33343358

3335-
static int test_func_type(void)
3359+
static int test_info_raw(void)
33363360
{
33373361
unsigned int i;
33383362
int err = 0;
33393363

3340-
for (i = 0; i < ARRAY_SIZE(func_type_test); i++)
3341-
err |= count_result(do_test_func_type(i));
3364+
if (args.info_raw_test_num)
3365+
return count_result(do_test_info_raw(args.info_raw_test_num));
3366+
3367+
for (i = 1; i <= ARRAY_SIZE(info_raw_tests); i++)
3368+
err |= count_result(do_test_info_raw(i));
33423369

33433370
return err;
33443371
}
33453372

33463373
static void usage(const char *cmd)
33473374
{
3348-
fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] |"
3349-
" [-g test_num (1 - %zu)] |"
3350-
" [-f test_num (1 - %zu)] | [-p] | [-k] ]\n",
3375+
fprintf(stderr, "Usage: %s [-l] [[-r btf_raw_test_num (1 - %zu)] |\n"
3376+
"\t[-g btf_get_info_test_num (1 - %zu)] |\n"
3377+
"\t[-f btf_file_test_num (1 - %zu)] |\n"
3378+
"\t[-k btf_prog_info_raw_test_num (1 - %zu)] |\n"
3379+
"\t[-p (pretty print test)]]\n",
33513380
cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests),
3352-
ARRAY_SIZE(file_tests));
3381+
ARRAY_SIZE(file_tests), ARRAY_SIZE(info_raw_tests));
33533382
}
33543383

33553384
static int parse_args(int argc, char **argv)
33563385
{
3357-
const char *optstr = "lpkf:r:g:";
3386+
const char *optstr = "lpk:f:r:g:";
33583387
int opt;
33593388

33603389
while ((opt = getopt(argc, argv, optstr)) != -1) {
@@ -3378,7 +3407,8 @@ static int parse_args(int argc, char **argv)
33783407
args.pprint_test = true;
33793408
break;
33803409
case 'k':
3381-
args.func_type_test = true;
3410+
args.info_raw_test_num = atoi(optarg);
3411+
args.info_raw_test = true;
33823412
break;
33833413
case 'h':
33843414
usage(argv[0]);
@@ -3413,6 +3443,14 @@ static int parse_args(int argc, char **argv)
34133443
return -1;
34143444
}
34153445

3446+
if (args.info_raw_test_num &&
3447+
(args.info_raw_test_num < 1 ||
3448+
args.info_raw_test_num > ARRAY_SIZE(info_raw_tests))) {
3449+
fprintf(stderr, "BTF prog info raw test number must be [1 - %zu]\n",
3450+
ARRAY_SIZE(info_raw_tests));
3451+
return -1;
3452+
}
3453+
34163454
return 0;
34173455
}
34183456

@@ -3445,16 +3483,17 @@ int main(int argc, char **argv)
34453483
if (args.pprint_test)
34463484
err |= test_pprint();
34473485

3448-
if (args.func_type_test)
3449-
err |= test_func_type();
3486+
if (args.info_raw_test)
3487+
err |= test_info_raw();
34503488

34513489
if (args.raw_test || args.get_info_test || args.file_test ||
3452-
args.pprint_test || args.func_type_test)
3490+
args.pprint_test || args.info_raw_test)
34533491
goto done;
34543492

34553493
err |= test_raw();
34563494
err |= test_get_info();
34573495
err |= test_file();
3496+
err |= test_info_raw();
34583497

34593498
done:
34603499
print_summary();

0 commit comments

Comments
 (0)