Hi!

Background
==========

This series adds a generic ethtool loopback framework with GET/SET
netlink commands, using a component/name/id/depth model that
represents loopback points across the network path.

This is v2.

Design
======

The loopback model uses four axes to identify a loopback point:

 1. Component (MAC, PHY, MODULE) -- identifies the Linux driver
    boundary that owns the loopback. This maps to the Linux driver
    model, not to 802.3 sublayers directly.

 2. Name -- identifies the sublayer within the component using IEEE
    802.3 vocabulary (e.g. "mac", "pcs", "pma", "pmd", "mii" for MAC
    and PHY components; "cmis-host", "cmis-media" for MODULE). The
    name is a free-form string to avoid over-constraining the enum,
    but recommended names are documented with references to 802.3
    clauses.

 3. Id -- optional instance selector within a component type (e.g.
    PHY index from phy_link_topology, port number). Defaults to 0
    when there is only one instance.

 4. Depth -- ordering index within a component instance. When a
    component has multiple loopback points of the same type (e.g. two
    PCS blocks inside a rate-adaptation PHY), depth distinguishes
    them. Lower values are closer to the host, higher toward the
    line/media. Defaults to 0 when there is only one loopback point
    per (component, name) tuple.

Direction uses IEEE 802.3 terminology: "local" (host TX -> looped back
-> host RX, traffic originating from host returns to host) and
"remote" (line RX -> looped back -> line TX, traffic from far end
returns to far end). Direction is defined from the component's own
viewpoint -- this convention holds regardless of where the component
sits in the system topology.

Cross-component ordering comes from existing infrastructure (PHY link
topology, phy_index). Multi-netdev shared-resource loopbacks (QSGMII,
port breakout) are out of scope; drivers should only expose loopbacks
they can scope to a single netdev.

A filtered DUMP (with a dev-index in the header) lists all loopback
entries for that netdev; an unfiltered DUMP iterates over all netdevs.
The doit handler supports exact lookup by (component, name, id).

V2 design rationale
===================

Why keep name as a string for now? The review discussed replacing name
with an enum. I decided not to do that in v2.

Pros:
 - enforces more consistency across drivers
 - makes userspace parsing simpler
 - makes selftests stricter
 - keeps the UAPI taxonomy explicit

Cons:
 - freezes the stage taxonomy before we fully understand the MAC side
 - risks forcing unlike hardware points into the same enum bucket
 - makes later extension more expensive
 - may standardize the spelling without standardizing the actual
   semantics
   
This series still does not attempt to model the full datapath as a DAG
or expose a generic topology dump. That would likely be useful for
future diagnostics, traffic generators, and deeper validation, but it
also looks like a larger design problem than loopback itself.

The intent of v2 is not to solve that larger problem now, but also not
to block it:

 - component gives the Linux ownership boundary
 - name keeps room for stage-specific vocabulary
 - id selects the component instance
 - depth orders loopback points within that instance

If a richer topology API is needed later, it should be additive rather
than requiring this loopback API to be replaced.

Oleksij's more topology-heavy use cases are therefore not fully solved
by this series, but the current model should still be extendable for
them.

CMIS support
============

The Common Management Interface Specification (CMIS) defines four
diagnostic loopback types, characterized by location (Host or Media
Side) and signal direction:

 - Host Side Input (Rx->Tx) -- local
 - Host Side Output (Tx->Rx) -- remote
 - Media Side Input (Rx->Tx) -- local
 - Media Side Output (Tx->Rx) -- remote

Support is detected via Page 13h Byte 128, and loopback is controlled
via Page 13h Bytes 180-183 (one byte per type, one bit per lane).

The CMIS helpers work entirely over get/set_module_eeprom_by_page, so
any driver that already has EEPROM page access gets module loopback
without new ethtool_ops or driver changes.

Currently, only mellanox/mlxsw, and broadcom/bnxt support CMIS
operations. I'll follow-up with mlx5 support.

Implementation
==============

Patch 1/12 ethtool: Add dump_one_dev callback for per-device sub-iteration
  Adds the dump_one_dev callback to ethnl_request_ops, the ifindex and
  pos_sub fields to ethnl_dump_ctx, and the dispatch logic in
  ethnl_default_start() and ethnl_default_dumpit(). No functional
  change; no command uses dump_one_dev yet.

