Implement decoding of BPF_PROG_TEST_RUN command of bpf syscall

* configure.ac: Check for union bpf_attr.test.duration.
* bpf.c (decode_BPF_PROG_TEST_RUN): New function.
(SYS_FUNC(bpf)) <bpf_cmd_decoders>: Use it.
* NEWS: Mention this.
* tests/bpf.c: Include "print_fields.h".
Add macro guard for BPF_PROG_TEST_RUN decoder test.
[HAVE_UNION_BPF_ATTR_TEST_DURATION] (sample_BPF_PROG_TEST_RUN_attr):
New variable.
[HAVE_UNION_BPF_ATTR_TEST_DURATION] (init_BPF_PROG_TEST_RUN_first,
print_BPF_PROG_TEST_RUN_first, init_BPF_PROG_TEST_RUN_attr,
print_BPF_PROG_TEST_RUN_attr): New functions.
(main) [HAVE_UNION_BPF_ATTR_TEST_DURATION]: Use them.
This commit is contained in:
Дмитрий Левин 2017-11-20 00:29:10 +00:00
parent 2d95b53db4
commit 875115da2d
4 changed files with 96 additions and 1 deletions

1
NEWS
View File

@ -4,6 +4,7 @@ Noteworthy changes in release ?.?? (????-??-??)
* Improvements
* Implemented decoding of netlink descriptor attributes as file descriptors.
* Implemented decoding of hugetlb page size selection flags.
* Implemented decoding of BPF_PROG_TEST_RUN command of bpf syscall.
* Enhanced decoding of getsockopt and setsockopt syscalls for SOL_NETLINK
level.
* Enhanced decoding of BPF_MAP_CREATE command of bpf syscall.

27
bpf.c
View File

@ -280,6 +280,32 @@ DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)
return RVAL_DECODED;
}
DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)
{
struct {
uint32_t prog_fd, retval, data_size_in, data_size_out;
uint64_t ATTRIBUTE_ALIGNED(8) data_in, data_out;
uint32_t repeat, duration;
} attr = {};
const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
memcpy(&attr, data, len);
PRINT_FIELD_FD("{test={", attr, prog_fd, tcp);
PRINT_FIELD_U(", ", attr, retval);
PRINT_FIELD_U(", ", attr, data_size_in);
PRINT_FIELD_U(", ", attr, data_size_out);
PRINT_FIELD_X(", ", attr, data_in);
PRINT_FIELD_X(", ", attr, data_out);
PRINT_FIELD_U(", ", attr, repeat);
PRINT_FIELD_U(", ", attr, duration);
tprints("}");
decode_attr_extra_data(tcp, data, size, sizeof(attr));
tprints("}");
return RVAL_DECODED;
}
SYS_FUNC(bpf)
{
static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
@ -293,6 +319,7 @@ SYS_FUNC(bpf)
BPF_CMD_ENTRY(BPF_OBJ_GET),
BPF_CMD_ENTRY(BPF_PROG_ATTACH),
BPF_CMD_ENTRY(BPF_PROG_DETACH),
BPF_CMD_ENTRY(BPF_PROG_TEST_RUN),
};
const unsigned int cmd = tcp->u_arg[0];

View File

@ -464,6 +464,7 @@ AC_CHECK_HEADERS([linux/bpf.h], [
st_CHECK_UNION_BPF_ATTR([flags])
st_CHECK_UNION_BPF_ATTR([numa_node])
st_CHECK_UNION_BPF_ATTR([prog_flags])
AC_CHECK_MEMBERS([union bpf_attr.test.duration],,, [#include <linux/bpf.h>])
])
AC_CHECK_TYPES(m4_normalize([

View File

@ -35,7 +35,8 @@
|| defined HAVE_UNION_BPF_ATTR_BPF_FD \
|| defined HAVE_UNION_BPF_ATTR_FLAGS \
|| defined HAVE_UNION_BPF_ATTR_NUMA_NODE \
|| defined HAVE_UNION_BPF_ATTR_PROG_FLAGS)
|| defined HAVE_UNION_BPF_ATTR_PROG_FLAGS \
|| defined HAVE_UNION_BPF_ATTR_TEST_DURATION)
# include <stddef.h>
# include <stdio.h>
@ -43,6 +44,7 @@
# include <string.h>
# include <unistd.h>
# include <linux/bpf.h>
# include "print_fields.h"
static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
static const char *errstr;
@ -561,6 +563,66 @@ print_BPF_PROG_DETACH_attr(const unsigned long addr)
# endif /* HAVE_UNION_BPF_ATTR_ATTACH_FLAGS */
/* BPF_PROG_TEST_RUN command appears in kernel 4.12. */
# ifdef HAVE_UNION_BPF_ATTR_TEST_DURATION
static unsigned int
init_BPF_PROG_TEST_RUN_first(const unsigned long eop)
{
static const union bpf_attr attr = { .test.prog_fd = -1 };
static const unsigned int offset = sizeof(attr.test.prog_fd);
const unsigned long addr = eop - offset;
memcpy((void *) addr, &attr.test.prog_fd, offset);
return offset;
}
static void
print_BPF_PROG_TEST_RUN_first(const unsigned long addr)
{
printf("test={prog_fd=-1, retval=0, data_size_in=0, data_size_out=0"
", data_in=0, data_out=0, repeat=0, duration=0}");
}
static const union bpf_attr sample_BPF_PROG_TEST_RUN_attr = {
.test = {
.prog_fd = -1,
.retval = 0xfac1fed2,
.data_size_in = 0xfac3fed4,
.data_size_out = 0xfac5fed6,
.data_in = (uint64_t) 0xfacef11dbadc2ded,
.data_out = (uint64_t) 0xfacef33dbadc4ded,
.repeat = 0xfac7fed8,
.duration = 0xfac9feda
}
};
static unsigned int
init_BPF_PROG_TEST_RUN_attr(const unsigned long eop)
{
static const unsigned int offset =
offsetofend(union bpf_attr, test);
const unsigned long addr = eop - offset;
memcpy((void *) addr, &sample_BPF_PROG_TEST_RUN_attr, offset);
return offset;
}
static void
print_BPF_PROG_TEST_RUN_attr(const unsigned long addr)
{
PRINT_FIELD_D("test={", sample_BPF_PROG_TEST_RUN_attr.test, prog_fd);
PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, retval);
PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_size_in);
PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_size_out);
PRINT_FIELD_X(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_in);
PRINT_FIELD_X(", ", sample_BPF_PROG_TEST_RUN_attr.test, data_out);
PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, repeat);
PRINT_FIELD_U(", ", sample_BPF_PROG_TEST_RUN_attr.test, duration);
printf("}");
}
# endif /* HAVE_UNION_BPF_ATTR_TEST_DURATION */
int
main(void)
{
@ -592,6 +654,10 @@ main(void)
TEST_BPF(BPF_PROG_DETACH);
# endif
# ifdef HAVE_UNION_BPF_ATTR_TEST_DURATION
TEST_BPF(BPF_PROG_TEST_RUN);
# endif
sys_bpf(0xfacefeed, end_of_page, 40);
printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
end_of_page, errstr);