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