Patch 2/12 ethtool: Convert per-PHY commands to dump_one_dev
  Converts PSE, PLCA, PHY, and MSE commands from the separate
  ethnl_perphy_{start,dumpit,done} handlers to use the generic
  dump_one_dev callback via a shared ethnl_perphy_dump_one_dev()
  function.

Patch 3/12 ethtool: Add loopback netlink UAPI definitions
  Adds the YAML spec and generated UAPI header for the new
  LOOPBACK_GET/SET commands. Each loopback entry carries a component
  type, optional id, name string, depth, supported directions
  bitmask, and current direction.

Patch 4/12 ethtool: Add loopback GET/SET netlink implementation
  Implements GET/SET dispatch in a new loopback.c. GET uses the
  dump_one_dev infrastructure for dump enumeration (by flat index)
  and supports doit exact lookup by (component, id, name) via
  parse_request. SET switches on the component and calls the right
  handler per entry. No components are wired yet.

Patch 5/12 ethtool: Add CMIS loopback helpers for module loopback control
  Adds cmis_loopback.c with the MODULE component handlers and wires
  them into loopback.c's dispatch. GET enumerates entries by index
  (ethtool_cmis_get_loopback_by_index) or looks up by name
  (ethtool_cmis_get_loopback). SET (ethtool_cmis_set_loopback)
  resolves name to control byte indices and enforces mutual
  exclusivity.

Patch 6/12 selftests: drv-net: Add loopback driver test
  Adds loopback_drv.py with generic tests that work on any device
  with module loopback support: enable/disable, direction switching,
  idempotent enable, and rejection while interface is up.

Patch 7/12 ethtool: Add MAC loopback support via ethtool_ops
  Extends struct ethtool_ops with three loopback callbacks for
  driver-level MAC loopback: get_loopback (exact lookup by name/id),
  get_loopback_by_index (dump enumeration), and set_loopback. Wires
  the MAC component into loopback.c's dispatch. For dump enumeration,
  MAC entries are tried first, then MODULE/CMIS entries follow at the
  next index offset.

Patch 8/12 netdevsim: Add MAC loopback simulation
  Implements the three ethtool loopback ops in netdevsim. Exposes a
  single MAC loopback entry ("mac") with both local and remote
  support. State is stored in memory and exposed via debugfs under
  ethtool/mac_lb/{supported,direction}.

Patch 9/12 selftests: drv-net: Add MAC loopback netdevsim test
  Adds loopback_nsim.py with netdevsim-specific tests for MAC
  loopback: entry presence, SET/GET round-trip with debugfs
  verification, and error paths.

Patch 10/12 MAINTAINERS: Add entry for ethtool loopback
  Adds a MAINTAINERS entry for the ethtool loopback subsystem covering
  the core loopback and CMIS loopback netlink implementation, and the
  associated selftests.

Patch 11/12 netdevsim: Add module EEPROM simulation via debugfs
  Adds get/set_module_eeprom_by_page to netdevsim, backed by a
  256-page x 128-byte array exposed via debugfs.

Patch 12/12 selftests: drv-net: Add CMIS loopback netdevsim test
  Extends loopback_nsim.py with netdevsim-specific tests that seed the
  EEPROM via debugfs: capability reporting, EEPROM byte verification,
  combined MAC + MODULE dump, and error paths.

Changes since v1
================

 - Split dump_one_dev infrastructure patch into two: one adding the
   generic callback infrastructure, one converting per-PHY commands
   to use it. (Jakub)

 - Used Jakub's suggested pattern for filtered dumps: initialize both
   ifindex and pos_ifindex in _start(), then break early in the loop
   when pos_ifindex diverges, avoiding a separate single-device code
   path. (Jakub)

 - Dropped PCS as a top-level component. Components now map to Linux
   driver boundaries: MAC, PHY, MODULE. Sublayer granularity (pcs,
   pma, pmd, mii) lives in the name attribute using IEEE 802.3
   vocabulary. (Maxime)

 - Renamed near-end/far-end to local/remote per IEEE 802.3
   terminology. (Maxime)

 - Added depth field to ETHTOOL_A_LOOPBACK_ENTRY for ordering
   multiple loopback points within a single component instance (e.g.
   rate-adaptation PHY with two PCS blocks). (Jakub)

 - Documented the viewpoint convention: direction is always from the
   component's own perspective, local = toward host, remote = toward
   line, regardless of system topology. (Oleksij)

 - Expanded component doc strings to explain that the name attribute
   uses IEEE 802.3 sublayer vocabulary. (Andrew, Maxime)

