Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/drivers/net/ring_reconfig.py
38237 views
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: GPL-2.0
3
4
"""
5
Test channel and ring size configuration via ethtool (-L / -G).
6
"""
7
8
from lib.py import ksft_run, ksft_exit, ksft_pr
9
from lib.py import ksft_eq
10
from lib.py import NetDrvEpEnv, EthtoolFamily, GenerateTraffic
11
from lib.py import defer, NlError
12
13
14
def channels(cfg) -> None:
15
"""
16
Twiddle channel counts in various combinations of parameters.
17
We're only looking for driver adhering to the requested config
18
if the config is accepted and crashes.
19
"""
20
ehdr = {'header':{'dev-index': cfg.ifindex}}
21
chans = cfg.eth.channels_get(ehdr)
22
23
all_keys = ["rx", "tx", "combined"]
24
mixes = [{"combined"}, {"rx", "tx"}, {"rx", "combined"}, {"tx", "combined"},
25
{"rx", "tx", "combined"},]
26
27
# Get the set of keys that device actually supports
28
restore = {}
29
supported = set()
30
for key in all_keys:
31
if key + "-max" in chans:
32
supported.add(key)
33
restore |= {key + "-count": chans[key + "-count"]}
34
35
defer(cfg.eth.channels_set, ehdr | restore)
36
37
def test_config(config):
38
try:
39
cfg.eth.channels_set(ehdr | config)
40
get = cfg.eth.channels_get(ehdr)
41
for k, v in config.items():
42
ksft_eq(get.get(k, 0), v)
43
except NlError as e:
44
failed.append(mix)
45
ksft_pr("Can't set", config, e)
46
else:
47
ksft_pr("Okay", config)
48
49
failed = []
50
for mix in mixes:
51
if not mix.issubset(supported):
52
continue
53
54
# Set all the values in the mix to 1, other supported to 0
55
config = {}
56
for key in all_keys:
57
config[key + "-count"] = 1 if key in mix else 0
58
test_config(config)
59
60
for mix in mixes:
61
if not mix.issubset(supported):
62
continue
63
if mix in failed:
64
continue
65
66
# Set all the values in the mix to max, other supported to 0
67
config = {}
68
for key in all_keys:
69
config[key + "-count"] = chans[key + '-max'] if key in mix else 0
70
test_config(config)
71
72
73
def _configure_min_ring_cnt(cfg) -> None:
74
""" Try to configure a single Rx/Tx ring. """
75
ehdr = {'header':{'dev-index': cfg.ifindex}}
76
chans = cfg.eth.channels_get(ehdr)
77
78
all_keys = ["rx-count", "tx-count", "combined-count"]
79
restore = {}
80
config = {}
81
for key in all_keys:
82
if key in chans:
83
restore[key] = chans[key]
84
config[key] = 0
85
86
if chans.get('combined-count', 0) > 1:
87
config['combined-count'] = 1
88
elif chans.get('rx-count', 0) > 1 and chans.get('tx-count', 0) > 1:
89
config['tx-count'] = 1
90
config['rx-count'] = 1
91
else:
92
# looks like we're already on 1 channel
93
return
94
95
cfg.eth.channels_set(ehdr | config)
96
defer(cfg.eth.channels_set, ehdr | restore)
97
98
99
def ringparam(cfg) -> None:
100
"""
101
Tweak the ringparam configuration. Try to run some traffic over min
102
ring size to make sure it actually functions.
103
"""
104
ehdr = {'header':{'dev-index': cfg.ifindex}}
105
rings = cfg.eth.rings_get(ehdr)
106
107
restore = {}
108
maxes = {}
109
params = set()
110
for key in rings.keys():
111
if 'max' in key:
112
param = key[:-4]
113
maxes[param] = rings[key]
114
params.add(param)
115
restore[param] = rings[param]
116
117
defer(cfg.eth.rings_set, ehdr | restore)
118
119
# Speed up the reconfig by configuring just one ring
120
_configure_min_ring_cnt(cfg)
121
122
# Try to reach min on all settings
123
for param in params:
124
val = rings[param]
125
while True:
126
try:
127
cfg.eth.rings_set({'header':{'dev-index': cfg.ifindex},
128
param: val // 2})
129
if val == 0:
130
break
131
val //= 2
132
except NlError:
133
break
134
135
get = cfg.eth.rings_get(ehdr)
136
ksft_eq(get[param], val)
137
138
ksft_pr(f"Reached min for '{param}' at {val} (max {rings[param]})")
139
140
GenerateTraffic(cfg).wait_pkts_and_stop(10000)
141
142
# Try max across all params, if the driver supports large rings
143
# this may OOM so we ignore errors
144
try:
145
ksft_pr("Applying max settings")
146
config = {p: maxes[p] for p in params}
147
cfg.eth.rings_set(ehdr | config)
148
except NlError as e:
149
ksft_pr("Can't set max params", config, e)
150
else:
151
GenerateTraffic(cfg).wait_pkts_and_stop(10000)
152
153
154
def main() -> None:
155
""" Ksft boiler plate main """
156
157
with NetDrvEpEnv(__file__) as cfg:
158
cfg.eth = EthtoolFamily()
159
160
ksft_run([channels,
161
ringparam],
162
args=(cfg, ))
163
ksft_exit()
164
165
166
if __name__ == "__main__":
167
main()
168
169