Skip to content

Commit 79db658

Browse files
author
Martin KaFai Lau
committedMar 19, 2025
Merge branch 'selftests-bpf-migrate-test_xdp_vlan-sh-into-test_progs'
Bastien Curutchet says: ==================== selftests/bpf: Migrate test_xdp_vlan.sh into test_progs Hi all, This patch series continues the work to migrate the script tests into prog_tests. test_xdp_vlan.sh tests the ability of an XDP program to modify the VLAN ids on the fly. This isn't currently covered by an other test in the test_progs framework so I add a new file prog_tests/xdp_vlan.c that does the exact same tests (same network topology, same BPF programs) and remove the script. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Martin KaFai Lau <[email protected]>
2 parents a259804 + f8df95e commit 79db658

File tree

6 files changed

+186
-264
lines changed

6 files changed

+186
-264
lines changed
 

‎tools/testing/selftests/bpf/Makefile

+1-3
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ TEST_FILES = xsk_prereqs.sh $(wildcard progs/btf_dump_test_case_*.c)
101101
# Order correspond to 'make run_tests' order
102102
TEST_PROGS := test_kmod.sh \
103103
test_lirc_mode2.sh \
104-
test_xdp_vlan_mode_generic.sh \
105-
test_xdp_vlan_mode_native.sh \
106104
test_tc_tunnel.sh \
107105
test_tc_edt.sh \
108106
test_xdping.sh \
@@ -115,7 +113,7 @@ TEST_PROGS := test_kmod.sh \
115113

116114
TEST_PROGS_EXTENDED := \
117115
ima_setup.sh verify_sig_setup.sh \
118-
test_xdp_vlan.sh test_bpftool.py
116+
test_bpftool.py
119117