Changes since RFC v2
====================

 - Switched LOOPBACK_GET from doit-with-array to dumpit, where each
   loopback entry is a separate netlink message. Uses the new generic
   dump_one_dev sub-iterator infrastructure instead of duplicating the
   perphy dump pattern. (Maxime)

 - u32 to u8 to represent the enums in the YAML. (Maxime)

 - Tried to document the YAML better. (Andrew)

 - Added doit exact lookup by (component, id, name) via
   parse_request, so single-entry GET doesn't need a flat index.

 - Added MAC loopback support via three new ethtool_ops callbacks
   (get_loopback(), get_loopback_by_index(), set_loopback()) with
   netdevsim implementation and tests.

 - Added MAINTAINERS entry.

Opens/limitations
=================

 - mlx5 CMIS support is still not part of the series.
 - PHY loopback is defined in the UAPI but not yet implemented.
 - No per-lane support -- loopback is all-or-nothing (0xff/0x00)
   across lanes.

Related work
============

[1] Generic loopback support, v1
  https://lore.kernel.org/netdev/[email protected]/
[2] Generic loopback support, RFC v2
  https://lore.kernel.org/netdev/[email protected]/
[3] New loopback modes
  https://lore.kernel.org/netdev/[email protected]/
[4] PHY loopback
  
https://lore.kernel.org/netdev/[email protected]/
[5] bnxt_en: add .set_module_eeprom_by_page() support
  
https://lore.kernel.org/netdev/[email protected]/
[6] net/mlx5e: Implement set_module_eeprom_by_page ethtool callback
  https://lore.kernel.org/netdev/[email protected]/


Björn Töpel (12):
  ethtool: Add dump_one_dev callback for per-device sub-iteration
  ethtool: Convert per-PHY commands to dump_one_dev
  ethtool: Add loopback netlink UAPI definitions
  ethtool: Add loopback GET/SET netlink implementation
  ethtool: Add CMIS loopback helpers for module loopback control
  selftests: drv-net: Add loopback driver test
  ethtool: Add MAC loopback support via ethtool_ops
  netdevsim: Add MAC loopback simulation
  selftests: drv-net: Add MAC loopback netdevsim test
  MAINTAINERS: Add entry for ethtool loopback
  netdevsim: Add module EEPROM simulation via debugfs
  selftests: drv-net: Add CMIS loopback netdevsim test

 Documentation/netlink/specs/ethtool.yaml      | 142 ++++++
 MAINTAINERS                                   |   6 +
 drivers/net/netdevsim/ethtool.c               | 147 +++++++
 drivers/net/netdevsim/netdevsim.h             |  15 +
 include/linux/ethtool.h                       |  28 ++
 .../uapi/linux/ethtool_netlink_generated.h    |  67 +++
 net/ethtool/Makefile                          |   2 +-
 net/ethtool/cmis_loopback.c                   | 407 ++++++++++++++++++
 net/ethtool/loopback.c                        | 351 +++++++++++++++
 net/ethtool/mse.c                             |   1 +
 net/ethtool/netlink.c                         | 284 ++++--------
 net/ethtool/netlink.h                         |  49 +++
 net/ethtool/phy.c                             |   1 +
 net/ethtool/plca.c                            |   2 +
 net/ethtool/pse-pd.c                          |   1 +
 .../testing/selftests/drivers/net/hw/Makefile |   2 +
 .../selftests/drivers/net/hw/loopback_drv.py  | 227 ++++++++++
 .../selftests/drivers/net/hw/loopback_nsim.py | 343 +++++++++++++++
 18 files changed, 1865 insertions(+), 210 deletions(-)
 create mode 100644 net/ethtool/cmis_loopback.c
 create mode 100644 net/ethtool/loopback.c
 create mode 100755 tools/testing/selftests/drivers/net/hw/loopback_drv.py
 create mode 100755 tools/testing/selftests/drivers/net/hw/loopback_nsim.py


base-commit: d1e59a46973719e458bec78d00dd767d7a7ba71f
-- 
2.53.0


Reply via email to