-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: Add tests for extending sleepable global subprogs
Add tests for freplace behavior with the combination of sleepable and non-sleepable global subprogs. The changes_pkt_data selftest did all the hardwork, so simply rename it and include new support for more summarization tests for might_sleep bit. Sleepable extensions don't work yet, so add support but disable it for now, allow support to be tested once it's enabled (and ensure we will complain then). Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]>
- Loading branch information
Showing
4 changed files
with
193 additions
and
108 deletions.
There are no files selected for viewing
107 changes: 0 additions & 107 deletions
107
tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
#include "bpf/libbpf.h" | ||
#include "summarization_freplace.skel.h" | ||
#include "summarization.skel.h" | ||
#include <test_progs.h> | ||
|
||
static void print_verifier_log(const char *log) | ||
{ | ||
if (env.verbosity >= VERBOSE_VERY) | ||
fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log); | ||
} | ||
|
||
static void test_aux(const char *main_prog_name, | ||
const char *to_be_replaced, | ||
const char *replacement, | ||
bool expect_load, | ||
const char *err_msg) | ||
{ | ||
struct summarization_freplace *freplace = NULL; | ||
struct bpf_program *freplace_prog = NULL; | ||
struct bpf_program *main_prog = NULL; | ||
LIBBPF_OPTS(bpf_object_open_opts, opts); | ||
struct summarization *main = NULL; | ||
char log[16*1024]; | ||
int err; | ||
|
||
opts.kernel_log_buf = log; | ||
opts.kernel_log_size = sizeof(log); | ||
if (env.verbosity >= VERBOSE_SUPER) | ||
opts.kernel_log_level = 1 | 2 | 4; | ||
main = summarization__open_opts(&opts); | ||
if (!ASSERT_OK_PTR(main, "summarization__open")) | ||
goto out; | ||
main_prog = bpf_object__find_program_by_name(main->obj, main_prog_name); | ||
if (!ASSERT_OK_PTR(main_prog, "main_prog")) | ||
goto out; | ||
bpf_program__set_autoload(main_prog, true); | ||
err = summarization__load(main); | ||
print_verifier_log(log); | ||
if (!ASSERT_OK(err, "summarization__load")) | ||
goto out; | ||
freplace = summarization_freplace__open_opts(&opts); | ||
if (!ASSERT_OK_PTR(freplace, "summarization_freplace__open")) | ||
goto out; | ||
freplace_prog = bpf_object__find_program_by_name(freplace->obj, replacement); | ||
if (!ASSERT_OK_PTR(freplace_prog, "freplace_prog")) | ||
goto out; | ||
bpf_program__set_autoload(freplace_prog, true); | ||
bpf_program__set_autoattach(freplace_prog, true); | ||
bpf_program__set_attach_target(freplace_prog, | ||
bpf_program__fd(main_prog), | ||
to_be_replaced); | ||
err = summarization_freplace__load(freplace); | ||
print_verifier_log(log); | ||
|
||
/* Sleepable extension prog doesn't work yet, but make sure we catch | ||
* this condition and activate the error below in case it becomes | ||
* supported, as we would need to test this condition then. | ||
*/ | ||
if (!strcmp("might_sleep", replacement)) { | ||
ASSERT_EQ(err, -EINVAL, "might_sleep load must fail"); | ||
test__skip(); | ||
goto out; | ||
} | ||
|
||
if (expect_load) { | ||
ASSERT_OK(err, "summarization_freplace__load"); | ||
} else { | ||
ASSERT_ERR(err, "summarization_freplace__load"); | ||
ASSERT_HAS_SUBSTR(log, err_msg, "error log"); | ||
} | ||
|
||
out: | ||
summarization_freplace__destroy(freplace); | ||
summarization__destroy(main); | ||
} | ||
|
||
/* There are two global subprograms in both summarization.skel.h: | ||
* - one changes packet data; | ||
* - another does not. | ||
* It is ok to freplace subprograms that change packet data with those | ||
* that either do or do not. It is only ok to freplace subprograms | ||
* that do not change packet data with those that do not as well. | ||
* The below tests check outcomes for each combination of such freplace. | ||
* Also test a case when main subprogram itself is replaced and is a single | ||
* subprogram in a program. | ||
* | ||
* This holds for might_sleep programs. It is ok to replace might_sleep with | ||
* might_sleep and with does_not_sleep, but does_not_sleep cannot be replaced | ||
* with might_sleep. | ||
*/ | ||
void test_summarization_freplace(void) | ||
{ | ||
struct { | ||
const char *main; | ||
const char *to_be_replaced; | ||
bool has_side_effect; | ||
} mains[2][4] = { | ||
{ | ||
{ "main_changes_with_subprogs", "changes_pkt_data", true }, | ||
{ "main_changes_with_subprogs", "does_not_change_pkt_data", false }, | ||
{ "main_changes", "main_changes", true }, | ||
{ "main_does_not_change", "main_does_not_change", false }, | ||
}, | ||
{ | ||
{ "main_might_sleep_with_subprogs", "might_sleep", true }, | ||
{ "main_might_sleep_with_subprogs", "does_not_sleep", false }, | ||
{ "main_might_sleep", "might_sleep", true }, | ||
{ "main_does_not_sleep", "does_not_sleep", false }, | ||
}, | ||
}; | ||
const char *pkt_err = "Extension program changes packet data"; | ||
const char *slp_err = "Extension program may sleep"; | ||
struct { | ||
const char *func; | ||
bool has_side_effect; | ||
const char *err_msg; | ||
} replacements[2][2] = { | ||
{ | ||
{ "changes_pkt_data", true, pkt_err }, | ||
{ "does_not_change_pkt_data", false, pkt_err }, | ||
}, | ||
{ | ||
{ "might_sleep", true, slp_err }, | ||
{ "does_not_sleep", false, slp_err }, | ||
}, | ||
}; | ||
char buf[64]; | ||
|
||
for (int t = 0; t < 2; t++) { | ||
for (int i = 0; i < ARRAY_SIZE(mains); ++i) { | ||
for (int j = 0; j < ARRAY_SIZE(replacements); ++j) { | ||
snprintf(buf, sizeof(buf), "%s_with_%s", | ||
mains[t][i].to_be_replaced, replacements[t][j].func); | ||
if (!test__start_subtest(buf)) | ||
continue; | ||
test_aux(mains[t][i].main, mains[t][i].to_be_replaced, replacements[t][j].func, | ||
mains[t][i].has_side_effect || !replacements[t][j].has_side_effect, | ||
replacements[t][j].err_msg); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters