mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
To: netdev-bot+sashiko@kernel.org
Cc: andrew@lunn.ch, kuba@kernel.org, davem@davemloft.net,
	edumazet@google.com, pabeni@redhat.com, horms@kernel.org,
	linux@armlinux.org.uk, hkallweit1@gmail.com, corbet@lwn.net,
	skhan@linuxfoundation.org, o.rempel@pengutronix.de,
	vladimir.oltean@nxp.com, f.fainelli@gmail.com,
	thomas.petazzoni@bootlin.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org
Subject: Re: [PATCH net-next v2 1/3] selftests: drv-net: Introduce a selftest for ethtool flow control
Date: Tue, 13 Oct 2026 11:04:57 +0200	[thread overview]
Message-ID: <f06aba7f-0e5f-4c9e-b53a-b5b817b3e6c6@bootlin.com> (raw)
In-Reply-To: <179065239849.434549.14198730559380952270@kernel.org>



On 9/29/26 05:26, netdev-bot+sashiko@kernel.org wrote:

>> +def get_local_pause_supported(cfg):
>> +    """ Return the errcode and the local pause supported linkmodes """
>> +
>> +    ret, data = ethtool_ret(f"{cfg.ifname}")
>> +    if ret != 0:
>> +        raise KsftFailEx(f"ethtool {cfg.ifname} failed: {ret}")
>> +
>> +    return ret, _ethtool_pause_use_to_linkmodes(data["supported-pause-frame-use"])
> 
> [Severity: Low]
> What happens here on a device without get_link_ksettings?
> 
> ethtool only prints "supported-pause-frame-use", "advertised-pause-frame-use",
> "auto-negotiation" and "supports-auto-negotiation" when the link modes reply
> succeeds. Plain "ethtool <dev>" still exits 0 when other replies, such as
> link-detected, are present.
> 
> In that case this line raises an uncaught KeyError. ksft_run() reports that
> as a failure with a traceback, not as a skip.
> 
> require_pause_supported_allof() calls this function before any capability
> check. pause_setup() also indexes link["auto-negotiation"] and
> link["supports-auto-negotiation"] directly, for both the local and the
> remote interface.
> 
> Speed and duplex are already guarded with "in" checks. Could these keys be
> guarded the same way?

There are a few of these drivers, will address.

> 
> [ ... ]
> 

> 
>> +def pause_setup(cfg):
>> +    """ The starting conditions every test counts on, restored on exit:
>> +        - both ports admin up
>> +        - link autoneg on on both sides ifsupported
>> +        - link actually up (carrier on)
>> +    """
>> +
>> +    # Get init pause parameters
>> +    ret, params = ethtool_ret(f"-a {cfg.ifname}")
>> +    if ret == 0:
>> +        defer(cmd, f"ethtool -A {cfg.ifname} rx {onoff(params['rx'])} "
>> +                   f"tx {onoff(params['tx'])} "
>> +                   f"autoneg {onoff(params['autonegotiate'])}")
>> +
>> +    # Get init link parameters
>> +    link = ethtool(f"{cfg.ifname}", json=True)[0]
>> +    if link["auto-negotiation"]:
>> +        defer(cmd, f"ethtool -s {cfg.ifname} autoneg on")
> 
> [Severity: Medium]
> The defer queue is LIFO (ksft_flush_defer() pops from the end), so at
> teardown the link restore runs first. The pause restore follows right
> after it, with no wait for autoneg to complete.
> 
> Can the pause restore be refused in that window? i40e ties pause autoneg
> to the link autoneg state:
That's a i40e driver issue :) The tests aren't build around the HW behaviour.

> 
>> +    elif "speed" in link and "duplex" in link:
>> +        defer(cmd, f"ethtool -s {cfg.ifname} autoneg off speed {link['speed']} "
>> +                   f"duplex {link['duplex'].lower()}")
>> +
>> +    # Local interface admin up, link aneg on
>> +    ip(f"link set {cfg.ifname} up")
>> +    if link["supports-auto-negotiation"] and not link["auto-negotiation"]:
>> +        ethtool(f"-s {cfg.ifname} autoneg on")
> 
> [Severity: Medium]
> Is the original forced link configuration lost if autoneg is off but speed
> or duplex is missing from the JSON?
> 
> In that case no defer is registered, but "ethtool -s <if> autoneg on" still
> runs.
> 
> The patch already expects both keys can be missing. forced_link_settings()
> falls back when duplex is missing. Speed is omitted when unknown, for
> example while the port is admin down, and this function only brings the
> port up after reading the settings.
> 
> The remote side below has the same if/elif with no fallback before
> "ethtool -s <remote_ifname> autoneg on". That can leave a shared peer in
> autoneg mode after the test exits.

Ok I'll add a restore step here

