Re: [RFC net-next 0/4] ethtool: CMIS module diagnostic loopback support

From: Björn Töpel

Date: Tue Feb 24 2026 - 05:29:27 EST


Good feedback, Kuba! ...more thinking...

On Tue, 24 Feb 2026 at 00:04, Jakub Kicinski <kuba@xxxxxxxxxx> wrote:
...
As a reference, there's a v2-ish version here (API I suggested +
netdevsim plumbing) [1].

What I discovered was that the "layer"/IEEE abstraction I suggested
didn't even fit nicely with the CMIS module loopback work -- I had to
split PMD into PMD-HOST/PMD-MODULE to fit the CMIS spec, which felt
like a hack.

I've obviously taken too high-level a "PCIe device" view of the world.
Looking at Maxime's slides from netdev 0x17 [2] reveals a more
complicated world; multiple PHY-like things in the path (onboard PHY,
module, external PHY, ...). My model doesn't cover what Maxime
outlines.

Instead, like Jakub hinted at, userspace should reason in terms of
"loopback entities" (or IDs) that correspond to "places where loopback
can be applied”, not in terms of PCS/PMA/PMD topology.

A loopback entity would have:
an ID / type (which matches a driver),
a direction,
an optional descriptive name.

Reiterating what Jakub said earlier, using hwstamp-source as a
precedent, you could imagine something like:

struct {
enum type; // MAC, PHY, SFP
int type_id; // if type=PHY - phy id
int depth; // counting from CPU, first loopback opportunity is 1
// second is 2, etc.
bool direction; // towards CPU/host vs towards network
char name[16]; // "pcs", "far", "near", "post-fec", whatever
}

I'm not sure that depth/name are actually useful here.

Concretely, that could look like this in ethtool:

/* What kind of kernel object owns this loopback. */
enum ethtool_loopback_owner {
ETHTOOL_LB_OWNER_MAC, /* struct net_device / MAC driver */
ETHTOOL_LB_OWNER_PHY, /* struct phy_device (phylib PHY) */
ETHTOOL_LB_OWNER_MODULE, /* module / SFP driver, e.g. CMIS */
};

enum ethtool_loopback_dir {
ETHTOOL_LB_DIR_HOST_LOOP_HOST,
ETHTOOL_LB_DIR_LINE_LOOP_LINE,
};

/* One "loopback entity" associated with the netdev. */
struct ethtool_loopback_entry {
u32 id; /* per-netdev */
enum ethtool_loopback_owner owner;
u32 depth; /* ??? */
enum ethtool_loopback_dir direction; /* enum ethtool_loopback_dir */
bool enabled;
char name[16]; /* ??? "mac",
"phy-pcs", "module-far", ... */
};

/* Aggregate for GET: list all possible endpoints + their status. */
struct ethtool_loopback_state {
struct ethtool_loopback_entry entries[16];
unsigned int n_entries;
};

>From a driver POV:
* The MAC driver can add its own MAC-level loopback entity (owner =
MAC).
* If there is one or more phydevs, it can call into a phylib helper
(e.g. phy_get_loopback_state()) to append PHY entities (owner =
PHY).
* If there is a CMIS module, it can append its entities (owner = MODULE).

# ethtool --show-loopback eth0
Loopback endpoints for eth0:
id owner depth direction name enabled
0 mac 1 host->loop->host mac off
1 phy 2 host->loop->host phy-pcs on
2 module 3 line->loop->line cmis-far off

# Enable endpoint 2
ethtool --set-loopback eth0 id 2 on


Does this model make more sense, especially for the multi-PHY / CMIS
cases Maxime described?


Björn

[1] https://github.com/fb-bjorn/linux/compare/master...fb-bjorn:linux:ethtool-loopback-rfc-v2
[2] https://netdevconf.info/0x17/docs/netdev-0x17-paper2-talk-slides/multi-port-multi-phy-interfaces.pdf