1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3 4import errno 5import os 6from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_raises, KsftSkipEx 7from lib.py import CmdExitFailure, EthtoolFamily, NlError 8from lib.py import NetDrvEnv 9from lib.py import defer, ethtool, ip 10 11 12def _get_hds_mode(cfg, netnl) -> str: 13 try: 14 rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}}) 15 except NlError as e: 16 raise KsftSkipEx('ring-get not supported by device') 17 if 'tcp-data-split' not in rings: 18 raise KsftSkipEx('tcp-data-split not supported by device') 19 return rings['tcp-data-split'] 20 21 22def _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 30def _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 50def get_hds(cfg, netnl) -> None: 51 _get_hds_mode(cfg, netnl) 52 53 54def 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 62def set_hds_enable(cfg, netnl) -> None: 63 try: 64 netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'enabled'}) 65 except NlError as e: 66 if e.error == errno.EINVAL: 67 raise KsftSkipEx("disabling of HDS not supported by the device") 68 elif e.error == errno.EOPNOTSUPP: 69 raise KsftSkipEx("ring-set not supported by the device") 70 try: 71 rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}}) 72 except NlError as e: 73 raise KsftSkipEx('ring-get not supported by device') 74 if 'tcp-data-split' not in rings: 75 raise KsftSkipEx('tcp-data-split not supported by device') 76 77 ksft_eq('enabled', rings['tcp-data-split']) 78 79def set_hds_disable(cfg, netnl) -> None: 80 try: 81 netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'disabled'}) 82 except NlError as e: 83 if e.error == errno.EINVAL: 84 raise KsftSkipEx("disabling of HDS not supported by the device") 85 elif e.error == errno.EOPNOTSUPP: 86 raise KsftSkipEx("ring-set not supported by the device") 87 try: 88 rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}}) 89 except NlError as e: 90 raise KsftSkipEx('ring-get not supported by device') 91 if 'tcp-data-split' not in rings: 92 raise KsftSkipEx('tcp-data-split not supported by device') 93 94 ksft_eq('disabled', rings['tcp-data-split']) 95 96def set_hds_thresh_zero(cfg, netnl) -> None: 97 try: 98 netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': 0}) 99 except NlError as e: 100 if e.error == errno.EINVAL: 101 raise KsftSkipEx("hds-thresh-set not supported by the device") 102 elif e.error == errno.EOPNOTSUPP: 103 raise KsftSkipEx("ring-set not supported by the device") 104 try: 105 rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}}) 106 except NlError as e: 107 raise KsftSkipEx('ring-get not supported by device') 108 if 'hds-thresh' not in rings: 109 raise KsftSkipEx('hds-thresh not supported by device') 110 111 ksft_eq(0, rings['hds-thresh']) 112 113def set_hds_thresh_max(cfg, netnl) -> None: 114 try: 115 rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}}) 116 except NlError as e: 117 raise KsftSkipEx('ring-get not supported by device') 118 if 'hds-thresh' not in rings: 119 raise KsftSkipEx('hds-thresh not supported by device') 120 try: 121 netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': rings['hds-thresh-max']}) 122 except NlError as e: 123 if e.error == errno.EINVAL: 124 raise KsftSkipEx("hds-thresh-set not supported by the device") 125 elif e.error == errno.EOPNOTSUPP: 126 raise KsftSkipEx("ring-set not supported by the device") 127 rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}}) 128 ksft_eq(rings['hds-thresh'], rings['hds-thresh-max']) 129 130def set_hds_thresh_gt(cfg, netnl) -> None: 131 try: 132 rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}}) 133 except NlError as e: 134 raise KsftSkipEx('ring-get not supported by device') 135 if 'hds-thresh' not in rings: 136 raise KsftSkipEx('hds-thresh not supported by device') 137 if 'hds-thresh-max' not in rings: 138 raise KsftSkipEx('hds-thresh-max not defined by device') 139 hds_gt = rings['hds-thresh-max'] + 1 140 with ksft_raises(NlError) as e: 141 netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_gt}) 142 ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) 143 144 145def 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 158def 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 174def 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 187def 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 203def 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 211def 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 225def 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 241def main() -> None: 242 with NetDrvEnv(__file__, queue_count=3) as cfg: 243 ksft_run([get_hds, 244 get_hds_thresh, 245 set_hds_disable, 246 set_hds_enable, 247 set_hds_thresh_zero, 248 set_hds_thresh_max, 249 set_hds_thresh_gt, 250 set_xdp, 251 enabled_set_xdp, 252 ioctl, 253 ioctl_set_xdp, 254 ioctl_enabled_set_xdp], 255 args=(cfg, EthtoolFamily())) 256 ksft_exit() 257 258if __name__ == "__main__": 259 main() 260