ethtool -m: reading an SFP's EEPROM, and the error you get when you cannot

ethtool -m reads the transceiver's own EEPROM over I2C: identity on page A0h, live temperature and optical power on A2h. Cannot get module EEPROM information: Operation not supported means the driver has no way to ask, not that the optic is bad.

Short version: ethtool -m eth0 asks the NIC driver to read the transceiver's own EEPROM over I2C, identity on page A0h and live optical telemetry on A2h. Cannot get module EEPROM information: Operation not supported is not a dying optic. It is the driver saying it has no way to ask, which on a virtual NIC is the correct answer.

Every failure string below came off one of our own Firecracker VMs, which has a virtio NIC and no SFP cage. The populated dumps are quoted from vendor documentation and the SFF-8472 spec, each with a Source line, because a virtual interface has no optic to read.

The error comes from the driver, not from the optic

Operation not supported means the driver implements no module EEPROM read at all. Nothing is seated wrong, and nothing on the far end matters yet.

root@net-01:~# ethtool -m eth0
netlink error: Operation not supported

The string most people search for is spelled differently, and the same machine prints it when you add an option:

root@net-01:~# ethtool -m eth0 hex on
Cannot get module EEPROM information: Operation not supported

Same errno, two spellings, because the requests take different routes. Modern ethtool asks the kernel over netlink (MODULE_EEPROM_GET), which returns at most half a page per request. A full hex dump cannot be expressed that way, so ethtool falls back to the older ioctl pair, and that is the code printing Cannot get module EEPROM information: plus strerror(errno). The prefix tells you which path ran, the suffix is the kernel's answer either way.

The receipts are one command away:

root@net-01:~# ethtool -i eth0
driver: virtio_net
version: 1.0.0
bus-info: LNRO0005:01
supports-eeprom-access: no

virtio_net is paravirtual: behind it is a queue shared with the hypervisor, not a cage with an I2C bus. supports-eeprom-access refers to the card's own EEPROM, which is a different command with its own message:

root@net-01:~# ethtool -e eth0
Cannot get EEPROM data: Operation not supported

-e dumps the network card's EEPROM, -m dumps the plug-in module's. The prefix on the error is how you tell which one was refused.

What ethtool -m is actually asking the hardware for

It asks the driver to run an I2C read against two fixed addresses inside the module. SFF-8472 keeps the original 256-byte GBIC and SFP map at two-wire address A0h and adds a second address, A2h, for diagnostics. A0h is identity, unchanged from the older specs, which is what keeps a modern optic readable by ancient software. A2h reports how the module is doing right now.

The kernel offers two ways in. The netlink request carries offset, length, page, bank and I2C address. The legacy ioctl pair returns one 512-byte buffer, A0h in the first half and A2h in the second, which is why an SFF-8472 dump is 512 bytes and not 256. A driver that implements neither leaves the kernel nothing to call, so it answers EOPNOTSUPP.

-m also decodes QSFP and QSFP28, which use the paged SFF-8636 map. That is what the page, bank and i2c parameters are for. Everything below is the SFP case.

The identity page: A0h is the module's passport

A0h holds what the module is, who built it and its serial number, written at manufacture and readable with the link down and the far end dark.

Identifier                                : 0x03 (SFP)
Connector                                 : 0x07 (LC)
Transceiver type                          : Ethernet: 1000BASE-SX
BR, Nominal                               : 2100MBd
Length (50um)                             : 300m
Laser wavelength                          : 850nm
Vendor name                               : JDSU
Vendor OUI                                : 00:01:9c
Vendor PN                                 : PLRXPL-VI-S24-22
Source: NVIDIA Cumulus Linux documentation, ethtool -m on a JDSU 1000BASE-SX SFP (abridged), https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-44/Monitoring-and-Troubleshooting/Troubleshooting-Network-Interfaces/Monitoring-Interfaces-and-Transceivers-Using-ethtool/

Every line is a byte offset with a decoder in front of it. The map below is SFF-8472 Rev 12.3, Table 4-1. Bytes 63 and 95 hold checksums over the fields in front of them.

ethtool lineA0h bytesWhat is stored there
Identifier0Form factor code, 0x03 is SFP or SFP+
Connector2Connector code, 0x07 is LC
BR, Nominal12Nominal bit rate, units of 100 MBd
Length (SMF / 50um / 62.5um / copper)14 to 19Reach per medium
Vendor name20 to 3516 ASCII characters, space padded
Vendor OUI37 to 39IEEE company ID of the maker
Vendor PN40 to 55Part number, 16 ASCII characters
Laser wavelength60 to 61Nanometres, reused for cable compliance on DACs
Vendor SN68 to 83Serial number, 16 ASCII characters
Date code84 to 91Manufacture date, YYMMDD plus lot
Diagnostic Monitoring Type92Bit 6 DDM present, bit 5 internal calibration, bit 4 external

