aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c
blob: ead40016c32457eca95c7dfb75ea19ee0dc0c8ea (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// SPDX-License-Identifier: GPL-2.0
#include <uapi/linux/bpf.h>
#include <linux/if_link.h>
#include <test_progs.h>

#include "test_xdp_devmap_helpers.skel.h"
#include "test_xdp_with_devmap_frags_helpers.skel.h"
#include "test_xdp_with_devmap_helpers.skel.h"

#define IFINDEX_LO 1

static void test_xdp_with_devmap_helpers(void)
{
	struct test_xdp_with_devmap_helpers *skel;
	struct bpf_prog_info info = {};
	struct bpf_devmap_val val = {
		.ifindex = IFINDEX_LO,
	};
	__u32 len = sizeof(info);
	int err, dm_fd, map_fd;
	__u32 idx = 0;


	skel = test_xdp_with_devmap_helpers__open_and_load();
	if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
		return;

	dm_fd = bpf_program__fd(skel->progs.xdp_redir_prog);
	err = bpf_xdp_attach(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE, NULL);
	if (!ASSERT_OK(err, "Generic attach of program with 8-byte devmap"))
		goto out_close;

	err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);
	ASSERT_OK(err, "XDP program detach");

	dm_fd = bpf_program__fd(skel->progs.xdp_dummy_dm);
	map_fd = bpf_map__fd(skel->maps.dm_ports);
	err = bpf_obj_get_info_by_fd(dm_fd, &info, &len);
	if (!ASSERT_OK(err, "bpf_obj_get_info_by_fd"))
		goto out_close;

	val.bpf_prog.fd = dm_fd;
	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
	ASSERT_OK(err, "Add program to devmap entry");

	err = bpf_map_lookup_elem(map_fd, &idx, &val);
	ASSERT_OK(err, "Read devmap entry");
	ASSERT_EQ(info.id, val.bpf_prog.id, "Match program id to devmap entry prog_id");

	/* can not attach BPF_XDP_DEVMAP program to a device */
	err = bpf_xdp_attach(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE, NULL);
	if (!ASSERT_NEQ(err, 0, "Attach of BPF_XDP_DEVMAP program"))
		bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);

	val.ifindex = 1;
	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_prog);
	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
	ASSERT_NEQ(err, 0, "Add non-BPF_XDP_DEVMAP program to devmap entry");

	/* Try to attach BPF_XDP program with frags to devmap when we have
	 * already loaded a BPF_XDP program on the map
	 */
	idx = 1;
	val.ifindex = 1;
	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_dm_frags);
	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
	ASSERT_NEQ(err, 0, "Add BPF_XDP program with frags to devmap entry");

out_close:
	test_xdp_with_devmap_helpers__destroy(skel);
}

static void test_neg_xdp_devmap_helpers(void)
{
	struct test_xdp_devmap_helpers *skel;

	skel = test_xdp_devmap_helpers__open_and_load();
	if (!ASSERT_EQ(skel, NULL,
		    "Load of XDP program accessing egress ifindex without attach type")) {
		test_xdp_devmap_helpers__destroy(skel);
	}
}

static void test_xdp_with_devmap_frags_helpers(void)
{
	struct test_xdp_with_devmap_frags_helpers *skel;
	struct bpf_prog_info info = {};
	struct bpf_devmap_val val = {
		.ifindex = IFINDEX_LO,
	};
	__u32 len = sizeof(info);
	int err, dm_fd_frags, map_fd;
	__u32 idx = 0;

	skel = test_xdp_with_devmap_frags_helpers__open_and_load();
	if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
		return;

	dm_fd_frags = bpf_program__fd(skel->progs.xdp_dummy_dm_frags);
	map_fd = bpf_map__fd(skel->maps.dm_ports);
	err = bpf_obj_get_info_by_fd(dm_fd_frags, &info, &len);
	if (!ASSERT_OK(err, "bpf_obj_get_info_by_fd"))
		goto out_close;

	val.bpf_prog.fd = dm_fd_frags;
	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
	ASSERT_OK(err, "Add frags program to devmap entry");

	err = bpf_map_lookup_elem(map_fd, &idx, &val);
	ASSERT_OK(err, "Read devmap entry");
	ASSERT_EQ(info.id, val.bpf_prog.id,
		  "Match program id to devmap entry prog_id");

	/* Try to attach BPF_XDP program to devmap when we have
	 * already loaded a BPF_XDP program with frags on the map
	 */
	idx = 1;
	val.ifindex = 1;
	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_dm);
	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
	ASSERT_NEQ(err, 0, "Add BPF_XDP program to devmap entry");

out_close:
	test_xdp_with_devmap_frags_helpers__destroy(skel);
}

void serial_test_xdp_devmap_attach(void)
{
	if (test__start_subtest("DEVMAP with programs in entries"))
		test_xdp_with_devmap_helpers();

	if (test__start_subtest("DEVMAP with frags programs in entries"))
		test_xdp_with_devmap_frags_helpers();

	if (test__start_subtest("Verifier check of DEVMAP programs"))
		test_neg_xdp_devmap_helpers();
}