Commit d3b35898 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

selftests: drv-net: gro: run the test against HW GRO and LRO



Run the test against HW GRO and LRO. NICs I have pass the base cases.
Interestingly all are happy to build GROs larger than 64k.

Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260113000740.255360-6-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 8171f6a7
Loading
Loading
Loading
Loading
+55 −17
Original line number Diff line number Diff line
@@ -87,11 +87,15 @@ def _set_ethtool_feat(dev, current, feats, host=None):
    if no_change:
        return

    ethtool(" ".join(new), host=host)
    eth_cmd = ethtool(" ".join(new), host=host)
    defer(ethtool, " ".join(old), host=host)

    # If ethtool printed something kernel must have modified some features
    if eth_cmd.stdout:
        ksft_pr(eth_cmd)

def _setup(cfg, test_name):

def _setup(cfg, mode, test_name):
    """ Setup hardware loopback mode for GRO testing. """

    if not hasattr(cfg, "bin_remote"):
@@ -108,6 +112,7 @@ def _setup(cfg, test_name):
        _set_mtu_restore(cfg.dev, 4096, None)
        _set_mtu_restore(cfg.remote_dev, 4096, cfg.remote)

    if mode == "sw":
        flush_path = f"/sys/class/net/{cfg.ifname}/gro_flush_timeout"
        irq_path = f"/sys/class/net/{cfg.ifname}/napi_defer_hard_irqs"

@@ -118,6 +123,38 @@ def _setup(cfg, test_name):
                          {"generic-receive-offload": True,
                           "rx-gro-hw": False,
                           "large-receive-offload": False})
    elif mode == "hw":
        _set_ethtool_feat(cfg.ifname, cfg.feat,
                          {"generic-receive-offload": False,
                           "rx-gro-hw": True,
                           "large-receive-offload": False})

        # Some NICs treat HW GRO as a GRO sub-feature so disabling GRO
        # will also clear HW GRO. Use a hack of installing XDP generic
        # to skip SW GRO, even when enabled.
        feat = ethtool(f"-k {cfg.ifname}", json=True)[0]
        if not feat["rx-gro-hw"]["active"]:
            ksft_pr("Driver clears HW GRO and SW GRO is cleared, using generic XDP workaround")
            prog = cfg.net_lib_dir / "xdp_dummy.bpf.o"
            ip(f"link set dev {cfg.ifname} xdpgeneric obj {prog} sec xdp")
            defer(ip, f"link set dev {cfg.ifname} xdpgeneric off")

            # Attaching XDP may change features, fetch the latest state
            feat = ethtool(f"-k {cfg.ifname}", json=True)[0]

            _set_ethtool_feat(cfg.ifname, feat,
                              {"generic-receive-offload": True,
                               "rx-gro-hw": True,
                               "large-receive-offload": False})
    elif mode == "lro":
        # netdevsim advertises LRO for feature inheritance testing with
        # bonding/team tests but it doesn't actually perform the offload
        cfg.require_nsim(nsim_test=False)

        _set_ethtool_feat(cfg.ifname, cfg.feat,
                          {"generic-receive-offload": False,
                           "rx-gro-hw": False,
                           "large-receive-offload": True})

    try:
        # Disable TSO for local tests
@@ -133,19 +170,20 @@ def _setup(cfg, test_name):
def _gro_variants():
    """Generator that yields all combinations of protocol and test types."""

    for mode in ["sw", "hw", "lro"]:
        for protocol in ["ipv4", "ipv6", "ipip"]:
            for test_name in ["data", "ack", "flags", "tcp", "ip", "large"]:
            yield protocol, test_name
                yield mode, protocol, test_name


@ksft_variants(_gro_variants())
def test(cfg, protocol, test_name):
def test(cfg, mode, protocol, test_name):
    """Run a single GRO test with retries."""

    ipver = "6" if protocol[-1] == "6" else "4"
    cfg.require_ipver(ipver)

    _setup(cfg, test_name)
    _setup(cfg, mode, test_name)

    base_cmd_args = [
        f"--{protocol}",
+5 −2
Original line number Diff line number Diff line
@@ -248,9 +248,12 @@ class NetDrvEpEnv(NetDrvEnvBase):
        if not self.addr_v[ipver] or not self.remote_addr_v[ipver]:
            raise KsftSkipEx(f"Test requires IPv{ipver} connectivity")

    def require_nsim(self):
        if self._ns is None:
    def require_nsim(self, nsim_test=True):
        """Require or exclude netdevsim for this test"""
        if nsim_test and self._ns is None:
            raise KsftXfailEx("Test only works on netdevsim")
        if nsim_test is False and self._ns is not None:
            raise KsftXfailEx("Test does not work on netdevsim")

    def _require_cmd(self, comm, key, host=None):
        cached = self._required_cmd.get(comm, {})