Skip to content

Commit 75cc19c

Browse files
TaeheeYookuba-moo
authored andcommitted
selftests: drv-net: add xdp cases for ping.py
ping.py has 3 cases, test_v4, test_v6 and test_tcp. But these cases are not executed on the XDP environment. So, it adds XDP environment, existing tests(test_v4, test_v6, and test_tcp) are executed too on the below XDP environment. So, it adds XDP cases. 1. xdp-generic + single-buffer 2. xdp-generic + multi-buffer 3. xdp-native + single-buffer 4. xdp-native + multi-buffer 5. xdp-offload It also makes test_{v4 | v6 | tcp} sending large size packets. this may help to check whether multi-buffer is working or not. Note that the physical interface may be down and then up when xdp is attached or detached. This takes some period to activate traffic. So sleep(10) is added if the test interface is the physical interface. netdevsim and veth type interfaces skip sleep. Signed-off-by: Taehee Yoo <ap420073@gmail.com> Link: https://patch.msgid.link/20250309134219.91670-9-ap420073@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent a70f891 commit 75cc19c

File tree

2 files changed

+191
-15
lines changed

2 files changed

+191
-15
lines changed

tools/testing/selftests/drivers/net/ping.py

Lines changed: 185 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,219 @@
11
#!/usr/bin/env python3
22
# SPDX-License-Identifier: GPL-2.0
33

4+
import os
5+
import random, string, time
46
from lib.py import ksft_run, ksft_exit
5-
from lib.py import ksft_eq
6-
from lib.py import NetDrvEpEnv
7+
from lib.py import ksft_eq, KsftSkipEx, KsftFailEx
8+
from lib.py import EthtoolFamily, NetDrvEpEnv
79
from lib.py import bkg, cmd, wait_port_listen, rand_port
10+
from lib.py import ethtool, ip
811

12+
remote_ifname=""
13+
no_sleep=False
914

10-
def test_v4(cfg) -> None:
15+
def _test_v4(cfg) -> None:
1116
cfg.require_v4()
1217

1318
cmd(f"ping -c 1 -W0.5 {cfg.remote_v4}")
1419
cmd(f"ping -c 1 -W0.5 {cfg.v4}", host=cfg.remote)
20+
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.remote_v4}")
21+
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.v4}", host=cfg.remote)
1522

16-
17-
def test_v6(cfg) -> None:
23+
def _test_v6(cfg) -> None:
1824
cfg.require_v6()
1925

20-
cmd(f"ping -c 1 -W0.5 {cfg.remote_v6}")
21-
cmd(f"ping -c 1 -W0.5 {cfg.v6}", host=cfg.remote)
22-
26+
cmd(f"ping -c 1 -W5 {cfg.remote_v6}")
27+
cmd(f"ping -c 1 -W5 {cfg.v6}", host=cfg.remote)
28+
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.remote_v6}")
29+
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.v6}", host=cfg.remote)
2330

24-
def test_tcp(cfg) -> None:
31+
def _test_tcp(cfg) -> None:
2532
cfg.require_cmd("socat", remote=True)
2633

2734
port = rand_port()
2835
listen_cmd = f"socat -{cfg.addr_ipver} -t 2 -u TCP-LISTEN:{port},reuseport STDOUT"
2936

37+
test_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(65536))
3038
with bkg(listen_cmd, exit_wait=True) as nc:
3139
wait_port_listen(port)
3240

33-
cmd(f"echo ping | socat -t 2 -u STDIN TCP:{cfg.baddr}:{port}",
41+
cmd(f"echo {test_string} | socat -t 2 -u STDIN TCP:{cfg.baddr}:{port}",
3442
shell=True, host=cfg.remote)
35-
ksft_eq(nc.stdout.strip(), "ping")
43+
ksft_eq(nc.stdout.strip(), test_string)
3644

45+
test_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(65536))
3746
with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as nc:
3847
wait_port_listen(port, host=cfg.remote)
3948

