xref: /linux/tools/testing/selftests/drivers/net/hw/iou-zcrx.py (revision a34b0e4e21d6be3c3d620aa7f9dfbf0e9550c19e)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3
4import re
5from os import path
6from lib.py import ksft_run, ksft_exit, KsftSkipEx, ksft_variants, KsftNamedVariant
7from lib.py import NetDrvEpEnv
8from lib.py import bkg, cmd, defer, ethtool, rand_port, wait_port_listen
9from lib.py import EthtoolFamily
10
11SKIP_CODE = 42
12
13def create_rss_ctx(cfg):
14    output = ethtool(f"-X {cfg.ifname} context new start {cfg.target} equal 1").stdout
15    values = re.search(r'New RSS context is (\d+)', output).group(1)
16    return int(values)
17
18
19def set_flow_rule(cfg):
20    output = ethtool(f"-N {cfg.ifname} flow-type tcp6 dst-port {cfg.port} action {cfg.target}").stdout
21    values = re.search(r'ID (\d+)', output).group(1)
22    return int(values)
23
24
25def set_flow_rule_rss(cfg, rss_ctx_id):
26    output = ethtool(f"-N {cfg.ifname} flow-type tcp6 dst-port {cfg.port} context {rss_ctx_id}").stdout
27    values = re.search(r'ID (\d+)', output).group(1)
28    return int(values)
29
30
31def single(cfg):
32    channels = cfg.ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
33    channels = channels['combined-count']
34    if channels < 2:
35        raise KsftSkipEx('Test requires NETIF with at least 2 combined channels')
36
37    rings = cfg.ethnl.rings_get({'header': {'dev-index': cfg.ifindex}})
38    rx_rings = rings['rx']
39    hds_thresh = rings.get('hds-thresh', 0)
40
41    cfg.ethnl.rings_set({'header': {'dev-index': cfg.ifindex},
42                         'tcp-data-split': 'enabled',
43                         'hds-thresh': 0,
44                         'rx': 64})
45    defer(cfg.ethnl.rings_set, {'header': {'dev-index': cfg.ifindex},
46                                'tcp-data-split': 'unknown',
47                                'hds-thresh': hds_thresh,
48                                'rx': rx_rings})
49
50    cfg.target = channels - 1
51    ethtool(f"-X {cfg.ifname} equal {cfg.target}")
52    defer(ethtool, f"-X {cfg.ifname} default")
53
54    flow_rule_id = set_flow_rule(cfg)
55    defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
56
57
58def rss(cfg):
59    channels = cfg.ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
60    channels = channels['combined-count']
61    if channels < 2:
62        raise KsftSkipEx('Test requires NETIF with at least 2 combined channels')
63
64    rings = cfg.ethnl.rings_get({'header': {'dev-index': cfg.ifindex}})
65    rx_rings = rings['rx']
66    hds_thresh = rings.get('hds-thresh', 0)
67
68    cfg.ethnl.rings_set({'header': {'dev-index': cfg.ifindex},
69                         'tcp-data-split': 'enabled',
70                         'hds-thresh': 0,
71                         'rx': 64})
72    defer(cfg.ethnl.rings_set, {'header': {'dev-index': cfg.ifindex},
73                                'tcp-data-split': 'unknown',
74                                'hds-thresh': hds_thresh,
75                                'rx': rx_rings})
76
77    cfg.target = channels - 1
78    ethtool(f"-X {cfg.ifname} equal {cfg.target}")
79    defer(ethtool, f"-X {cfg.ifname} default")
80
81    rss_ctx_id = create_rss_ctx(cfg)
82    defer(ethtool, f"-X {cfg.ifname} delete context {rss_ctx_id}")
83
84    flow_rule_id = set_flow_rule_rss(cfg, rss_ctx_id)
85    defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
86
87
88@ksft_variants([
89    KsftNamedVariant("single", single),
90    KsftNamedVariant("rss", rss),
91])
92def test_zcrx(cfg, setup) -> None:
93    cfg.require_ipver('6')
94
95    setup(cfg)
96    rx_cmd = f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} -q {cfg.target}"
97    tx_cmd = f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} -l 12840"
98    with bkg(rx_cmd, exit_wait=True):
99        wait_port_listen(cfg.port, proto="tcp")
100        cmd(tx_cmd, host=cfg.remote)
101
102
103@ksft_variants([
104    KsftNamedVariant("single", single),
105    KsftNamedVariant("rss", rss),
106])
107def test_zcrx_oneshot(cfg, setup) -> None:
108    cfg.require_ipver('6')
109
110    setup(cfg)
111    rx_cmd = f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} -q {cfg.target} -o 4"
112    tx_cmd = f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} -l 4096 -z 16384"
113    with bkg(rx_cmd, exit_wait=True):
114        wait_port_listen(cfg.port, proto="tcp")
115        cmd(tx_cmd, host=cfg.remote)
116
117
118def test_zcrx_large_chunks(cfg) -> None:
119    """Test zcrx with large buffer chunks."""
120
121    cfg.require_ipver('6')
122
123    combined_chans = _get_combined_channels(cfg)
124    if combined_chans < 2:
125        raise KsftSkipEx('at least 2 combined channels required')
126    (rx_ring, hds_thresh) = _get_current_settings(cfg)
127    port = rand_port()
128
129    ethtool(f"-G {cfg.ifname} tcp-data-split on")
130    defer(ethtool, f"-G {cfg.ifname} tcp-data-split auto")
131
132    ethtool(f"-G {cfg.ifname} hds-thresh 0")
133    defer(ethtool, f"-G {cfg.ifname} hds-thresh {hds_thresh}")
134
135    ethtool(f"-G {cfg.ifname} rx 64")
136    defer(ethtool, f"-G {cfg.ifname} rx {rx_ring}")
137
138    ethtool(f"-X {cfg.ifname} equal {combined_chans - 1}")
139    defer(ethtool, f"-X {cfg.ifname} default")
140
141    flow_rule_id = _set_flow_rule(cfg, port, combined_chans - 1)
142    defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
143
144    rx_cmd = f"{cfg.bin_local} -s -p {port} -i {cfg.ifname} -q {combined_chans - 1} -x 2"
145    tx_cmd = f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {port} -l 12840"
146
147    probe = cmd(rx_cmd + " -d", fail=False)
148    if probe.ret == SKIP_CODE:
149        raise KsftSkipEx(probe.stdout)
150
151    with bkg(rx_cmd, exit_wait=True):
152        wait_port_listen(port, proto="tcp")
153        cmd(tx_cmd, host=cfg.remote)
154
155
156def main() -> None:
157    with NetDrvEpEnv(__file__) as cfg:
158        cfg.bin_local = path.abspath(path.dirname(__file__) + "/../../../drivers/net/hw/iou-zcrx")
159        cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)
160
161        cfg.ethnl = EthtoolFamily()
162        cfg.port = rand_port()
163        ksft_run(globs=globals(), cases=[test_zcrx, test_zcrx_oneshot], args=(cfg, ))
164    ksft_exit()
165
166
167if __name__ == "__main__":
168    main()
169