> 
> [ ... ]
> 
>> +def pause_test_support(cfg, pauseparams):
>> +    """ Verify that the supported linkmodes Pause and Asym_Pause match the
>> +        ability to configure the rx and tx pauseparams.
> 
> [ ... ]
> 
>> +    The expectation is for drivers to refuse setting pauseparams that don't
>> +    match the Pause and Asym_Pause bits in the supported linkmodes with a
>> +    -EOPNOTSUPP return value. Unsupported pause params must be rejected.
> 
> [Severity: Low]
> This isn't a bug, but expect_pauseparams_set() also accepts EINVAL for
> unsupported combinations:
> 
>     ksft_in(ret, (errno.EOPNOTSUPP, errno.EINVAL), note)
> 
> phylink_ethtool_set_pauseparam() also returns -EINVAL for rx != tx when
> Asym_Pause is not supported. Should the docstring mention EINVAL too?

Docstrings are gonna be shrunk down as pylint says the file's too big... I'll
update.

> 
> [ ... ]
> 
>> +    # We check that what we can configure in the pause params matches what we
>> +    # support under various contditions : Link aneg on/off, pause aneg on/off
>> +    ret, _ = ethtool_ret(f"-s {cfg.ifname} autoneg on", is_get = False)
>> +    if ret != 0:
>> +        ksft_pr("link autoneg on refused, not tested")
>> +    else:
> 
> [ ... ]
> 
>> +    if not forced:
>> +        ksft_pr("link speed unknown, the forced link is not tested")
>> +        return
>> +
>> +    ret, _ = ethtool_ret(f"-s {cfg.ifname} autoneg off {forced}", is_get = False)
>> +    if ret != 0:
>> +        ksft_pr(f"link autoneg off {forced} refused, not tested")
>> +        return
> 
> [Severity: Low]
> Can a variant be reported as passed without running a single pause
> parameter assertion?
> 
> If "ethtool -s <if> autoneg on" fails, the first group is skipped and only
> logged with ksft_pr(). If forced is then empty, or the forced
> "ethtool -s ... autoneg off" fails, the function returns normally.
> 
> ksft_run() sets KSFT_RESULT = True before each case and does not check
> whether the case made any assertions. The case is counted as a pass rather
> than a skip.
> 
> Should these paths raise KsftSkipEx when nothing was tested?

OK

> 
>> +
>> +    ret, _ = ethtool_ret(f"-A {cfg.ifname} rx {rx} tx {tx} autoneg off",
>> +                         is_get = False)
>> +    expect_pauseparams_set(ret, linkmodes, supported, "link autoneg off")
>> +
>> +    ret, _ = ethtool_ret(f"-A {cfg.ifname} rx {rx} tx {tx} autoneg on",
>> +                         is_get = False)
>> +    expect_pauseparams_set(ret, linkmodes, supported, "link autoneg off")
> 
> [Severity: Medium]
> Does this require pause autoneg to be accepted on a forced link? That goes
> against the uAPI documentation for struct ethtool_pauseparam in
> include/uapi/linux/ethtool.h:
> 
>  * Drivers should reject a non-zero setting of @autoneg when
>  * autoneogotiation is disabled (or not supported) for the link.
> 
> expect_pauseparams_set() decides success only from Pause/Asym_Pause. Those
> bits describe the MAC's pause frame abilities.

No, MAC + PHY.

> They don't say whether pause
> can be negotiated, or forced while link autoneg is running.
> 
> Several drivers fail at least one of the four link autoneg / pause autoneg
> combinations:
> 
>   bnxt_set_pauseparam() returns -EINVAL for pause autoneg without
>   BNXT_AUTONEG_SPEED, which is what the uAPI describes.
> 
>   mlx5e_ethtool_set_pauseparam() returns -EINVAL for any pause autoneg
>   request.
> 
>   ixgbe_set_pauseparam() returns -EINVAL when
>   !ixgbe_device_supports_autoneg_fc().
> 
>   i40e_set_pauseparam() returns -EOPNOTSUPP whenever pause->autoneg !=
>   is_an. That already fails the link autoneg on / pause autoneg off step.

That's why we write those tests

> 
> pause_advertising_test() has a related problem because it only skips on
> EOPNOTSUPP. It treats an EINVAL refusal of pause autoneg from mlx5, bnxt or
> ixgbe as applied. It then checks the advertisement against a configuration
> the device never accepted.
> 
> [ ... ]
> 
>> +def pause_advertising_test(cfg, pauseparams):
>> +    """Pause advertisement
> 
> [ ... ]
> 
>> +    The validation is made by looking at the advertised modes locally, as well
>> +    as what the peer's 'lp_advertising' values report.
>> +    """
> 
> [Severity: Low]
> Is the lp_advertising part of this docstring accurate for this patch?
> 
> The body never queries the peer. It only reads the local
> "advertised-pause-frame-use", which phy_ethtool_ksettings_get() copies from
> the software phydev->advertising bitmap.
> 
> wait_for_aneg(cfg) also returns success if the link hasn't dropped within
> 2 seconds:
> 
>         if not link_drop and time.monotonic() > restart_by:
>             return wait_for_link(cfg)
> 
> Together, these mean a MAC that never restarts autoneg, or a PHY that
> misprograms its advertisement register, would still pass.
> 
> A later commit in this series, "selftests: drv-net: pause: Validate the
> pause autonegotiation with a partner", adds controllable_lp() and a
> get_peer_pause_lp_advertising() check to pause_advertising_test(). That
> closes the gap by the end of the series.
> 
> [ ... ]
> 
>> +    # It's OK to skip here, we're already validating the EOPNOTSUPP behaviour
>> +    # the pause_test_support test.
>> +    ret = set_local_pauseparams(cfg, rx, tx, True)
>> +    if ret == errno.EOPNOTSUPP:
>> +        raise KsftSkipEx(f"RX {rx} TX {tx} not supported")
>> +
>> +    # Wait for link parameters to re-negotiate and link to come back up. It must
>> +    # come back up, otherwise that means changing pauseparams can bring the
>> +    # link down.
>> +    ret = wait_for_aneg(cfg)
> 
> [Severity: Medium]
> What happens when set_local_pauseparams() fails with something other than
> EOPNOTSUPP?
> 
> The docstrings of set_local_pauseparams() and get_local_pauseparams() say
> "Raise an error if the return is not 0 or EOPNOTSUPP". Neither function
> raises. Both just return the result of ethtool_ret(), which uses
> cmd(..., fail=False).
> 
> Here, an EINVAL, an EBUSY, or ethtool's raw exit code 1 is silently dropped,
> and ret is overwritten by wait_for_aneg(). The advertising checks then run
> against whatever state was there before, because pause_setup() does not
> put the pause params into a known state.

Ok will address

> 
> require_pause_supported_allof() has already confirmed that the modes are
> supported. So the result is either a false pass, or a failure with a
> "must advertise" message that blames the PHY. For example,
> mlx5e_ethtool_set_pauseparam() returns -EINVAL whenever pauseparam->autoneg
> is set.
> 
> [ ... ]
> 
>> +def main():
>> +    with NetDrvEpEnv(__file__, nsim_test=False) as cfg:
>> +        cfg.ethnl = EthtoolFamily()
> 
> [Severity: Low]
> This isn't a bug, but cfg.ethnl doesn't seem to be used anywhere in
> pause.py, since everything goes through the ethtool CLI. Can this
> assignment and the EthtoolFamily import be dropped? As it stands, if the
> ethtool genl family can't be resolved, the whole test aborts even though it
> doesn't need that family.

Ok

Maxime

  reply	other threads:[~2026-10-13  9:05 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-25 18:26 [PATCH net-next v2 0/3] selftests: drv-net: Introduce flow-control selftest Maxime Chevallier (Netdev Foundation)
2026-09-25 18:26 ` [PATCH net-next v2 1/3] selftests: drv-net: Introduce a selftest for ethtool flow control Maxime Chevallier (Netdev Foundation)
2026-09-29  3:26   ` netdev-bot+sashiko
2026-10-13  9:04     ` Maxime Chevallier [this message]
2026-10-13 12:29       ` Andrew Lunn
2026-09-25 18:26 ` [PATCH net-next v2 2/3] selftests: drv-net: pause: Validate the pause autonegotiation with a partner Maxime Chevallier (Netdev Foundation)
2026-09-29  3:26   ` netdev-bot+sashiko
2026-10-13  9:35     ` Maxime Chevallier
2026-10-13 12:37       ` Andrew Lunn
2026-10-13 14:02         ` Maxime Chevallier
2026-10-13 14:49           ` Andrew Lunn
2026-09-25 18:26 ` [PATCH net-next v2 3/3] selftests: drv-net: pause: Validate pause autoneg interactions with link autoneg Maxime Chevallier (Netdev Foundation)
2026-09-29  3:26   ` netdev-bot+sashiko
2026-09-30 23:07 ` [PATCH net-next v2 0/3] selftests: drv-net: Introduce flow-control selftest Jakub Kicinski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f06aba7f-0e5f-4c9e-b53a-b5b817b3e6c6@bootlin.com \
    --to=maxime.chevallier@bootlin.com \
    --cc=andrew@lunn.ch \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=f.fainelli@gmail.com \
    --cc=hkallweit1@gmail.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=netdev-bot+sashiko@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=o.rempel@pengutronix.de \
    --cc=pabeni@redhat.com \
    --cc=skhan@linuxfoundation.org \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=vladimir.oltean@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®