120118
TEST_KMODS := bpf_testmod.ko bpf_test_no_cfi.ko bpf_test_modorder_x.ko \
121119
bpf_test_modorder_y.ko
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Network topology:
5+
* ----------- -----------
6+
* | NS1 | | NS2 |
7+
* | veth0 -|--------|- veth0 |
8+
* ----------- -----------
9+
*
10+
*/
11+
12+
#define _GNU_SOURCE
13+
#include <net/if.h>
14+
#include <uapi/linux/if_link.h>
15+
16+
#include "network_helpers.h"
17+
#include "test_progs.h"
18+
#include "test_xdp_vlan.skel.h"
19+
20+
21+
#define VETH_NAME "veth0"
22+
#define NS_MAX_SIZE 32
23+
#define NS1_NAME "ns-xdp-vlan-1-"
24+
#define NS2_NAME "ns-xdp-vlan-2-"
25+
#define NS1_IP_ADDR "100.64.10.1"
26+
#define NS2_IP_ADDR "100.64.10.2"
27+
#define VLAN_ID 4011
28+
29+
static int setup_network(char *ns1, char *ns2)
30+
{
31+
if (!ASSERT_OK(append_tid(ns1, NS_MAX_SIZE), "create ns1 name"))
32+
goto fail;
33+
if (!ASSERT_OK(append_tid(ns2, NS_MAX_SIZE), "create ns2 name"))
34+
goto fail;
35+
36+
SYS(fail, "ip netns add %s", ns1);
37+
SYS(fail, "ip netns add %s", ns2);
38+
SYS(fail, "ip -n %s link add %s type veth peer name %s netns %s",
39+
ns1, VETH_NAME, VETH_NAME, ns2);
40+
41+
/* NOTICE: XDP require VLAN header inside packet payload
42+
* - Thus, disable VLAN offloading driver features
43+
*/
44+
SYS(fail, "ip netns exec %s ethtool -K %s rxvlan off txvlan off", ns1, VETH_NAME);
45+
SYS(fail, "ip netns exec %s ethtool -K %s rxvlan off txvlan off", ns2, VETH_NAME);
46+
47+
/* NS1 configuration */
48+
SYS(fail, "ip -n %s addr add %s/24 dev %s", ns1, NS1_IP_ADDR, VETH_NAME);
49+
SYS(fail, "ip -n %s link set %s up", ns1, VETH_NAME);
50+
51+
/* NS2 configuration */
52+
SYS(fail, "ip -n %s link add link %s name %s.%d type vlan id %d",
53+
ns2, VETH_NAME, VETH_NAME, VLAN_ID, VLAN_ID);
54+
SYS(fail, "ip -n %s addr add %s/24 dev %s.%d", ns2, NS2_IP_ADDR, VETH_NAME, VLAN_ID);
55+
SYS(fail, "ip -n %s link set %s up", ns2, VETH_NAME);
56+
SYS(fail, "ip -n %s link set %s.%d up", ns2, VETH_NAME, VLAN_ID);
57+
58+
/* At this point ping should fail because VLAN tags are only used by NS2 */
59+
return !SYS_NOFAIL("ip netns exec %s ping -W 1 -c1 %s", ns2, NS1_IP_ADDR);
60+
61+
fail:
62+
return -1;
63+
}
64+
65+
static void cleanup_network(const char *ns1, const char *ns2)
66+
{
67+
SYS_NOFAIL("ip netns del %s", ns1);
68+
SYS_NOFAIL("ip netns del %s", ns2);
69+
}
70+
71+
static void xdp_vlan(struct bpf_program *xdp, struct bpf_program *tc, u32 flags)
72+
{
73+
LIBBPF_OPTS(bpf_tc_hook, tc_hook, .attach_point = BPF_TC_EGRESS);
74+
LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1);
75+
char ns1[NS_MAX_SIZE] = NS1_NAME;
76+
char ns2[NS_MAX_SIZE] = NS2_NAME;
77+
struct nstoken *nstoken = NULL;
78+
int interface;
79+
int ret;
80+
81+
if (!ASSERT_OK(setup_network(ns1, ns2), "setup network"))
82+
goto cleanup;
83+
84+
nstoken = open_netns(ns1);
85+
if (!ASSERT_OK_PTR(nstoken, "open NS1"))
86+
goto cleanup;
87+
88+
interface = if_nametoindex(VETH_NAME);
89+
if (!ASSERT_NEQ(interface, 0, "get interface index"))
90+
goto cleanup;
91+
92+
ret = bpf_xdp_attach(interface, bpf_program__fd(xdp), flags, NULL);
93+
if (!ASSERT_OK(ret, "attach xdp_vlan_change"))
94+
goto cleanup;
95+
96+
tc_hook.ifindex = interface;
97+
ret = bpf_tc_hook_create(&tc_hook);
98+
if (!ASSERT_OK(ret, "bpf_tc_hook_create"))
99+
goto detach_xdp;
100+
101+
/* Now we'll use BPF programs to pop/push the VLAN tags */
102+
tc_opts.prog_fd = bpf_program__fd(tc);
103+
ret = bpf_tc_attach(&tc_hook, &tc_opts);
104+
if (!ASSERT_OK(ret, "bpf_tc_attach"))
105+
goto detach_xdp;
106+
107+
close_netns(nstoken);
108+
nstoken = NULL;
109+
110+
/* Now the namespaces can reach each-other, test with pings */
111+
SYS(detach_tc, "ip netns exec %s ping -i 0.2 -W 2 -c 2 %s > /dev/null", ns1, NS2_IP_ADDR);
112+
SYS(detach_tc, "ip netns exec %s ping -i 0.2 -W 2 -c 2 %s > /dev/null", ns2, NS1_IP_ADDR);
113+
114+
115+
detach_tc:
116+
bpf_tc_detach(&tc_hook, &tc_opts);
117+
detach_xdp:
118+
bpf_xdp_detach(interface, flags, NULL);
119+
cleanup:
120+
close_netns(nstoken);
121+
cleanup_network(ns1, ns2);
122+
}
123+
124+
/* First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"
125+
* egress use TC to add back VLAN tag 4011
126+
*/
127+
void test_xdp_vlan_change(void)
128+
{
129+
struct test_xdp_vlan *skel;
130+
131+
skel = test_xdp_vlan__open_and_load();
132+
if (!ASSERT_OK_PTR(skel, "xdp_vlan__open_and_load"))
133+
return;
134+
135+
if (test__start_subtest("0"))
136+
xdp_vlan(skel->progs.xdp_vlan_change, skel->progs.tc_vlan_push, 0);
137+
138+
if (test__start_subtest("DRV_MODE"))
139+
xdp_vlan(skel->progs.xdp_vlan_change, skel->progs.tc_vlan_push,
140+
XDP_FLAGS_DRV_MODE);
141+
142+
if (test__start_subtest("SKB_MODE"))
143+
xdp_vlan(skel->progs.xdp_vlan_change, skel->progs.tc_vlan_push,
144+
XDP_FLAGS_SKB_MODE);
145+
146+
test_xdp_vlan__destroy(skel);
147+
}
148+
149+
/* Second test: XDP prog fully remove vlan header
150+
*
151+
* Catch kernel bug for generic-XDP, that doesn't allow us to
152+
* remove a VLAN header, because skb->protocol still contain VLAN
153+
* ETH_P_8021Q indication, and this cause overwriting of our changes.
154+
*/
155+
void test_xdp_vlan_remove(void)
156+
{
157+
struct test_xdp_vlan *skel;
158+
159+
skel = test_xdp_vlan__open_and_load();
160+
if (!ASSERT_OK_PTR(skel, "xdp_vlan__open_and_load"))
161+
return;
162+
163+
if (test__start_subtest("0"))
164+
xdp_vlan(skel->progs.xdp_vlan_remove_outer2, skel->progs.tc_vlan_push, 0);
165+
166+
if (test__start_subtest("DRV_MODE"))
167+
xdp_vlan(skel->progs.xdp_vlan_remove_outer2, skel->progs.tc_vlan_push,
168+
XDP_FLAGS_DRV_MODE);
169+
170+
if (test__start_subtest("SKB_MODE"))
171+
xdp_vlan(skel->progs.xdp_vlan_remove_outer2, skel->progs.tc_vlan_push,
172+
XDP_FLAGS_SKB_MODE);
173+
174+
test_xdp_vlan__destroy(skel);
175+
}

