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