Byte 92 is the one to remember. It decides whether anything in the next section exists.

The diagnostics page: five live numbers on A2h

A2h carries five values the module measures for itself and refreshes continuously: temperature, supply voltage, laser bias current, transmit power and receive power. Each is a 16-bit field of raw counts, and ethtool does the unit conversion.

Laser bias current                        : 21.348 mA
Laser output power                        : 0.3186 mW / -4.97 dBm
Receiver signal average optical power     : 0.3195 mW / -4.96 dBm
Module temperature                        : 41.70 degrees C / 107.05 degrees F
Module voltage                            : 3.2947 V
Source: NVIDIA Cumulus Linux documentation, same JDSU dump (abridged; the source also carries every flag and threshold line), https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-44/Monitoring-and-Troubleshooting/Troubleshooting-Network-Interfaces/Monitoring-Interfaces-and-Transceivers-Using-ethtool/
ethtool lineA2h bytesRaw encoding (SFF-8472 section 9.2)
Module temperature96 to 97Signed, steps of 1/256 degrees C
Module voltage98 to 99Unsigned, LSB 100 microvolts, 0 to 6.55 V
Laser bias current100 to 101Unsigned, LSB 2 microamps, 0 to 131 mA
Laser output power102 to 103Unsigned, LSB 0.1 microwatt, 0 to 6.5535 mW
Receiver optical power104 to 105Same encoding as transmit power

Power prints twice because the EEPROM stores linear counts and engineers compare optics in decibels. That conversion is why a dead receiver reads -inf dBm: zero milliwatts has no logarithm. Bit 3 of A0h byte 92 decides whether the receive figure is average power or OMA, which is why ethtool spells the line out instead of saying rx power.

Alarm and warning thresholds: four fences around every value

The vendor writes four fences per value into A2h bytes 0 to 39 at manufacture: high alarm, low alarm, high warning, low warning. The module compares its own measurements against them and sets flag bits at bytes 112 to 117. ethtool prints the fences and the flags. It computes nothing.

An alarm marks the edge of the tolerance the module was designed for, while the warning level, as NVIDIA's Cumulus documentation puts it, "is a little bit closer to expected norms". A warning means look now. An alarm means the vendor no longer promises the link.

The one every network engineer eventually meets:

Laser output power                        : 0.0251 mW / -16.00 dBm
Receiver signal average optical power     : 0.0000 mW / -inf dBm
Laser rx power low alarm                  : On
Source: cloudalbania, Troubleshooting physical fiber SFP network modules, https://cloudalbania.com/2022-01-troubleshooting-physical-fiber-sfp-network-modules/

The local laser is lit and nothing is coming back: a cut or unplugged fibre, a dirty or half-seated connector, the wrong strand of a pair, or a far end whose transmitter is off. The module cannot say which, but it has proved the fault is outside the server.

Resist memorising a good number. Is -18 dBm bad? There is no universal answer, because the fences are set per vendor and per optic type, which is exactly why they live beside the measurement. Bias current is the one to trend rather than to threshold: a laser drawing steadily more current over months is aging.

The other failure strings, and which layer said no

The prefix belongs to ethtool. The suffix is the kernel's errno rendered by strerror, and it names the layer that refused. A name that does not exist never reaches a driver:

root@net-01:~# ethtool -m enp0s31f6
netlink error: no device matches name (offset 24)
netlink error: No such device

An interface that exists but is not a NIC gets the same answer as our virtio port, because neither has a module read to offer:

root@net-01:~# ethtool -m lo
netlink error: Operation not supported
ErrnoWhat you seeWho refusedCheck first
EOPNOTSUPPOperation not supported (ours, captured)Driver has no module EEPROM hookethtool -i. Virtual NICs never will. Real ones may want newer driver or NIC firmware
ENODEVNo such device (ours, captured)Name resolution, or an empty cage on a real portThe interface name, then whether a module is seated
EIOInput/output error (reported, Mellanox MT26448)The I2C transaction itselfReseat the module, then swap it
EPERMOperation not permitted (reported, 10GBASE-T copper SFP+)Privilege, or NIC firmware refusingRun as root, then NIC firmware
noneDump stops after the identity fieldsNothing. The module has no diagnosticsA0h byte 92 bit 6, and whether it is a DAC