‎tools/testing/selftests/bpf/progs/test_xdp_vlan.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ bool parse_eth_frame(struct ethhdr *eth, void *data_end, struct parse_pkt *pkt)
102102
#define TESTVLAN 4011 /* 0xFAB */
103103
// #define TO_VLAN 4000 /* 0xFA0 (hint 0xOA0 = 160) */
104104

105-
SEC("xdp_drop_vlan_4011")
106-
int xdp_prognum0(struct xdp_md *ctx)
105+
SEC("xdp")
106+
int xdp_drop_vlan_4011(struct xdp_md *ctx)
107107
{
108108
void *data_end = (void *)(long)ctx->data_end;
109109
void *data = (void *)(long)ctx->data;
@@ -144,8 +144,8 @@ Load prog with ip tool:
144144
/* Changing VLAN to zero, have same practical effect as removing the VLAN. */
145145
#define TO_VLAN 0
146146

147-
SEC("xdp_vlan_change")
148-
int xdp_prognum1(struct xdp_md *ctx)
147+
SEC("xdp")
148+
int xdp_vlan_change(struct xdp_md *ctx)
149149
{
150150
void *data_end = (void *)(long)ctx->data_end;
151151
void *data = (void *)(long)ctx->data;
@@ -178,8 +178,8 @@ int xdp_prognum1(struct xdp_md *ctx)
178178
#endif
179179
#define VLAN_HDR_SZ 4 /* bytes */
180180

181-
SEC("xdp_vlan_remove_outer")
182-
int xdp_prognum2(struct xdp_md *ctx)
181+
SEC("xdp")
182+
int xdp_vlan_remove_outer(struct xdp_md *ctx)
183183
{
184184
void *data_end = (void *)(long)ctx->data_end;
185185
void *data = (void *)(long)ctx->data;
@@ -224,8 +224,8 @@ void shift_mac_4bytes_32bit(void *data)
224224
p[1] = p[0];
225225
}
226226

227-
SEC("xdp_vlan_remove_outer2")
228-
int xdp_prognum3(struct xdp_md *ctx)
227+
SEC("xdp")
228+
int xdp_vlan_remove_outer2(struct xdp_md *ctx)
229229
{
230230
void *data_end = (void *)(long)ctx->data_end;
231231
void *data = (void *)(long)ctx->data;
@@ -254,8 +254,8 @@ int xdp_prognum3(struct xdp_md *ctx)
254254
* The TC-clsact eBPF programs (currently) need to be attach via TC commands
255255
*/
256256

257-
SEC("tc_vlan_push")
258-
int _tc_progA(struct __sk_buff *ctx)
257+
SEC("tc")
258+
int tc_vlan_push(struct __sk_buff *ctx)
259259
{
260260
bpf_skb_vlan_push(ctx, bpf_htons(ETH_P_8021Q), TESTVLAN);
261261

0 commit comments

Comments
 (0)
Please sign in to comment.