[PATCH v2 bpf-next 5/5] selftest: Add tests for XDP programs in devmap entries
From: David Ahern <dsahern@kernel.org>
Date: 2020-05-28 00:14:35
Subsystem:
bpf [general] (safe dynamic programs and tools), bpf [selftests] (test runners & infrastructure), kernel selftest framework, the rest, xdp (express data path) · Maintainers:
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Shuah Khan, Linus Torvalds, David S. Miller, Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend
Add tests to verify ability to add an XDP program to a entry in a DEVMAP. Add negative tests to show DEVMAP programs can not be attached to devices as a normal XDP program, and accesses to egress_ifindex require BPF_XDP_DEVMAP attach type. Signed-off-by: David Ahern <dsahern@kernel.org> --- .../bpf/prog_tests/xdp_devmap_attach.c | 94 +++++++++++++++++++ .../selftests/bpf/progs/test_xdp_devmap.c | 19 ++++ .../selftests/bpf/progs/test_xdp_devmap2.c | 19 ++++ .../bpf/progs/test_xdp_with_devmap.c | 17 ++++ 4 files changed, 149 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_devmap.c create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_devmap2.c create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_with_devmap.c
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c b/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c
new file mode 100644
index 000000000000..d81b2b366f39
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c@@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <uapi/linux/bpf.h> +#include <linux/if_link.h> +#include <test_progs.h> + +#define IFINDEX_LO 1 + +void test_xdp_devmap_attach(void) +{ + struct bpf_prog_load_attr attr = { + .prog_type = BPF_PROG_TYPE_XDP, + }; + struct bpf_object *obj, *dm_obj = NULL; + int err, dm_fd = -1, fd = -1, map_fd; + struct bpf_prog_info info = {}; + struct devmap_val val = { + .ifindex = IFINDEX_LO, + }; + __u32 id, len = sizeof(info); + __u32 duration = 0, idx = 0; + + attr.file = "./test_xdp_with_devmap.o", + err = bpf_prog_load_xattr(&attr, &obj, &fd); + if (CHECK(err, "load of xdp program with 8-byte devmap", + "err %d errno %d\n", err, errno)) + return; + + /* can not attach program with DEVMAPs that allow programs */ + err = bpf_set_link_xdp_fd(IFINDEX_LO, fd, XDP_FLAGS_SKB_MODE); + CHECK(err == 0, "Generic attach of program with 8-byte devmap", + "should have failed\n"); + + map_fd = bpf_object__find_map_fd_by_name(obj, "dm_ports"); + if (CHECK(map_fd < 0, "Lookup dm_ports map", + "err %d errno %d\n", err, errno)) + goto out_close; + + /* + * basic test - load program to be installed in devmap; + * also verifies access to ingress and egress ifindices. + */ + attr.expected_attach_type = BPF_XDP_DEVMAP; + attr.file = "./test_xdp_devmap.o"; + err = bpf_prog_load_xattr(&attr, &dm_obj, &dm_fd); + if (CHECK(err, "Load of BPF_XDP_DEVMAP program", + "err %d errno %d\n", err, errno)) + goto out_close; + + err = bpf_obj_get_info_by_fd(dm_fd, &info, &len); + if (CHECK_FAIL(err)) + goto out_close; + + val.bpf_prog_fd = dm_fd; + err = bpf_map_update_elem(map_fd, &idx, &val, 0); + CHECK(err, "Add program to devmap entry", + "err %d errno %d\n", err, errno); + + err = bpf_map_lookup_elem(map_fd, &id, &val); + CHECK(err, "Read devmap entry", + "err %d errno %d\n", err, errno); + CHECK(info.id != val.bpf_prog_id, "Expected program id in devmap entry", + "expected %u read %u\n", info.id, val.bpf_prog_id); + + /* can not attach BPF_XDP_DEVMAP program to a device */ + err = bpf_set_link_xdp_fd(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE); + CHECK(err == 0, "Attach of BPF_XDP_DEVMAP program", + "should have failed\n"); + + bpf_object__close(dm_obj); + + /* Load of BPF_XDP_DEVMAP as XDP should fail because of egress index */ + attr.expected_attach_type = 0; + err = bpf_prog_load_xattr(&attr, &dm_obj, &dm_fd); + if (CHECK(err == 0, + "Load of XDP program accessing egress ifindex without attach type", + "should have failed\n")) + bpf_object__close(dm_obj); + + attr.file = "./xdp_dummy.o"; + err = bpf_prog_load_xattr(&attr, &dm_obj, &dm_fd); + if (CHECK_FAIL(err)) + goto out_close; + + val.ifindex = 1; + val.bpf_prog_fd = dm_fd; + err = bpf_map_update_elem(map_fd, &idx, &val, 0); + CHECK(err == 0, "Add non-BPF_XDP_DEVMAP program to devmap entry", + "should have failed\n"); + + bpf_object__close(dm_obj); + +out_close: + bpf_object__close(obj); +}
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_devmap.c b/tools/testing/selftests/bpf/progs/test_xdp_devmap.c
new file mode 100644
index 000000000000..64fc2c3cae01
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_xdp_devmap.c@@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 +/* program inserted into devmap entry */ +#include <linux/bpf.h> +#include <bpf/bpf_helpers.h> + +SEC("xdp_devmap_log") +int xdpdm_devlog(struct xdp_md *ctx) +{ + char fmt[] = "devmap redirect: dev %u -> dev %u len %u\n"; + void *data_end = (void *)(long)ctx->data_end; + void *data = (void *)(long)ctx->data; + unsigned int len = data_end - data; + + bpf_trace_printk(fmt, sizeof(fmt), ctx->ingress_ifindex, ctx->egress_ifindex, len); + + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_devmap2.c b/tools/testing/selftests/bpf/progs/test_xdp_devmap2.c
new file mode 100644
index 000000000000..64fc2c3cae01
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_xdp_devmap2.c@@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 +/* program inserted into devmap entry */ +#include <linux/bpf.h> +#include <bpf/bpf_helpers.h> + +SEC("xdp_devmap_log") +int xdpdm_devlog(struct xdp_md *ctx) +{ + char fmt[] = "devmap redirect: dev %u -> dev %u len %u\n"; + void *data_end = (void *)(long)ctx->data_end; + void *data = (void *)(long)ctx->data; + unsigned int len = data_end - data; + + bpf_trace_printk(fmt, sizeof(fmt), ctx->ingress_ifindex, ctx->egress_ifindex, len); + + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_with_devmap.c b/tools/testing/selftests/bpf/progs/test_xdp_with_devmap.c
new file mode 100644
index 000000000000..815cd59b4866
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_xdp_with_devmap.c@@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/bpf.h> +#include <bpf/bpf_helpers.h> + +struct bpf_map_def SEC("maps") dm_ports = { + .type = BPF_MAP_TYPE_DEVMAP, + .key_size = sizeof(__u32), + .value_size = sizeof(struct devmap_val), + .max_entries = 4, +}; + +SEC("xdp_devmap") +int xdp_with_devmap(struct xdp_md *ctx) +{ + return bpf_redirect_map(&dm_ports, 1, 0); +}
--
2.21.1 (Apple Git-122.3)