Verify NULL parameter rejection in load APIs, graceful failure on argument/flag mismatch in burst execution APIs, and safe return of the libpcap stub.
Signed-off-by: Marat Khalili <[email protected]> Acked-by: Konstantin Ananyev <[email protected]> --- app/test/test_bpf.c | 128 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c index 026ba18b754a..6422bae6fe5f 100644 --- a/app/test/test_bpf.c +++ b/app/test/test_bpf.c @@ -3514,6 +3514,121 @@ run_test(const struct bpf_test *tst) } +/* Test all eBPF load APIs with prm set to NULL. */ +static int +test_bpf_load_null(void) +{ + struct rte_bpf *bpf; + int saved_errno; + + rte_errno = 0; + bpf = rte_bpf_load(NULL); + saved_errno = rte_errno; + rte_bpf_destroy(bpf); + RTE_TEST_ASSERT_NULL(bpf, "rte_bpf_load(NULL) did not return NULL\n"); + RTE_TEST_ASSERT_EQUAL(saved_errno, EINVAL, + "rte_bpf_load(NULL) did not set rte_errno to EINVAL\n"); + + rte_errno = 0; + bpf = rte_bpf_elf_load(NULL, "a", "b"); + saved_errno = rte_errno; + rte_bpf_destroy(bpf); + RTE_TEST_ASSERT_NULL(bpf, "rte_bpf_elf_load(NULL, \"a\", \"b\") did not return NULL\n"); + RTE_TEST_ASSERT_EQUAL(saved_errno, EINVAL, + "rte_bpf_elf_load(NULL, \"a\", \"b\") did not set rte_errno to EINVAL\n"); + + rte_errno = 0; + bpf = rte_bpf_load_ex(NULL); + saved_errno = rte_errno; + rte_bpf_destroy(bpf); + RTE_TEST_ASSERT_NULL(bpf, "rte_bpf_load_ex(NULL) did not return NULL\n"); + RTE_TEST_ASSERT_EQUAL(saved_errno, EINVAL, + "rte_bpf_load_ex(NULL) did not set rte_errno to EINVAL\n"); + + return 0; +} +REGISTER_FAST_TEST(bpf_load_null_autotest, NOHUGE_OK, ASAN_OK, test_bpf_load_null); + +/* Test calling wrong API for execution of a multi-argument eBPF program. */ +static int +test_bpf_exec_wrong_nb_prog_arg(void) +{ + static const struct ebpf_insn ins[] = { + { .code = (EBPF_ALU64 | EBPF_MOV | BPF_K), .dst_reg = EBPF_REG_0, .imm = 0 }, + { .code = (BPF_JMP | EBPF_EXIT), } + }; + static const struct rte_bpf_prm_ex prm = { + .sz = sizeof(struct rte_bpf_prm_ex), + .origin = RTE_BPF_ORIGIN_RAW, + .raw.ins = ins, + .raw.nb_ins = RTE_DIM(ins), + .prog_arg = { + { .type = RTE_BPF_ARG_RAW, .size = sizeof(uint64_t) }, + { .type = RTE_BPF_ARG_RAW, .size = sizeof(uint64_t) }, + }, + .nb_prog_arg = 2, /* Intentionally mismatched: expects 2, burst gives 1 */ + }; + + struct rte_bpf *bpf; + uint64_t rc[1]; + void *ctx[1] = {NULL}; + uint32_t result; + int saved_errno; + + bpf = rte_bpf_load_ex(&prm); + RTE_TEST_ASSERT_NOT_NULL(bpf, "rte_bpf_load_ex failed\n"); + + rte_errno = 0; + result = rte_bpf_exec_burst(bpf, ctx, rc, 1); + saved_errno = rte_errno; + rte_bpf_destroy(bpf); + RTE_TEST_ASSERT_EQUAL(result, 0, "rte_bpf_exec_burst did not return 0\n"); + RTE_TEST_ASSERT_EQUAL(saved_errno, EINVAL, + "rte_bpf_exec_burst did not set rte_errno to EINVAL\n"); + + return 0; +} +REGISTER_FAST_TEST(bpf_exec_wrong_nb_prog_arg_autotest, NOHUGE_OK, ASAN_OK, + test_bpf_exec_wrong_nb_prog_arg); + +/* Test passing unsupported flags when executing an eBPF program. */ +static int +test_bpf_exec_wrong_flags(void) +{ + static const struct ebpf_insn ins[] = { + { .code = (EBPF_ALU64 | EBPF_MOV | BPF_K), .dst_reg = EBPF_REG_0, .imm = 0 }, + { .code = (BPF_JMP | EBPF_EXIT), } + }; + static const struct rte_bpf_prm_ex prm = { + .sz = sizeof(struct rte_bpf_prm_ex), + .origin = RTE_BPF_ORIGIN_RAW, + .raw.ins = ins, + .raw.nb_ins = RTE_DIM(ins), + .prog_arg = { { .type = RTE_BPF_ARG_RAW, .size = sizeof(uint64_t) } }, + .nb_prog_arg = 1, + }; + + struct rte_bpf *bpf; + uint64_t rc[1]; + struct rte_bpf_prog_ctx ctx_ex[1] = {}; + uint32_t result; + int saved_errno; + + bpf = rte_bpf_load_ex(&prm); + RTE_TEST_ASSERT_NOT_NULL(bpf, "rte_bpf_load_ex failed\n"); + + rte_errno = 0; + result = rte_bpf_exec_burst_ex(bpf, ctx_ex, rc, 1, UINT64_MAX); + saved_errno = rte_errno; + rte_bpf_destroy(bpf); + RTE_TEST_ASSERT_EQUAL(result, 0, "rte_bpf_exec_burst_ex did not return 0\n"); + RTE_TEST_ASSERT_EQUAL(saved_errno, EINVAL, + "rte_bpf_exec_burst_ex did not set rte_errno to EINVAL\n"); + + return 0; +} +REGISTER_FAST_TEST(bpf_exec_wrong_flags_autotest, NOHUGE_OK, ASAN_OK, test_bpf_exec_wrong_flags); + static int test_bpf(void) { @@ -4444,7 +4559,18 @@ REGISTER_FAST_TEST(bpf_elf_autotest, NOHUGE_OK, ASAN_OK, test_bpf_elf); static int test_bpf_convert(void) { - printf("BPF convert RTE_HAS_LIBPCAP is undefined, skipping test\n"); + int dummy = 0; + struct rte_bpf_prm *prm; + + prm = rte_bpf_convert(NULL); + rte_free(prm); + RTE_TEST_ASSERT_NULL(prm, "rte_bpf_convert(NULL) without libpcap did not return NULL\n"); + + prm = rte_bpf_convert((const struct bpf_program *)&dummy); + rte_free(prm); + RTE_TEST_ASSERT_NULL(prm, "rte_bpf_convert(&dummy) without libpcap did not return NULL\n"); + + printf("BPF convert RTE_HAS_LIBPCAP is undefined, skipping full test\n"); return TEST_SKIPPED; } -- 2.43.0

