22# SPDX-License-Identifier: GPL-2.0
33
44import errno
5+ import os
56from lib .py import ksft_run , ksft_exit , ksft_eq , ksft_raises , KsftSkipEx
6- from lib .py import EthtoolFamily , NlError
7+ from lib .py import CmdExitFailure , EthtoolFamily , NlError
78from lib .py import NetDrvEnv
9+ from lib .py import defer , ethtool , ip
810
9- def get_hds (cfg , netnl ) -> None :
11+
12+ def _get_hds_mode (cfg , netnl ) -> str :
1013 try :
1114 rings = netnl .rings_get ({'header' : {'dev-index' : cfg .ifindex }})
1215 except NlError as e :
1316 raise KsftSkipEx ('ring-get not supported by device' )
1417 if 'tcp-data-split' not in rings :
1518 raise KsftSkipEx ('tcp-data-split not supported by device' )
19+ return rings ['tcp-data-split' ]
20+
21+
22+ def _xdp_onoff (cfg ):
23+ test_dir = os .path .dirname (os .path .realpath (__file__ ))
24+ prog = test_dir + "/../../net/lib/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+
1653
1754def get_hds_thresh (cfg , netnl ) -> None :
1855 try :
@@ -104,6 +141,103 @@ def set_hds_thresh_gt(cfg, netnl) -> None:
104141 netnl .rings_set ({'header' : {'dev-index' : cfg .ifindex }, 'hds-thresh' : hds_gt })
105142 ksft_eq (e .exception .nl_msg .error , - errno .EINVAL )
106143
144+
145+ def set_xdp (cfg , netnl ) -> None :
146+ """
147+ Enable single-buffer XDP on the device.
148+ When HDS is in "auto" / UNKNOWN mode, XDP installation should work.
149+ """
150+ mode = _get_hds_mode (cfg , netnl )
151+ if mode == 'enabled' :
152+ netnl .rings_set ({'header' : {'dev-index' : cfg .ifindex },
153+ 'tcp-data-split' : 'unknown' })
154+
155+ _xdp_onoff (cfg )
156+
157+
158+ def enabled_set_xdp (cfg , netnl ) -> None :
159+ """
160+ Enable single-buffer XDP on the device.
161+ When HDS is in "enabled" mode, XDP installation should not work.
162+ """
163+ _get_hds_mode (cfg , netnl )
164+ netnl .rings_set ({'header' : {'dev-index' : cfg .ifindex },
165+ 'tcp-data-split' : 'enabled' })
166+
167+ defer (netnl .rings_set , {'header' : {'dev-index' : cfg .ifindex },
168+ 'tcp-data-split' : 'unknown' })
169+
170+ with ksft_raises (CmdExitFailure ) as e :
171+ _xdp_onoff (cfg )
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 ) # Trigger skip if not supported
193+
194+ netnl .rings_set ({'header' : {'dev-index' : cfg .ifindex },
195+ 'tcp-data-split' : 'enabled' })
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 ioctl (cfg , netnl ) -> None :
204+ mode1 = _get_hds_mode (cfg , netnl )
205+ _ioctl_ringparam_modify (cfg , netnl )
206+ mode2 = _get_hds_mode (cfg , netnl )
207+
208+ ksft_eq (mode1 , mode2 )
209+
210+
211+ def ioctl_set_xdp (cfg , netnl ) -> None :
212+ """
213+ Like set_xdp(), but we perturb the settings via the legacy ioctl.
214+ """
215+ mode = _get_hds_mode (cfg , netnl )
216+ if mode == 'enabled' :
217+ netnl .rings_set ({'header' : {'dev-index' : cfg .ifindex },
218+ 'tcp-data-split' : 'unknown' })
219+
220+ _ioctl_ringparam_modify (cfg , netnl )
221+
222+ _xdp_onoff (cfg )
223+
224+
225+ def ioctl_enabled_set_xdp (cfg , netnl ) -> None :
226+ """
227+ Enable single-buffer XDP on the device.
228+ When HDS is in "enabled" mode, XDP installation should not work.
229+ """
230+ _get_hds_mode (cfg , netnl ) # Trigger skip if not supported
231+
232+ netnl .rings_set ({'header' : {'dev-index' : cfg .ifindex },
233+ 'tcp-data-split' : 'enabled' })
234+ defer (netnl .rings_set , {'header' : {'dev-index' : cfg .ifindex },
235+ 'tcp-data-split' : 'unknown' })
236+
237+ with ksft_raises (CmdExitFailure ) as e :
238+ _xdp_onoff (cfg )
239+
240+
107241def main () -> None :
108242 with NetDrvEnv (__file__ , queue_count = 3 ) as cfg :
109243 ksft_run ([get_hds ,
@@ -112,7 +246,12 @@ def main() -> None:
112246 set_hds_enable ,
113247 set_hds_thresh_zero ,
114248 set_hds_thresh_max ,
115- set_hds_thresh_gt ],
249+ set_hds_thresh_gt ,
250+ set_xdp ,
251+ enabled_set_xdp ,
252+ ioctl ,
253+ ioctl_set_xdp ,
254+ ioctl_enabled_set_xdp ],
116255 args = (cfg , EthtoolFamily ()))
117256 ksft_exit ()
118257
0 commit comments