Re: sfp module info and diagnostics
On 8.4.2019. 22:13, Stuart Henderson wrote: > On 2019/04/08 19:55, Hrvoje Popovski wrote: >> On 8.4.2019. 11:33, David Gwynne wrote: >>> this updates the ifconfig part of the diff >> This is great feature... thank you .. >> it would be great if dBm could be exported via snmp :) > You can do this via net-snmp already: > http://sysadvent.blogspot.com/2008/12/day-4-extending-net-snmps-snmpd.html?m=1 > > Better integration would be nice one day, but it adds complication (not > least it wants some caching mechanism, rather than triggering a slow NIC > operation every time a query comes in), and what already works is enough > to save a lot of time, disruption and expense (especially if €quinix > £emote hand$ are involved!) moving fibres to alternative equipment to > check light levels. Which is why I deliberately didn't mention the > S word ;) > ok ok, no S word :)
Re: sfp module info and diagnostics
On 8.4.2019. 19:55, Hrvoje Popovski wrote: > On 8.4.2019. 11:33, David Gwynne wrote: >> this updates the ifconfig part of the diff > > This is great feature... thank you .. maybe to put laser wavelength in sff output? ix0 - 1000BASE-LX x3550m4# ifconfig ix0 sff ix0: identifier SFP (03) connector: LC (07) vendor: FiberStore product: SFP1G-LX-31 revision: (unknown) serial: F175EX02389 date: 2017-05-31 temperature: 39.33 C vcc: 3.39 V tx-bias: 15.35 mA tx-power: -6.13 dBm rx-power: -5.58 dBm average SFP 33 Temperature = 31.285C SFP 33 Voltage = 3.333V SFP 33 Tx Bias Current = 18.400mA SFP 33 Tx Power = -6.0467dBm SFP 33 Rx Power = -5.1670dBm ix0 - 10GBASE-ER x3550m4# ifconfig ix0 sff ix0: identifier SFP (03) connector: LC (07) vendor: OEM product: CSS-907A15DE-15 revision: 1.0 serial: 1803070025 date: 2018-03-08 temperature: 37.88 C vcc: 3.31 V tx-bias: 72.39 mA tx-power: 0.90 dBm rx-power: -0.14 dBm average SFP+ 33 Temperature = 24.453C SFP+ 33 Voltage = 3.252V SFP+ 33 Tx Bias Current = 74.740mA SFP+ 33 Tx Power = 1.1598dBm SFP+ 33 Rx Power = -0.4479dBm it's strange that with ix0 media is 10GSFP+Cu. i think that is should be 10GbaseER ? ix0: flags=8843 mtu 1500 media: Ethernet autoselect (10GSFP+Cu full-duplex,rxpause,txpause) status: active supported media: media 10GSFP+Cu media autoselect ixl1 - 10GBASE-SR x3550m4# ifconfig ixl1 sff ixl1: identifier SFP (03) connector: LC (07) vendor: OEM product: 10GB-SFP-SR-H revision: 10 serial: HXP96S02 date: 2014-03-03 temperature: 30.80 C vcc: 3.33 V tx-bias: 5.85 mA tx-power: -3.31 dBm rx-power: -4.40 dBm average SFP+ 34 Temperature = 35.398C SFP+ 34 Voltage = 3.277V SFP+ 34 Tx Bias Current = 10.884mA SFP+ 34 Tx Power = -2.6930dBm SFP+ 34 Rx Power = -3.3838dBm
Re: sfp module info and diagnostics
FWIW (I was interested so put something together), here's a sample diff on top with one method of printing alarms. (I went for the < > checks rather than table 3.18 flag bits, mostly because I didn't fancy the "check again after 100ms" that the latter wanted). --- sff.c.orig Mon Apr 8 22:27:45 2019 +++ sff.c Mon Apr 8 22:46:34 2019 @@ -202,6 +202,10 @@ static const char *sff8024_con_names[] = { #define SFF8472_DDM_TEC108 /* Measured TEC current */ /* optional */ +#define ALRM_LOW_OFFSET2 +#define WARN_HIGH_OFFSET 4 +#define WARN_LOW_OFFSET6 + #define SFF_TEMP_FACTOR256.0 #define SFF_VCC_FACTOR 1.0 #define SFF_BIAS_FACTOR500.0 @@ -380,6 +384,27 @@ if_sff_power2dbm(uint16_t power) return (10.0 * log10f((float)power / 1.0)); } +static const char * +if_sff_alarm(struct if_sffpage *ddm, size_t value) +{ + /* SFF-8472 table 3.15 */ + size_t alrm_high = (value-96) * 4; + size_t alrm_low = alrm_high + ALRM_LOW_OFFSET; + size_t warn_high = alrm_high + WARN_HIGH_OFFSET; + size_t warn_low = alrm_high + WARN_LOW_OFFSET; + + if(if_sff_int(ddm, value) > if_sff_int(ddm, alrm_high)) + return " (HIGH ALARM)"; + else if(if_sff_int(ddm, value) < if_sff_int(ddm, alrm_low)) + return " (LOW ALARM)"; + else if(if_sff_int(ddm, value) > if_sff_int(ddm, warn_high)) + return " (HIGH WARNING)"; + else if(if_sff_int(ddm, value) < if_sff_int(ddm, warn_low)) + return " (LOW WARNING)"; + + return ""; +} + static int if_sff8472(int s, const char *ifname, int dump, const struct if_sffpage *pg0) { @@ -416,17 +441,22 @@ if_sff8472(int s, const char *ifname, int dump, const "(WARNING: needs more code)\n"); } - printf("\ttemperature: %.02f C\n", - if_sff_int(&ddm, SFF8472_DDM_TEMP) / SFF_TEMP_FACTOR); - printf("\tvcc: %.02f V\n", - if_sff_uint(&ddm, SFF8472_DDM_VCC) / SFF_VCC_FACTOR); - printf("\ttx-bias: %.02f mA\n", - if_sff_uint(&ddm, SFF8472_DDM_TX_BIAS) / SFF_BIAS_FACTOR); - printf("\ttx-power: %.02f dBm\n", - if_sff_power2dbm(if_sff_uint(&ddm, SFF8472_DDM_TX_POWER))); - printf("\trx-power: %.02f dBm %s\n", + printf("\ttemperature: %.02f C%s\n", + if_sff_int(&ddm, SFF8472_DDM_TEMP) / SFF_TEMP_FACTOR, + if_sff_alarm(&ddm, SFF8472_DDM_TEMP)); + printf("\tvcc: %.02f V%s\n", + if_sff_uint(&ddm, SFF8472_DDM_VCC) / SFF_VCC_FACTOR, + if_sff_alarm(&ddm, SFF8472_DDM_VCC)); + printf("\ttx-bias: %.02f mA%s\n", + if_sff_uint(&ddm, SFF8472_DDM_TX_BIAS) / SFF_BIAS_FACTOR, + if_sff_alarm(&ddm, SFF8472_DDM_TX_BIAS)); + printf("\ttx-power: %.02f dBm%s\n", + if_sff_power2dbm(if_sff_uint(&ddm, SFF8472_DDM_TX_POWER)), + if_sff_alarm(&ddm, SFF8472_DDM_TX_BIAS)); + printf("\trx-power: %.02f dBm %s%s\n", if_sff_power2dbm(if_sff_uint(&ddm, SFF8472_DDM_RX_POWER)), - ISSET(ddm_types, SFF8472_DDM_TYPE_AVG_POWER) ? "average" : "OMA"); + ISSET(ddm_types, SFF8472_DDM_TYPE_AVG_POWER) ? "average" : "OMA", + if_sff_alarm(&ddm, SFF8472_DDM_RX_POWER)); return (0); }
Re: sfp module info and diagnostics
On 2019/04/08 19:55, Hrvoje Popovski wrote: > On 8.4.2019. 11:33, David Gwynne wrote: > > this updates the ifconfig part of the diff > > This is great feature... thank you .. > it would be great if dBm could be exported via snmp :) You can do this via net-snmp already: http://sysadvent.blogspot.com/2008/12/day-4-extending-net-snmps-snmpd.html?m=1 Better integration would be nice one day, but it adds complication (not least it wants some caching mechanism, rather than triggering a slow NIC operation every time a query comes in), and what already works is enough to save a lot of time, disruption and expense (especially if €quinix £emote hand$ are involved!) moving fibres to alternative equipment to check light levels. Which is why I deliberately didn't mention the S word ;) > x3550m4# ifconfig ix0 sff > ix0: identifier SFP (03) > connector: LC (07) > vendor: Intel Corp > product: FTLX8571D3BCV-IT > revision: A > serial: MTB07YW > date: 2015-03-26 > temperature: 39.21 C > vcc: 3.36 V > tx-bias: 7.97 mA > tx-power: -2.66 dBm > rx-power: -4.22 dBm average > > > switch side > SFP+ 33 Temperature = 32.133C > SFP+ 33 Voltage = 3.283V > SFP+ 33 Tx Bias Current = 10.728mA > SFP+ 33 Tx Power = -2.6978dBm > SFP+ 33 Rx Power = -2.2643dBm > > dBm values on openbsd and switch should be similar, right ? It depends .. When I tested, openbsd<>flexbox, the values were different for each SFP, but swapping the SFPs between the devices, the values followed the SFP. This does make sense though. Typically you have two strands of fibre and different connectors which can behave differently (or in the other case with bidi, losses are a little higher for one wavelength than the other). Also the SFPs are individual devices with manufacturing differences, some will be better than others.
Re: sfp module info and diagnostics
David Gwynne(da...@gwynne.id.au) on 2019.04.08 19:33:53 +1000: > this updates the ifconfig part of the diff > > it should have the following improvements: > > - actually applying to -current (thanks hrvoje) > - use vis(3) when printing the strings out (thanks deraadt@) > - make the code less special > - use %.02f for the diag values consistently, and more sane units > (thanks mikeb@) > > mikeb also suggested showing dBm instead of watts for power. this adds > it, but uses log10f, which in turn uses libm. is that ok/worth it? yes, dBm is what you need to see if the link checks out. Actually printing both would be nice. ethtool has Laser output power: 0.4939 mW / -3.06 dBm but if you dont like that, dBm is preferable. Thanks for doing this! > > ix1 now looks like this: > > dlg@ix ifconfig$ sudo ./obj/ifconfig ix1 sff > ix1: identifier SFP (03) > connector: LC (07) > vendor: FINISAR CORP. > product: FTLX8571D3BCL-FC > revision: A > serial: AQG28W3 > date: 2013-10-19 > temperature: 34.88 C > vcc: 3.36 V > tx-bias: 7.97 mA > tx-power: -2.11 dBm > rx-power: -2.13 dBm average > > the other end (so you can compare): > > eait-78-520-16-1#sh int te0/6 trans > Interface Name : TenGigabitEthernet 0/6 > SFP+ is present > SFP+ 6 Serial Base ID fields > SFP+ 6 Id = 0x03 > SFP+ 6 Ext Id = 0x04 > SFP+ 6 Connector= 0x07 > SFP+ 6 Transceiver Code = 0x10 0x00 0x00 0x00 0x00 0x00 > 0x00 0x00 > SFP+ 6 Encoding = 0x06 > SFP+ 6 BR Nominal = 0x67 > SFP+ 6 Length(SFM)Km= 0x00 > SFP+ 6 Length(SFM) 100m= 0x00 > SFP+ 6 Length(OM3) 10m= 0x1e > SFP+ 6 Length(OM2) 10m= 0x08 > SFP+ 6 Length(OM1) 10m= 0x03 > SFP+ 6 Length(Copper-1m/AOC-1m/OM4-10m) = 0x00 > SFP+ 6 Vendor Rev = A > SFP+ 6 Laser Wavelength = 850 nm > SFP+ 6 CheckCodeBase= 0x9e > SFP+ 6 Serial Extended ID fields > SFP+ 6 Options = 0x00 0x1a > SFP+ 6 BR max = 0 > SFP+ 6 BR min = 0 > SFP+ 6 Vendor SN= AQG2A7A > SFP+ 6 Datecode = 131020 > SFP+ 6 CheckCodeExt = 0xc0 > SFP+ 6 Extended Transceiver Code= 0x00 > > SFP+ 6 Diagnostic Information > === > SFP+ 6 Rx Power measurement type= Average > === > SFP+ 6 Temp High Alarm threshold= 78.000C > SFP+ 6 Voltage High Alarm threshold = 3.700V > SFP+ 6 Bias High Alarm threshold= 13.200mA > SFP+ 6 TX Power High Alarm threshold= 0.dBm > SFP+ 6 RX Power High Alarm threshold= 0.dBm > SFP+ 6 Temp Low Alarm threshold = -13.000C > SFP+ 6 Voltage Low Alarm threshold = 2.900V > SFP+ 6 Bias Low Alarm threshold = 4.000mA > SFP+ 6 TX Power Low Alarm threshold = -5.9998dBm > SFP+ 6 RX Power Low Alarm threshold = -20.dBm > === > SFP+ 6 Temp High Warning threshold = 73.000C > SFP+ 6 Voltage High Warning threshold = 3.600V > SFP+ 6 Bias High Warning threshold = 12.600mA > SFP+ 6 TX Power High Warning threshold = -1.0002dBm > SFP+ 6 RX Power High Warning threshold = -1.0002dBm > SFP+ 6 Temp Low Warning threshold = -8.000C > SFP+ 6 Voltage Low Warning threshold= 3.000V > SFP+ 6 Bias Low Warning threshold = 5.000mA > SFP+ 6 TX Power Low Warning threshold = -5.0004dBm > SFP+ 6 RX Power Low Warning threshold = -18.0134dBm > === > SFP+ 6 Temperature = 48.875C > SFP+ 6 Voltage = 3.338V > SFP+ 6 Tx Bias Current = 8.660mA > SFP+ 6 Tx Power = -2.4260dBm > SFP+ 6 Rx Power = -2.2243dBm > === > SFP+ 6 Data Ready state Bar = False > SFP+ 6 Rx LOS state = False > SFP+ 6 Tx Fault state = False > SFP+ 6 Rate Select state= False > SFP+ 6 RS state = False > SFP+ 6 Tx Disable state = False > === > SFP+ 6 Temperature High Alarm Flag = False > SFP+ 6 Voltage High Alarm Flag = False > SFP+ 6 Tx Bias High Alarm Flag = False > SFP+ 6 Tx Power High Alarm Flag = False > SFP+ 6 Rx Power High Alarm Flag = False > SFP+ 6 Temperature Low Alarm Flag = False > SFP+ 6 Voltage Low Alarm Flag = False > SFP+ 6 Tx Bias Low Alarm Flag = False > SFP+ 6 Tx Power Low Alarm Flag = False > SFP+ 6 Rx Power Low Al
Re: sfp module info and diagnostics
On 8.4.2019. 11:33, David Gwynne wrote: > this updates the ifconfig part of the diff This is great feature... thank you .. it would be great if dBm could be exported via snmp :) switch - Dell S4810 ix0 - sfp+ 10GBASE-SR optics ix1 - sfp 1000BASE-SX optics ixl0 - 10G passive DAC cables x3550m4# ifconfig ix0 sff ix0: identifier SFP (03) connector: LC (07) vendor: Intel Corp product: FTLX8571D3BCV-IT revision: A serial: MTB07YW date: 2015-03-26 temperature: 39.21 C vcc: 3.36 V tx-bias: 7.97 mA tx-power: -2.66 dBm rx-power: -4.22 dBm average switch side SFP+ 33 Temperature = 32.133C SFP+ 33 Voltage = 3.283V SFP+ 33 Tx Bias Current = 10.728mA SFP+ 33 Tx Power = -2.6978dBm SFP+ 33 Rx Power = -2.2643dBm dBm values on openbsd and switch should be similar, right ? x3550m4# ifconfig ix1 sff ix1: identifier SFP (03) connector: LC (07) vendor: CISCO-FINISAR product: FTRJ-8519-7D-CSC revision: (unknown) serial: H11H167 date: 2004-01-23 x3550m4# ifconfig ixl0 sff ixl0: identifier SFP (03) connector: Copper Pigtail (21) vendor: Amphenol product: 616740005 revision: C serial: CN0358VV6751650 date: 2016-07-07
Re: sfp module info and diagnostics
On 2019/04/08 13:57, Stuart Henderson wrote: > Here's a complete diff. Tested on amd64 with ix, working great there. > distrib/special/ifconfig still builds okay, I'll run a full mkr later on > i386/amd64. > > This is extremely useful for the bgpd "target market" ;) oops, here's attempt #2 with the missing piece. Index: sbin/ifconfig/Makefile === RCS file: /cvs/src/sbin/ifconfig/Makefile,v retrieving revision 1.14 diff -u -p -r1.14 Makefile --- sbin/ifconfig/Makefile 3 May 2016 17:52:33 - 1.14 +++ sbin/ifconfig/Makefile 8 Apr 2019 13:01:28 - @@ -1,10 +1,10 @@ # $OpenBSD: Makefile,v 1.14 2016/05/03 17:52:33 jca Exp $ PROG= ifconfig -SRCS= ifconfig.c brconfig.c +SRCS= ifconfig.c brconfig.c sff.c MAN= ifconfig.8 -LDADD= -lutil +LDADD= -lutil -lm DPADD= ${LIBUTIL} .include Index: sbin/ifconfig/ifconfig.c === RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v retrieving revision 1.397 diff -u -p -r1.397 ifconfig.c --- sbin/ifconfig/ifconfig.c11 Mar 2019 11:25:48 - 1.397 +++ sbin/ifconfig/ifconfig.c8 Apr 2019 13:01:28 - @@ -340,6 +340,8 @@ voidumb_setclass(const char *, int); void umb_roaming(const char *, int); void utf16_to_char(uint16_t *, int, char *, size_t); intchar_to_utf16(const char *, uint16_t *, size_t); +void transceiver(const char *, int); +void transceiverdump(const char *, int); #else void setignore(const char *, int); #endif @@ -589,6 +591,9 @@ const structcmd { { "datapath", NEXTARG,0, switch_datapathid }, { "portno", NEXTARG2, 0, NULL, switch_portno }, { "addlocal", NEXTARG,0, addlocal }, + { "transceiver", 0, 0, transceiver }, + { "sff",0, 0, transceiver }, + { "sffdump",0, 0, transceiverdump }, #else /* SMALL */ { "powersave", NEXTARG0, 0, setignore }, { "priority", NEXTARG,0, setignore }, @@ -4033,6 +4038,22 @@ unsetpwe3neighbor(const char *val, int d if (ioctl(s, SIOCDPWE3NEIGHBOR, &req) == -1) warn("-pweneighbor"); +} + +intif_sff_info(int, const char *, int); + +void +transceiver(const char *value, int d) +{ + if (if_sff_info(s, name, 0) == -1) + err(1, "%s %s", name, __func__); +} + +void +transceiverdump(const char *value, int d) +{ + if (if_sff_info(s, name, 1) == -1) + err(1, "%s transceiver", name); } #endif /* SMALL */ Index: sbin/ifconfig/sff.c === RCS file: sbin/ifconfig/sff.c diff -N sbin/ifconfig/sff.c --- /dev/null 1 Jan 1970 00:00:00 - +++ sbin/ifconfig/sff.c 8 Apr 2019 13:01:28 - @@ -0,0 +1,464 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef SMALL + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +#ifndef ISSET +#define ISSET(_w, _m) ((_w) & (_m)) +#endif + +#define SFF8024_ID_UNKNOWN 0x00 +#define SFF8024_ID_GBIC0x01 +#define SFF8024_ID_MOBO0x02 /* Module/connector soldered to mobo */ +/* using SFF-8472 */ +#define SFF8024_ID_SFP 0x03 /* SFP/SFP+/SFP28 */ +#define SFF8024_ID_300PIN_XBI 0x04 /* 300 pin XBI */ +#define SFF8024_ID_XENPAK 0x05 +#define SFF8024_ID_XFP 0x06 +#define SFF8024_ID_XFF 0x07 +#define SFF8024_ID_XFPE0x08 /* XFP-E */ +#define SFF8024_ID_XPAK0x09 +#define SFF8024_ID_X2 0x0a +#define SFF8024_ID_DWDM_SFP0x0b /* DWDM-SFP/SFP+ */ +/* not using SFF-8472 */ +#define SFF8024_ID_QSFP0x0c +#define SFF8024_ID_QSFP_PLUS 0x0d /* or later */ +/* using SFF-8436/8665/8685 et
Re: sfp module info and diagnostics
Here's a complete diff. Tested on amd64 with ix, working great there. distrib/special/ifconfig still builds okay, I'll run a full mkr later on i386/amd64. This is extremely useful for the bgpd "target market" ;) Index: sbin/ifconfig/Makefile === RCS file: /cvs/src/sbin/ifconfig/Makefile,v retrieving revision 1.14 diff -u -p -r1.14 Makefile --- sbin/ifconfig/Makefile 3 May 2016 17:52:33 - 1.14 +++ sbin/ifconfig/Makefile 8 Apr 2019 12:45:33 - @@ -1,10 +1,10 @@ # $OpenBSD: Makefile,v 1.14 2016/05/03 17:52:33 jca Exp $ PROG= ifconfig -SRCS= ifconfig.c brconfig.c +SRCS= ifconfig.c brconfig.c sff.c MAN= ifconfig.8 -LDADD= -lutil +LDADD= -lutil -lm DPADD= ${LIBUTIL} .include Index: sbin/ifconfig/ifconfig.c === RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v retrieving revision 1.397 diff -u -p -r1.397 ifconfig.c --- sbin/ifconfig/ifconfig.c11 Mar 2019 11:25:48 - 1.397 +++ sbin/ifconfig/ifconfig.c8 Apr 2019 12:45:33 - @@ -340,6 +340,8 @@ voidumb_setclass(const char *, int); void umb_roaming(const char *, int); void utf16_to_char(uint16_t *, int, char *, size_t); intchar_to_utf16(const char *, uint16_t *, size_t); +void transceiver(const char *, int); +void transceiverdump(const char *, int); #else void setignore(const char *, int); #endif @@ -589,6 +591,9 @@ const structcmd { { "datapath", NEXTARG,0, switch_datapathid }, { "portno", NEXTARG2, 0, NULL, switch_portno }, { "addlocal", NEXTARG,0, addlocal }, + { "transceiver", 0, 0, transceiver }, + { "sff",0, 0, transceiver }, + { "sffdump",0, 0, transceiverdump }, #else /* SMALL */ { "powersave", NEXTARG0, 0, setignore }, { "priority", NEXTARG,0, setignore }, @@ -4033,6 +4038,22 @@ unsetpwe3neighbor(const char *val, int d if (ioctl(s, SIOCDPWE3NEIGHBOR, &req) == -1) warn("-pweneighbor"); +} + +intif_sff_info(int, const char *, int); + +void +transceiver(const char *value, int d) +{ + if (if_sff_info(s, name, 0) == -1) + err(1, "%s %s", name, __func__); +} + +void +transceiverdump(const char *value, int d) +{ + if (if_sff_info(s, name, 1) == -1) + err(1, "%s transceiver", name); } #endif /* SMALL */ Index: sbin/ifconfig/sff.c === RCS file: sbin/ifconfig/sff.c diff -N sbin/ifconfig/sff.c --- /dev/null 1 Jan 1970 00:00:00 - +++ sbin/ifconfig/sff.c 8 Apr 2019 12:45:33 - @@ -0,0 +1,464 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef SMALL + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +#ifndef ISSET +#define ISSET(_w, _m) ((_w) & (_m)) +#endif + +#define SFF8024_ID_UNKNOWN 0x00 +#define SFF8024_ID_GBIC0x01 +#define SFF8024_ID_MOBO0x02 /* Module/connector soldered to mobo */ +/* using SFF-8472 */ +#define SFF8024_ID_SFP 0x03 /* SFP/SFP+/SFP28 */ +#define SFF8024_ID_300PIN_XBI 0x04 /* 300 pin XBI */ +#define SFF8024_ID_XENPAK 0x05 +#define SFF8024_ID_XFP 0x06 +#define SFF8024_ID_XFF 0x07 +#define SFF8024_ID_XFPE0x08 /* XFP-E */ +#define SFF8024_ID_XPAK0x09 +#define SFF8024_ID_X2 0x0a +#define SFF8024_ID_DWDM_SFP0x0b /* DWDM-SFP/SFP+ */ +/* not using SFF-8472 */ +#define SFF8024_ID_QSFP0x0c +#define SFF8024_ID_QSFP_PLUS 0x0d /* or later */ +/* using SFF-8436/8665/8685 et al */ +#define SFF8024_ID_CXP 0x0e /* or later */ +#define SFF8024_ID_HD4X0x0f /
Re: sfp module info and diagnostics
this updates the ifconfig part of the diff it should have the following improvements: - actually applying to -current (thanks hrvoje) - use vis(3) when printing the strings out (thanks deraadt@) - make the code less special - use %.02f for the diag values consistently, and more sane units (thanks mikeb@) mikeb also suggested showing dBm instead of watts for power. this adds it, but uses log10f, which in turn uses libm. is that ok/worth it? ix1 now looks like this: dlg@ix ifconfig$ sudo ./obj/ifconfig ix1 sff ix1: identifier SFP (03) connector: LC (07) vendor: FINISAR CORP. product: FTLX8571D3BCL-FC revision: A serial: AQG28W3 date: 2013-10-19 temperature: 34.88 C vcc: 3.36 V tx-bias: 7.97 mA tx-power: -2.11 dBm rx-power: -2.13 dBm average the other end (so you can compare): eait-78-520-16-1#sh int te0/6 trans Interface Name : TenGigabitEthernet 0/6 SFP+ is present SFP+ 6 Serial Base ID fields SFP+ 6 Id = 0x03 SFP+ 6 Ext Id = 0x04 SFP+ 6 Connector= 0x07 SFP+ 6 Transceiver Code = 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 SFP+ 6 Encoding = 0x06 SFP+ 6 BR Nominal = 0x67 SFP+ 6 Length(SFM)Km= 0x00 SFP+ 6 Length(SFM) 100m= 0x00 SFP+ 6 Length(OM3) 10m= 0x1e SFP+ 6 Length(OM2) 10m= 0x08 SFP+ 6 Length(OM1) 10m= 0x03 SFP+ 6 Length(Copper-1m/AOC-1m/OM4-10m) = 0x00 SFP+ 6 Vendor Rev = A SFP+ 6 Laser Wavelength = 850 nm SFP+ 6 CheckCodeBase= 0x9e SFP+ 6 Serial Extended ID fields SFP+ 6 Options = 0x00 0x1a SFP+ 6 BR max = 0 SFP+ 6 BR min = 0 SFP+ 6 Vendor SN= AQG2A7A SFP+ 6 Datecode = 131020 SFP+ 6 CheckCodeExt = 0xc0 SFP+ 6 Extended Transceiver Code= 0x00 SFP+ 6 Diagnostic Information === SFP+ 6 Rx Power measurement type= Average === SFP+ 6 Temp High Alarm threshold= 78.000C SFP+ 6 Voltage High Alarm threshold = 3.700V SFP+ 6 Bias High Alarm threshold= 13.200mA SFP+ 6 TX Power High Alarm threshold= 0.dBm SFP+ 6 RX Power High Alarm threshold= 0.dBm SFP+ 6 Temp Low Alarm threshold = -13.000C SFP+ 6 Voltage Low Alarm threshold = 2.900V SFP+ 6 Bias Low Alarm threshold = 4.000mA SFP+ 6 TX Power Low Alarm threshold = -5.9998dBm SFP+ 6 RX Power Low Alarm threshold = -20.dBm === SFP+ 6 Temp High Warning threshold = 73.000C SFP+ 6 Voltage High Warning threshold = 3.600V SFP+ 6 Bias High Warning threshold = 12.600mA SFP+ 6 TX Power High Warning threshold = -1.0002dBm SFP+ 6 RX Power High Warning threshold = -1.0002dBm SFP+ 6 Temp Low Warning threshold = -8.000C SFP+ 6 Voltage Low Warning threshold= 3.000V SFP+ 6 Bias Low Warning threshold = 5.000mA SFP+ 6 TX Power Low Warning threshold = -5.0004dBm SFP+ 6 RX Power Low Warning threshold = -18.0134dBm === SFP+ 6 Temperature = 48.875C SFP+ 6 Voltage = 3.338V SFP+ 6 Tx Bias Current = 8.660mA SFP+ 6 Tx Power = -2.4260dBm SFP+ 6 Rx Power = -2.2243dBm === SFP+ 6 Data Ready state Bar = False SFP+ 6 Rx LOS state = False SFP+ 6 Tx Fault state = False SFP+ 6 Rate Select state= False SFP+ 6 RS state = False SFP+ 6 Tx Disable state = False === SFP+ 6 Temperature High Alarm Flag = False SFP+ 6 Voltage High Alarm Flag = False SFP+ 6 Tx Bias High Alarm Flag = False SFP+ 6 Tx Power High Alarm Flag = False SFP+ 6 Rx Power High Alarm Flag = False SFP+ 6 Temperature Low Alarm Flag = False SFP+ 6 Voltage Low Alarm Flag = False SFP+ 6 Tx Bias Low Alarm Flag = False SFP+ 6 Tx Power Low Alarm Flag = False SFP+ 6 Rx Power Low Alarm Flag = False === SFP+ 6 Temperature High Warning Flag= False SFP+ 6 Voltage High Warning Flag= False SFP+ 6 Tx Bias High Warning Flag= False SFP+ 6 Tx Power High Warning Flag = False SFP+ 6 Rx Power High Warning Flag = False SFP+ 6 Temperature Low Warning Flag = False SFP+ 6 Voltage Low Warning Flag = False SFP+ 6 Tx Bias Low Warning Flag = False SFP+ 6 Tx Power Low Warning Flag= False SFP+ 6 Rx Power Low W
sfp module info and diagnostics
this adds support to ifconfig for reading info from transceivers. it looks like this: dlg@ix ifconfig$ sudo ./obj/ifconfig ix0 transceiver ix0: identifier SFP (03) connector: Copper Pigtail (21) vendor: Amphenol product: 616740001 revision: B serial: CN0V250M36J0T86 date: 2013-07-04 dlg@ix ifconfig$ sudo ./obj/ifconfig ix1 transceiver ix1: identifier SFP (03) connector: LC (07) vendor: FINISAR CORP. product: FTLX8571D3BCL-FC revision: A serial: AQG28W3 date: 2013-10-19 temperature: 34.60 C vcc: 3.3553 V tx-bias: 7986.0 uA tx-power: 0.6128 mW rx-power: 0.6153 mW average dlg@ix ifconfig$ sudo ./obj/ifconfig ixl0 transceiver ixl0: identifier QSFP+ (0d) this is all specified by the SFF (small formfactor) group in SNIA, but it is a lot of disparate documentation to get into your head. the top level summary is that sfp modules have an i2c bus wired up to them, and answer reads at device address 0xa0. there is a 256 byte page at that address with information like the type of module, and depending on the type you can find the manufacturer, product name, serial number, and so on. a later spec added support a "digital diagnostics monitoring" (DDM) or "digital optical monitoring" (DOM) capability where there's live status/diag information available at i2c address 0xa2. again, it's a 256 byte page, but the values change all the time based on what the module is doing. this is where the temperature and laser power stuff is. ive implemented basic support for the above, which is specific to some sfp shaped modules (so sfp+ and sfp28 too) and gbics. devices report whether they support the diag page, so it only fetches and parses that if page 0 on 0xa0 says it can. there are different specs for the other types of modules, in particular qsfp and related modules have a very different layout. however, they still use the same device addresses and pages, it's just that the contents of the page vary. support for qsfp will be forthcoming if this goes ahead. dumping more info generally will happen as time and interest permits too. i've only implemented the kernel backend for this on ix and ixl. ixl support is patchy because it relies on a command that only exists in high API versions (like 1.7). ix seems pretty consistent. other nics can grow support as time and hw availability permites. i don't have an em(4) with optics, so that might be hard for me to do myself, but i tried to make the kernel side as easy as possible so people should have a good chance at figuring it out. do those power units sound plausible or are the factors off? this was originally requested by rachel roch on misc@ in "Viewing SFP diagnostic data in OpenBSD ?" thoughts? Index: sys/sys/sockio.h === RCS file: /cvs/src/sys/sys/sockio.h,v retrieving revision 1.80 diff -u -p -r1.80 sockio.h --- sys/sys/sockio.h26 Feb 2019 03:19:11 - 1.80 +++ sys/sys/sockio.h8 Apr 2019 02:05:36 - @@ -68,6 +68,7 @@ /* 53 and 54 used to be SIOC[SG]IFMEDIA with a 32 bit media word */ #defineSIOCSIFMEDIA_IOWR('i', 55, struct ifreq)/* set net media */ #defineSIOCGIFMEDIA_IOWR('i', 56, struct ifmediareq) /* get net media */ +#defineSIOCGIFSFFPAGE _IOWR('i', 57, struct if_sffpage) /* get SFF page */ #defineSIOCDIFPHYADDR _IOW('i', 73, struct ifreq)/* delete gif addrs */ #defineSIOCSLIFPHYADDR _IOW('i', 74, struct if_laddrreq) /* set gif addrs */ Index: sys/net/if.c === RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.573 diff -u -p -r1.573 if.c --- sys/net/if.c1 Mar 2019 04:47:32 - 1.573 +++ sys/net/if.c8 Apr 2019 02:05:36 - @@ -144,6 +144,8 @@ int if_detached_ioctl(struct ifnet *, u_ intifioctl_get(u_long, caddr_t); intifconf(caddr_t); +static int + if_sffpage_check(const caddr_t); intif_getgroup(caddr_t, struct ifnet *); intif_getgroupmembers(caddr_t); @@ -2143,6 +2172,19 @@ ifioctl(struct socket *so, u_long cmd, c NET_UNLOCK(); break; + case SIOCGIFSFFPAGE: + error = suser(p); + if (error != 0) + break; + + error = if_sffpage_check(data); + if (error != 0) + break; + + /* don't take NET_LOCK because i2c reads take a long time */ + error = ((*ifp->if_ioctl)(ifp, cmd, data)); + break; + case SIOCSETKALIVE: case SIOCDIFPHYADDR: case SIOCSLIFPHYADDR: @@ -2304,6 +2346,22 @@ ifioctl_get(u_long cmd, caddr_t data) return (error); } +static int +if_sffpage_check(const caddr_t data) +{ + const struct if_sffpage *sff = (const struct if_sffpage *)data;