lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210325120020.236504-6-memxor@gmail.com>
Date:   Thu, 25 Mar 2021 17:30:03 +0530
From:   Kumar Kartikeya Dwivedi <memxor@...il.com>
To:     bpf@...r.kernel.org
Cc:     brouer@...hat.com, Kumar Kartikeya Dwivedi <memxor@...il.com>,
        Toke Høiland-Jørgensen <toke@...hat.com>,
        Alexei Starovoitov <ast@...nel.org>,
        Daniel Borkmann <daniel@...earbox.net>,
        Andrii Nakryiko <andrii@...nel.org>,
        Martin KaFai Lau <kafai@...com>,
        Song Liu <songliubraving@...com>, Yonghong Song <yhs@...com>,
        John Fastabend <john.fastabend@...il.com>,
        KP Singh <kpsingh@...nel.org>, Shuah Khan <shuah@...nel.org>,
        "David S. Miller" <davem@...emloft.net>,
        Jakub Kicinski <kuba@...nel.org>,
        Jesper Dangaard Brouer <hawk@...nel.org>,
        Peter Zijlstra <peterz@...radead.org>,
        linux-kernel@...r.kernel.org, netdev@...r.kernel.org,
        linux-kselftest@...r.kernel.org
Subject: [PATCH bpf-next 5/5] libbpf: add selftests for TC-BPF API

This adds some basic tests for the low level bpf_tc_* API and its
bpf_program__attach_tc_* wrapper on top.

Reviewed-by: Toke Høiland-Jørgensen <toke@...hat.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@...il.com>
---
 .../selftests/bpf/prog_tests/test_tc_bpf.c    | 261 ++++++++++++++++++
 .../selftests/bpf/progs/test_tc_bpf_kern.c    |  18 ++
 2 files changed, 279 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/test_tc_bpf.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_tc_bpf_kern.c

