Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144184649
D25494.id73796.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
39 KB
Referenced Files
None
Subscribers
None
D25494.id73796.diff
View Options
Index: lib/libifconfig/Makefile
===================================================================
--- lib/libifconfig/Makefile
+++ lib/libifconfig/Makefile
@@ -13,7 +13,8 @@
libifconfig_inet6.c \
libifconfig_internal.c \
libifconfig_lagg.c \
- libifconfig_media.c
+ libifconfig_media.c \
+ libifconfig_sfp.c
# If libifconfig become public uncomment those two lines
#INCSDIR= ${INCLUDEDIR}
Index: lib/libifconfig/libifconfig_sfp.h
===================================================================
--- /dev/null
+++ lib/libifconfig/libifconfig_sfp.h
@@ -0,0 +1,474 @@
+/*-
+ * Copyright (c) 2014 Alexander V. Chernikov. All rights reserved.
+ * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <libifconfig.h>
+
+struct ifconfig_sfp_info;
+struct ifconfig_sfp_info_strings;
+
+#define SFF_VENDOR_STRING_SIZE 16
+#define SFF_VENDOR_DATE_SIZE 6
+
+struct ifconfig_sfp_vendor_info {
+ char name[SFF_VENDOR_STRING_SIZE + 1];
+ char pn[SFF_VENDOR_STRING_SIZE + 1];
+ char sn[SFF_VENDOR_STRING_SIZE + 1];
+ char date[SFF_VENDOR_DATE_SIZE + 5];
+};
+
+struct ifconfig_sfp_status {
+ double temp;
+ double voltage;
+ struct {
+ uint16_t rx;
+ uint16_t tx;
+ } power[4];
+ uint32_t bitrate;
+};
+
+#define SFF_DUMP_SIZE 256
+
+#define SFP_DUMP_START 0
+#define SFP_DUMP_SIZE 128
+
+#define QSFP_DUMP0_START 0
+#define QSFP_DUMP0_SIZE 82
+#define QSFP_DUMP1_START 128
+#define QSFP_DUMP1_SIZE 128
+
+struct ifconfig_sfp_dump {
+ uint8_t data[SFF_DUMP_SIZE];
+ bool qsfp;
+};
+
+int ifconfig_sfp_get_sfp_info(ifconfig_handle_t *h, const char *name,
+ struct ifconfig_sfp_info *sfp);
+
+void ifconfig_sfp_get_sfp_info_strings(struct ifconfig_sfp_info *sfp,
+ struct ifconfig_sfp_info_strings *strings);
+
+int ifconfig_sfp_get_sfp_vendor_info(ifconfig_handle_t *h, const char *name,
+ struct ifconfig_sfp_vendor_info *vi);
+
+int ifconfig_sfp_get_sfp_status(ifconfig_handle_t *h, const char *name,
+ struct ifconfig_sfp_status *ss);
+
+double mW_to_dBm(uint16_t);
+
+int ifconfig_sfp_get_sfp_dump(ifconfig_handle_t *h, const char *name,
+ struct ifconfig_sfp_dump *buf);
+
+enum sfp_id;
+const char *ifconfig_sfp_id_debug(enum sfp_id);
+const char *ifconfig_sfp_id_string(enum sfp_id);
+const char *ifconfig_sfp_id_description(enum sfp_id);
+
+enum sfp_conn;
+const char *ifconfig_sfp_conn_debug(enum sfp_conn);
+const char *ifconfig_sfp_conn_string(enum sfp_conn);
+
+enum sfp_eth_10g;
+const char *ifconfig_sfp_eth_10g_debug(enum sfp_eth_10g);
+const char *ifconfig_sfp_eth_10g_string(enum sfp_eth_10g);
+
+enum sfp_eth;
+const char *ifconfig_sfp_eth_debug(enum sfp_eth);
+const char *ifconfig_sfp_eth_string(enum sfp_eth);
+
+enum sfp_fc_len;
+const char *ifconfig_sfp_fc_len_debug(enum sfp_fc_len);
+const char *ifconfig_sfp_fc_len_string(enum sfp_fc_len);
+
+enum sfp_cab_tech;
+const char *ifconfig_sfp_cab_tech_debug(enum sfp_cab_tech);
+const char *ifconfig_sfp_cab_tech_string(enum sfp_cab_tech);
+
+enum sfp_fc_media;
+const char *ifconfig_sfp_fc_media_debug(enum sfp_fc_media);
+const char *ifconfig_sfp_fc_media_string(enum sfp_fc_media);
+
+enum sfp_fc_speed;
+const char *ifconfig_sfp_fc_speed_debug(enum sfp_fc_speed);
+const char *ifconfig_sfp_fc_speed_string(enum sfp_fc_speed);
+
+enum sfp_eth_1040g;
+const char *ifconfig_sfp_eth_1040g_debug(enum sfp_eth_1040g);
+const char *ifconfig_sfp_eth_1040g_string(enum sfp_eth_1040g);
+
+enum sfp_eth_ext;
+const char *ifconfig_sfp_eth_ext_debug(enum sfp_eth_ext);
+const char *ifconfig_sfp_eth_ext_string(enum sfp_eth_ext);
+
+enum sfp_rev;
+const char *ifconfig_sfp_rev_debug(enum sfp_rev);
+const char *ifconfig_sfp_rev_string(enum sfp_rev);
+
+#define $_ENUM_ITEM(_enum, prefix, name, num) prefix##name = (num),
+#define $ENUM_ITEM($$, name, num) $_ENUM_ITEM($$, name, num)
+
+#define $_ENUM($, enu, pre) enum enu { pre##MAP($) }
+#define $ENUM($, $$) $_ENUM($, $$)
+
+/* SFF-8024 Rev. 4.6 Table 4-1: Indentifier Values */
+/* enum, symbol, display, description */
+#define SFP_ID_MAP($) \
+ $(0x00, UNKNOWN, Unknown, Unknown or unspecified) \
+ $(0x01, GBIC, GBIC, GBIC) \
+ $(0x02, SFF, SFF, \
+ Module soldered to motherboard (ex: SFF)) \
+ $(0x03, SFP, SFP/SFP+/SFP28, SFP or SFP+) \
+ $(0x04, XBI, XBI, 300 pin XBI) \
+ $(0x05, XENPAK, Xenpak, Xenpak) \
+ $(0x06, XFP, XFP, XFP) \
+ $(0x07, XFF, XFF, XFF) \
+ $(0x08, XFPE, XFP-E, XFP-E) \
+ $(0x09, XPAK, XPAK, XPAK) \
+ $(0x0A, X2, X2, X2) \
+ $(0x0B, DWDM_SFP, DWDM-SFP/SFP+, DWDM-SFP/SFP+) \
+ $(0x0C, QSFP, QSFP, QSFP) \
+ $(0x0D, QSFPPLUS, QSFP+, QSFP+ or later) \
+ $(0x0E, CXP, CXP, CXP) \
+ $(0x0F, HD4X, HD4X, Shielded Mini Multilane HD 4X) \
+ $(0x10, HD8X, HD8X, Shielded Mini Multilane HD 8X) \
+ $(0x11, QSFP28, QSFP28, QSFP28 or later) \
+ $(0x12, CXP2, CXP2, CXP2 (aka CXP28)) \
+ $(0x13, CDFP, CDFP, CDFP (Style 1/Style 2)) \
+ $(0x14, SMM4, SMM4, \
+ Shielded Mini Multilane HD 4X fanout) \
+ $(0x15, SMM8, SMM8, \
+ Shielded Mini Multilane HD 8X fanout) \
+ $(0x16, CDFP3, CDFP3, CDFP (Style 3)) \
+ $(0x17, MICROQSFP, microQSFP, microQSFP) \
+ $(0x18, QSFP_DD, QSFP-DD, \
+ QSFP-DD 8X pluggable transceiver) \
+ $(0x19, QSFP8X, QSFP8X, QSFP 8X pluggable transceiver) \
+ $(0x1A, SFP_DD, SFP-DD, \
+ SFP-DD 2X pluggable transceiver) \
+ $(0x1B, DSFP, DSFP, \
+ DSFP Dual SFP pluggable transceiver) \
+ $(0x1C, X4ML, x4MiniLink/OcuLink, x4 MiniLink/OcuLink) \
+ $(0x1D, X8ML, x8MiniLink, x8 MiniLink) \
+ $(0x1E, QSFP_CMIS, QSFP+(CMIS), \
+ QSFP+ or later w/ Common Management Interface Specification)
+
+#define $$SFP_ID sfp_id, SFP_ID_
+#define $(num, name, _disp, _desc) $ENUM_ITEM($$SFP_ID, name, num)
+$ENUM($, $$SFP_ID);
+#undef $
+
+/* SFF-8024 Rev. 4.6 Table 4-3: Connector Types */
+#define SFP_CONN_MAP($) \
+ $(0x00, UNKNOWN, Unknown) \
+ $(0x01, SC, SC) \
+ $(0x02, FC_1_COPPER, Fibre Channel Style 1 copper) \
+ $(0x03, FC_2_COPPER, Fibre Channel Style 2 copper) \
+ $(0x04, BNC_TNC, BNC/TNC) \
+ $(0x05, FC_COAX, Fibre Channel coaxial) \
+ $(0x06, FIBER_JACK, Fiber Jack) \
+ $(0x07, LC, LC) \
+ $(0x08, MT_RJ, MT-RJ) \
+ $(0x09, MU, MU) \
+ $(0x0A, SG, SG) \
+ $(0x0B, OPTICAL_PIGTAIL, Optical pigtail) \
+ $(0x0C, MPO_1X12_POPTIC, MPO 1x12 Parallel Optic) \
+ $(0x0D, MPO_2X16_POPTIC, MPO 2x16 Parallel Optic) \
+ $(0x20, HSSDC_II, HSSDC II) \
+ $(0x21, COPPER_PIGTAIL, Copper pigtail) \
+ $(0x22, RJ45, RJ45) \
+ $(0x23, NONE, No separable connector) \
+ $(0x24, MXC_2X16, MXC 2x16) \
+ $(0x25, CS_OPTICAL, CS optical connector) \
+ $(0x26, MINI_CS_OPTICAL, Mini CS optical connector) \
+ $(0x27, MPO_2X12_POPTIC, MPO 2x12 Parallel Optic) \
+ $(0x28, MPO_1X16_POPTIC, MPO 1x16 Parallel Optic)
+
+#define $$SFP_CONN sfp_conn, SFP_CONN_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_CONN, name, num)
+$ENUM($, $$SFP_CONN);
+#undef $
+
+/* SFF-8472 Rev. 11.4 table 3.5: Transceiver codes */
+
+/* 10G Ethernet/IB compliance codes, byte 3 */
+#define SFP_ETH_10G_MAP($) \
+ $(0x80, 10G_BASE_ER, 10G Base-ER) \
+ $(0x40, 10G_BASE_LRM, 10G Base-LRM) \
+ $(0x20, 10G_BASE_LR, 10G Base-LR) \
+ $(0x10, 10G_BASE_SR, 10G Base-SR) \
+ $(0x08, 1X_SX, 1X SX) \
+ $(0x04, 1X_LX, 1X LX) \
+ $(0x02, 1X_COPPER_ACTIVE, 1X Copper Active) \
+ $(0x01, 1X_COPPER_PASSIVE, 1X Copper Passive)
+
+#define $$SFP_ETH_10G sfp_eth_10g, SFP_ETH_10G_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_ETH_10G, name, num)
+$ENUM($, $$SFP_ETH_10G);
+#undef $
+
+/* Ethernet compliance codes, byte 6 */
+#define SFP_ETH_MAP($) \
+ $(0x80, BASE_PX, BASE-PX) \
+ $(0x40, BASE_BX10, BASE-BX10) \
+ $(0x20, 100BASE_FX, 100BASE-FX) \
+ $(0x10, 100BASE_LX_LX10, 100BASE-LX/LX10) \
+ $(0x08, 1000BASE_T, 1000BASE-T) \
+ $(0x04, 1000BASE_CX, 1000BASE-CX) \
+ $(0x02, 1000BASE_LX, 1000BASE-LX) \
+ $(0x01, 1000BASE_SX, 1000BASE-SX)
+
+#define $$SFP_ETH sfp_eth, SFP_ETH_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_ETH, name, num)
+$ENUM($, $$SFP_ETH);
+#undef $
+
+/* FC link length, byte 7 */
+#define SFP_FC_LEN_MAP($) \
+ $(0x80, VERY_LONG, very long distance) \
+ $(0x40, SHORT, short distance) \
+ $(0x20, INTERMEDIATE, intermediate distance) \
+ $(0x10, LONG, long distance) \
+ $(0x08, MEDIUM, medium distance)
+
+#define $$SFP_FC_LEN sfp_fc_len, SFP_FC_LEN_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_FC_LEN, name, num)
+$ENUM($, $$SFP_FC_LEN);
+#undef $
+
+/* Channel/Cable technology, byte 7-8 */
+#define SFP_CAB_TECH_MAP($) \
+ $(0x0400, SA, Shortwave laser (SA)) \
+ $(0x0200, LC, Longwave laser (LC)) \
+ $(0x0100, EL_INTER, Electrical inter-enclosure (EL)) \
+ $(0x0080, EL_INTRA, Electrical intra-enclosure (EL)) \
+ $(0x0040, SN, Shortwave laser (SN)) \
+ $(0x0020, SL, Shortwave laser (SL)) \
+ $(0x0010, LL, Longwave laser (LL)) \
+ $(0x0008, ACTIVE, Active Cable) \
+ $(0x0004, PASSIVE, Passive Cable)
+
+#define $$SFP_CAB_TECH sfp_cab_tech, SFP_CAB_TECH_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_CAB_TECH, name, num)
+$ENUM($, $$SFP_CAB_TECH);
+#undef $
+
+/* FC Transmission media, byte 9 */
+#define SFP_FC_MEDIA_MAP($) \
+ $(0x80, TW, Twin Axial Pair (TW)) \
+ $(0x40, TP, Twisted Pair (TP)) \
+ $(0x20, MI, Miniature Coax (MI)) \
+ $(0x10, TV, Video Coax (TV)) \
+ $(0x08, M6, Miltimode 62.5um (M6)) \
+ $(0x04, M5, Multimode 50um (M5)) \
+ $(0x02, RESERVED, Reserved) \
+ $(0x01, SM, Single Mode (SM))
+
+#define $$SFP_FC_MEDIA sfp_fc_media, SFP_FC_MEDIA_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_FC_MEDIA, name, num)
+$ENUM($, $$SFP_FC_MEDIA);
+#undef $
+
+/* FC Speed, byte 10 */
+#define SFP_FC_SPEED_MAP($) \
+ $(0x80, 1200, 1200 MBytes/sec) \
+ $(0x40, 800, 800 MBytes/sec) \
+ $(0x20, 1600, 1600 MBytes/sec) \
+ $(0x10, 400, 400 MBytes/sec) \
+ $(0x08, 3200, 3200 MBytes/sec) \
+ $(0x04, 200, 200 MBytes/sec) \
+ $(0x01, 100, 100 MBytes/sec)
+
+#define $$SFP_FC_SPEED sfp_fc_speed, SFP_FC_SPEED_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_FC_SPEED, name, num)
+$ENUM($, $$SFP_FC_SPEED);
+#undef $
+
+/* SFF-8436 Rev. 4.8 table 33: Specification compliance */
+
+/* 10/40G Ethernet compliance codes, byte 128 + 3 */
+#define SFP_ETH_1040G_MAP($) \
+ $(0x80, EXTENDED, Extended) \
+ $(0x40, 10GBASE_LRM, 10GBASE-LRM) \
+ $(0x20, 10GBASE_LR, 10GBASE-LR) \
+ $(0x10, 10GBASE_SR, 10GBASE-SR) \
+ $(0x08, 40GBASE_CR4, 40GBASE-CR4) \
+ $(0x04, 40GBASE_SR4, 40GBASE-SR4) \
+ $(0x02, 40GBASE_LR4, 40GBASE-LR4) \
+ $(0x01, 40G_ACTIVE, 40G Active Cable)
+
+#define SFF_8636_EXT_COMPLIANCE 0x80
+
+#define $$SFP_ETH_1040G sfp_eth_1040g, SFP_ETH_1040G_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_ETH_1040G, name, num)
+$ENUM($, $$SFP_ETH_1040G);
+#undef $
+
+/* SFF-8024 Rev. 4.6 table 4-4: Extended Specification Compliance */
+#define SFP_ETH_EXT_MAP($) \
+ $(0xFF, RESERVED_FF, Reserved) \
+ $(0x55, 128GFC_LW, 128GFC LW) \
+ $(0x54, 128GFC_SW, 128GFC SW) \
+ $(0x53, 128GFC_EA, 128GFC EA) \
+ $(0x52, 64GFC_LW, 64GFC LW) \
+ $(0x51, 64GFC_SW, 64GFC SW) \
+ $(0x50, 64GFC_EA, 64GFC EA) \
+ $(0x4F, RESERVED_4F, Reserved) \
+ $(0x4E, RESERVED_4E, Reserved) \
+ $(0x4D, RESERVED_4D, Reserved) \
+ $(0x4C, RESERVED_4C, Reserved) \
+ $(0x4B, RESERVED_4B, Reserved) \
+ $(0x4A, RESERVED_4A, Reserved) \
+ $(0x49, RESERVED_49, Reserved) \
+ $(0x48, RESERVED_48, Reserved) \
+ $(0x47, RESERVED_47, Reserved) \
+ $(0x46, 200GBASE_LR4, 200GBASE-LR4) \
+ $(0x45, 50GBASE_LR, 50GBASE-LR) \
+ $(0x44, 200G_1550NM_PSM4, 200G 1550nm PSM4) \
+ $(0x43, 200GBASE_FR4, 200GBASE-FR4) \
+ $(0x42, 50GBASE_FR_200GBASE_DR4, 50GBASE-FR or 200GBASE-DR4) \
+ $(0x41, 50GBASE_SR_100GBASE_SR2_200GBASE_SR4, \
+ 50GBASE-SR/100GBASE-SR2/200GBASE-SR4) \
+ $(0x40, 50GBASE_CR_100GBASE_CR2_200GBASE_CR4, \
+ 50GBASE-CR/100GBASE-CR2/200GBASE-CR4) \
+ $(0x3F, RESERVED_3F, Reserved) \
+ $(0x3E, RESERVED_3E, Reserved) \
+ $(0x3D, RESERVED_3D, Reserved) \
+ $(0x3C, RESERVED_3C, Reserved) \
+ $(0x3B, RESERVED_3B, Reserved) \
+ $(0x3A, RESERVED_3A, Reserved) \
+ $(0x39, RESERVED_39, Reserved) \
+ $(0x38, RESERVED_38, Reserved) \
+ $(0x37, RESERVED_37, Reserved) \
+ $(0x36, RESERVED_36, Reserved) \
+ $(0x35, RESERVED_35, Reserved) \
+ $(0x34, RESERVED_34, Reserved) \
+ $(0x33, 50_100_200GAUI_AOC_HI_BER, \
+ 50GAUI/100GAUI-2/200GAUI-4 AOC (BER <2.6e-4)) \
+ $(0x32, 50_100_200GAUI_ACC_HI_BER, \
+ 50GAUI/100GAUI-2/200GAUI-4 ACC (BER <2.6e-4)) \
+ $(0x31, 50_100_200GAUI_AOC_LO_BER, \
+ 50GAUI/100GAUI-2/200GAUI-4 AOC (BER <1e-6)) \
+ $(0x30, 50_100_200GAUI_ACC_LO_BER, \
+ 50GAUI/100GAUI-2/200GAUI-4 ACC (BER <1e-6)) \
+ $(0x2F, RESERVED_2F, Reserved) \
+ $(0x2E, RESERVED_2E, Reserved) \
+ $(0x2D, RESERVED_2D, Reserved) \
+ $(0x2C, RESERVED_2C, Reserved) \
+ $(0x2B, RESERVED_2B, Reserved) \
+ $(0x2A, RESERVED_2A, Reserved) \
+ $(0x29, RESERVED_29, Reserved) \
+ $(0x28, RESERVED_28, Reserved) \
+ $(0x27, 100G_LR, 100G-LR) \
+ $(0x26, 100G_FR, 100G-FR) \
+ $(0x25, 100GBASE_DR, 100GBASE-DR) \
+ $(0x24, 4WDM_40_MSA, 4WDM-40 MSA) \
+ $(0x23, 4WDM_20_MSA, 4WDM-20 MSA) \
+ $(0x22, 4WDM_10_MSA, 4WDM-10 MSA) \
+ $(0x21, 100G_PAM4_BIDI, 100G PAM4 BiDi) \
+ $(0x20, 100G_SWDM4, 100G SWDM4) \
+ $(0x1F, 40G_SWDM4, 40G SWDM4) \
+ $(0x1E, 2_5GBASE_T, 2.5GBASE-T) \
+ $(0x1D, 5GBASE_T, 5GBASE-T) \
+ $(0x1C, 10GBASE_T_SR, 10GBASE-T Short Reach) \
+ $(0x1B, 100G_1550NM_WDM, 100G 1550nm WDM) \
+ $(0x1A, 100GE_DWDM2, 100GE-DWDM2) \
+ $(0x19, 100G_25GAUI_C2M_ACC, 100G ACC or 25GAUI C2M ACC) \
+ $(0x18, 100G_25GAUI_C2M_AOC, 100G AOC or 25GAUI C2M AOC) \
+ $(0x17, 100G_CLR4, 100G CLR4) \
+ $(0x16, 10GBASE_T_SFI, \
+ 10GBASE-T with SFI electrical interface) \
+ $(0x15, G959_1_P1L1_2D2, G959.1 profile P1L1-2D2) \
+ $(0x14, G959_1_P1S1_2D2, G959.1 profile P1S1-2D2) \
+ $(0x13, G959_1_P1I1_2D1, G959.1 profile P1I1-2D1) \
+ $(0x12, 40G_PSM4, 40G PSM4 Parallel SMF) \
+ $(0x11, 4X_10GBASE_SR, 4 x 10GBASE-SR) \
+ $(0x10, 40GBASE_ER4, 40GBASE-ER4) \
+ $(0x0F, RESERVED_0F, Reserved) \
+ $(0x0E, RESERVED_0E, Reserved) \
+ $(0x0D, CA_25G_N, 25GBASE-CR CA-25G-N) \
+ $(0x0C, CA_25G_S, 25GBASE-CR CA-25G-S) \
+ $(0x0B, CA_L, 100GBASE-CR4 or 25GBASE-CR CA-L) \
+ $(0x0A, RESERVED_0A, Reserved) \
+ $(0x09, OBSOLETE, Obsolete) \
+ $(0x08, 100G_25GAUI_C2M_ACC_1, \
+ 100G ACC (Active Copper Cable) or 25GAUI C2M ACC) \
+ $(0x07, 100G_PSM4_P_SMF, 100G PSM4 Parallel SMF) \
+ $(0x06, 100G_CWDM4, 100G CWDM4) \
+ $(0x05, 100GBASE_SR10, 100GBASE-SR10) \
+ $(0x04, 100GBASE_ER4_25GBASE_ER, 100GBASE-ER4 or 25GBASE-ER) \
+ $(0x03, 100GBASE_LR4_25GBASE_LR, 100GBASE-LR4 or 25GBASE-LR) \
+ $(0x02, 100GBASE_SR4_25GBASE_SR, 100GBASE-SR4 or 25GBASE-SR) \
+ $(0x01, 100G_25GAUI_C2M_AOC_1, \
+ 100G AOC (Active Optical Cable) or 25GAUI C2M AOC) \
+ $(0x00, UNSPECIFIED, Unspecified)
+
+#define $$SFP_ETH_EXT sfp_eth_ext, SFP_ETH_EXT_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_ETH_EXT, name, num)
+$ENUM($, $$SFP_ETH_EXT);
+#undef $
+
+/* SFF-8636 Rev. 2.9 table 6.3: Revision compliance */
+#define SFP_REV_MAP($) \
+ $(0x1, SFF_8436_REV_LE_4_8, SFF-8436 rev <=4.8) \
+ $(0x2, SFF_8436_REV_LE_4_8_ALT, SFF-8436 rev <=4.8) \
+ $(0x3, SFF_8636_REV_LE_1_3, SFF-8636 rev <=1.3) \
+ $(0x4, SFF_8636_REV_LE_1_4, SFF-8636 rev <=1.4) \
+ $(0x5, SFF_8636_REV_LE_1_5, SFF-8636 rev <=1.5) \
+ $(0x6, SFF_8636_REV_LE_2_0, SFF-8636 rev <=2.0) \
+ $(0x7, SFF_8636_REV_LE_2_7, SFF-8636 rev <=2.7) \
+ $(0x8, SFF_8363_REV_GE_2_8, SFF-8636 rev >=2.8) \
+ $(0x0, UNSPECIFIED, Unspecified)
+
+#define $$SFP_REV sfp_rev, SFP_REV_
+#define $(num, name, _string) $ENUM_ITEM($$SFP_REV, name, num)
+$ENUM($, $$SFP_REV);
+#undef $
+
+#define SFP_ENUMS_MAP($) \
+ $(sfp_id, Transceiver identifier) \
+ $(sfp_conn, Connector type) \
+ $(sfp_eth_10g, 10G Ethernet/IB compliance) \
+ $(sfp_eth, Ethernet compliance) \
+ $(sfp_fc_len, FC link length) \
+ $(sfp_cab_tech, Channel/cable technology) \
+ $(sfp_fc_media, FC transmission media) \
+ $(sfp_fc_speed, FC speed) \
+ $(sfp_eth_1040g, 10/40G Ethernet compliance) \
+ $(sfp_eth_ext, Extended specification compliance) \
+ $(sfp_rev, Revision compliance)
+
+#define $(field, _string) uint8_t field;
+struct ifconfig_sfp_info { SFP_ENUMS_MAP($) };
+#undef $
+#define $(field, _string) const char *field;
+struct ifconfig_sfp_info_strings { SFP_ENUMS_MAP($) };
+#undef $
Index: lib/libifconfig/libifconfig_sfp.c
===================================================================
--- /dev/null
+++ lib/libifconfig/libifconfig_sfp.c
@@ -0,0 +1,612 @@
+/*-
+ * Copyright (c) 2014 Alexander V. Chernikov. All rights reserved.
+ * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/sff8436.h>
+#include <net/sff8472.h>
+
+#include <math.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libifconfig.h>
+#include <libifconfig_sfp.h>
+#include <libifconfig_internal.h>
+
+struct i2c_info {
+ struct ifreq ifr;
+ ifconfig_handle_t *h;
+ int error; /* Store first error */
+ bool qsfp; /* True if transceiver is QSFP */
+};
+
+#define $(enu) \
+static uint8_t \
+enu##_find_zero_bit(int value, int sz) \
+{ \
+ int v, m; \
+ \
+ for (v = 1, m = 1 << (8 * sz); v < m; v <<= 1) { \
+ if ((value & v) == 0) \
+ continue; \
+ if (ifconfig_##enu##_string(value & v) != NULL) { \
+ return (value & v); \
+ } \
+ } \
+ return (0); \
+}
+$(sfp_eth_10g)
+$(sfp_eth)
+$(sfp_fc_len)
+$(sfp_cab_tech)
+$(sfp_fc_media)
+$(sfp_fc_speed)
+$(sfp_eth_1040g)
+#undef $
+
+/*
+ * Reads i2c data from opened kernel socket.
+ */
+static int
+read_i2c(struct i2c_info *ii, uint8_t addr, uint8_t off, uint8_t len,
+ uint8_t *buf)
+{
+ struct ifi2creq req;
+ int i, l;
+
+ if (ii->error != 0)
+ return (ii->error);
+
+ ii->ifr.ifr_data = (caddr_t)&req;
+
+ i = 0;
+ l = 0;
+ memset(&req, 0, sizeof(req));
+ req.dev_addr = addr;
+ req.offset = off;
+ req.len = len;
+
+ while (len > 0) {
+ l = MIN(sizeof(req.data), len);
+ req.len = l;
+ if (ifconfig_ioctlwrap(ii->h, AF_LOCAL, SIOCGI2C,
+ &ii->ifr) != 0) {
+ ii->error = errno;
+ return (errno);
+ }
+
+ memcpy(&buf[i], req.data, l);
+ len -= l;
+ i += l;
+ req.offset += l;
+ }
+
+ return (0);
+}
+
+static int
+i2c_info_init(struct i2c_info *ii, ifconfig_handle_t *h, const char *name)
+{
+ uint8_t id_byte;
+
+ memset(ii, 0, sizeof(*ii));
+ strlcpy(ii->ifr.ifr_name, name, sizeof(ii->ifr.ifr_name));
+ ii->h = h;
+
+ /*
+ * Try to read byte 0 from i2c:
+ * Both SFF-8472 and SFF-8436 use it as
+ * 'identification byte'.
+ * Stop reading status on zero as value -
+ * this might happen in case of empty transceiver slot.
+ */
+ id_byte = 0;
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_ID, 1, &id_byte);
+ if (ii->error != 0)
+ return (-1);
+ switch (id_byte) {
+ case 0:
+ h->error.errtype = OTHER;
+ h->error.errcode = ENOENT;
+ return (-1);
+ case SFF_8024_ID_QSFP:
+ case SFF_8024_ID_QSFPPLUS:
+ case SFF_8024_ID_QSFP28:
+ ii->qsfp = true;
+ default:
+ return (0);
+ }
+}
+
+static int
+get_sfp_info(struct i2c_info *ii, struct ifconfig_sfp_info *sfp)
+{
+ uint8_t code;
+
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_ID, 1, &sfp->sfp_id);
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_CONNECTOR, 1, &sfp->sfp_conn);
+
+ /* Use extended compliance code if it's valid */
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_TRANS, 1, &sfp->sfp_eth_ext);
+ if (sfp->sfp_eth_ext == 0) {
+ /* Next, check 10G Ethernet/IB CCs */
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_TRANS_START, 1, &code);
+ sfp->sfp_eth_10g = sfp_eth_10g_find_zero_bit(code, 1);
+ if (sfp->sfp_eth_10g == 0) {
+ /* No match. Try Ethernet 1G */
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_TRANS_START + 3,
+ 1, &code);
+ sfp->sfp_eth = sfp_eth_find_zero_bit(code, 1);
+ }
+ }
+
+ return (ii->error);
+}
+
+static int
+get_qsfp_info(struct i2c_info *ii, struct ifconfig_sfp_info *sfp)
+{
+ uint8_t code;
+
+ read_i2c(ii, SFF_8436_BASE, SFF_8436_ID, 1, &sfp->sfp_id);
+ read_i2c(ii, SFF_8436_BASE, SFF_8436_CONNECTOR, 1, &sfp->sfp_conn);
+
+ read_i2c(ii, SFF_8436_BASE, SFF_8436_STATUS, 1, &sfp->sfp_rev);
+
+ /* Check for extended specification compliance */
+ read_i2c(ii, SFF_8436_BASE, SFF_8436_CODE_E1040100G, 1, &code);
+ if (code & SFF_8636_EXT_COMPLIANCE) {
+ read_i2c(ii, SFF_8436_BASE, SFF_8436_OPTIONS_START, 1,
+ &sfp->sfp_eth_ext);
+ } else {
+ /* Check 10/40G Ethernet class only */
+ sfp->sfp_eth_1040g = sfp_eth_1040g_find_zero_bit(code, 1);
+ }
+
+ return (ii->error);
+}
+
+int
+ifconfig_sfp_get_sfp_info(ifconfig_handle_t *h,
+ const char *name, struct ifconfig_sfp_info *sfp)
+{
+ struct i2c_info ii;
+ char buf[8];
+
+ memset(sfp, 0, sizeof(*sfp));
+
+ if (i2c_info_init(&ii, h, name) != 0)
+ return (-1);
+
+ /* Read bytes 3-10 at once */
+ read_i2c(&ii, SFF_8472_BASE, SFF_8472_TRANS_START, 8, buf);
+ if (ii.error != 0)
+ return (ii.error);
+
+ /* Check 10G ethernet first */
+ sfp->sfp_eth_10g = sfp_eth_10g_find_zero_bit(buf[0], 1);
+ if (sfp->sfp_eth_10g == 0) {
+ /* No match. Try 1G */
+ sfp->sfp_eth = sfp_eth_find_zero_bit(buf[3], 1);
+ }
+ sfp->sfp_cab_tech = sfp_cab_tech_find_zero_bit((buf[4]<<8)|buf[5], 2);
+ sfp->sfp_fc_len = sfp_fc_len_find_zero_bit(buf[4], 1);
+ sfp->sfp_fc_media = sfp_fc_media_find_zero_bit(buf[6], 1);
+ sfp->sfp_fc_speed = sfp_fc_speed_find_zero_bit(buf[7], 1);
+
+ if (ii.qsfp)
+ return (get_qsfp_info(&ii, sfp));
+ return (get_sfp_info(&ii, sfp));
+}
+
+/*
+ * Print SFF-8472/SFF-8436 string to supplied buffer.
+ * All (vendor-specific) strings are padded right with '0x20'.
+ */
+static void
+get_sff_string(struct i2c_info *ii, uint8_t addr, uint8_t off, char *dst)
+{
+ read_i2c(ii, addr, off, SFF_VENDOR_STRING_SIZE, dst);
+ dst += SFF_VENDOR_STRING_SIZE;
+ do { *dst-- = '\0'; } while (*dst == 0x20);
+}
+
+static void
+get_sff_date(struct i2c_info *ii, uint8_t addr, uint8_t off, char *dst)
+{
+ char buf[SFF_VENDOR_DATE_SIZE];
+
+ read_i2c(ii, addr, off, SFF_VENDOR_DATE_SIZE, buf);
+ sprintf(dst, "20%c%c-%c%c-%c%c", buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5]);
+}
+
+static int
+get_sfp_vendor_info(struct i2c_info *ii, struct ifconfig_sfp_vendor_info *vi)
+{
+ get_sff_string(ii, SFF_8472_BASE, SFF_8472_VENDOR_START, vi->name);
+ get_sff_string(ii, SFF_8472_BASE, SFF_8472_PN_START, vi->pn);
+ get_sff_string(ii, SFF_8472_BASE, SFF_8472_SN_START, vi->sn);
+ get_sff_date(ii, SFF_8472_BASE, SFF_8472_DATE_START, vi->date);
+ return (ii->error);
+}
+
+static int
+get_qsfp_vendor_info(struct i2c_info *ii, struct ifconfig_sfp_vendor_info *vi)
+{
+ get_sff_string(ii, SFF_8436_BASE, SFF_8436_VENDOR_START, vi->name);
+ get_sff_string(ii, SFF_8436_BASE, SFF_8436_PN_START, vi->pn);
+ get_sff_string(ii, SFF_8436_BASE, SFF_8436_SN_START, vi->sn);
+ get_sff_date(ii, SFF_8436_BASE, SFF_8436_DATE_START, vi->date);
+ return (ii->error);
+}
+
+int
+ifconfig_sfp_get_sfp_vendor_info(ifconfig_handle_t *h,
+ const char *name, struct ifconfig_sfp_vendor_info *vi)
+{
+ struct i2c_info ii;
+
+ memset(vi, 0, sizeof(*vi));
+
+ if (i2c_info_init(&ii, h, name) != 0)
+ return (-1);
+
+ if (ii.qsfp)
+ return (get_qsfp_vendor_info(&ii, vi));
+ return (get_sfp_vendor_info(&ii, vi));
+}
+
+/*
+ * Converts internal temperature (SFF-8472, SFF-8436)
+ * 16-bit unsigned value to human-readable representation:
+ *
+ * Internally measured Module temperature are represented
+ * as a 16-bit signed twos complement value in increments of
+ * 1/256 degrees Celsius, yielding a total range of –128C to +128C
+ * that is considered valid between –40 and +125C.
+ */
+static double
+get_sff_temp(struct i2c_info *ii, uint8_t addr, uint8_t off)
+{
+ double d;
+ uint8_t buf[2];
+
+ read_i2c(ii, addr, off, 2, buf);
+ d = (double)buf[0];
+ d += (double)buf[1] / 256;
+ return (d);
+}
+
+/*
+ * Retrieves supplied voltage (SFF-8472, SFF-8436).
+ * 16-bit usigned value, treated as range 0..+6.55 Volts
+ */
+static double
+get_sff_voltage(struct i2c_info *ii, uint8_t addr, uint8_t off)
+{
+ double d;
+ uint8_t buf[2];
+
+ read_i2c(ii, addr, off, 2, buf);
+ d = (double)((buf[0] << 8) | buf[1]);
+ return (d / 10000);
+}
+
+double
+mW_to_dBm(uint16_t mW)
+{
+ /*
+ * Assume internally-calibrated data.
+ * This is always true for SFF-8346, and explicitly
+ * checked for SFF-8472.
+ */
+ return (10.0 * log10(1.0 * mW / 10000));
+}
+
+static uint16_t
+get_sff_power(struct i2c_info *ii, uint8_t addr, uint8_t off)
+{
+ uint8_t buf[2];
+
+ read_i2c(ii, addr, off, 2, buf);
+ if (ii->error != 0)
+ return (0);
+
+ return ((buf[0] << 8) + buf[1]);
+}
+
+static int
+get_sfp_status(struct i2c_info *ii, struct ifconfig_sfp_status *ss)
+{
+ uint8_t diag_type, flags;
+
+ /* Read diagnostic monitoring type */
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_DIAG_TYPE, 1, (caddr_t)&diag_type);
+ if (ii->error != 0)
+ return (-1);
+
+ /*
+ * Read monitoring data IFF it is supplied AND is
+ * internally calibrated
+ */
+ flags = SFF_8472_DDM_DONE | SFF_8472_DDM_INTERNAL;
+ if ((diag_type & flags) != flags) {
+ ii->h->error.errtype = OTHER;
+ ii->h->error.errcode = ENXIO;
+ return (-1);
+ }
+
+ ss->temp = get_sff_temp(ii, SFF_8472_DIAG, SFF_8472_TEMP);
+ ss->voltage = get_sff_voltage(ii, SFF_8472_DIAG, SFF_8472_VCC);
+ ss->power[0].rx = get_sff_power(ii, SFF_8472_DIAG, SFF_8472_RX_POWER);
+ ss->power[0].tx = get_sff_power(ii, SFF_8472_DIAG, SFF_8472_TX_POWER);
+ return (ii->error);
+}
+
+static uint32_t
+get_qsfp_bitrate(struct i2c_info *ii)
+{
+ uint8_t code;
+ uint32_t rate;
+
+ code = 0;
+ read_i2c(ii, SFF_8436_BASE, SFF_8436_BITRATE, 1, &code);
+ rate = code * 100;
+ if (code == 0xFF) {
+ read_i2c(ii, SFF_8436_BASE, SFF_8636_BITRATE, 1, &code);
+ rate = code * 250;
+ }
+
+ return (rate);
+}
+
+static int
+get_qsfp_status(struct i2c_info *ii, struct ifconfig_sfp_status *ss)
+{
+ ss->temp = get_sff_temp(ii, SFF_8436_BASE, SFF_8436_TEMP);
+ ss->voltage = get_sff_voltage(ii, SFF_8436_BASE, SFF_8436_VCC);
+ for (size_t chan = 0; chan < nitems(ss->power); ++chan) {
+ uint8_t rxoffs = SFF_8436_RX_CH1_MSB + chan * sizeof(uint16_t);
+ uint8_t txoffs = SFF_8436_TX_CH1_MSB + chan * sizeof(uint16_t);
+ ss->power[chan].rx = get_sff_power(ii, SFF_8436_BASE, rxoffs);
+ ss->power[chan].tx = get_sff_power(ii, SFF_8436_BASE, txoffs);
+ }
+ ss->bitrate = get_qsfp_bitrate(ii);
+ return (ii->error);
+}
+
+int
+ifconfig_sfp_get_sfp_status(ifconfig_handle_t *h, const char *name,
+ struct ifconfig_sfp_status *ss)
+{
+ struct i2c_info ii;
+
+ memset(ss, 0, sizeof(*ss));
+
+ if (i2c_info_init(&ii, h, name) != 0)
+ return (-1);
+
+ if (ii.qsfp)
+ return (get_qsfp_status(&ii, ss));
+ return (get_sfp_status(&ii, ss));
+}
+
+static const char *
+sfp_id_string_alt(uint8_t value)
+{
+ const char *id;
+
+ if (value <= SFF_8024_ID_LAST)
+ id = sff_8024_id[value];
+ else if (value > 0x80)
+ id = "Vendor specific";
+ else
+ id = "Reserved";
+
+ return (id);
+}
+
+static const char *
+sfp_conn_string_alt(uint8_t value)
+{
+ const char *conn;
+
+ if (value >= 0x0D && value <= 0x1F)
+ conn = "Unallocated";
+ else if (value >= 0x24 && value <= 0x7F)
+ conn = "Unallocated";
+ else
+ conn = "Vendor specific";
+
+ return (conn);
+}
+
+void
+ifconfig_sfp_get_sfp_info_strings(struct ifconfig_sfp_info *sfp,
+ struct ifconfig_sfp_info_strings *strings)
+{
+#define $(enu, _descr) strings->enu = ifconfig_##enu##_string(sfp->enu);
+SFP_ENUMS_MAP($)
+#undef $
+ if (strings->sfp_id == NULL)
+ strings->sfp_id = sfp_id_string_alt(sfp->sfp_id);
+ if (strings->sfp_conn == NULL)
+ strings->sfp_conn = sfp_conn_string_alt(sfp->sfp_conn);
+ if (strings->sfp_rev == NULL)
+ strings->sfp_rev = "Unallocated";
+}
+
+int
+ifconfig_sfp_get_sfp_dump(ifconfig_handle_t *h, const char *name,
+ struct ifconfig_sfp_dump *dump)
+{
+ struct i2c_info ii;
+ uint8_t *buf = dump->data;
+
+ memset(dump->data, 0, sizeof(dump->data));
+
+ if (i2c_info_init(&ii, h, name) != 0)
+ return (-1);
+
+ if (ii.qsfp) {
+ dump->qsfp = true;
+ read_i2c(&ii, SFF_8436_BASE, QSFP_DUMP0_START, QSFP_DUMP0_SIZE,
+ buf);
+ read_i2c(&ii, SFF_8436_BASE, QSFP_DUMP1_START, QSFP_DUMP1_SIZE,
+ buf + QSFP_DUMP1_START);
+ } else {
+ read_i2c(&ii, SFF_8472_BASE, SFP_DUMP_START, SFP_DUMP_SIZE,
+ buf);
+ }
+
+ return (ii.error != 0 ? -1 : 0);
+}
+
+/* The rest of this file is just boring boilerplate code. */
+
+#define $_DEBUG_CASE(_enum, prefix, name) \
+ case prefix##name: return #prefix#name;
+#define $DEBUG_CASE($$, name) $_DEBUG_CASE($$, name)
+
+#define $SWITCH_MAP_FUNC_BODY($, pre, v) \
+{ \
+ switch (v) { \
+ pre##MAP($) \
+ default: return (NULL); \
+ } \
+}
+
+#define $_DEBUG_FUNC($, enm, pre) \
+const char * \
+ifconfig_##enm##_debug(enum enm v) \
+$SWITCH_MAP_FUNC_BODY($, pre, v)
+#define $DEBUG_FUNC($, $$) $_DEBUG_FUNC($, $$)
+
+#define $_STRING_CASE(_enum, prefix, name, string) \
+ case prefix##name: return (#string);
+#define $STRING_CASE($$, name, string) $_STRING_CASE($$, name, string)
+
+#define $_STRING_FUNC($, enu, pre) \
+const char * \
+ifconfig_##enu##_string(enum enu v) \
+$SWITCH_MAP_FUNC_BODY($, pre, v)
+#define $STRING_FUNC($, $$) $_STRING_FUNC($, $$)
+
+#define $(_num, name, _str, _desc) $DEBUG_CASE($$SFP_ID, name)
+$DEBUG_FUNC($, $$SFP_ID);
+#undef $
+#define $(_num, name, str, _desc) $STRING_CASE($$SFP_ID, name, str)
+$STRING_FUNC($, $$SFP_ID);
+#undef $
+#define $(_num, name, _str, desc) $STRING_CASE($$SFP_ID, name, desc)
+const char *
+ifconfig_sfp_id_description(enum sfp_id v)
+$SWITCH_MAP_FUNC_BODY($, SFP_ID_, v)
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_CONN, name)
+$DEBUG_FUNC($, $$SFP_CONN);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_CONN, name, string)
+$STRING_FUNC($, $$SFP_CONN);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_ETH_10G, name)
+$DEBUG_FUNC($, $$SFP_ETH_10G);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_ETH_10G, name, string)
+$STRING_FUNC($, $$SFP_ETH_10G);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_ETH, name)
+$DEBUG_FUNC($, $$SFP_ETH);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_ETH, name, string)
+$STRING_FUNC($, $$SFP_ETH);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_FC_LEN, name)
+$DEBUG_FUNC($, $$SFP_FC_LEN);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_FC_LEN, name, string)
+$STRING_FUNC($, $$SFP_FC_LEN);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_CAB_TECH, name)
+$DEBUG_FUNC($, $$SFP_CAB_TECH);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_CAB_TECH, name, string)
+$STRING_FUNC($, $$SFP_CAB_TECH);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_FC_MEDIA, name)
+$DEBUG_FUNC($, $$SFP_FC_MEDIA);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_FC_MEDIA, name, string)
+$STRING_FUNC($, $$SFP_FC_MEDIA);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_FC_SPEED, name)
+$DEBUG_FUNC($, $$SFP_FC_SPEED);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_FC_SPEED, name, string)
+$STRING_FUNC($, $$SFP_FC_SPEED);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_ETH_1040G, name)
+$DEBUG_FUNC($, $$SFP_ETH_1040G);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_ETH_1040G, name, string)
+$STRING_FUNC($, $$SFP_ETH_1040G);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_ETH_EXT, name)
+$DEBUG_FUNC($, $$SFP_ETH_EXT);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_ETH_EXT, name, string)
+$STRING_FUNC($, $$SFP_ETH_EXT);
+#undef $
+
+#define $(_num, name, _string) $DEBUG_CASE($$SFP_REV, name)
+$DEBUG_FUNC($, $$SFP_REV);
+#undef $
+#define $(_num, name, string) $STRING_CASE($$SFP_REV, name, string)
+$STRING_FUNC($, $$SFP_REV);
+#undef $
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 7, 3:15 AM (13 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28452326
Default Alt Text
D25494.id73796.diff (39 KB)
Attached To
Mode
D25494: libifconfig: Add functionality for querying SFP modules
Attached
Detach File
Event Timeline
Log In to Comment