You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First, we need to unbreak access to the igb's I2C bus in the kernel.
That's in our `cesnet/2025-06-04` branch, and because I'm lazy, I
upgraded the kernel to the latest 6.6 LTS (6.6.93) in one go.
Unfortunately, this is "not enough" to get a simple hwmon-based access
to the SFP's TX/RX power. On Clearfog, these are provided by the `sfp`
driver, but the generic SFP layer is actually not used by igb at all.
Also, in the end we will very likely require reimplementing the readout
of these optical parameters in userspace because the hwmon abstractions
work in µW, and therefore their resolution is too coarse (because
1 µW == -30dBm, 2 µW == -27 dBm, etc). The DWDM SFP MSA actually says
that the TX power has a resolution of 1 µW, whereas the RX power has a
resolution of 0.1 µW.
Also, some SFPs have calibration data, that might require FP math, and
there's no FP in the kernel. This might not be the case for CWDM/DWDM
SFPs where the MSA prescribes certain fixed values, but hey, I will
never underestimate vendor creativity.
Fortunately, the `ethtool` got support for JSON output recently, at
least for some subcommands. The `-m` flag only got supported in 6.14,
which came out in April this year, so let's bump that within Buildroot
(in our `cesnet/2025-06-02` branch). Unfortunately, the output appears
to be broken (it dumps not just JSON, but also the usual text crap), and
the actual runtime parameters about the laser performance data are not
included in the JSON part:
EDFA-LINE-SDN-ID210511 ~ # /tmp/ethtool --json -m oscW
[ {
"identifier": 3,
"identifier_description": "SFP",
"extended_identifier": 4,
"extended_identifier_description": "GBIC/SFP defined by 2-wire interface ID",
"connector": 7,
"connector_description": "LC",
"transceiver_codes": [ 0,0,0,0,128,16,1,5,0 ],
"transceiver_type": "FC: 100 MBytes/sec",
"encoding": 1,
"encoding_description": "8B/10B",
"br_nominal": 1300,
"rate_identifier": 0,
"rate_identifier_description": "unspecified",
"length_(smf)": 100,
"length_(om2)": 0,
"length_(om1)": 0,
"length_(copper_or_active_cable)": 0,
"length_(om3)": 0,
"laser_wavelength": 1510,
"vendor_name": "FS",
"vendor_oui": [ 0,0,0 ],
"vendor_pn": "CW51-1G-100-1510",
"vendor_rev": "A",
"option_values": [ 0,26 ],
"option": "TX_DISABLE implemented",
"br_margin_max": 0,
"br_margin_min": 0,
"vendor_sn": "C1810000594",
"date_code": "181009"
} ]
Optical diagnostics support : Yes
Laser bias current : 18.216 mA
Laser output power : 1.4071 mW / 1.48 dBm
Receiver signal average optical power : 0.0071 mW / -21.49 dBm
Module temperature : 43.87 degrees C / 110.96 degrees F
Module voltage : 3.2844 V
Alarm/warning flags implemented : Yes
Laser bias current high alarm : Off
Laser bias current low alarm : Off
Laser bias current high warning : Off
Laser bias current low warning : Off
Laser output power high alarm : Off
Laser output power low alarm : Off
Laser output power high warning : Off
Laser output power low warning : Off
Module temperature high alarm : Off
Module temperature low alarm : Off
Module temperature high warning : Off
Module temperature low warning : Off
Module voltage high alarm : Off
Module voltage low alarm : Off
Module voltage high warning : Off
Module voltage low warning : Off
Laser rx power high alarm : Off
Laser rx power low alarm : Off
Laser rx power high warning : Off
Laser rx power low warning : Off
Laser bias current high alarm threshold : 100.000 mA
Laser bias current low alarm threshold : 0.000 mA
Laser bias current high warning threshold : 95.000 mA
Laser bias current low warning threshold : 0.100 mA
Laser output power high alarm threshold : 3.9811 mW / 6.00 dBm
Laser output power low alarm threshold : 0.7943 mW / -1.00 dBm
Laser output power high warning threshold : 3.1623 mW / 5.00 dBm
Laser output power low warning threshold : 1.0000 mW / 0.00 dBm
Module temperature high alarm threshold : 90.00 degrees C / 194.00 degrees F
Module temperature low alarm threshold : -45.00 degrees C / -49.00 degrees F
Module temperature high warning threshold : 85.00 degrees C / 185.00 degrees F
Module temperature low warning threshold : -40.00 degrees C / -40.00 degrees F
Module voltage high alarm threshold : 3.8000 V
Module voltage low alarm threshold : 2.7000 V
Module voltage high warning threshold : 3.7000 V
Module voltage low warning threshold : 2.8000 V
Laser rx power high alarm threshold : 0.2512 mW / -6.00 dBm
Laser rx power low alarm threshold : 0.0008 mW / -30.97 dBm
Laser rx power high warning threshold : 0.1995 mW / -7.00 dBm
Laser rx power low warning threshold : 0.0010 mW / -30.00 dBm
Also, this apparently only works on the built-in SFP. I tried to get
more details by strace, but I failed horribly, very likely due to [1]:
EDFA-LINE-SDN-ID210513 ~ # strace /tmp/ethtool -m oscE
[...]
socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC) = 3
setsockopt(3, SOL_NETLINK, NETLINK_EXT_ACK, [1], 4) = 0
bind(3, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, nl_pid=8115, nl_groups=00000000}, [12]) = 0
sendto(3, [{nlmsg_len=32, nlmsg_type=0x10 /* NLMSG_??? */, nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=1, nlmsg_pid=0}, "\x03\x01\x00\x00\x0c\x00\x02\x00\x65\x74\x68\x74\x6f\x6f\x6c\x00"], 32, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 32
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base=[{nlmsg_len=956, nlmsg_type=0x10 /* NLMSG_??? */, nlmsg_flags=0, nlmsg_seq=1, nlmsg_pid=8115}, "\x01\x02\x00\x00\x0c\x00\x02\x00\x65\x74\x68\x74\x6f\x6f\x6c\x00\x06\x00\x01\x00\x14\x00\x00\x00\x08\x00\x03\x00\x01\x00\x00\x00"...], iov_len=65536}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 956
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base=[{nlmsg_len=36, nlmsg_type=NLMSG_ERROR, nlmsg_flags=NLM_F_CAPPED, nlmsg_seq=1, nlmsg_pid=8115}, {error=0, msg={nlmsg_len=32, nlmsg_type=0x10 /* NLMSG_??? */, nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=1, nlmsg_pid=0}}], iov_len=65536}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 36
sendto(3, [{nlmsg_len=76, nlmsg_type=0x14 /* NLMSG_??? */, nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=2, nlmsg_pid=0}, "\x1f\x01\x00\x00\x10\x00\x01\x80\x09\x00\x02\x00\x6f\x73\x63\x45\x00\x00\x00\x00\x08\x00\x03\x00\x01\x00\x00\x00\x08\x00\x02\x00"...], 76, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 76
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base=[{nlmsg_len=96, nlmsg_type=NLMSG_ERROR, nlmsg_flags=0, nlmsg_seq=2, nlmsg_pid=8115}, {error=-EIO, msg=[{nlmsg_len=76, nlmsg_type=0x14 /* NLMSG_??? */, nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=2, nlmsg_pid=0}, "\x1f\x01\x00\x00\x10\x00\x01\x80\x09\x00\x02\x00\x6f\x73\x63\x45\x00\x00\x00\x00\x08\x00\x03\x00\x01\x00\x00\x00\x08\x00\x02\x00"...]}], iov_len=65536}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 96
dup(2) = 4
fcntl64(4, F_GETFL) = 0x2 (flags O_RDWR)
statx(4, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, STATX_BASIC_STATS, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFCHR|0620, stx_size=0, ...}) = 0
write(4, "netlink error: Input/output erro"..., 34netlink error: Input/output error
I have no clue whether the igb driver actually supports this feature. If
not, we should be able to read the info from the module's EEPROM
directly via the bit-banged I2C bus (as provided by the igb driver,
after all), but then `ethtool` appears to be really, really focusing on
working over netlink, and it doesn't seem to support "offline" parsing
of EEPROM dumps...
[1] strace/strace#314
Change-Id: Id1bc237726e2911ebbd3c8cf2708cc2280ed4000
0 commit comments