Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/drivers/net/hw/nic_timestamp.py
50904 views
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: GPL-2.0
3
# pylint: disable=locally-disabled, invalid-name, attribute-defined-outside-init, too-few-public-methods
4
5
"""
6
Tests related to configuration of HW timestamping
7
"""
8
9
import errno
10
import ctypes
11
import fcntl
12
import socket
13
from lib.py import ksft_run, ksft_exit, ksft_ge, ksft_eq, KsftSkipEx
14
from lib.py import NetDrvEnv, EthtoolFamily, NlError
15
16
17
SIOCSHWTSTAMP = 0x89b0
18
SIOCGHWTSTAMP = 0x89b1
19
class hwtstamp_config(ctypes.Structure):
20
""" Python copy of struct hwtstamp_config """
21
_fields_ = [
22
("flags", ctypes.c_int),
23
("tx_type", ctypes.c_int),
24
("rx_filter", ctypes.c_int),
25
]
26
27
28
class ifreq(ctypes.Structure):
29
""" Python copy of struct ifreq """
30
_fields_ = [
31
("ifr_name", ctypes.c_char * 16),
32
("ifr_data", ctypes.POINTER(hwtstamp_config)),
33
]
34
35
36
def __get_hwtimestamp_support(cfg):
37
""" Retrieve supported configuration information """
38
39
try:
40
tsinfo = cfg.ethnl.tsinfo_get({'header': {'dev-name': cfg.ifname}})
41
except NlError as e:
42
if e.error == errno.EOPNOTSUPP:
43
raise KsftSkipEx("timestamping configuration is not supported") from e
44
raise
45
46
ctx = {}
47
tx = tsinfo.get('tx-types', {})
48
rx = tsinfo.get('rx-filters', {})
49
50
bits = tx.get('bits', {})
51
ctx['tx'] = bits.get('bit', [])
52
bits = rx.get('bits', {})
53
ctx['rx'] = bits.get('bit', [])
54
return ctx
55
56
57
def __get_hwtimestamp_config_ioctl(cfg):
58
""" Retrieve current TS configuration information (via ioctl) """
59
60
config = hwtstamp_config()
61
62
req = ifreq()
63
req.ifr_name = cfg.ifname.encode()
64
req.ifr_data = ctypes.pointer(config)
65
66
try:
67
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
68
fcntl.ioctl(sock.fileno(), SIOCGHWTSTAMP, req)
69
sock.close()
70
71
except OSError as e:
72
if e.errno == errno.EOPNOTSUPP:
73
raise KsftSkipEx("timestamping configuration is not supported via ioctl") from e
74
raise
75
return config
76
77
78
def __get_hwtimestamp_config(cfg):
79
""" Retrieve current TS configuration information (via netLink) """
80
81
try:
82
tscfg = cfg.ethnl.tsconfig_get({'header': {'dev-name': cfg.ifname}})
83
except NlError as e:
84
if e.error == errno.EOPNOTSUPP:
85
raise KsftSkipEx("timestamping configuration is not supported via netlink") from e
86
raise
87
return tscfg
88
89
90
def __set_hwtimestamp_config_ioctl(cfg, ts):
91
""" Setup new TS configuration information (via ioctl) """
92
config = hwtstamp_config()
93
config.rx_filter = ts['rx-filters']['bits']['bit'][0]['index']
94
config.tx_type = ts['tx-types']['bits']['bit'][0]['index']
95
req = ifreq()
96
req.ifr_name = cfg.ifname.encode()
97
req.ifr_data = ctypes.pointer(config)
98
try:
99
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
100
fcntl.ioctl(sock.fileno(), SIOCSHWTSTAMP, req)
101
sock.close()
102
103
except OSError as e:
104
if e.errno == errno.EOPNOTSUPP:
105
raise KsftSkipEx("timestamping configuration is not supported via ioctl") from e
106
raise
107
108
109
def __set_hwtimestamp_config(cfg, ts):
110
""" Setup new TS configuration information (via netlink) """
111
112
ts['header'] = {'dev-name': cfg.ifname}
113
try:
114
res = cfg.ethnl.tsconfig_set(ts)
115
except NlError as e:
116
if e.error == errno.EOPNOTSUPP:
117
raise KsftSkipEx("timestamping configuration is not supported via netlink") from e
118
raise
119
return res
120
121
122
def __perform_hwtstamp_tx(cfg, is_ioctl):
123
"""
124
Test TX timestamp configuration via either netlink or ioctl.
125
The driver should apply provided config and report back proper state.
126
"""
127
128
orig_tscfg = __get_hwtimestamp_config(cfg)
129
ts = __get_hwtimestamp_support(cfg)
130
tx = ts['tx']
131
for t in tx:
132
res = None
133
tscfg = orig_tscfg
134
tscfg['tx-types']['bits']['bit'] = [t]
135
if is_ioctl:
136
__set_hwtimestamp_config_ioctl(cfg, tscfg)
137
else:
138
res = __set_hwtimestamp_config(cfg, tscfg)
139
if res is None:
140
res = __get_hwtimestamp_config(cfg)
141
resioctl = __get_hwtimestamp_config_ioctl(cfg)
142
ksft_eq(res['tx-types']['bits']['bit'], [t])
143
ksft_eq(resioctl.tx_type, t['index'])
144
__set_hwtimestamp_config(cfg, orig_tscfg)
145
146
def test_hwtstamp_tx_netlink(cfg):
147
"""
148
Test TX timestamp configuration setup via netlink.
149
The driver should apply provided config and report back proper state.
150
"""
151
__perform_hwtstamp_tx(cfg, False)
152
153
154
def test_hwtstamp_tx_ioctl(cfg):
155
"""
156
Test TX timestamp configuration setup via ioctl.
157
The driver should apply provided config and report back proper state.
158
"""
159
__perform_hwtstamp_tx(cfg, True)
160
161
162
def __perform_hwtstamp_rx(cfg, is_ioctl):
163
"""
164
Test RX timestamp configuration.
165
The filter configuration is taken from the list of supported filters.
166
The driver should apply the config without error and report back proper state.
167
Some extension of the timestamping scope is allowed for PTP filters.
168
"""
169
170
orig_tscfg = __get_hwtimestamp_config(cfg)
171
ts = __get_hwtimestamp_support(cfg)
172
rx = ts['rx']
173
for r in rx:
174
res = None
175
tscfg = orig_tscfg
176
tscfg['rx-filters']['bits']['bit'] = [r]
177
if is_ioctl:
178
__set_hwtimestamp_config_ioctl(cfg, tscfg)
179
else:
180
res = __set_hwtimestamp_config(cfg, tscfg)
181
if res is None:
182
res = __get_hwtimestamp_config(cfg)
183
resioctl = __get_hwtimestamp_config_ioctl(cfg)
184
ksft_eq(resioctl.rx_filter, res['rx-filters']['bits']['bit'][0]['index'])
185
if r['index'] == 0 or r['index'] == 1:
186
ksft_eq(res['rx-filters']['bits']['bit'][0]['index'], r['index'])
187
else:
188
# the driver can fallback to some value which has higher coverage for timestamping
189
ksft_ge(res['rx-filters']['bits']['bit'][0]['index'], r['index'])
190
__set_hwtimestamp_config(cfg, orig_tscfg)
191
192
193
def test_hwtstamp_rx_netlink(cfg):
194
"""
195
Test RX timestamp configuration via netlink.
196
The filter configuration is taken from the list of supported filters.
197
The driver should apply the config without error and report back proper state.
198
Some extension of the timestamping scope is allowed for PTP filters.
199
"""
200
__perform_hwtstamp_rx(cfg, False)
201
202
203
def test_hwtstamp_rx_ioctl(cfg):
204
"""
205
Test RX timestamp configuration via ioctl.
206
The filter configuration is taken from the list of supported filters.
207
The driver should apply the config without error and report back proper state.
208
Some extension of the timestamping scope is allowed for PTP filters.
209
"""
210
__perform_hwtstamp_rx(cfg, True)
211
212
213
def main() -> None:
214
""" Ksft boiler plate main """
215
216
with NetDrvEnv(__file__, nsim_test=False) as cfg:
217
cfg.ethnl = EthtoolFamily()
218
ksft_run([test_hwtstamp_tx_ioctl, test_hwtstamp_tx_netlink,
219
test_hwtstamp_rx_ioctl, test_hwtstamp_rx_netlink],
220
args=(cfg,))
221
ksft_exit()
222
223
224
if __name__ == "__main__":
225
main()
226
227