Read our ENODEV carefully: the name was rejected before any hardware was touched, so here it means no interface by that name. On a switch with a real port and an empty cage the same errno arrives from the other end of the stack, which is how it was reported against a Mellanox switch running SONiC.

We tried to capture the permission case and did not get one:

root@net-01:~# su - probe -c 'ethtool -m eth0'
-sh: 1: ethtool: not found

ethtool lives in /usr/sbin, which is not on an ordinary user's PATH, so the shell gave up before the kernel was asked. Useful on its own, and the reason we will not tell you what unprivileged ethtool -m returns on your hardware: we did not measure it.

When the honest answer is: this optic has no diagnostics

A passive DAC or a copper twisted-pair module answers the identity page and then stops. Nothing failed. Diagnostic monitoring is optional in SFF-8472, A0h byte 92 bit 6 declares whether the module implements it, and when that bit is clear there are no thresholds, no flags and no live values to print. NVIDIA's Cumulus documentation says it plainly: this does not apply to DAC and twisted pair interfaces.

The kernel carries scar tissue from it. A bnx2x fix exists purely to check whether a transceiver implements DDM before touching the diagnostics, because a module can comply with SFF-8472 without implementing them. When a DAC shows vendor, part number and serial but no receive power, that short output is the complete answer.

Reading the serial number without touching the fibre

ethtool -m eth0 | grep -i 'vendor sn' pulls the serial straight out of A0h bytes 68 to 83, with the link up, the cable in place and nobody standing in the aisle.

Vendor SN                                 : AGC143953079
Date code                                 : 140926
Source: ethtool patch adding SFP serial number and date to the EEPROM dump (Ed Swierk, 2015), https://alioth-lists-archive.debian.net/pipermail/kernel-svn-changes/2015-October/021079.html

Those two lines are younger than the command. Until a 2015 patch the dump decoded the engineering fields and left the serial number and date code out, and it exists because the people filing hardware returns kept needing them. That is still the main use: paste the serial into the RMA, then confirm the optic that came back is the one that left the rack.

The date code gives module age during failure analysis, which turns "this port flaps" into "these three optics share a lot". The vendor OUI is the IEEE company ID burned in at manufacture, worth comparing against the brand on the shell when relabelled optics are a possibility.

For a fleet sweep, loop over the names in /sys/class/net, run ethtool -m on each and keep the ones that exit 0. That exit status is itself the inventory: ports that answer have a readable module, ports that return EOPNOTSUPP have a driver that cannot look.

Quick reference

Command or offsetWhat it gives you
ethtool -m eth0Decoded module EEPROM, with diagnostics if the module has them
ethtool --module-info eth0The same command, long spelling
ethtool -m eth0 hex onRaw hex, which falls back to the ioctl path
ethtool -m eth0 page N bank N i2c NAddress a paged map (QSFP, SFF-8636)
ethtool -e eth0The NIC's own EEPROM, a different device entirely
A0h bytes 0 to 95Identity: vendor, PN, SN, date code, wavelength, DDM flag at 92
A2h bytes 0 to 39Four factory thresholds per monitored value
A2h bytes 96 to 105Temperature, voltage, TX bias, TX power, RX power
A2h bytes 112 to 117Current alarm and warning flag bits
Operation not supportedThe driver implements no module read
No such deviceNo interface by that name, or nothing in the cage
Input/output errorThe I2C read itself failed
Operation not permittedPrivilege or NIC firmware refused

Verified on ethtool version 6.1 and kernel 6.1.155+, on a Linux Camp Firecracker VM whose only interface is virtio_net. The error strings are that machine's own output. Every populated dump is quoted from the source named inside its block.

Common questions

Why does ethtool -m say Operation not supported? Because the driver implements no module EEPROM read, so the kernel returns EOPNOTSUPP. Every virtual NIC behaves this way, and some real ones do until a driver or NIC firmware update. Check ethtool -i first.

How do I read an SFP's serial number in Linux? ethtool -m <iface> | grep -i 'vendor sn'. The serial is 16 ASCII characters at bytes 68 to 83 of the A0h page, decoded by ethtool since 2015. Add date code to the pattern for the manufacture date.

What is the difference between an alarm and a warning threshold? Both are factory values stored in the module. The alarm marks the edge of the vendor's design tolerance, the warning sits closer to normal running as an early signal. The module sets the flags itself; ethtool only reports them.

Why does my DAC cable show no RX power? Because passive DAC and twisted-pair modules do not implement digital diagnostic monitoring. Bit 6 of A0h byte 92 is clear, so there are no live values and no thresholds to print. The identity fields still read normally.

More from the Field Manual, or work through the training tracks.