diff --git a/tools/testing/selftests/bpf/prog_tests/test_tc_bpf.c b/tools/testing/selftests/bpf/prog_tests/test_tc_bpf.c
new file mode 100644
index 000000000000..8bab56b4dea0
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/test_tc_bpf.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <linux/err.h>
+#include <bpf/libbpf.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <test_progs.h>
+#include <linux/if_ether.h>
+
+#define LO_IFINDEX 1
+
+static int test_tc_cls_internal(int fd, __u32 parent_id)
+{
+	struct bpf_tc_cls_attach_id id = {};
+	struct bpf_tc_cls_info info = {};
+	int ret;
+	DECLARE_LIBBPF_OPTS(bpf_tc_cls_opts, opts, .handle = 1, .priority = 10,
+			    .class_id = TC_H_MAKE(1UL << 16, 1),
+			    .chain_index = 5);
+
+	ret = bpf_tc_cls_attach_dev(fd, LO_IFINDEX, parent_id, ETH_P_IP, &opts,
+				    &id);
+	if (CHECK_FAIL(ret < 0))
+		return ret;
+
+	ret = bpf_tc_cls_get_info_dev(fd, LO_IFINDEX, parent_id, ETH_P_IP, NULL,
+				      &info);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	ret = -1;
+
+	if (CHECK_FAIL(info.id.ifindex != id.ifindex) ||
+	    CHECK_FAIL(info.id.parent_id != id.parent_id) ||
+	    CHECK_FAIL(info.id.handle != id.handle) ||
+	    CHECK_FAIL(info.id.protocol != id.protocol) ||
+	    CHECK_FAIL(info.id.chain_index != id.chain_index) ||
+	    CHECK_FAIL(info.id.priority != id.priority) ||
+	    CHECK_FAIL(info.id.ifindex != LO_IFINDEX) ||
+	    CHECK_FAIL(info.id.parent_id != parent_id) ||
+	    CHECK_FAIL(info.id.handle != 1) ||
+	    CHECK_FAIL(info.id.priority != 10) ||
+	    CHECK_FAIL(info.id.protocol != ETH_P_IP) ||
+	    CHECK_FAIL(info.class_id != TC_H_MAKE(1UL << 16, 1)) ||
+	    CHECK_FAIL(info.id.chain_index != 5))
+		goto end;
+
+	opts.direct_action = true;
+	ret = bpf_tc_cls_replace_dev(fd, id.ifindex, id.parent_id, id.protocol,
+				     &opts, &id);
+	if (CHECK_FAIL(ret < 0))
+		return ret;
+
+end:;
+	ret = bpf_tc_cls_detach_dev(&id);
+	CHECK_FAIL(ret < 0);
+	return ret;
+}
+
+static int test_tc_cls(struct bpf_program *prog, __u32 parent_id)
+{
+	struct bpf_tc_cls_info info = {};
+	struct bpf_link *link;
+	int ret;
+	DECLARE_LIBBPF_OPTS(bpf_tc_cls_opts, opts, .priority = 10, .handle = 1,
+			    .class_id = TC_H_MAKE(1UL << 16, 1));
+
+	link = bpf_program__attach_tc_cls_dev(prog, LO_IFINDEX, parent_id,
+					      ETH_P_ALL, &opts);
+	if (CHECK_FAIL(IS_ERR_OR_NULL(link)))
+		return PTR_ERR(link);
+
+	ret = bpf_tc_cls_get_info_dev(bpf_program__fd(prog), LO_IFINDEX,
+				      parent_id, ETH_P_ALL, NULL, &info);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	ret = -1;
+
+	if (CHECK_FAIL(info.id.ifindex != LO_IFINDEX) ||
+	    CHECK_FAIL(info.id.handle != 1) ||
+	    CHECK_FAIL(info.id.priority != 10) ||
+	    CHECK_FAIL(info.id.protocol != ETH_P_ALL) ||
+	    CHECK_FAIL(info.class_id != TC_H_MAKE(1UL << 16, 1)))
+		goto end;
+
+	/* Demonstrate changing attributes (e.g. to direct action) */
+	opts.class_id = TC_H_MAKE(1UL << 16, 2);
+	opts.direct_action = true;
+
+	/* Disconnect as we drop to the lower level API, which invalidates the
+	 * link.
+	 */
+	bpf_link__disconnect(link);
+
+	ret = bpf_tc_cls_change_dev(bpf_program__fd(prog), info.id.ifindex,
+				    info.id.parent_id, info.id.protocol, &opts,
+				    &info.id);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	ret = bpf_tc_cls_get_info_dev(bpf_program__fd(prog), info.id.ifindex,
+				      info.id.parent_id, info.id.protocol, NULL,
+				      &info);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	ret = -1;
+
+	if (CHECK_FAIL(info.class_id != TC_H_MAKE(1UL << 16, 2)))
+		goto end;
+	if (CHECK_FAIL((info.bpf_flags & TCA_BPF_FLAG_ACT_DIRECT) != 1))
+		goto end;
+
+	ret = bpf_tc_cls_detach_dev(&info.id);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+end:
+	ret = bpf_link__destroy(link);
+	CHECK_FAIL(ret < 0);
+	return ret;
+}
+
+static int test_tc_act_internal(int fd)
+{
+	struct bpf_tc_act_info info = {};
+	__u32 index = 0;
+	int ret;
+	DECLARE_LIBBPF_OPTS(bpf_tc_act_opts, opts, 0);
+
+	ret = bpf_tc_act_attach(fd, &opts, &index);
+	if (CHECK_FAIL(ret < 0 || !index))
+		goto end;
+
+	index = 0;
+	ret = bpf_tc_act_attach(fd, &opts, &index);
+	if (CHECK_FAIL(ret < 0 || !index))
+		goto end;
+
+	opts.index = 3;
+	index = 0;
+	ret = bpf_tc_act_attach(fd, &opts, &index);
+	if (CHECK_FAIL(ret < 0 || !index))
+		goto end;
+
+	index = 0;
+	ret = bpf_tc_act_replace(fd, &opts, &index);
+	if (CHECK_FAIL(ret < 0 || !index))
+		goto end;
+
+	opts.index = 1;
+	ret = bpf_tc_act_attach(fd, &opts, &index);
+	if (CHECK_FAIL(!ret || ret != -EEXIST)) {
+		ret = -1;
+		goto end;
+	}
+
+	for (int i = 0; i < 3; i++) {
+		memset(&info, 0, sizeof(info));
+
+		ret = bpf_tc_act_get_info(fd, &info);
+		if (CHECK_FAIL(ret < 0 && ret != -ESRCH))
+			goto end;
+
+		if (CHECK_FAIL(ret == -ESRCH))
+			goto end;
+
+		if (CHECK_FAIL(info.refcnt != 1))
+			goto end;
+
+		ret = bpf_tc_act_detach(info.index);
+		if (CHECK_FAIL(ret < 0))
+			goto end;
+	}
+
+	CHECK_FAIL(bpf_tc_act_get_info(fd, &info) == -ESRCH);
+
+end:
+	ret = bpf_tc_act_detach(0);
+	CHECK_FAIL(ret < 0);
+	return ret;
+}
+
+static int test_tc_act(struct bpf_program *prog)
+{
+	struct bpf_tc_act_info info = {};
+	struct bpf_link *link;
+	int ret;
+	DECLARE_LIBBPF_OPTS(bpf_tc_act_opts, opts, .index = 42);
+
+	link = bpf_program__attach_tc_act(prog, &opts);
+	if (CHECK_FAIL(IS_ERR_OR_NULL(link)))
+		return PTR_ERR(link);
+
+	ret = bpf_tc_act_get_info(bpf_program__fd(prog), &info);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	if (CHECK_FAIL(info.index != 42))
+		goto end;
+
+end:
+	ret = bpf_link__destroy(link);
+	CHECK_FAIL(ret < 0);
+	return ret;
+}
+
+void test_test_tc_bpf(void)
+{
+	const char *file = "./test_tc_bpf_kern.o";
+	int cls_fd, act_fd, ret;
+	struct bpf_program *clsp, *actp;
+	struct bpf_object *obj;
+
+	obj = bpf_object__open(file);
+	if (CHECK_FAIL(IS_ERR_OR_NULL(obj)))
+		return;
+
+	clsp = bpf_object__find_program_by_title(obj, "classifier");
+	if (CHECK_FAIL(IS_ERR_OR_NULL(clsp)))
+		goto end;
+
+	actp = bpf_object__find_program_by_title(obj, "action");
+	if (CHECK_FAIL(IS_ERR_OR_NULL(clsp)))
+		goto end;
+
+	ret = bpf_object__load(obj);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	cls_fd = bpf_program__fd(clsp);
+	act_fd = bpf_program__fd(actp);
+
+	if (CHECK_FAIL(system("tc qdisc add dev lo clsact")))
+		goto end;
+
+	ret = test_tc_cls_internal(cls_fd, BPF_TC_CLSACT_INGRESS);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	ret = test_tc_cls(clsp, BPF_TC_CLSACT_EGRESS);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	system("tc qdisc del dev lo clsact");
+
+	ret = test_tc_act_internal(act_fd);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+	ret = test_tc_act(actp);
+	if (CHECK_FAIL(ret < 0))
+		goto end;
+
+end:
+	bpf_object__close(obj);
+	return;
+}
diff --git a/tools/testing/selftests/bpf/progs/test_tc_bpf_kern.c b/tools/testing/selftests/bpf/progs/test_tc_bpf_kern.c
new file mode 100644
index 000000000000..d39644ea0fd7
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_tc_bpf_kern.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+// Dummy prog to test tc_bpf API
+
+SEC("classifier")
+int cls(struct __sk_buff *skb)
+{
+	return 0;
+}
+
+SEC("action")
+int act(struct __sk_buff *skb)
+{
+	return 0;
+}
-- 
2.30.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