40-
cmd(f"echo ping | socat -t 2 -u STDIN TCP:{cfg.remote_baddr}:{port}", shell=True)
41-
ksft_eq(nc.stdout.strip(), "ping")
42-
49+
cmd(f"echo {test_string} | socat -t 2 -u STDIN TCP:{cfg.remote_baddr}:{port}", shell=True)
50+
ksft_eq(nc.stdout.strip(), test_string)
51+
52+
def _set_offload_checksum(cfg, netnl, on) -> None:
53+
try:
54+
ethtool(f" -K {cfg.ifname} rx {on} tx {on} ")
55+
except:
56+
return
57+
58+
def _set_xdp_generic_sb_on(cfg) -> None:
59+
test_dir = os.path.dirname(os.path.realpath(__file__))
60+
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
61+
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
62+
cmd(f"ip link set dev {cfg.ifname} mtu 1500 xdpgeneric obj {prog} sec xdp", shell=True)
63+
64+
if no_sleep != True:
65+
time.sleep(10)
66+
67+
def _set_xdp_generic_mb_on(cfg) -> None:
68+
test_dir = os.path.dirname(os.path.realpath(__file__))
69+
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
70+
cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote)
71+
ip("link set dev %s mtu 9000 xdpgeneric obj %s sec xdp.frags" % (cfg.ifname, prog))
72+
73+
if no_sleep != True:
74+
time.sleep(10)
75+
76+
def _set_xdp_native_sb_on(cfg) -> None:
77+
test_dir = os.path.dirname(os.path.realpath(__file__))
78+
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
79+
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
80+
cmd(f"ip -j link set dev {cfg.ifname} mtu 1500 xdp obj {prog} sec xdp", shell=True)
81+
xdp_info = ip("-d link show %s" % (cfg.ifname), json=True)[0]
82+
if xdp_info['xdp']['mode'] != 1:
83+
"""
84+
If the interface doesn't support native-mode, it falls back to generic mode.
85+
The mode value 1 is native and 2 is generic.
86+
So it raises an exception if mode is not 1(native mode).
87+
"""
88+
raise KsftSkipEx('device does not support native-XDP')
89+
90+
if no_sleep != True:
91+
time.sleep(10)
92+
93+
def _set_xdp_native_mb_on(cfg) -> None:
94+
test_dir = os.path.dirname(os.path.realpath(__file__))
95+
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
96+
cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote)
97+
try:
98+
cmd(f"ip link set dev {cfg.ifname} mtu 9000 xdp obj {prog} sec xdp.frags", shell=True)
99+
except Exception as e:
100+
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
101+
raise KsftSkipEx('device does not support native-multi-buffer XDP')
102+
103+
if no_sleep != True:
104+
time.sleep(10)
105+
106+
def _set_xdp_offload_on(cfg) -> None:
107+
test_dir = os.path.dirname(os.path.realpath(__file__))
108+
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
109+
cmd(f"ip link set dev {cfg.ifname} mtu 1500", shell=True)
110+
try:
111+
cmd(f"ip link set dev {cfg.ifname} xdpoffload obj {prog} sec xdp", shell=True)
112+
except Exception as e:
113+
raise KsftSkipEx('device does not support offloaded XDP')
114+
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
115+
116+
if no_sleep != True:
117+
time.sleep(10)
118+
119+
def get_interface_info(cfg) -> None:
120+
global remote_ifname
121+
global no_sleep
122+
123+
remote_info = cmd(f"ip -4 -o addr show to {cfg.remote_v4} | awk '{{print $2}}'", shell=True, host=cfg.remote).stdout
124+
remote_ifname = remote_info.rstrip('\n')
125+
if remote_ifname == "":
126+
raise KsftFailEx('Can not get remote interface')
127+
local_info = ip("-d link show %s" % (cfg.ifname), json=True)[0]
128+
if 'parentbus' in local_info and local_info['parentbus'] == "netdevsim":
129+
no_sleep=True
130+
if 'linkinfo' in local_info and local_info['linkinfo']['info_kind'] == "veth":
131+
no_sleep=True
132+
133+
def set_interface_init(cfg) -> None:
134+
cmd(f"ip link set dev {cfg.ifname} mtu 1500", shell=True)
135+
cmd(f"ip link set dev {cfg.ifname} xdp off ", shell=True)
136+
cmd(f"ip link set dev {cfg.ifname} xdpgeneric off ", shell=True)
137+
cmd(f"ip link set dev {cfg.ifname} xdpoffload off", shell=True)
138+
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
139+
140+
def test_default(cfg, netnl) -> None:
141+
_set_offload_checksum(cfg, netnl, "off")
142+
_test_v4(cfg)
143+
_test_v6(cfg)
144+
_test_tcp(cfg)
145+
_set_offload_checksum(cfg, netnl, "on")
146+
_test_v4(cfg)
147+
_test_v6(cfg)
148+
_test_tcp(cfg)
149+
150+
def test_xdp_generic_sb(cfg, netnl) -> None:
151+
_set_xdp_generic_sb_on(cfg)
152+
_set_offload_checksum(cfg, netnl, "off")
153+
_test_v4(cfg)
154+
_test_v6(cfg)
155+
_test_tcp(cfg)
156+
_set_offload_checksum(cfg, netnl, "on")
157+
_test_v4(cfg)
158+
_test_v6(cfg)
159+
_test_tcp(cfg)
160+
ip("link set dev %s xdpgeneric off" % cfg.ifname)
161+
162+
def test_xdp_generic_mb(cfg, netnl) -> None:
163+
_set_xdp_generic_mb_on(cfg)
164+
_set_offload_checksum(cfg, netnl, "off")
165+
_test_v4(cfg)
166+
_test_v6(cfg)
167+
_test_tcp(cfg)
168+
_set_offload_checksum(cfg, netnl, "on")
169+
_test_v4(cfg)
170+
_test_v6(cfg)
171+
_test_tcp(cfg)
172+
ip("link set dev %s xdpgeneric off" % cfg.ifname)
173+
174+
def test_xdp_native_sb(cfg, netnl) -> None:
175+
_set_xdp_native_sb_on(cfg)
176+
_set_offload_checksum(cfg, netnl, "off")
177+
_test_v4(cfg)
178+
_test_v6(cfg)
179+
_test_tcp(cfg)
180+
_set_offload_checksum(cfg, netnl, "on")
181+
_test_v4(cfg)
182+
_test_v6(cfg)
183+
_test_tcp(cfg)
184+
ip("link set dev %s xdp off" % cfg.ifname)
185+
186+
def test_xdp_native_mb(cfg, netnl) -> None:
187+
_set_xdp_native_mb_on(cfg)
188+
_set_offload_checksum(cfg, netnl, "off")
189+
_test_v4(cfg)
190+
_test_v6(cfg)
191+
_test_tcp(cfg)
192+
_set_offload_checksum(cfg, netnl, "on")
193+
_test_v4(cfg)
194+
_test_v6(cfg)
195+
_test_tcp(cfg)
196+
ip("link set dev %s xdp off" % cfg.ifname)
197+
198+
def test_xdp_offload(cfg, netnl) -> None:
199+
_set_xdp_offload_on(cfg)
200+
_test_v4(cfg)
201+
_test_v6(cfg)
202+
_test_tcp(cfg)
203+
ip("link set dev %s xdpoffload off" % cfg.ifname)
43204

44205
def main() -> None:
45206
with NetDrvEpEnv(__file__) as cfg:
46-
ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, ))
207+
get_interface_info(cfg)
208+
set_interface_init(cfg)
209+
ksft_run([test_default,
210+
test_xdp_generic_sb,
211+
test_xdp_generic_mb,
212+
test_xdp_native_sb,
213+
test_xdp_native_mb,
214+
test_xdp_offload],
215+
args=(cfg, EthtoolFamily()))
216+
set_interface_init(cfg)
47217
ksft_exit()
48218

49219

tools/testing/selftests/net/lib/xdp_dummy.bpf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@ int xdp_dummy_prog(struct xdp_md *ctx)
1010
return XDP_PASS;
1111
}
1212

13+
SEC("xdp.frags")
14+
int xdp_dummy_prog_frags(struct xdp_md *ctx)
15+
{
16+
return XDP_PASS;
17+
}
18+
1319
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)