xref: /openbmc/linux/tools/testing/selftests/bpf/prog_tests/xdp_link.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1fe48230cSAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2fe48230cSAndrii Nakryiko /* Copyright (c) 2020 Facebook */
3fe48230cSAndrii Nakryiko #include <uapi/linux/if_link.h>
4fe48230cSAndrii Nakryiko #include <test_progs.h>
5fe48230cSAndrii Nakryiko #include "test_xdp_link.skel.h"
6fe48230cSAndrii Nakryiko 
7fe48230cSAndrii Nakryiko #define IFINDEX_LO 1
8fe48230cSAndrii Nakryiko 
serial_test_xdp_link(void)9d3f7b166SYucong Sun void serial_test_xdp_link(void)
10fe48230cSAndrii Nakryiko {
11fe48230cSAndrii Nakryiko 	struct test_xdp_link *skel1 = NULL, *skel2 = NULL;
124b27480dSToke Høiland-Jørgensen 	__u32 id1, id2, id0 = 0, prog_fd1, prog_fd2;
13e4e284a8SAndrii Nakryiko 	LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
14fe48230cSAndrii Nakryiko 	struct bpf_link_info link_info;
15fe48230cSAndrii Nakryiko 	struct bpf_prog_info prog_info;
16fe48230cSAndrii Nakryiko 	struct bpf_link *link;
174b27480dSToke Høiland-Jørgensen 	int err;
18fe48230cSAndrii Nakryiko 	__u32 link_info_len = sizeof(link_info);
19fe48230cSAndrii Nakryiko 	__u32 prog_info_len = sizeof(prog_info);
20fe48230cSAndrii Nakryiko 
21fe48230cSAndrii Nakryiko 	skel1 = test_xdp_link__open_and_load();
224b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK_PTR(skel1, "skel_load"))
23fe48230cSAndrii Nakryiko 		goto cleanup;
24fe48230cSAndrii Nakryiko 	prog_fd1 = bpf_program__fd(skel1->progs.xdp_handler);
25fe48230cSAndrii Nakryiko 
26fe48230cSAndrii Nakryiko 	skel2 = test_xdp_link__open_and_load();
274b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK_PTR(skel2, "skel_load"))
28fe48230cSAndrii Nakryiko 		goto cleanup;
29fe48230cSAndrii Nakryiko 	prog_fd2 = bpf_program__fd(skel2->progs.xdp_handler);
30fe48230cSAndrii Nakryiko 
31fe48230cSAndrii Nakryiko 	memset(&prog_info, 0, sizeof(prog_info));
32*c5a237a4SIlya Leoshkevich 	err = bpf_prog_get_info_by_fd(prog_fd1, &prog_info, &prog_info_len);
334b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "fd_info1"))
34fe48230cSAndrii Nakryiko 		goto cleanup;
35fe48230cSAndrii Nakryiko 	id1 = prog_info.id;
36fe48230cSAndrii Nakryiko 
37fe48230cSAndrii Nakryiko 	memset(&prog_info, 0, sizeof(prog_info));
38*c5a237a4SIlya Leoshkevich 	err = bpf_prog_get_info_by_fd(prog_fd2, &prog_info, &prog_info_len);
394b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "fd_info2"))
40fe48230cSAndrii Nakryiko 		goto cleanup;
41fe48230cSAndrii Nakryiko 	id2 = prog_info.id;
42fe48230cSAndrii Nakryiko 
43fe48230cSAndrii Nakryiko 	/* set initial prog attachment */
44e4e284a8SAndrii Nakryiko 	err = bpf_xdp_attach(IFINDEX_LO, prog_fd1, XDP_FLAGS_REPLACE, &opts);
454b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "fd_attach"))
46fe48230cSAndrii Nakryiko 		goto cleanup;
47fe48230cSAndrii Nakryiko 
48fe48230cSAndrii Nakryiko 	/* validate prog ID */
49e4e284a8SAndrii Nakryiko 	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
504b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
514b27480dSToke Høiland-Jørgensen 		goto cleanup;
52fe48230cSAndrii Nakryiko 
53fe48230cSAndrii Nakryiko 	/* BPF link is not allowed to replace prog attachment */
54fe48230cSAndrii Nakryiko 	link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);
55bad2e478SAndrii Nakryiko 	if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
56fe48230cSAndrii Nakryiko 		bpf_link__destroy(link);
57fe48230cSAndrii Nakryiko 		/* best-effort detach prog */
58e4e284a8SAndrii Nakryiko 		opts.old_prog_fd = prog_fd1;
59e4e284a8SAndrii Nakryiko 		bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);
60fe48230cSAndrii Nakryiko 		goto cleanup;
61fe48230cSAndrii Nakryiko 	}
62fe48230cSAndrii Nakryiko 
63fe48230cSAndrii Nakryiko 	/* detach BPF program */
64e4e284a8SAndrii Nakryiko 	opts.old_prog_fd = prog_fd1;
65e4e284a8SAndrii Nakryiko 	err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);
664b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "prog_detach"))
67fe48230cSAndrii Nakryiko 		goto cleanup;
68fe48230cSAndrii Nakryiko 
69fe48230cSAndrii Nakryiko 	/* now BPF link should attach successfully */
70fe48230cSAndrii Nakryiko 	link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);
71bad2e478SAndrii Nakryiko 	if (!ASSERT_OK_PTR(link, "link_attach"))
72fe48230cSAndrii Nakryiko 		goto cleanup;
73fe48230cSAndrii Nakryiko 	skel1->links.xdp_handler = link;
74fe48230cSAndrii Nakryiko 
75fe48230cSAndrii Nakryiko 	/* validate prog ID */
76e4e284a8SAndrii Nakryiko 	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
774b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
78fe48230cSAndrii Nakryiko 		goto cleanup;
79fe48230cSAndrii Nakryiko 
80fe48230cSAndrii Nakryiko 	/* BPF prog attach is not allowed to replace BPF link */
81e4e284a8SAndrii Nakryiko 	opts.old_prog_fd = prog_fd1;
82e4e284a8SAndrii Nakryiko 	err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, XDP_FLAGS_REPLACE, &opts);
834b27480dSToke Høiland-Jørgensen 	if (!ASSERT_ERR(err, "prog_attach_fail"))
84fe48230cSAndrii Nakryiko 		goto cleanup;
85fe48230cSAndrii Nakryiko 
86fe48230cSAndrii Nakryiko 	/* Can't force-update when BPF link is active */
87e4e284a8SAndrii Nakryiko 	err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, 0, NULL);
884b27480dSToke Høiland-Jørgensen 	if (!ASSERT_ERR(err, "prog_update_fail"))
89fe48230cSAndrii Nakryiko 		goto cleanup;
90fe48230cSAndrii Nakryiko 
91fe48230cSAndrii Nakryiko 	/* Can't force-detach when BPF link is active */
92e4e284a8SAndrii Nakryiko 	err = bpf_xdp_detach(IFINDEX_LO, 0, NULL);
934b27480dSToke Høiland-Jørgensen 	if (!ASSERT_ERR(err, "prog_detach_fail"))
94fe48230cSAndrii Nakryiko 		goto cleanup;
95fe48230cSAndrii Nakryiko 
96fe48230cSAndrii Nakryiko 	/* BPF link is not allowed to replace another BPF link */
97fe48230cSAndrii Nakryiko 	link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);
98bad2e478SAndrii Nakryiko 	if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
99fe48230cSAndrii Nakryiko 		bpf_link__destroy(link);
100fe48230cSAndrii Nakryiko 		goto cleanup;
101fe48230cSAndrii Nakryiko 	}
102fe48230cSAndrii Nakryiko 
103fe48230cSAndrii Nakryiko 	bpf_link__destroy(skel1->links.xdp_handler);
104fe48230cSAndrii Nakryiko 	skel1->links.xdp_handler = NULL;
105fe48230cSAndrii Nakryiko 
106fe48230cSAndrii Nakryiko 	/* new link attach should succeed */
107fe48230cSAndrii Nakryiko 	link = bpf_program__attach_xdp(skel2->progs.xdp_handler, IFINDEX_LO);
108bad2e478SAndrii Nakryiko 	if (!ASSERT_OK_PTR(link, "link_attach"))
109fe48230cSAndrii Nakryiko 		goto cleanup;
110fe48230cSAndrii Nakryiko 	skel2->links.xdp_handler = link;
111fe48230cSAndrii Nakryiko 
112e4e284a8SAndrii Nakryiko 	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
1134b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "id2_check_err") || !ASSERT_EQ(id0, id2, "id2_check_val"))
114fe48230cSAndrii Nakryiko 		goto cleanup;
115fe48230cSAndrii Nakryiko 
116fe48230cSAndrii Nakryiko 	/* updating program under active BPF link works as expected */
117fe48230cSAndrii Nakryiko 	err = bpf_link__update_program(link, skel1->progs.xdp_handler);
1184b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "link_upd"))
119fe48230cSAndrii Nakryiko 		goto cleanup;
120fe48230cSAndrii Nakryiko 
121fe48230cSAndrii Nakryiko 	memset(&link_info, 0, sizeof(link_info));
122*c5a237a4SIlya Leoshkevich 	err = bpf_link_get_info_by_fd(bpf_link__fd(link),
123*c5a237a4SIlya Leoshkevich 				      &link_info, &link_info_len);
1244b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "link_info"))
125fe48230cSAndrii Nakryiko 		goto cleanup;
126fe48230cSAndrii Nakryiko 
1274b27480dSToke Høiland-Jørgensen 	ASSERT_EQ(link_info.type, BPF_LINK_TYPE_XDP, "link_type");
1284b27480dSToke Høiland-Jørgensen 	ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");
1294b27480dSToke Høiland-Jørgensen 	ASSERT_EQ(link_info.xdp.ifindex, IFINDEX_LO, "link_ifindex");
130fe48230cSAndrii Nakryiko 
131036a05f5SToke Høiland-Jørgensen 	/* updating program under active BPF link with different type fails */
132036a05f5SToke Høiland-Jørgensen 	err = bpf_link__update_program(link, skel1->progs.tc_handler);
133036a05f5SToke Høiland-Jørgensen 	if (!ASSERT_ERR(err, "link_upd_invalid"))
134036a05f5SToke Høiland-Jørgensen 		goto cleanup;
135036a05f5SToke Høiland-Jørgensen 
13690806cccSAndrii Nakryiko 	err = bpf_link__detach(link);
1374b27480dSToke Høiland-Jørgensen 	if (!ASSERT_OK(err, "link_detach"))
13890806cccSAndrii Nakryiko 		goto cleanup;
13990806cccSAndrii Nakryiko 
14090806cccSAndrii Nakryiko 	memset(&link_info, 0, sizeof(link_info));
141*c5a237a4SIlya Leoshkevich 	err = bpf_link_get_info_by_fd(bpf_link__fd(link),
142*c5a237a4SIlya Leoshkevich 				      &link_info, &link_info_len);
1434b27480dSToke Høiland-Jørgensen 
1444b27480dSToke Høiland-Jørgensen 	ASSERT_OK(err, "link_info");
1454b27480dSToke Høiland-Jørgensen 	ASSERT_EQ(link_info.prog_id, id1, "link_prog_id");
14690806cccSAndrii Nakryiko 	/* ifindex should be zeroed out */
1474b27480dSToke Høiland-Jørgensen 	ASSERT_EQ(link_info.xdp.ifindex, 0, "link_ifindex");
14890806cccSAndrii Nakryiko 
149fe48230cSAndrii Nakryiko cleanup:
150fe48230cSAndrii Nakryiko 	test_xdp_link__destroy(skel1);
151fe48230cSAndrii Nakryiko 	test_xdp_link__destroy(skel2);
152fe48230cSAndrii Nakryiko }
153