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

From: Björn Töpel

Date: Sun Feb 22 2026 - 14:59:25 EST


Andrew/Kuba!

Thanks for having a look!

On Fri, 20 Feb 2026 at 22:12, Jakub Kicinski <kuba@xxxxxxxxxx> wrote:

>> > 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
>> > }
>>
>> Lets see what comes from the drawing board, but i was more thinking
>> about expanding the bitmap this proposal already has, extending it to
>> other layers.
>
>IIUC the bitmap this proposal has is basically a product of
>direction x depth: [host, network] x [nearest, furthest]
>plus its scoped to SFP.

(Digging into different ways to loopback, rather than drawing board,
but here goes! ;-))

I'd agree with Jakub here, unless I'm not getting the details of what
you mean, Andrew. Sounds like we'd end up with a huge bitmap? I
suggest tweaking Jakub's idea to something like:

/* loopback.c: A new ETHTOOL_MSG_LOOPBACK_{GET,SET} */

/* Loopback layers/scope
enum ethtool_loopback_layer {
ETHTOOL_LB_LAYER_SW = 0, /* Software/Kernel stack loopback */
ETHTOOL_LB_LAYER_MAC, /* MAC/Controller internal */
ETHTOOL_LB_LAYER_PCS, /* Physical Coding Sublayer (Digital) */
ETHTOOL_LB_LAYER_PMA, /* SerDes / Analog-Digital boundary */
ETHTOOL_LB_LAYER_PMD, /* Transceiver / Module internal */
ETHTOOL_LB_LAYER_EXT, /* External physical plug/cable */
};

/* Loopback Direction (XXX is local/remote easier to understand?) */
enum ethtool_loopback_dir {
ETHTOOL_LB_DIR_NEAR_END = 0, /* Host -> Loop -> Host */
ETHTOOL_LB_DIR_FAR_END, /* Line -> Loop -> Line */
};

struct ethtool_loopback_layer_cfg {
enum ethtool_loopback_layer layer; /* ETHTOOL_LB_L_MAC, etc. */
enum ethtool_loopback_dir direction; /* NEAR or FAR */
u32 lane_mask; /* Specific lanes */
u32 flags; /* patterns? reserved... */
bool enabled;
char name[16];
};

struct ethtool_loopback_cfg {
struct ethtool_loopback_layer_cfg *entries;
u32 num_layers;
};

struct ethtool_ops {
/* ... */

/* Query which layers/lane-combos are physically possible */
int (*get_loopback_caps)(struct net_device *dev,
struct ethtool_loopback_cfg *caps);

/* Get current active status for all layers */
int (*get_loopback_state)(struct net_device *dev,
struct ethtool_loopback_cfg *state);

/* Set one or more layer/lane configurations atomically */
int (*set_loopback)(struct net_device *dev,
const struct ethtool_loopback_cfg *cfg,
struct netlink_ext_ack *extack);
};

As for layers; EXT vs PMD? EXT could be a loopback plug, whereas PMD
would be CMIS, or whatever the driver detects.

Userland would be something like:

# ethtool --show-loopback eth0
Loopback Status for eth0:
Layer: SW | State: OFF
Layer: MAC | State: OFF
Layer: PMA | State: ON | Lanes: 0x1 (Lane 0) | Direction: Near-End (Local)
Layer: PMD | State: ON | Lanes: 0xF (All) | Direction: Far-End (Remote)
Layer: EXT | State: ON | Detected: External Loopback Plug

# ethtool --set-loopback <dev> [layer[:lanes][:direction]] ... [off]

# # Simple MAC loopback:
# ethtool --set-loopback eth0 mac (Defaults: lanes=all, dir=near)
# # Specific SerDes (PMA) lane:
# ethtool --set-loopback eth0 pma:lane0
# # Complex multi-layer (PMA Near + PMD Far):
# ethtool --set-loopback eth0 pma:0x1:near pmd:all:far
# # Disable all loopbacks:
ethtool --set-loopback eth0 off

Thoughts? Is this somewhat close to what you had in mind, Andrew?

I'm far from an expert on the details here, so the folks with more
knowledge, please chime in!


Cheers,
Björn