Path: blob/master/tools/testing/selftests/drivers/net/hds.py
26288 views
#!/usr/bin/env python31# SPDX-License-Identifier: GPL-2.023import errno4import os5from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_raises, KsftSkipEx6from lib.py import CmdExitFailure, EthtoolFamily, NlError7from lib.py import NetDrvEnv8from lib.py import defer, ethtool, ip, random91011def _get_hds_mode(cfg, netnl) -> str:12try:13rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})14except NlError as e:15raise KsftSkipEx('ring-get not supported by device')16if 'tcp-data-split' not in rings:17raise KsftSkipEx('tcp-data-split not supported by device')18return rings['tcp-data-split']192021def _xdp_onoff(cfg):22prog = cfg.net_lib_dir / "xdp_dummy.bpf.o"23ip("link set dev %s xdp obj %s sec xdp" %24(cfg.ifname, prog))25ip("link set dev %s xdp off" % cfg.ifname)262728def _ioctl_ringparam_modify(cfg, netnl) -> None:29"""30Helper for performing a hopefully unimportant IOCTL SET.31IOCTL does not support HDS, so it should not affect the HDS config.32"""33try:34rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})35except NlError as e:36raise KsftSkipEx('ring-get not supported by device')3738if 'tx' not in rings:39raise KsftSkipEx('setting Tx ring size not supported')4041try:42ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] // 2}")43except CmdExitFailure as e:44ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] * 2}")45defer(ethtool, f"-G {cfg.ifname} tx {rings['tx']}")464748def get_hds(cfg, netnl) -> None:49_get_hds_mode(cfg, netnl)505152def get_hds_thresh(cfg, netnl) -> None:53try:54rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})55except NlError as e:56raise KsftSkipEx('ring-get not supported by device')57if 'hds-thresh' not in rings:58raise KsftSkipEx('hds-thresh not supported by device')5960def set_hds_enable(cfg, netnl) -> None:61try:62netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'enabled'})63except NlError as e:64if e.error == errno.EINVAL:65raise KsftSkipEx("disabling of HDS not supported by the device")66elif e.error == errno.EOPNOTSUPP:67raise KsftSkipEx("ring-set not supported by the device")68try:69rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})70except NlError as e:71raise KsftSkipEx('ring-get not supported by device')72if 'tcp-data-split' not in rings:73raise KsftSkipEx('tcp-data-split not supported by device')7475ksft_eq('enabled', rings['tcp-data-split'])7677def set_hds_disable(cfg, netnl) -> None:78try:79netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'disabled'})80except NlError as e:81if e.error == errno.EINVAL:82raise KsftSkipEx("disabling of HDS not supported by the device")83elif e.error == errno.EOPNOTSUPP:84raise KsftSkipEx("ring-set not supported by the device")85try:86rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})87except NlError as e:88raise KsftSkipEx('ring-get not supported by device')89if 'tcp-data-split' not in rings:90raise KsftSkipEx('tcp-data-split not supported by device')9192ksft_eq('disabled', rings['tcp-data-split'])9394def set_hds_thresh_zero(cfg, netnl) -> None:95try:96netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': 0})97except NlError as e:98if e.error == errno.EINVAL:99raise KsftSkipEx("hds-thresh-set not supported by the device")100elif e.error == errno.EOPNOTSUPP:101raise KsftSkipEx("ring-set not supported by the device")102try:103rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})104except NlError as e:105raise KsftSkipEx('ring-get not supported by device')106if 'hds-thresh' not in rings:107raise KsftSkipEx('hds-thresh not supported by device')108109ksft_eq(0, rings['hds-thresh'])110111def set_hds_thresh_random(cfg, netnl) -> None:112try:113rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})114except NlError as e:115raise KsftSkipEx('ring-get not supported by device')116if 'hds-thresh' not in rings:117raise KsftSkipEx('hds-thresh not supported by device')118if 'hds-thresh-max' not in rings:119raise KsftSkipEx('hds-thresh-max not defined by device')120121if rings['hds-thresh-max'] < 2:122raise KsftSkipEx('hds-thresh-max is too small')123elif rings['hds-thresh-max'] == 2:124hds_thresh = 1125else:126while True:127hds_thresh = random.randint(1, rings['hds-thresh-max'] - 1)128if hds_thresh != rings['hds-thresh']:129break130131try:132netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_thresh})133except NlError as e:134if e.error == errno.EINVAL:135raise KsftSkipEx("hds-thresh-set not supported by the device")136elif e.error == errno.EOPNOTSUPP:137raise KsftSkipEx("ring-set not supported by the device")138rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})139ksft_eq(hds_thresh, rings['hds-thresh'])140141def set_hds_thresh_max(cfg, netnl) -> None:142try:143rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})144except NlError as e:145raise KsftSkipEx('ring-get not supported by device')146if 'hds-thresh' not in rings:147raise KsftSkipEx('hds-thresh not supported by device')148try:149netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': rings['hds-thresh-max']})150except NlError as e:151if e.error == errno.EINVAL:152raise KsftSkipEx("hds-thresh-set not supported by the device")153elif e.error == errno.EOPNOTSUPP:154raise KsftSkipEx("ring-set not supported by the device")155rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})156ksft_eq(rings['hds-thresh'], rings['hds-thresh-max'])157158def set_hds_thresh_gt(cfg, netnl) -> None:159try:160rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})161except NlError as e:162raise KsftSkipEx('ring-get not supported by device')163if 'hds-thresh' not in rings:164raise KsftSkipEx('hds-thresh not supported by device')165if 'hds-thresh-max' not in rings:166raise KsftSkipEx('hds-thresh-max not defined by device')167hds_gt = rings['hds-thresh-max'] + 1168with ksft_raises(NlError) as e:169netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_gt})170ksft_eq(e.exception.nl_msg.error, -errno.EINVAL)171172173def set_xdp(cfg, netnl) -> None:174"""175Enable single-buffer XDP on the device.176When HDS is in "auto" / UNKNOWN mode, XDP installation should work.177"""178mode = _get_hds_mode(cfg, netnl)179if mode == 'enabled':180netnl.rings_set({'header': {'dev-index': cfg.ifindex},181'tcp-data-split': 'unknown'})182183_xdp_onoff(cfg)184185186def enabled_set_xdp(cfg, netnl) -> None:187"""188Enable single-buffer XDP on the device.189When HDS is in "enabled" mode, XDP installation should not work.190"""191_get_hds_mode(cfg, netnl)192netnl.rings_set({'header': {'dev-index': cfg.ifindex},193'tcp-data-split': 'enabled'})194195defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},196'tcp-data-split': 'unknown'})197198with ksft_raises(CmdExitFailure) as e:199_xdp_onoff(cfg)200201202def set_xdp(cfg, netnl) -> None:203"""204Enable single-buffer XDP on the device.205When HDS is in "auto" / UNKNOWN mode, XDP installation should work.206"""207mode = _get_hds_mode(cfg, netnl)208if mode == 'enabled':209netnl.rings_set({'header': {'dev-index': cfg.ifindex},210'tcp-data-split': 'unknown'})211212_xdp_onoff(cfg)213214215def enabled_set_xdp(cfg, netnl) -> None:216"""217Enable single-buffer XDP on the device.218When HDS is in "enabled" mode, XDP installation should not work.219"""220_get_hds_mode(cfg, netnl) # Trigger skip if not supported221222netnl.rings_set({'header': {'dev-index': cfg.ifindex},223'tcp-data-split': 'enabled'})224defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},225'tcp-data-split': 'unknown'})226227with ksft_raises(CmdExitFailure) as e:228_xdp_onoff(cfg)229230231def ioctl(cfg, netnl) -> None:232mode1 = _get_hds_mode(cfg, netnl)233_ioctl_ringparam_modify(cfg, netnl)234mode2 = _get_hds_mode(cfg, netnl)235236ksft_eq(mode1, mode2)237238239def ioctl_set_xdp(cfg, netnl) -> None:240"""241Like set_xdp(), but we perturb the settings via the legacy ioctl.242"""243mode = _get_hds_mode(cfg, netnl)244if mode == 'enabled':245netnl.rings_set({'header': {'dev-index': cfg.ifindex},246'tcp-data-split': 'unknown'})247248_ioctl_ringparam_modify(cfg, netnl)249250_xdp_onoff(cfg)251252253def ioctl_enabled_set_xdp(cfg, netnl) -> None:254"""255Enable single-buffer XDP on the device.256When HDS is in "enabled" mode, XDP installation should not work.257"""258_get_hds_mode(cfg, netnl) # Trigger skip if not supported259260netnl.rings_set({'header': {'dev-index': cfg.ifindex},261'tcp-data-split': 'enabled'})262defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},263'tcp-data-split': 'unknown'})264265with ksft_raises(CmdExitFailure) as e:266_xdp_onoff(cfg)267268269def main() -> None:270with NetDrvEnv(__file__, queue_count=3) as cfg:271ksft_run([get_hds,272get_hds_thresh,273set_hds_disable,274set_hds_enable,275set_hds_thresh_random,276set_hds_thresh_zero,277set_hds_thresh_max,278set_hds_thresh_gt,279set_xdp,280enabled_set_xdp,281ioctl,282ioctl_set_xdp,283ioctl_enabled_set_xdp],284args=(cfg, EthtoolFamily()))285ksft_exit()286287if __name__ == "__main__":288main()289290291