Path: blob/master/tools/testing/selftests/drivers/net/hds.py
29270 views
#!/usr/bin/env python31# SPDX-License-Identifier: GPL-2.023import errno4import os5from typing import Union6from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_raises, KsftSkipEx7from lib.py import CmdExitFailure, EthtoolFamily, NlError8from lib.py import NetDrvEnv9from lib.py import defer, ethtool, ip, random101112def _get_hds_mode(cfg, netnl) -> str:13try:14rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})15except NlError as e:16raise KsftSkipEx('ring-get not supported by device')17if 'tcp-data-split' not in rings:18raise KsftSkipEx('tcp-data-split not supported by device')19return rings['tcp-data-split']202122def _xdp_onoff(cfg):23prog = cfg.net_lib_dir / "xdp_dummy.bpf.o"24ip("link set dev %s xdp obj %s sec xdp" %25(cfg.ifname, prog))26ip("link set dev %s xdp off" % cfg.ifname)272829def _ioctl_ringparam_modify(cfg, netnl) -> None:30"""31Helper for performing a hopefully unimportant IOCTL SET.32IOCTL does not support HDS, so it should not affect the HDS config.33"""34try:35rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})36except NlError as e:37raise KsftSkipEx('ring-get not supported by device')3839if 'tx' not in rings:40raise KsftSkipEx('setting Tx ring size not supported')4142try:43ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] // 2}")44except CmdExitFailure as e:45ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] * 2}")46defer(ethtool, f"-G {cfg.ifname} tx {rings['tx']}")474849def get_hds(cfg, netnl) -> None:50_get_hds_mode(cfg, netnl)515253def get_hds_thresh(cfg, netnl) -> None:54try:55rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})56except NlError as e:57raise KsftSkipEx('ring-get not supported by device')58if 'hds-thresh' not in rings:59raise KsftSkipEx('hds-thresh not supported by device')606162def _hds_reset(cfg, netnl, rings) -> None:63cur = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})6465arg = {'header': {'dev-index': cfg.ifindex}}66if cur.get('tcp-data-split') != rings.get('tcp-data-split'):67# Try to reset to "unknown" first, we don't know if the setting68# was the default or user chose it. Default seems more likely.69arg['tcp-data-split'] = "unknown"70netnl.rings_set(arg)71cur = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})72if cur['tcp-data-split'] == rings['tcp-data-split']:73del arg['tcp-data-split']74else:75# Try the explicit setting76arg['tcp-data-split'] = rings['tcp-data-split']77if cur.get('hds-thresh') != rings.get('hds-thresh'):78arg['hds-thresh'] = rings['hds-thresh']79if len(arg) > 1:80netnl.rings_set(arg)818283def _defer_reset_hds(cfg, netnl) -> Union[dict, None]:84try:85rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})86if 'hds-thresh' in rings or 'tcp-data-split' in rings:87defer(_hds_reset, cfg, netnl, rings)88except NlError as e:89pass909192def set_hds_enable(cfg, netnl) -> None:93_defer_reset_hds(cfg, netnl)94try:95netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'enabled'})96except NlError as e:97if e.error == errno.EINVAL:98raise KsftSkipEx("disabling of HDS not supported by the device")99elif e.error == errno.EOPNOTSUPP:100raise KsftSkipEx("ring-set not supported by the device")101try:102rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})103except NlError as e:104raise KsftSkipEx('ring-get not supported by device')105if 'tcp-data-split' not in rings:106raise KsftSkipEx('tcp-data-split not supported by device')107108ksft_eq('enabled', rings['tcp-data-split'])109110def set_hds_disable(cfg, netnl) -> None:111_defer_reset_hds(cfg, netnl)112try:113netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'tcp-data-split': 'disabled'})114except NlError as e:115if e.error == errno.EINVAL:116raise KsftSkipEx("disabling of HDS not supported by the device")117elif e.error == errno.EOPNOTSUPP:118raise KsftSkipEx("ring-set not supported by the device")119try:120rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})121except NlError as e:122raise KsftSkipEx('ring-get not supported by device')123if 'tcp-data-split' not in rings:124raise KsftSkipEx('tcp-data-split not supported by device')125126ksft_eq('disabled', rings['tcp-data-split'])127128def set_hds_thresh_zero(cfg, netnl) -> None:129_defer_reset_hds(cfg, netnl)130try:131netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': 0})132except NlError as e:133if e.error == errno.EINVAL:134raise KsftSkipEx("hds-thresh-set not supported by the device")135elif e.error == errno.EOPNOTSUPP:136raise KsftSkipEx("ring-set not supported by the device")137try:138rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})139except NlError as e:140raise KsftSkipEx('ring-get not supported by device')141if 'hds-thresh' not in rings:142raise KsftSkipEx('hds-thresh not supported by device')143144ksft_eq(0, rings['hds-thresh'])145146def set_hds_thresh_random(cfg, netnl) -> None:147_defer_reset_hds(cfg, netnl)148try:149rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})150except NlError as e:151raise KsftSkipEx('ring-get not supported by device')152if 'hds-thresh' not in rings:153raise KsftSkipEx('hds-thresh not supported by device')154if 'hds-thresh-max' not in rings:155raise KsftSkipEx('hds-thresh-max not defined by device')156157if rings['hds-thresh-max'] < 2:158raise KsftSkipEx('hds-thresh-max is too small')159elif rings['hds-thresh-max'] == 2:160hds_thresh = 1161else:162while True:163hds_thresh = random.randint(1, rings['hds-thresh-max'] - 1)164if hds_thresh != rings['hds-thresh']:165break166167try:168netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_thresh})169except NlError as e:170if e.error == errno.EINVAL:171raise KsftSkipEx("hds-thresh-set not supported by the device")172elif e.error == errno.EOPNOTSUPP:173raise KsftSkipEx("ring-set not supported by the device")174rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})175ksft_eq(hds_thresh, rings['hds-thresh'])176177def set_hds_thresh_max(cfg, netnl) -> None:178_defer_reset_hds(cfg, netnl)179try:180rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})181except NlError as e:182raise KsftSkipEx('ring-get not supported by device')183if 'hds-thresh' not in rings:184raise KsftSkipEx('hds-thresh not supported by device')185try:186netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': rings['hds-thresh-max']})187except NlError as e:188if e.error == errno.EINVAL:189raise KsftSkipEx("hds-thresh-set not supported by the device")190elif e.error == errno.EOPNOTSUPP:191raise KsftSkipEx("ring-set not supported by the device")192rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})193ksft_eq(rings['hds-thresh'], rings['hds-thresh-max'])194195def set_hds_thresh_gt(cfg, netnl) -> None:196_defer_reset_hds(cfg, netnl)197try:198rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})199except NlError as e:200raise KsftSkipEx('ring-get not supported by device')201if 'hds-thresh' not in rings:202raise KsftSkipEx('hds-thresh not supported by device')203if 'hds-thresh-max' not in rings:204raise KsftSkipEx('hds-thresh-max not defined by device')205hds_gt = rings['hds-thresh-max'] + 1206with ksft_raises(NlError) as e:207netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_gt})208ksft_eq(e.exception.nl_msg.error, -errno.EINVAL)209210211def set_xdp(cfg, netnl) -> None:212"""213Enable single-buffer XDP on the device.214When HDS is in "auto" / UNKNOWN mode, XDP installation should work.215"""216mode = _get_hds_mode(cfg, netnl)217if mode == 'enabled':218_defer_reset_hds(cfg, netnl)219netnl.rings_set({'header': {'dev-index': cfg.ifindex},220'tcp-data-split': 'unknown'})221222_xdp_onoff(cfg)223224225def enabled_set_xdp(cfg, netnl) -> None:226"""227Enable single-buffer XDP on the device.228When HDS is in "enabled" mode, XDP installation should not work.229"""230_get_hds_mode(cfg, netnl)231netnl.rings_set({'header': {'dev-index': cfg.ifindex},232'tcp-data-split': 'enabled'})233234defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},235'tcp-data-split': 'unknown'})236237with ksft_raises(CmdExitFailure) as e:238_xdp_onoff(cfg)239240241def set_xdp(cfg, netnl) -> None:242"""243Enable single-buffer XDP on the device.244When HDS is in "auto" / UNKNOWN mode, XDP installation should work.245"""246mode = _get_hds_mode(cfg, netnl)247if mode == 'enabled':248netnl.rings_set({'header': {'dev-index': cfg.ifindex},249'tcp-data-split': 'unknown'})250251_xdp_onoff(cfg)252253254def enabled_set_xdp(cfg, netnl) -> None:255"""256Enable single-buffer XDP on the device.257When HDS is in "enabled" mode, XDP installation should not work.258"""259_get_hds_mode(cfg, netnl) # Trigger skip if not supported260261netnl.rings_set({'header': {'dev-index': cfg.ifindex},262'tcp-data-split': 'enabled'})263defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},264'tcp-data-split': 'unknown'})265266with ksft_raises(CmdExitFailure) as e:267_xdp_onoff(cfg)268269270def ioctl(cfg, netnl) -> None:271mode1 = _get_hds_mode(cfg, netnl)272_ioctl_ringparam_modify(cfg, netnl)273mode2 = _get_hds_mode(cfg, netnl)274275ksft_eq(mode1, mode2)276277278def ioctl_set_xdp(cfg, netnl) -> None:279"""280Like set_xdp(), but we perturb the settings via the legacy ioctl.281"""282mode = _get_hds_mode(cfg, netnl)283if mode == 'enabled':284netnl.rings_set({'header': {'dev-index': cfg.ifindex},285'tcp-data-split': 'unknown'})286287_ioctl_ringparam_modify(cfg, netnl)288289_xdp_onoff(cfg)290291292def ioctl_enabled_set_xdp(cfg, netnl) -> None:293"""294Enable single-buffer XDP on the device.295When HDS is in "enabled" mode, XDP installation should not work.296"""297_get_hds_mode(cfg, netnl) # Trigger skip if not supported298299netnl.rings_set({'header': {'dev-index': cfg.ifindex},300'tcp-data-split': 'enabled'})301defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},302'tcp-data-split': 'unknown'})303304with ksft_raises(CmdExitFailure) as e:305_xdp_onoff(cfg)306307308def main() -> None:309with NetDrvEnv(__file__, queue_count=3) as cfg:310ksft_run([get_hds,311get_hds_thresh,312set_hds_disable,313set_hds_enable,314set_hds_thresh_random,315set_hds_thresh_zero,316set_hds_thresh_max,317set_hds_thresh_gt,318set_xdp,319enabled_set_xdp,320ioctl,321ioctl_set_xdp,322ioctl_enabled_set_xdp],323args=(cfg, EthtoolFamily()))324ksft_exit()325326if __name__ == "__main__":327main()328329330