Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,222 @@
# SPDX-License-Identifier: GPL-2.0
"""Shared helpers for devmem TCP selftests."""
import re
from lib.py import (bkg, cmd, defer, ethtool, rand_port, wait_port_listen,
ksft_eq, KsftSkipEx, NetNSEnter, EthtoolFamily,
NetdevFamily)
def require_devmem(cfg):
"""Probe ncdevmem on cfg.ifname and SKIP the test if devmem isn't supported."""
if not hasattr(cfg, "devmem_probed"):
probe_command = f"{cfg.bin_local} -f {cfg.ifname}"
cfg.devmem_supported = cmd(probe_command, fail=False, shell=True).ret == 0
cfg.devmem_probed = True
if not cfg.devmem_supported:
raise KsftSkipEx("Test requires devmem support")
def configure_nic(cfg):
"""Channels, rings, RSS, queue lease for netkit devmem."""
if not hasattr(cfg, 'netns'):
return
cfg.require_ipver('6')
ethnl = EthtoolFamily()
channels = ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
channels = channels['combined-count']
if channels < 2:
raise KsftSkipEx(
'Test requires NETIF with at least 2 combined channels'
)
rings = ethnl.rings_get({'header': {'dev-index': cfg.ifindex}})
orig_rx_rings = rings['rx']
orig_hds_thresh = rings.get('hds-thresh', 0)
orig_data_split = rings.get('tcp-data-split', 'unknown')
ethnl.rings_set({'header': {'dev-index': cfg.ifindex},
'tcp-data-split': 'enabled',
'hds-thresh': 0,
'rx': min(64, orig_rx_rings)})
defer(ethnl.rings_set, {'header': {'dev-index': cfg.ifindex},
'tcp-data-split': orig_data_split,
'hds-thresh': orig_hds_thresh,
'rx': orig_rx_rings})
cfg.src_queue = channels - 1
ethtool(f"-X {cfg.ifname} equal {cfg.src_queue}")
defer(ethtool, f"-X {cfg.ifname} default")
if not hasattr(cfg, 'nk_queue'):
with NetNSEnter(str(cfg.netns)):
netdevnl = NetdevFamily()
lease_result = netdevnl.queue_create({
"ifindex": cfg.nk_guest_ifindex,
"type": "rx",
"lease": {
"ifindex": cfg.ifindex,
"queue": {"id": cfg.src_queue, "type": "rx"},
"netns-id": 0,
},
})
cfg.nk_queue = lease_result['id']
def set_flow_rule(cfg, port):
"""Install a flow rule steering to src_queue and return the flow rule ID."""
output = ethtool(
f"-N {cfg.ifname} flow-type tcp6 dst-port {port}"
f" action {cfg.src_queue}"
).stdout
return int(re.search(r'ID (\d+)', output).group(1))
def ncdevmem_rx(cfg, port, verify=True, fail_on_linear=False, flow_steer=False):
"""Build the ncdevmem RX listener command."""
if hasattr(cfg, 'netns'):
flow_rule_id = set_flow_rule(cfg, port)
defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
ifname = cfg.nk_guest_ifname
addr = cfg.nk_guest_ipv6
extras = [f"-t {cfg.nk_queue}", "-q 1", "-n"]
else:
ifname = cfg.ifname
addr = cfg.addr
extras = []
if flow_steer:
extras.append(f"-c {cfg.remote_addr}")
if verify:
extras.append("-v 7")
if fail_on_linear:
extras.append("-L")
parts = [cfg.bin_local, "-l", f"-f {ifname}", f"-s {addr}",
f"-p {port}", *extras]
return " ".join(parts)
def ncdevmem_tx(cfg, port, chunk_size=0):
"""Build the ncdevmem TX send command."""
if hasattr(cfg, 'netns'):
ifname = cfg.nk_guest_ifname
addr = cfg.remote_addr_v['6']
extras = ["-t 0", "-q 1", "-n"]
else:
ifname = cfg.ifname
addr = cfg.remote_addr
extras = []
if chunk_size:
extras.append(f"-z {chunk_size}")
parts = [cfg.bin_local, f"-f {ifname}", f"-s {addr}",
f"-p {port}", *extras]
return " ".join(parts)
def socat_send(cfg, port, buf_size=0):
"""Socat command for sending to the devmem listener.
When buf_size > 0, force one TCP segment per write of exactly that size by
setting socat's buffer (-b) and disabling Nagle (TCP_NODELAY).
"""
proto = f"TCP{cfg.addr_ipver}"
if hasattr(cfg, 'netns'):
addr = f"[{cfg.nk_guest_ipv6}]"
else:
addr = cfg.baddr
suffix = f",bind={cfg.remote_baddr}:{port}"
buf = ""
if buf_size:
buf = f"-b {buf_size}"
suffix += ",nodelay"
return f"socat {buf} -u - {proto}:{addr}:{port}{suffix}"
def socat_listen(cfg, port):
"""Socat listen command for TX tests."""
return f"socat -U - TCP{cfg.addr_ipver}-LISTEN:{port}"
def setup_test(cfg, bin_local):
"""Stash the local ncdevmem path on cfg and deploy it to the remote."""
cfg.bin_local = bin_local
cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)
def run_rx(cfg):
"""Run the devmem RX test."""
require_devmem(cfg)
configure_nic(cfg)
port = rand_port()
socat = socat_send(cfg, port)
data_pipe = (f"yes $(echo -e \x01\x02\x03\x04\x05\x06) | head -c 1K"
f" | {socat}")
netns = getattr(cfg, "netns", None)
listen_cmd = ncdevmem_rx(cfg, port, flow_steer=not hasattr(cfg, 'netns'))
with bkg(listen_cmd, exit_wait=True, ns=netns) as ncdevmem:
wait_port_listen(port, proto="tcp", ns=netns)
cmd(data_pipe, host=cfg.remote, shell=True)
ksft_eq(ncdevmem.ret, 0)
def run_tx(cfg):
"""Run the devmem TX test."""
require_devmem(cfg)
configure_nic(cfg)
netns = getattr(cfg, "netns", None)
port = rand_port()
tx_cmd = ncdevmem_tx(cfg, port)
listen_cmd = socat_listen(cfg, port)
with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as socat:
wait_port_listen(port, host=cfg.remote)
cmd(f"bash -c 'echo -e \"hello\\nworld\" | {tx_cmd}'", ns=netns, shell=True)
ksft_eq(socat.stdout.strip(), "hello\nworld")
def run_tx_chunks(cfg):
"""Run the devmem TX chunking test."""
require_devmem(cfg)
configure_nic(cfg)
netns = getattr(cfg, "netns", None)
port = rand_port()
tx_cmd = ncdevmem_tx(cfg, port, chunk_size=3)
listen_cmd = socat_listen(cfg, port)
with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as socat:
wait_port_listen(port, host=cfg.remote)
cmd(f"bash -c 'echo -e \"hello\\nworld\" | {tx_cmd}'", ns=netns, shell=True)
ksft_eq(socat.stdout.strip(), "hello\nworld")
def run_rx_hds(cfg):
"""Run the HDS test by running devmem RX across a segment size sweep."""
require_devmem(cfg)
configure_nic(cfg)
netns = getattr(cfg, "netns", None)
for size in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]:
port = rand_port()
listen_cmd = ncdevmem_rx(cfg, port, verify=False,
fail_on_linear=True)
socat = socat_send(cfg, port, buf_size=size)
with bkg(listen_cmd, exit_wait=True, ns=netns) as ncdevmem:
wait_port_listen(port, proto="tcp", ns=netns)
cmd(f"dd if=/dev/zero bs={size} count=1 2>/dev/null | "
f"{socat}", host=cfg.remote, shell=True)
ksft_eq(ncdevmem.ret, 0, f"HDS failed for payload size {size}")