On 8/14/24 1:48 PM, Eduard Zingerman wrote:
Hi Martin,
Please note that after changes for struct_ops map autoload by libbpf,
test_loader could be use to test struct_ops related changes.
Also, test_loader now supports __xlated macro which allows to verify
rewrites applied by verifier.
For example, the sample below works:
struct st_ops_args;
struct bpf_testmod_st_ops {
int (*test_prologue)(struct st_ops_args *args);
int (*test_epilogue)(struct st_ops_args *args);
int (*test_pro_epilogue)(struct st_ops_args *args);
struct module *owner;
};
__success
__xlated("0: *(u64 *)(r10 -8) = r1")
__xlated("1: r0 = 0")
__xlated("2: r1 = *(u64 *)(r10 -8)")
__xlated("3: r1 = *(u64 *)(r1 +0)")
__xlated("4: r6 = *(u32 *)(r1 +0)")
__xlated("5: w6 += 10000")
__xlated("6: *(u32 *)(r1 +0) = r6")
__xlated("7: r6 = r1")
__xlated("8: call kernel-function")
__xlated("9: r1 = r6")
__xlated("10: call kernel-function")
__xlated("11: w0 *= 2")
__xlated("12: exit")
It is appealing to be able to check at the xlated instruction level for
.gen_pro/epilogue.
SEC("struct_ops/test_epilogue")
__naked int test_epilogue(void)
{
asm volatile (
"r0 = 0;"
I also want to test a struct_ops prog making kfunc call, e.g. the
BPF_PROG(test_epilogue_kfunc) in this patch. I have never tried this in asm, so
a n00b question. Do you know if there is an example how to call kfunc?
"exit;"
::: __clobber_all);
}
SEC(".struct_ops.link")
struct bpf_testmod_st_ops st_ops = {
.test_epilogue = (void *)test_epilogue,
};
(Complete example is in the attachment).
test_loader based tests can also trigger program execution via __retval() macro.
The only (minor) shortcoming that I see, is that test_loader would
load/unload st_ops map multiple times because of the following
interaction:
- test_loader assumes that each bpf program defines a test;
- test_loader re-creates all maps before each test;
- libbpf struct_ops autocreate logic marks all programs referenced
from struct_ops map as autoloaded.
If I understand correctly, there are redundant works but still work?
Potentially the test_loader can check all the loaded struct_ops progs of a
st_ops map at once which is an optimization.
Re: __retval(), the struct_ops progs is triggered by a SEC("syscall") prog.
Before calling this syscall prog, the st_ops map needs to be attached first. I
think the attach part is missing also? or there is a way?