Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/drivers/net/hds.py
26288 views
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: GPL-2.0
3
4
import errno
5
import os
6
from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_raises, KsftSkipEx
7
from lib.py import CmdExitFailure, EthtoolFamily, NlError
8
from lib.py import NetDrvEnv
9
from lib.py import defer, ethtool, ip, random
10
11
12
def _get_hds_mode(cfg, netnl) -> str:
13
try:
14
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
15
except NlError as e:
16
raise KsftSkipEx('ring-get not supported by device')
17
if 'tcp-data-split' not in rings:
18
raise KsftSkipEx('tcp-data-split not supported by device')
19
return rings['tcp-data-split']
20
21
22
def _xdp_onoff(cfg):
23
prog = cfg.net_lib_dir / "xdp_dummy.bpf.o"
24
ip("link set dev %s xdp obj %s sec xdp" %
25
(cfg.ifname, prog))
26
ip("link set dev %s xdp off" % cfg.ifname)
27
28
29
def _ioctl_ringparam_modify(cfg, netnl) -> None:
30
"""
31
Helper for performing a hopefully unimportant IOCTL SET.
32
IOCTL does not support HDS, so it should not affect the HDS config.
33
"""
34
try:
35
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
36
except NlError as e:
37
raise KsftSkipEx('ring-get not supported by device')
38
39
if 'tx' not in rings:
40
raise KsftSkipEx('setting Tx ring size not supported')
41
42
try:
43
ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] // 2}")
44
except CmdExitFailure as e:
45
ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] * 2}")
46
defer(ethtool, f"-G {cfg.ifname} tx {rings['tx']}")
47
48
49
def get_hds(cfg, netnl) -> None:
50
_get_hds_mode(cfg, netnl)
51
52
53
def get_hds_thresh(cfg, netnl) -> None:
54
try:
55
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
56
except NlError as e:
57
raise KsftSkipEx('ring-get not supported by device')
58
if 'hds-thresh' not in rings:
59
raise KsftSkipEx('hds-thresh not supported by device')
60
61
def set_hds_enable(cfg, netnl) -> None:
62
try:
63
netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'enabled'})
64
except NlError as e:
65
if e.error == errno.EINVAL:
66
raise KsftSkipEx("disabling of HDS not supported by the device")
67
elif e.error == errno.EOPNOTSUPP:
68
raise KsftSkipEx("ring-set not supported by the device")
69
try:
70
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
71
except NlError as e:
72
raise KsftSkipEx('ring-get not supported by device')
73
if 'tcp-data-split' not in rings:
74
raise KsftSkipEx('tcp-data-split not supported by device')
75
76
ksft_eq('enabled', rings['tcp-data-split'])
77
78
def set_hds_disable(cfg, netnl) -> None:
79
try:
80
netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'disabled'})
81
except NlError as e:
82
if e.error == errno.EINVAL:
83
raise KsftSkipEx("disabling of HDS not supported by the device")
84
elif e.error == errno.EOPNOTSUPP:
85
raise KsftSkipEx("ring-set not supported by the device")
86
try:
87
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
88
except NlError as e:
89
raise KsftSkipEx('ring-get not supported by device')
90
if 'tcp-data-split' not in rings:
91
raise KsftSkipEx('tcp-data-split not supported by device')
92
93
ksft_eq('disabled', rings['tcp-data-split'])
94
95
def set_hds_thresh_zero(cfg, netnl) -> None:
96
try:
97
netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': 0})
98
except NlError as e:
99
if e.error == errno.EINVAL:
100
raise KsftSkipEx("hds-thresh-set not supported by the device")
101
elif e.error == errno.EOPNOTSUPP:
102
raise KsftSkipEx("ring-set not supported by the device")
103
try:
104
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
105
except NlError as e:
106
raise KsftSkipEx('ring-get not supported by device')
107
if 'hds-thresh' not in rings:
108
raise KsftSkipEx('hds-thresh not supported by device')
109
110
ksft_eq(0, rings['hds-thresh'])
111
112
def set_hds_thresh_random(cfg, netnl) -> None:
113
try:
114
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
115
except NlError as e:
116
raise KsftSkipEx('ring-get not supported by device')
117
if 'hds-thresh' not in rings:
118
raise KsftSkipEx('hds-thresh not supported by device')
119
if 'hds-thresh-max' not in rings:
120
raise KsftSkipEx('hds-thresh-max not defined by device')
121
122
if rings['hds-thresh-max'] < 2:
123
raise KsftSkipEx('hds-thresh-max is too small')
124
elif rings['hds-thresh-max'] == 2:
125
hds_thresh = 1
126
else:
127
while True:
128
hds_thresh = random.randint(1, rings['hds-thresh-max'] - 1)
129
if hds_thresh != rings['hds-thresh']:
130
break
131
132
try:
133
netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_thresh})
134
except NlError as e:
135
if e.error == errno.EINVAL:
136
raise KsftSkipEx("hds-thresh-set not supported by the device")
137
elif e.error == errno.EOPNOTSUPP:
138
raise KsftSkipEx("ring-set not supported by the device")
139
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
140
ksft_eq(hds_thresh, rings['hds-thresh'])
141
142
def set_hds_thresh_max(cfg, netnl) -> None:
143
try:
144
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
145
except NlError as e:
146
raise KsftSkipEx('ring-get not supported by device')
147
if 'hds-thresh' not in rings:
148
raise KsftSkipEx('hds-thresh not supported by device')
149
try:
150
netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': rings['hds-thresh-max']})
151
except NlError as e:
152
if e.error == errno.EINVAL:
153
raise KsftSkipEx("hds-thresh-set not supported by the device")
154
elif e.error == errno.EOPNOTSUPP:
155
raise KsftSkipEx("ring-set not supported by the device")
156
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
157
ksft_eq(rings['hds-thresh'], rings['hds-thresh-max'])
158
159
def set_hds_thresh_gt(cfg, netnl) -> None:
160
try:
161
rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
162
except NlError as e:
163
raise KsftSkipEx('ring-get not supported by device')
164
if 'hds-thresh' not in rings:
165
raise KsftSkipEx('hds-thresh not supported by device')
166
if 'hds-thresh-max' not in rings:
167
raise KsftSkipEx('hds-thresh-max not defined by device')
168
hds_gt = rings['hds-thresh-max'] + 1
169
with ksft_raises(NlError) as e:
170
netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_gt})
171
ksft_eq(e.exception.nl_msg.error, -errno.EINVAL)
172
173
174
def set_xdp(cfg, netnl) -> None:
175
"""
176
Enable single-buffer XDP on the device.
177
When HDS is in "auto" / UNKNOWN mode, XDP installation should work.
178
"""
179
mode = _get_hds_mode(cfg, netnl)
180
if mode == 'enabled':
181
netnl.rings_set({'header': {'dev-index': cfg.ifindex},
182
'tcp-data-split': 'unknown'})
183
184
_xdp_onoff(cfg)
185
186
187
def enabled_set_xdp(cfg, netnl) -> None:
188
"""
189
Enable single-buffer XDP on the device.
190
When HDS is in "enabled" mode, XDP installation should not work.
191
"""
192
_get_hds_mode(cfg, netnl)
193
netnl.rings_set({'header': {'dev-index': cfg.ifindex},
194
'tcp-data-split': 'enabled'})
195
196
defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},
197
'tcp-data-split': 'unknown'})
198
199
with ksft_raises(CmdExitFailure) as e:
200
_xdp_onoff(cfg)
201
202
203
def set_xdp(cfg, netnl) -> None:
204
"""
205
Enable single-buffer XDP on the device.
206
When HDS is in "auto" / UNKNOWN mode, XDP installation should work.
207
"""
208
mode = _get_hds_mode(cfg, netnl)
209
if mode == 'enabled':
210
netnl.rings_set({'header': {'dev-index': cfg.ifindex},
211
'tcp-data-split': 'unknown'})
212
213
_xdp_onoff(cfg)
214
215
216
def enabled_set_xdp(cfg, netnl) -> None:
217
"""
218
Enable single-buffer XDP on the device.
219
When HDS is in "enabled" mode, XDP installation should not work.
220
"""
221
_get_hds_mode(cfg, netnl) # Trigger skip if not supported
222
223
netnl.rings_set({'header': {'dev-index': cfg.ifindex},
224
'tcp-data-split': 'enabled'})
225
defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},
226
'tcp-data-split': 'unknown'})
227
228
with ksft_raises(CmdExitFailure) as e:
229
_xdp_onoff(cfg)
230
231
232
def ioctl(cfg, netnl) -> None:
233
mode1 = _get_hds_mode(cfg, netnl)
234
_ioctl_ringparam_modify(cfg, netnl)
235
mode2 = _get_hds_mode(cfg, netnl)
236
237
ksft_eq(mode1, mode2)
238
239
240
def ioctl_set_xdp(cfg, netnl) -> None:
241
"""
242
Like set_xdp(), but we perturb the settings via the legacy ioctl.
243
"""
244
mode = _get_hds_mode(cfg, netnl)
245
if mode == 'enabled':
246
netnl.rings_set({'header': {'dev-index': cfg.ifindex},
247
'tcp-data-split': 'unknown'})
248
249
_ioctl_ringparam_modify(cfg, netnl)
250
251
_xdp_onoff(cfg)
252
253
254
def ioctl_enabled_set_xdp(cfg, netnl) -> None:
255
"""
256
Enable single-buffer XDP on the device.
257
When HDS is in "enabled" mode, XDP installation should not work.
258
"""
259
_get_hds_mode(cfg, netnl) # Trigger skip if not supported
260
261
netnl.rings_set({'header': {'dev-index': cfg.ifindex},
262
'tcp-data-split': 'enabled'})
263
defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},
264
'tcp-data-split': 'unknown'})
265
266
with ksft_raises(CmdExitFailure) as e:
267
_xdp_onoff(cfg)
268
269
270
def main() -> None:
271
with NetDrvEnv(__file__, queue_count=3) as cfg:
272
ksft_run([get_hds,
273
get_hds_thresh,
274
set_hds_disable,
275
set_hds_enable,
276
set_hds_thresh_random,
277
set_hds_thresh_zero,
278
set_hds_thresh_max,
279
set_hds_thresh_gt,
280
set_xdp,
281
enabled_set_xdp,
282
ioctl,
283
ioctl_set_xdp,
284
ioctl_enabled_set_xdp],
285
args=(cfg, EthtoolFamily()))
286
ksft_exit()
287
288
if __name__ == "__main__":
289
main()
290
291