diff options
author | Rob Johnston <rob.johnston@joyent.com> | 2017-12-13 23:43:54 +0000 |
---|---|---|
committer | Rob Johnston <rob.johnston@joyent.com> | 2018-02-02 01:40:47 +0000 |
commit | 4a99ae161887bed6eed6dcb1699f188f023921a2 (patch) | |
tree | 28c667e4ad741ea8bf4eefd5813921cf6c78b75d | |
parent | 6afca163c6f9158c8d995916782cd765188cbdf1 (diff) | |
download | illumos-joyent-4a99ae161887bed6eed6dcb1699f188f023921a2.tar.gz |
OS-6527 Add plaform-specific topo map for Joyent-Storage-Platform-7001
OS-6511 extend ipmi enumerator module to enumerate a node for the service processor
OS-6490 Implement topo module to enumerate dimms from smbios
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Joshua M. Clulow <jmc@joyent.com>
26 files changed, 1860 insertions, 33 deletions
@@ -5421,6 +5421,7 @@ f usr/lib/fm/topo/plugins/fac_prov_mptsas.so 0555 root bin f usr/lib/fm/topo/plugins/ipmi.so 0555 root bin f usr/lib/fm/topo/plugins/nic.so 0555 root bin f usr/lib/fm/topo/plugins/ses.so 0555 root bin +f usr/lib/fm/topo/plugins/smbios.so 0555 root bin f usr/lib/fm/topo/plugins/xfp.so 0555 root bin d usr/lib/fs 0755 root sys d usr/lib/fs/autofs 0755 root sys @@ -10162,9 +10163,13 @@ d usr/platform/i86pc/lib/fm/topo/maps 0755 root sys f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-1101-disk-hc-topology.xml 0444 root sys s usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3101-hc-topology.xml=./SSG-2028R-ACR24L-hc-topology.xml s usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3102-hc-topology.xml=./SSG-2028R-ACR24L-hc-topology.xml +f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-hc-topology.xml 0444 root sys +f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-chassis-hc-topology.xml 0444 root sys +f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-slot-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-chassis-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-disk-hc-topology.xml 0444 root sys +f usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-slot-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/chassis-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/chip-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/fan-hc-topology.xml 0444 root sys diff --git a/usr/src/lib/fm/topo/libtopo/common/hc.c b/usr/src/lib/fm/topo/libtopo/common/hc.c index df718d6490..b9001f0fd2 100644 --- a/usr/src/lib/fm/topo/libtopo/common/hc.c +++ b/usr/src/lib/fm/topo/libtopo/common/hc.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2017, Joyent, Inc. + * Copyright (c) 2018, Joyent, Inc. */ #include <stdio.h> @@ -191,6 +191,7 @@ static const hcc_t hc_canon[] = { { SCSI_DEVICE, TOPO_STABILITY_PRIVATE }, { SHELF, TOPO_STABILITY_PRIVATE }, { SES_ENCLOSURE, TOPO_STABILITY_PRIVATE }, + { SLOT, TOPO_STABILITY_PRIVATE }, { SMP_DEVICE, TOPO_STABILITY_PRIVATE }, { SP, TOPO_STABILITY_PRIVATE }, { STRAND, TOPO_STABILITY_PRIVATE }, diff --git a/usr/src/lib/fm/topo/libtopo/common/libtopo.h b/usr/src/lib/fm/topo/libtopo/common/libtopo.h index e0adb6e0ab..da6083a5be 100644 --- a/usr/src/lib/fm/topo/libtopo/common/libtopo.h +++ b/usr/src/lib/fm/topo/libtopo/common/libtopo.h @@ -23,7 +23,7 @@ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. */ #ifndef _LIBTOPO_H @@ -1001,6 +1001,10 @@ typedef enum topo_led_type { TOPO_LED_TYPE_PRESENT } topo_led_type_t; +typedef enum topo_slot_type { + TOPO_SLOT_TYPE_DIMM = 1 +} topo_slot_type_t; + #ifdef __cplusplus } diff --git a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers index c6ff800951..26bba754a1 100644 --- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers +++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, Joyent, Inc. # # @@ -90,6 +91,7 @@ SYMBOL_VERSION SUNWprivate { topo_method_unregister_all; topo_mod_alloc; topo_mod_auth; + topo_mod_clean_str; topo_mod_clrdebug; topo_mod_cpufmri; topo_mod_devfmri; diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h index a9fdeb02d8..e0efd3f79d 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2017, Joyent, Inc. + * Copyright (c) 2018, Joyent, Inc. */ #ifndef _TOPO_HC_H @@ -87,6 +87,7 @@ extern "C" { #define SHELF "shelf" #define SCSI_DEVICE "scsi-device" #define SES_ENCLOSURE "ses-enclosure" +#define SLOT "slot" #define SMP_DEVICE "smp-device" #define SP "sp" #define SUBCHASSIS "subchassis" @@ -190,6 +191,47 @@ extern "C" { */ #define TOPO_PROP_IPMI_ENTITY_LIST "entity-list" +/* + * These properties can be used to describe the network configuration of a + * given hardware components. They're currently used to describe the + * network config on the service processor (sp) + */ +#define TOPO_PGROUP_NETCFG "network-config" +#define TOPO_PROP_NETCFG_MACADDR "mac-address" +#define TOPO_PROP_NETCFG_VLAN_ID "vlan-id" +#define TOPO_PROP_NETCFG_IPV4_ADDR "ipv4-address" +#define TOPO_PROP_NETCFG_IPV4_SUBNET "ipv4-subnet" +#define TOPO_PROP_NETCFG_IPV4_GATEWAY "ipv4-gateway" +#define TOPO_PROP_NETCFG_IPV4_TYPE "ipv4-config-type" +#define TOPO_PROP_NETCFG_IPV6_ADDR "ipv6-address" +#define TOPO_PROP_NETCFG_IPV6_ROUTES "ipv6-routes" +#define TOPO_PROP_NETCFG_IPV6_TYPE "ipv6-config-type" + +/* Possible values for TOPO_PROP_NETCFG_TYPE */ +#define TOPO_NETCFG_TYPE_UNKNOWN "unknown" +#define TOPO_NETCFG_TYPE_STATIC "static" +#define TOPO_NETCFG_TYPE_DHCP "dhcp" + +#define TOPO_PGROUP_SLOT "slot" +#define TOPO_PROP_SLOT_TYPE "slot-type" + +#define TOPO_PGROUP_DIMM_SLOT "dimm-slot" +#define TOPO_PROP_DIMM_SLOT_FORM "form-factor" +#define TOPO_DIMM_SLOT_FORM_DIMM "DIMM" +#define TOPO_DIMM_SLOT_FORM_SODIMM "SODIMM" +#define TOPO_DIMM_SLOT_FORM_FBDIMM "FBDIMM" + +#define TOPO_PROP_DIMM_TYPE +#define TOPO_DIMM_TYPE_UNKNOWN "UNKNOWN" +#define TOPO_DIMM_TYPE_DDR "DDR" +#define TOPO_DIMM_TYPE_DDR2 "DDR2" +#define TOPO_DIMM_TYPE_DDR3 "DDR3" +#define TOPO_DIMM_TYPE_DDR4 "DDR4" +#define TOPO_DIMM_TYPE_LPDDR "LPDDR" +#define TOPO_DIMM_TYPE_LPDDR2 "LPDDR2" +#define TOPO_DIMM_TYPE_LPDDR3 "LPDDR3" +#define TOPO_DIMM_TYPE_LPDDR4 "LPDDR4" + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_mod.c b/usr/src/lib/fm/topo/libtopo/common/topo_mod.c index 295054dc5e..0fef1f7ca0 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. */ /* @@ -896,3 +897,12 @@ topo_mod_walk_init(topo_mod_t *mod, tnode_t *node, topo_mod_walk_cb_t cb_f, return (wp); } + +char * +topo_mod_clean_str(topo_mod_t *mod, const char *str) +{ + if (str == NULL) + return (NULL); + + return (topo_cleanup_auth_str(mod->tm_hdl, str)); +} diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_mod.h b/usr/src/lib/fm/topo/libtopo/common/topo_mod.h index e6dda440a0..517a593caf 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.h @@ -23,7 +23,7 @@ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. */ #ifndef _TOPO_MOD_H @@ -228,6 +228,7 @@ extern void topo_mod_setdebug(topo_mod_t *); extern void topo_mod_dprintf(topo_mod_t *, const char *, ...); extern const char *topo_mod_errmsg(topo_mod_t *); extern int topo_mod_errno(topo_mod_t *); +extern char *topo_mod_clean_str(topo_mod_t *, const char *); /* * Topo node utilities: callable from module enumeration, topo_mod_enumerate() diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_mod.map b/usr/src/lib/fm/topo/libtopo/common/topo_mod.map index 44b62bdf7f..1e5920c27b 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.map +++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.map @@ -1,5 +1,6 @@ # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, Joyent, Inc. # # CDDL HEADER START # @@ -64,6 +65,7 @@ SYMBOL_SCOPE { topo_mod_nvl2str { TYPE = FUNCTION; FLAGS = extern }; topo_mod_str2nvl { TYPE = FUNCTION; FLAGS = extern }; topo_mod_auth { TYPE = FUNCTION; FLAGS = extern }; + topo_mod_clean_str { TYPE = FUNCTION; FLAGS = extern }; topo_mod_walk_init { TYPE = FUNCTION; FLAGS = extern }; diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-chassis-hc-topology.xml b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-chassis-hc-topology.xml new file mode 100644 index 0000000000..d71085a615 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-chassis-hc-topology.xml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> +<!-- + + This file and its contents are supplied under the terms of the + Common Development and Distribution License ("CDDL"), version 1.0. + You may only use this file in accordance with the terms of version + 1.0 of the CDDL. + + A full copy of the text of the CDDL should have accompanied this + source. A copy of the CDDL is also available via the Internet at + http://www.illumos.org/license/CDDL. + + Copyright (c) 2018, Joyent, Inc. + +--> + +<topology name='chassis' scheme='hc'> + <range name='chassis' min='0' max='0'> + <node instance='0'> + <fac-enum provider='fac_prov_ipmi' /> + <!-- + chassis locate LED + --> + <facility name='locate' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='1' /> + <propmethod name='chassis_ident_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Chassis Intru' /> + <propitem value='System Temp' /> + </propval> + </propgroup> + </node> + </range> +</topology> diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-hc-topology.xml b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-hc-topology.xml new file mode 100644 index 0000000000..c185c50792 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-hc-topology.xml @@ -0,0 +1,88 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> +<!-- + + This file and its contents are supplied under the terms of the + Common Development and Distribution License ("CDDL"), version 1.0. + You may only use this file in accordance with the terms of version + 1.0 of the CDDL. + + A full copy of the text of the CDDL should have accompanied this + source. A copy of the CDDL is also available via the Internet at + http://www.illumos.org/license/CDDL. + + Copyright (c) 2018, Joyent, Inc. + +--> + +<topology name='i86pc' scheme='hc'> + + <range name='motherboard' min='0' max='0'> + <node instance='0'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + <propval name='label' type='string' value='MB' /> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='MB_10G Temp' /> + <propitem value='PCH Temp' /> + <propitem value='Peripheral Temp' /> + <propitem value='5VSB' /> + <propitem value='5VSB' /> + <propitem value='3.3VSB' /> + <propitem value='3.3VCC' /> + <propitem value='1.5V PCH' /> + <propitem value='1.2V BMC' /> + <propitem value='1.05V PCH' /> + <propitem value='12V' /> + <propitem value='5VCC' /> + <propitem value='VBAT' /> + <propitem value='VDIMMAB' /> + <propitem value='VDIMMCD' /> + <propitem value='VDIMMEF' /> + <propitem value='VDIMMGH' /> + </propval> + </propgroup> + </node> + + <dependents grouping='children'> + <range name='chip' min='0' max='1'> + <enum-method name='chip' version='1' /> + </range> + <range name='hostbridge' min='0' max='254'> + <enum-method name='hostbridge' version='1' /> + </range> + <range name='sp' min='0' max='0'> + <enum-method name='ipmi' version='1' /> + </range> + <range name='slot' min='0' max='15'> + <enum-method name='smbios' version='1' /> + <propmap name='Joyent-Storage-Platform-7001-slot' /> + </range> + </dependents> + + </range> + + <range name='chassis' min='0' max='0'> + <propmap name='Joyent-Storage-Platform-7001-chassis' /> + + <dependents grouping='children'> + + <range name='psu' min='0' max='1'> + <enum-method name='ipmi' version='1' /> + </range> + <range name='fan' min='0' max='7'> + <enum-method name='ipmi' version='1' /> + </range> + + </dependents> + </range> + + <range name='ses-enclosure' min='0' max='1'> + <enum-method name='ses' version='1' /> + </range> + +</topology> diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-slot-hc-topology.xml b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-slot-hc-topology.xml new file mode 100644 index 0000000000..6b16063427 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Joyent-Storage-Platform-7001-slot-hc-topology.xml @@ -0,0 +1,277 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> +<!-- + + This file and its contents are supplied under the terms of the + Common Development and Distribution License ("CDDL"), version 1.0. + You may only use this file in accordance with the terms of version + 1.0 of the CDDL. + + A full copy of the text of the CDDL should have accompanied this + source. A copy of the CDDL is also available via the Internet at + http://www.illumos.org/license/CDDL. + + Copyright (c) 2018, Joyent, Inc. + +--> + +<topology name='slot' scheme='hc'> + <range name='slot' min='0' max='15'> + <node instance='0' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMA1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='1' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMA2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='2' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMB1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='3' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMB2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='4' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMC1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='5' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMC2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='6' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMD1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='7' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMD2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='8' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMME1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='9' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMME2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='10' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMF1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='11' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMF1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='12' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMG1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='13' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMG2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='14' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMH1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='15' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMH2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + </range> <!-- slot --> +</topology> diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Makefile b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Makefile new file mode 100644 index 0000000000..bffc198721 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Storage-Platform-7001/Makefile @@ -0,0 +1,33 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2018, Joyent, Inc. +# + +# NOTE: The name of the xml file we are building is 'platform' +# specific, but its build is structured as 'arch' specific since +# 'uname -i' on all x86 platforms returns i86pc. + +ARCH = i86pc +CLASS = arch +DTDFILE = topology.dtd.1 + +TOPOFILE = \ + Joyent-Storage-Platform-7001-hc-topology.xml \ + Joyent-Storage-Platform-7001-chassis-hc-topology.xml \ + Joyent-Storage-Platform-7001-slot-hc-topology.xml + +SRCDIR = ../Joyent,Joyent-Storage-Platform-7001 + +PLATFORM = Joyent-Storage-Platform-7001 + +include ../Makefile.map diff --git a/usr/src/lib/fm/topo/maps/Makefile b/usr/src/lib/fm/topo/maps/Makefile index 7cf2a33dbe..49b86186a1 100644 --- a/usr/src/lib/fm/topo/maps/Makefile +++ b/usr/src/lib/fm/topo/maps/Makefile @@ -22,7 +22,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# Copyright (c) 2017, Joyent, Inc. +# Copyright (c) 2018, Joyent, Inc. # sparc_SUBDIRS = sun4u \ @@ -51,6 +51,7 @@ i386_SUBDIRS = i86pc \ SUNW,Sun-Fire-X4540 \ SUNW,Sun-Fire-X4600-M2 \ Joyent,Joyent-Compute-Platform-1101 \ + Joyent,Joyent-Storage-Platform-7001 \ SMCI,SSG-2028R-ACR24L SUBDIRS = $($(MACH)_SUBDIRS) diff --git a/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/Makefile b/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/Makefile index 66492c6a82..15401c3abb 100644 --- a/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/Makefile +++ b/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/Makefile @@ -22,7 +22,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# Copyright (c) 2017, Joyent, Inc. +# Copyright (c) 2018, Joyent, Inc. # # NOTE: The name of the xml file we are building is 'platform' @@ -41,7 +41,8 @@ ROOTJOYENTMAPS = $(JOYENT_PLATFORMS:%=$(arch_ROOTTOPOROOT)/%) TOPOFILE = \ SSG-2028R-ACR24L-hc-topology.xml \ SSG-2028R-ACR24L-chassis-hc-topology.xml \ - SSG-2028R-ACR24L-disk-hc-topology.xml + SSG-2028R-ACR24L-disk-hc-topology.xml \ + SSG-2028R-ACR24L-slot-hc-topology.xml SRCDIR = ../SMCI,SSG-2028R-ACR24L diff --git a/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/SSG-2028R-ACR24L-hc-topology.xml b/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/SSG-2028R-ACR24L-hc-topology.xml index 8a77d285a5..83bc2e217b 100644 --- a/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/SSG-2028R-ACR24L-hc-topology.xml +++ b/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/SSG-2028R-ACR24L-hc-topology.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> <!-- -Copyright (c) 2017, Joyent, Inc. +Copyright (c) 2018, Joyent, Inc. CDDL HEADER START @@ -64,6 +64,13 @@ Copyright (c) 2017, Joyent, Inc. <range name='hostbridge' min='0' max='254'> <enum-method name='hostbridge' version='1' /> </range> + <range name='sp' min='0' max='0'> + <enum-method name='ipmi' version='1' /> + </range> + <range name='slot' min='0' max='15'> + <enum-method name='smbios' version='1' /> + <propmap name='SSG-2028R-ACR24L-slot' /> + </range> </dependents> </range> diff --git a/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/SSG-2028R-ACR24L-slot-hc-topology.xml b/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/SSG-2028R-ACR24L-slot-hc-topology.xml new file mode 100644 index 0000000000..6b16063427 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/SMCI,SSG-2028R-ACR24L/SSG-2028R-ACR24L-slot-hc-topology.xml @@ -0,0 +1,277 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> +<!-- + + This file and its contents are supplied under the terms of the + Common Development and Distribution License ("CDDL"), version 1.0. + You may only use this file in accordance with the terms of version + 1.0 of the CDDL. + + A full copy of the text of the CDDL should have accompanied this + source. A copy of the CDDL is also available via the Internet at + http://www.illumos.org/license/CDDL. + + Copyright (c) 2018, Joyent, Inc. + +--> + +<topology name='slot' scheme='hc'> + <range name='slot' min='0' max='15'> + <node instance='0' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMA1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='1' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMA2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='2' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMB1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='3' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMB2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='4' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMC1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='5' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMC2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='6' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMD1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='7' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P1-DIMMD2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='8' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMME1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='9' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMME2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='10' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMF1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='11' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMF1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='12' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMG1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='13' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMG2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='14' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMH1 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + <node instance='15' static='true'> + <dependents grouping='children'> + <range name='dimm' min='0' max='0'> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='P2-DIMMH2 Temp' /> + </propval> + </propgroup> + </node> + </range> + </dependents> + </node> + + </range> <!-- slot --> +</topology> diff --git a/usr/src/lib/fm/topo/maps/common/topology.dtd.1 b/usr/src/lib/fm/topo/maps/common/topology.dtd.1 index ae749e6e46..ba474a66b6 100644 --- a/usr/src/lib/fm/topo/maps/common/topology.dtd.1 +++ b/usr/src/lib/fm/topo/maps/common/topology.dtd.1 @@ -3,6 +3,8 @@ Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. + Copyright (c) 2018, Joyent, Inc. + CDDL HEADER START The contents of this file are subject to the terms of the @@ -275,7 +277,8 @@ ( fac-enum?, facility*, propgroup*, set*, enum-method*, dependents? ) > <!ATTLIST node - instance CDATA #REQUIRED > + instance CDATA #REQUIRED + static (false|true) "false" > <!-- dependents diff --git a/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml index 1a459d854b..607f7e1eb1 100644 --- a/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml +++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml @@ -2,7 +2,7 @@ <!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -Copyright (c) 2017, Joyent, Inc. +Copyright (c) 2018, Joyent, Inc. CDDL HEADER START @@ -77,9 +77,15 @@ Copyright (c) 2017, Joyent, Inc. <enum-method name='chip' version='1' /> <propmap name='chip' /> </range> + <range name='slot' min='0' max='31'> + <enum-method name='smbios' version='1' /> + </range> <range name='hostbridge' min='0' max='254'> <enum-method name='hostbridge' version='1' /> </range> + <range name='sp' min='0' max='0'> + <enum-method name='ipmi' version='1' /> + </range> </dependents> </range> diff --git a/usr/src/lib/fm/topo/modules/common/Makefile b/usr/src/lib/fm/topo/modules/common/Makefile index d725016aef..f7f47f5e06 100644 --- a/usr/src/lib/fm/topo/modules/common/Makefile +++ b/usr/src/lib/fm/topo/modules/common/Makefile @@ -22,7 +22,7 @@ # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# Copyright (c) 2017, Joyent, Inc. +# Copyright (c) 2018, Joyent, Inc. # SUBDIRS = \ @@ -32,6 +32,7 @@ SUBDIRS = \ ipmi \ nic \ ses \ + smbios \ xfp ses: disk diff --git a/usr/src/lib/fm/topo/modules/common/ipmi/Makefile b/usr/src/lib/fm/topo/modules/common/ipmi/Makefile index b6f2839c42..4a0bf39401 100644 --- a/usr/src/lib/fm/topo/modules/common/ipmi/Makefile +++ b/usr/src/lib/fm/topo/modules/common/ipmi/Makefile @@ -22,7 +22,8 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 2018, Joyent, Inc. +# MODULE = ipmi CLASS = common @@ -31,4 +32,4 @@ MODULESRCS = ipmi_enum.c ipmi_methods.c include ../../Makefile.plugin -LDLIBS += -lipmi +LDLIBS += -lipmi -lnsl diff --git a/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c b/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c index ef7a2d23ac..1220305584 100644 --- a/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c +++ b/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2017, Joyent, Inc. + * Copyright (c) 2018, Joyent, Inc. */ #include <assert.h> @@ -29,6 +29,9 @@ #include <fm/topo_mod.h> #include <sys/fm/protocol.h> #include <string.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <sys/socket.h> #define TOPO_PGROUP_IPMI "ipmi" #define TOPO_PROP_IPMI_ENTITY_REF "entity_ref" @@ -472,6 +475,260 @@ ipmi_check_entity(ipmi_handle_t *ihp, ipmi_entity_t *ep, void *data) return (0); } +static const char * +ipmi2toposrc(uint8_t ipmi_ip_src) +{ + char *cfgtype; + + switch (ipmi_ip_src) { + case (IPMI_LAN_SRC_STATIC): + case (IPMI_LAN_SRC_BIOS): + cfgtype = TOPO_NETCFG_TYPE_STATIC; + break; + case (IPMI_LAN_SRC_DHCP): + cfgtype = TOPO_NETCFG_TYPE_DHCP; + break; + default: + cfgtype = TOPO_NETCFG_TYPE_UNKNOWN; + break; + } + return (cfgtype); +} + +/* + * Channel related IPMI commands reserve 4 bits for the channel number. + */ +#define IPMI_MAX_CHANNEL 0xf + +static int +ipmi_enum_sp(topo_mod_t *mod, tnode_t *pnode) +{ + ipmi_handle_t *ihp; + ipmi_channel_info_t *chinfo; + ipmi_lan_config_t lancfg = { 0 }; + boolean_t found_lan = B_TRUE; + char ipv4_addr[INET_ADDRSTRLEN], subnet[INET_ADDRSTRLEN]; + char gateway[INET_ADDRSTRLEN], macaddr[18]; + char ipv6_addr[INET6_ADDRSTRLEN]; + char **ipv6_routes; + const char *sp_rev, *ipv4_cfgtype, *ipv6_cfgtype; + nvlist_t *auth, *fmri; + tnode_t *sp_node; + topo_pgroup_info_t pgi; + int err, ch, i, ret = -1; + + if ((ihp = topo_mod_ipmi_hold(mod)) == NULL) + return (0); + + /* + * If we're able to successfully get the service processor version by + * issuing a GET_DEVICE_ID IPMI command over the KCS interface, then we + * can say with certainty that a service processor exists. If not, + * then either the SP is unresponsive or one isn't present. In either + * case, we bail. + */ + if ((sp_rev = ipmi_firmware_version(ihp)) == NULL) { + topo_mod_dprintf(mod, "failed to query SP"); + topo_mod_ipmi_rele(mod); + return (0); + } + + if ((auth = topo_mod_auth(mod, pnode)) == NULL) { + topo_mod_dprintf(mod, "topo_mod_auth() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + goto out; + } + if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, + SP, 0, NULL, auth, NULL, sp_rev, NULL)) == NULL) { + nvlist_free(auth); + topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + goto out; + } + nvlist_free(auth); + + if ((sp_node = topo_node_bind(mod, pnode, SP, 0, fmri)) == NULL) { + nvlist_free(fmri); + topo_mod_dprintf(mod, "topo_node_bind() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + goto out; + } + nvlist_free(fmri); + fmri = NULL; + + if (topo_node_label_set(sp_node, "service-processor", &err) != 0) { + topo_mod_dprintf(mod, "failed to set label on %s=%d: %s", SP, + 0, topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + goto out; + } + + if (topo_node_fru(pnode, &fmri, NULL, &err) != 0 || + topo_node_fru_set(sp_node, fmri, NULL, &err) != 0) { + topo_mod_dprintf(mod, "failed to set FRU on %s=%d: %s", SP, 0, + topo_strerror(err)); + nvlist_free(fmri); + (void) topo_mod_seterrno(mod, err); + goto out; + } + nvlist_free(fmri); + + /* + * Iterate through the channels to find the LAN channel. + */ + for (ch = 0; ch <= IPMI_MAX_CHANNEL; ch++) { + if ((chinfo = ipmi_get_channel_info(ihp, ch)) != NULL && + chinfo->ici_medium == IPMI_MEDIUM_8023LAN) { + found_lan = B_TRUE; + break; + } + } + /* + * If we found a LAN channel, look up its configuration so that we can + * expose it via node properties. + */ + if (found_lan != B_TRUE || + ipmi_lan_get_config(ihp, ch, &lancfg) != 0) { + (void) fprintf(stderr, "failed to get LAN config\n"); + (void) topo_mod_seterrno(mod, EMOD_UNKNOWN); + goto out; + } + + pgi.tpi_name = TOPO_PGROUP_NETCFG; + pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; + pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; + pgi.tpi_version = TOPO_VERSION; + + if (topo_pgroup_create(sp_node, &pgi, &err) != 0) { + (void) topo_mod_seterrno(mod, err); + goto out; + } + + /* Set MAC address property */ + (void) sprintf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x", + lancfg.ilc_macaddr[0], lancfg.ilc_macaddr[1], + lancfg.ilc_macaddr[2], lancfg.ilc_macaddr[3], + lancfg.ilc_macaddr[4], lancfg.ilc_macaddr[5]); + macaddr[17] = '\0'; + + if (topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_MACADDR, TOPO_PROP_IMMUTABLE, macaddr, + &err) != 0) { + topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s", + SP, 0, topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + goto out; + } + + /* Set VLAN ID property, if VLAN is enabled */ + if (lancfg.ilc_vlan_enabled == B_TRUE && + topo_prop_set_uint32(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_VLAN_ID, TOPO_PROP_IMMUTABLE, lancfg.ilc_vlan_id, + &err) != 0) { + topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s", + SP, 0, topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + goto out; + } + + /* Set IPv4 configuration properties if IPv4 is enabled */ + if (lancfg.ilc_ipv4_enabled == B_TRUE && + (inet_ntop(AF_INET, &lancfg.ilc_ipaddr, ipv4_addr, + sizeof (ipv4_addr)) == NULL || + inet_ntop(AF_INET, &lancfg.ilc_subnet, subnet, + sizeof (subnet)) == NULL || + inet_ntop(AF_INET, &lancfg.ilc_gateway_addr, gateway, + sizeof (gateway)) == NULL)) { + (void) fprintf(stderr, "failed to convert IP addresses: %s\n", + strerror(errno)); + (void) topo_mod_seterrno(mod, EMOD_UNKNOWN); + goto out; + } + ipv4_cfgtype = ipmi2toposrc(lancfg.ilc_ipaddr_source); + if (lancfg.ilc_ipv4_enabled == B_TRUE && + (topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_IPV4_ADDR, TOPO_PROP_IMMUTABLE, ipv4_addr, + &err) != 0 || + topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_IPV4_SUBNET, TOPO_PROP_IMMUTABLE, subnet, + &err) != 0 || + topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_IPV4_GATEWAY, TOPO_PROP_IMMUTABLE, gateway, + &err) != 0 || + topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_IPV4_TYPE, TOPO_PROP_IMMUTABLE, ipv4_cfgtype, + &err) != 0)) { + topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s", + SP, 0, topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + goto out; + } + + /* Set IPv6 configuration properties if IPv6 is enabled */ + if (lancfg.ilc_ipv6_enabled == B_TRUE) { + ipv6_cfgtype = ipmi2toposrc(lancfg.ilc_ipv6_source); + + if (inet_ntop(AF_INET6, &lancfg.ilc_ipv6_addr, ipv6_addr, + sizeof (ipv6_addr)) == NULL) { + (void) fprintf(stderr, "failed to convert IPv6 " + "address: %s\n", strerror(errno)); + (void) topo_mod_seterrno(mod, EMOD_UNKNOWN); + goto out; + } + + /* allocate and populate ipv6-routes string array */ + if ((ipv6_routes = topo_mod_zalloc(mod, + lancfg.ilc_ipv6_nroutes * sizeof (char *))) == NULL) { + /* errno set */ + goto out; + } + for (i = 0; i < lancfg.ilc_ipv6_nroutes; i++) { + if ((ipv6_routes[i] = topo_mod_alloc(mod, + INET6_ADDRSTRLEN)) == NULL) { + /* errno set */ + goto out; + } + } + for (i = 0; i < lancfg.ilc_ipv6_nroutes; i++) { + if (inet_ntop(AF_INET6, &lancfg.ilc_ipv6_routes[i], + ipv6_routes[i], sizeof (ipv6_routes[i])) == NULL) { + (void) fprintf(stderr, "failed to convert " + "IPv6 addresses: %s\n", strerror(errno)); + (void) topo_mod_seterrno(mod, EMOD_UNKNOWN); + goto out; + } + } + } + if (lancfg.ilc_ipv6_enabled == B_TRUE && + (topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_IPV6_ADDR, TOPO_PROP_IMMUTABLE, ipv6_addr, + &err) != 0 || + topo_prop_set_string_array(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_IPV6_ROUTES, TOPO_PROP_IMMUTABLE, + (const char **)ipv6_routes, lancfg.ilc_ipv6_nroutes, &err) != 0 || + topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG, + TOPO_PROP_NETCFG_IPV6_TYPE, TOPO_PROP_IMMUTABLE, ipv6_cfgtype, + &err) != 0)) { + topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s", + SP, 0, topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + goto out; + } + ret = 0; +out: + if (lancfg.ilc_ipv6_nroutes > 0) { + for (i = 0; i < lancfg.ilc_ipv6_nroutes; i++) + topo_mod_free(mod, ipv6_routes[i], INET6_ADDRSTRLEN); + topo_mod_free(mod, ipv6_routes, + lancfg.ilc_ipv6_nroutes * sizeof (char *)); + } + topo_mod_ipmi_rele(mod); + return (ret); +} + /* * libtopo enumeration point. This simply iterates over entities looking for * the appropriate type. @@ -486,10 +743,11 @@ ipmi_enum(topo_mod_t *mod, tnode_t *rnode, const char *name, int ret; /* - * If the node being passed in ISN'T the chassis node, then we're being - * asked to post-process a statically defined node. + * If the node being passed in ISN'T the chassis or motherboard node, + * then we're being asked to post-process a statically defined node. */ - if (strcmp(topo_node_name(rnode), CHASSIS) != 0) { + if (strcmp(topo_node_name(rnode), CHASSIS) != 0 && + strcmp(topo_node_name(rnode), MOTHERBOARD) != 0) { if (ipmi_post_process(mod, rnode) != 0) { topo_mod_dprintf(mod, "post processing of node %s=%d " "failed!", topo_node_name(rnode), @@ -499,6 +757,19 @@ ipmi_enum(topo_mod_t *mod, tnode_t *rnode, const char *name, return (0); } + /* + * For service processor enumeration we vector off into a special code + * path. + */ + if (strcmp(name, SP) == 0) { + if (ipmi_enum_sp(mod, rnode) != 0) { + topo_mod_dprintf(mod, "failed to enumerate the " + "service-processor"); + return (-1); + } + return (0); + } + if (strcmp(name, POWERMODULE) == 0) { data.ed_entity = IPMI_ET_POWER_DOMAIN; } else if (strcmp(name, PSU) == 0) { diff --git a/usr/src/lib/fm/topo/modules/common/smbios/Makefile b/usr/src/lib/fm/topo/modules/common/smbios/Makefile new file mode 100644 index 0000000000..04590063c5 --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/smbios/Makefile @@ -0,0 +1,22 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2018, Joyent, Inc. +# + +MODULE = smbios +CLASS = common +MODULESRCS = smbios_enum.c + +include ../../Makefile.plugin + +LDLIBS += -lsmbios diff --git a/usr/src/lib/fm/topo/modules/common/smbios/smbios_enum.c b/usr/src/lib/fm/topo/modules/common/smbios/smbios_enum.c new file mode 100644 index 0000000000..ecaa749bed --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/smbios/smbios_enum.c @@ -0,0 +1,483 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2018, Joyent, Inc. + */ + +#include <assert.h> +#include <fcntl.h> +#include <fm/libtopo.h> +#include <fm/topo_mod.h> +#include <sys/mc.h> +#include <sys/fm/protocol.h> +#include <string.h> +#include <unistd.h> + +#define TOPO_PGROUP_DIMM_PROPS "dimm-properties" + +typedef struct smb_enum_data { + topo_mod_t *sme_mod; + tnode_t *sme_pnode; + tnode_t *sme_slotnode; + topo_instance_t sme_slot_inst; + topo_instance_t sme_slot_maxinst; + smbios_info_t *sme_smb_info; + char *sme_slot_form; +} smb_enum_data_t; + +/* + * This function serves two purposes. It filters out memory devices that + * don't have a formfactor that represents a reasonably modern DIMM-like + * device (and hence not a device we're insterested in enumerating). It also + * converts the numeric SMBIOS type representation to a more generic TOPO dimm + * type. + * + * Caller must free the returned string. + */ +static char * +distill_dimm_form(topo_mod_t *mod, smbios_memdevice_t *smb_md) +{ + switch (smb_md->smbmd_form) { + case (SMB_MDFF_DIMM): + return (topo_mod_strdup(mod, TOPO_DIMM_SLOT_FORM_DIMM)); + case (SMB_MDFF_SODIMM): + return (topo_mod_strdup(mod, TOPO_DIMM_SLOT_FORM_SODIMM)); + case (SMB_MDFF_FBDIMM): + return (topo_mod_strdup(mod, TOPO_DIMM_SLOT_FORM_FBDIMM)); + default: + topo_mod_dprintf(mod, "skipping device with form factor 0x%x", + smb_md->smbmd_form); + return (NULL); + } +} + +static char * +smbios2topotype(topo_mod_t *mod, uint8_t type) +{ + switch (type) { + case (SMB_MDT_DDR): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_DDR)); + case (SMB_MDT_DDR2): + case (SMB_MDT_DDR2FBDIMM): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_DDR2)); + case (SMB_MDT_DDR3): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_DDR3)); + case (SMB_MDT_DDR4): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_DDR4)); + case (SMB_MDT_LPDDR): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_LPDDR)); + case (SMB_MDT_LPDDR2): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_LPDDR2)); + case (SMB_MDT_LPDDR3): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_LPDDR3)); + case (SMB_MDT_LPDDR4): + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_LPDDR4)); + default: + return (topo_mod_strdup(mod, TOPO_DIMM_TYPE_UNKNOWN)); + } +} + +static boolean_t +is_valid_string(const char *str) +{ + if (strcmp(str, SMB_DEFAULT1) != 0 && strcmp(str, SMB_DEFAULT2) != 0 && + strlen(str) > 0) + return (B_TRUE); + + return (B_FALSE); +} + +static tnode_t * +smbios_make_slot(smb_enum_data_t *smed, smbios_memdevice_t *smb_md) +{ + nvlist_t *auth, *fmri; + tnode_t *slotnode; + topo_mod_t *mod = smed->sme_mod; + topo_pgroup_info_t pgi; + int err; + + if ((auth = topo_mod_auth(mod, smed->sme_pnode)) == NULL) { + topo_mod_dprintf(mod, "topo_mod_auth() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + return (NULL); + } + + if ((fmri = topo_mod_hcfmri(mod, smed->sme_pnode, FM_HC_SCHEME_VERSION, + SLOT, smed->sme_slot_inst, NULL, auth, NULL, NULL, NULL)) == + NULL) { + nvlist_free(auth); + topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + return (NULL); + } + nvlist_free(auth); + if ((slotnode = topo_node_bind(mod, smed->sme_pnode, SLOT, + smed->sme_slot_inst, fmri)) == NULL) { + nvlist_free(fmri); + topo_mod_dprintf(mod, "topo_node_bind() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + return (NULL); + } + nvlist_free(fmri); + fmri = NULL; + + if (topo_node_label_set(slotnode, (char *)smb_md->smbmd_dloc, &err) != + 0) { + topo_mod_dprintf(mod, "failed to set label on %s=%d: %s", + SLOT, smed->sme_slot_inst, topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + return (NULL); + } + if (topo_node_fru(smed->sme_pnode, &fmri, NULL, &err) != 0 || + topo_node_fru_set(slotnode, fmri, NULL, &err) != 0) { + topo_mod_dprintf(mod, "failed to set FRU on %s=%d: %s", SLOT, + smed->sme_slot_inst, topo_strerror(err)); + nvlist_free(fmri); + (void) topo_mod_seterrno(mod, err); + return (NULL); + } + nvlist_free(fmri); + + pgi.tpi_name = TOPO_PGROUP_SLOT; + pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; + pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; + pgi.tpi_version = TOPO_VERSION; + if (topo_pgroup_create(slotnode, &pgi, &err) != 0 || + topo_prop_set_uint32(slotnode, TOPO_PGROUP_SLOT, + TOPO_PROP_SLOT_TYPE, TOPO_PROP_IMMUTABLE, TOPO_SLOT_TYPE_DIMM, + &err)) { + topo_mod_dprintf(mod, "failed to create slot properties: %s", + topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + return (NULL); + } + + pgi.tpi_name = TOPO_PGROUP_DIMM_SLOT; + pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; + pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; + pgi.tpi_version = TOPO_VERSION; + if (topo_pgroup_create(slotnode, &pgi, &err) != 0 || + topo_prop_set_string(slotnode, TOPO_PGROUP_DIMM_SLOT, + TOPO_PROP_DIMM_SLOT_FORM, TOPO_PROP_IMMUTABLE, smed->sme_slot_form, + &err)) { + topo_mod_dprintf(mod, "failed to create slot properties: %s", + topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + return (NULL); + } + return (slotnode); +} + +static tnode_t * +smbios_make_dimm(smb_enum_data_t *smed, smbios_memdevice_t *smb_md) +{ + nvlist_t *auth, *fmri; + smbios_info_t *smb_info = smed->sme_smb_info; + tnode_t *slotnode = smed->sme_slotnode; + tnode_t *dimmnode, *ret = NULL; + topo_mod_t *mod = smed->sme_mod; + topo_pgroup_info_t pgi; + const char *part = NULL, *rev = NULL, *serial = NULL; + char *type, *manuf = NULL, *prod = NULL, *asset = NULL, *loc = NULL; + int err, rc = 0; + + if ((auth = topo_mod_auth(mod, slotnode)) == NULL) { + topo_mod_dprintf(mod, "topo_mod_auth() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + return (NULL); + } + + if (smed->sme_smb_info != NULL) { + if (is_valid_string(smb_info->smbi_part) == B_TRUE) + part = smb_info->smbi_part; + if (is_valid_string(smb_info->smbi_version) == B_TRUE) + rev = smb_info->smbi_version; + if (is_valid_string(smb_info->smbi_serial) == B_TRUE) + serial = smb_info->smbi_serial; + if (is_valid_string(smb_info->smbi_manufacturer) == B_TRUE) + manuf = topo_mod_clean_str(mod, + smb_info->smbi_manufacturer); + if (is_valid_string(smb_info->smbi_product) == B_TRUE) + prod = topo_mod_clean_str(mod, smb_info->smbi_product); + if (is_valid_string(smb_info->smbi_asset) == B_TRUE) + asset = topo_mod_clean_str(mod, smb_info->smbi_asset); + if (is_valid_string(smb_info->smbi_location) == B_TRUE) + loc = topo_mod_clean_str(mod, smb_info->smbi_location); + } + + if ((fmri = topo_mod_hcfmri(mod, slotnode, FM_HC_SCHEME_VERSION, + DIMM, 0, NULL, auth, part, rev, serial)) == NULL) { + nvlist_free(auth); + topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s", + topo_mod_errmsg(mod)); + /* errno set */ + goto err; + } + nvlist_free(auth); + + if (topo_node_range_create(mod, slotnode, DIMM, 0, 0) < 0 || + (dimmnode = topo_node_bind(mod, slotnode, DIMM, 0, fmri)) == + NULL) { + nvlist_free(fmri); + topo_mod_dprintf(mod, "failed to bind dimm node: %s", + topo_mod_errmsg(mod)); + /* errno set */ + goto err; + } + + if (topo_node_fru_set(dimmnode, fmri, NULL, &err) != 0) { + topo_mod_dprintf(mod, "failed to set FRU on %s: %s", + DIMM, topo_strerror(err)); + nvlist_free(fmri); + (void) topo_mod_seterrno(mod, err); + goto err; + } + nvlist_free(fmri); + + if (topo_node_label_set(dimmnode, (char *)smb_md->smbmd_dloc, &err) != + 0) { + topo_mod_dprintf(mod, "failed to set label on %s: %s", + DIMM, topo_strerror(err)); + (void) topo_mod_seterrno(mod, err); + goto err; + } + + pgi.tpi_name = TOPO_PGROUP_DIMM_PROPS; + pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; + pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; + pgi.tpi_version = TOPO_VERSION; + if (topo_pgroup_create(dimmnode, &pgi, &err) != 0) { + (void) topo_mod_seterrno(mod, err); + goto err; + } + + rc += topo_prop_set_uint64(dimmnode, TOPO_PGROUP_DIMM_PROPS, "size", + TOPO_PROP_IMMUTABLE, smb_md->smbmd_size, &err); + if (rc == 0 && (type = smbios2topotype(mod, smb_md->smbmd_type)) != + NULL) { + rc += topo_prop_set_string(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "type", TOPO_PROP_IMMUTABLE, type, &err); + topo_mod_strfree(mod, type); + } + if (rc == 0 && smb_md->smbmd_set != 0 && smb_md->smbmd_set != 0xFF) + rc += topo_prop_set_uint32(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "set", TOPO_PROP_IMMUTABLE, smb_md->smbmd_set, &err); + if (rc == 0 && smb_md->smbmd_rank != 0) + rc += topo_prop_set_uint32(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "rank", TOPO_PROP_IMMUTABLE, smb_md->smbmd_rank, &err); + if (rc == 0 && smb_md->smbmd_clkspeed != 0) + rc += topo_prop_set_uint32(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "configured-speed", TOPO_PROP_IMMUTABLE, + smb_md->smbmd_clkspeed, &err); + if (rc == 0 && smb_md->smbmd_speed != 0) + rc += topo_prop_set_uint32(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "maximum-speed", TOPO_PROP_IMMUTABLE, smb_md->smbmd_speed, + &err); + if (rc == 0 && smb_md->smbmd_maxvolt != 0) + rc += topo_prop_set_double(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "maximum-voltage", TOPO_PROP_IMMUTABLE, + (smb_md->smbmd_maxvolt / 1000), &err); + if (rc == 0 && smb_md->smbmd_minvolt != 0) + rc += topo_prop_set_double(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "minimum-voltage", TOPO_PROP_IMMUTABLE, + (smb_md->smbmd_minvolt / 1000), &err); + if (rc == 0 && smb_md->smbmd_confvolt != 0) + rc += topo_prop_set_double(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "configured-voltage", TOPO_PROP_IMMUTABLE, + (smb_md->smbmd_confvolt / 1000), &err); + if (rc == 0 && manuf != NULL) + rc += topo_prop_set_string(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "manufacturer", TOPO_PROP_IMMUTABLE, manuf, &err); + if (rc == 0 && prod != NULL) + rc += topo_prop_set_string(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "product", TOPO_PROP_IMMUTABLE, prod, &err); + if (rc == 0 && asset != NULL) + rc += topo_prop_set_string(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "asset-tag", TOPO_PROP_IMMUTABLE, asset, &err); + if (rc == 0 && loc != NULL) + rc += topo_prop_set_string(dimmnode, TOPO_PGROUP_DIMM_PROPS, + "location", TOPO_PROP_IMMUTABLE, loc, &err); + + if (rc != 0) { + topo_mod_dprintf(mod, "error setting properties on %s node", + DIMM); + (void) topo_mod_seterrno(mod, err); + goto err; + } + ret = dimmnode; +err: + topo_mod_strfree(mod, manuf); + topo_mod_strfree(mod, prod); + topo_mod_strfree(mod, asset); + topo_mod_strfree(mod, loc); + return (ret); +} + +static int +smbios_enum_memory(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg) +{ + smbios_info_t smb_info; + smbios_memdevice_t smb_md; + smb_enum_data_t *smed = arg; + topo_mod_t *mod = smed->sme_mod; + tnode_t *slotnode; + + if (sp->smbstr_type != SMB_TYPE_MEMDEVICE) + return (0); + + if (smbios_info_memdevice(shp, sp->smbstr_id, &smb_md) != 0) { + topo_mod_dprintf(mod, "libsmbios error"); + return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); + } + + /* + * SMB_TYPE_MEMDEVICE records can also be used to represent memory + * that come in non-DIMM form factors. If we encounter something like + * that, then we skip over it. + */ + if ((smed->sme_slot_form = distill_dimm_form(mod, &smb_md)) == NULL) + return (0); + + if ((slotnode = smbios_make_slot(smed, &smb_md)) == NULL) { + topo_mod_dprintf(mod, "failed to create %s node", SLOT); + topo_mod_strfree(mod, smed->sme_slot_form); + /* errno set */ + return (-1); + } + topo_mod_strfree(mod, smed->sme_slot_form); + smed->sme_slotnode = slotnode; + + /* + * A size of zero indicates that the DIMM slot is not populated, so + * we skip creating a child dimm node and return. + */ + if (smb_md.smbmd_size == 0) { + smed->sme_slot_inst++; + return (0); + } + + if (smbios_info_common(shp, sp->smbstr_id, &smb_info) == 0) + smed->sme_smb_info = &smb_info; + + if (smbios_make_dimm(smed, &smb_md) == NULL) { + topo_mod_dprintf(mod, "failed to create %s node", DIMM); + /* errno set */ + return (-1); + } + /* + * If we've exceeded our max inst then return non-zero to cause + * the walk to terminate. + */ + if (++smed->sme_slot_inst > smed->sme_slot_maxinst) + return (1); + + return (0); +} + +/* + * A system with a functional memory controller driver will have one mc device + * node per chip instance, starting at instance 0. The driver provides an + * ioctl interface for retrieving a snapshot of the system's memory topology. + * If we're able to issue this ioctl on one of the mc device nodes then we'll + * return B_TRUE, indicating that this system has a minimally functional memory + * controller driver. + */ +static boolean_t +has_mc_driver() +{ + int mc_fd; + mc_snapshot_info_t mcs; + + if ((mc_fd = open("/dev/mc/mc0", O_RDONLY)) < 0) + return (B_FALSE); + + if (ioctl(mc_fd, MC_IOC_SNAPSHOT_INFO, &mcs) < 0) { + (void) close(mc_fd); + return (B_FALSE); + } + (void) close(mc_fd); + return (B_TRUE); +} + +/*ARGSUSED*/ +static int +smbios_enum(topo_mod_t *mod, tnode_t *rnode, const char *name, + topo_instance_t min, topo_instance_t max, void *arg, void *unused) +{ + smbios_hdl_t *smbh; + smb_enum_data_t smed = { 0 }; + + if ((smbh = topo_mod_smbios(mod)) == NULL) { + topo_mod_dprintf(mod, "failed to get libsmbios handle"); + return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); + } + smed.sme_mod = mod; + smed.sme_pnode = rnode; + smed.sme_slot_inst = min; + smed.sme_slot_maxinst = max; + + /* + * Currently we only support enumerating dimm-slot and dimm nodes, but + * this module could be expanded in the future to enumerate other + * hardware components from SMBIOS. + */ + if (strcmp(name, SLOT) == 0) { + /* + * If the system has a functional memory controller driver then + * we'll assume that it has responsibility for enumerating the + * memory topology. + */ + if (has_mc_driver() == B_TRUE) + return (0); + if (smbios_iter(smbh, smbios_enum_memory, &smed) < 0) + /* errno set */ + return (-1); + } else { + topo_mod_dprintf(mod, "smbios_enum() invoked for unsupported " + "node type: %s", name); + return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); + } + return (0); +} + +const topo_modops_t smbios_ops = { smbios_enum, NULL }; + +const topo_modinfo_t smbios_info = + { "smbios", FM_FMRI_SCHEME_HC, TOPO_VERSION, &smbios_ops }; + +/*ARGSUSED*/ +int +_topo_init(topo_mod_t *mod, topo_version_t version) +{ + if (getenv("TOPOSMBIOSDEBUG") != NULL) + topo_mod_setdebug(mod); + + if (topo_mod_register(mod, &smbios_info, TOPO_VERSION) != 0) { + topo_mod_dprintf(mod, "module registration failed: %s\n", + topo_mod_errmsg(mod)); + /* errno set */ + return (-1); + } + + topo_mod_dprintf(mod, "SMBIOS enumerator initialized\n"); + return (0); +} + +void +_topo_fini(topo_mod_t *mod) +{ + topo_mod_unregister(mod); +} diff --git a/usr/src/lib/libipmi/common/ipmi_lancfg.c b/usr/src/lib/libipmi/common/ipmi_lancfg.c index 3e3ebc6e81..b324891e3f 100644 --- a/usr/src/lib/libipmi/common/ipmi_lancfg.c +++ b/usr/src/lib/libipmi/common/ipmi_lancfg.c @@ -22,6 +22,9 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. + */ /* * Query and configure LAN interfaces over IPMI. This is done through the @@ -34,6 +37,7 @@ #include <strings.h> #include <libipmi.h> +#include <netinet/in.h> #include "ipmi_impl.h" @@ -65,10 +69,26 @@ typedef struct ipmi_cmd_lan_set_config { #define IPMI_LAN_PARAM_SUBNET_MASK 6 #define IPMI_LAN_PARAM_GATEWAY_ADDR 12 +/* VLAN/IPv6 parameters are currently only supported for GET operations */ +#define IPMI_LAN_PARAM_VLAN_ID 20 +#define IPMI_LAN_PARAM_IPVX_ENABLED 51 +#define IPMI_LAN_PARAM_IPV6_NUM_ADDRS 55 +#define IPMI_LAN_PARAM_IPV6_SADDR 56 +#define IPMI_LAN_PARAM_IPV6_DADDR 59 +#define IPMI_LAN_PARAM_IPV6_ROUTER_CONFIG 64 +#define IPMI_LAN_PARAM_IPV6_STATIC_ROUTE1 65 +#define IPMI_LAN_PARAM_IPV6_STATIC_ROUTE2 68 +#define IPMI_LAN_PARAM_IPV6_NUM_DYN_ROUTES 72 +#define IPMI_LAN_PARAM_IPV6_DYN_ROUTE 73 + #define IPMI_LAN_SET_COMPLETE 0x0 #define IPMI_LAN_SET_INPROGRESS 0x1 #define IPMI_LAN_SET_COMMIT 0x2 +/* bitfield values of IPMI_LAN_PARAM_IPV6_ROUTER_CONFIG param */ +#define IPMI_LAN_IPV6_STATIC_ROUTES_ENABLED 0x1 +#define IPMI_LAN_IPV6_DYNAMIC_ROUTES_ENABLED 0x2 + typedef struct ipmi_lan_entry { int ile_param; int ile_mask; @@ -78,7 +98,7 @@ typedef struct ipmi_lan_entry { size_t ile_len; } ipmi_lan_entry_t; -static ipmi_lan_entry_t ipmi_lan_table[] = { +static ipmi_lan_entry_t ipmi_lan_ipv4_table[] = { { IPMI_LAN_PARAM_IP_ADDR, IPMI_LAN_SET_IPADDR, 0, 0, offsetof(ipmi_lan_config_t, ilc_ipaddr), sizeof (uint32_t) }, { IPMI_LAN_PARAM_IP_SOURCE, IPMI_LAN_SET_IPADDR_SOURCE, 0, 0, @@ -91,8 +111,8 @@ static ipmi_lan_entry_t ipmi_lan_table[] = { offsetof(ipmi_lan_config_t, ilc_gateway_addr), sizeof (uint32_t) } }; -#define IPMI_LAN_NENTRIES \ - (sizeof (ipmi_lan_table) / sizeof (ipmi_lan_table[0])) +#define IPMI_LAN_IPV4_NENTRIES \ + (sizeof (ipmi_lan_ipv4_table) / sizeof (ipmi_lan_ipv4_table[0])) static int ipmi_lan_get_param(ipmi_handle_t *ihp, int channel, int param, int set, @@ -129,15 +149,44 @@ ipmi_lan_get_param(ipmi_handle_t *ihp, int channel, int param, int set, return (0); } +struct ipmi_lan_ipv6_addr { + uint8_t ipva_selector; + uint8_t ipva_source; + uint8_t ipva_addr[16]; + uint8_t ipva_prefixlen; + uint8_t ipva_status; +}; + +struct ipmi_lan_ipv6_numaddrs { + uint8_t inva_num_saddrs; + uint8_t inva_num_daddrs; + uint8_t inva_support; +}; + +struct ipmi_lan_vlan_cfg { + uint8_t ivla_vlanid_lower; + DECL_BITFIELD3( + ivla_vlanid_upper :4, + __reserved :3, + ivla_vlan_enable :1); +}; + int ipmi_lan_get_config(ipmi_handle_t *ihp, int channel, ipmi_lan_config_t *cfgp) { - uint8_t set; - int i; + uint8_t set, enabled, route_cfg, ndynroutes = 0; + int i, j; ipmi_lan_entry_t *lep; + struct ipmi_lan_ipv6_numaddrs numaddrs = { 0 }; + struct ipmi_lan_ipv6_addr addrv6 = { 0 }; + struct ipmi_lan_vlan_cfg vlancfg = { 0 }; + struct in6_addr sroute1 = { 0 }, sroute2 = { 0 }, droute = { 0 }; + boolean_t found_addr = B_FALSE; + boolean_t stat_routes_enabled = B_FALSE, dyn_routes_enabled = B_FALSE; if (ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_SET_IN_PROGRESS, 0, 0, &set, sizeof (set)) != 0) + /* errno set */ return (-1); if (set & IPMI_LAN_SET_INPROGRESS) @@ -145,14 +194,186 @@ ipmi_lan_get_config(ipmi_handle_t *ihp, int channel, ipmi_lan_config_t *cfgp) else cfgp->ilc_set_in_progress = B_FALSE; - for (i = 0; i < IPMI_LAN_NENTRIES; i++) { - lep = &ipmi_lan_table[i]; - if (ipmi_lan_get_param(ihp, channel, lep->ile_param, - lep->ile_set, lep->ile_block, - (char *)cfgp + lep->ile_offset, lep->ile_len) != 0) + /* + * First determine which IP addressing modes (IPv4/6) are enabled. On + * service processors that don't support a version of IPMI that is + * IPv6-aware, this parameter won't exist. If we fail to look it up + * then we'll assume that only IPv4 is enabled. + */ + if (ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_IPVX_ENABLED, 0, 0, + &enabled, sizeof (enabled)) != 0) { + cfgp->ilc_ipv4_enabled = B_TRUE; + cfgp->ilc_ipv6_enabled = B_FALSE; + } else { + switch (enabled) { + case 0: + cfgp->ilc_ipv4_enabled = B_TRUE; + cfgp->ilc_ipv6_enabled = B_FALSE; + break; + case 1: + cfgp->ilc_ipv4_enabled = B_FALSE; + cfgp->ilc_ipv6_enabled = B_TRUE; + break; + case 2: + cfgp->ilc_ipv4_enabled = B_TRUE; + cfgp->ilc_ipv6_enabled = B_TRUE; + break; + default: + return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE, NULL)); + } + } + + /* If IPv4 support is enabled, gather the current configuration. */ + if (cfgp->ilc_ipv4_enabled == B_TRUE) { + for (i = 0; i < IPMI_LAN_IPV4_NENTRIES; i++) { + lep = &ipmi_lan_ipv4_table[i]; + if (ipmi_lan_get_param(ihp, channel, lep->ile_param, + lep->ile_set, lep->ile_block, + (char *)cfgp + lep->ile_offset, lep->ile_len) != 0) + /* errno set */ + return (-1); + } + } + + /* Next check if VLAN is enabled, and if so, grab the VLAN ID. */ + if (ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_VLAN_ID, 0, + 0, &vlancfg, sizeof (struct ipmi_lan_vlan_cfg)) != 0) { + /* errno set */ + return (-1); + } + cfgp->ilc_vlan_enabled = vlancfg.ivla_vlan_enable; + if (cfgp->ilc_vlan_enabled == B_TRUE) { + cfgp->ilc_vlan_id = (vlancfg.ivla_vlanid_upper << 8) | + vlancfg.ivla_vlanid_lower; + } + + /* If IPv6 support isn't enabled, then we're all done here. */ + if (cfgp->ilc_ipv6_enabled != B_TRUE) + return (0); + + /* + * First check for a static address. If we can't find one, we'll look + * for a dynamic address. The spec allows for multiple IPv6 static and + * dynamic addresses to exist in various states. For simplicity, we + * will search for the first address that is configured and active. + */ + if (ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_IPV6_NUM_ADDRS, 0, + 0, &numaddrs, sizeof (numaddrs)) != 0) { + /* errno set */ + return (-1); + } + + for (i = 0; i < numaddrs.inva_num_saddrs; i++) { + if (ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_IPV6_SADDR, + i, 0, &addrv6, sizeof (addrv6)) == 0 && + addrv6.ipva_status == 0) { + found_addr = B_TRUE; + cfgp->ilc_ipv6_source = IPMI_LAN_SRC_STATIC; + break; + } + } + for (i = 0; found_addr == B_FALSE && i < numaddrs.inva_num_daddrs; + i++) { + if (ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_IPV6_DADDR, + i, 0, &addrv6, sizeof (addrv6)) == 0 && + addrv6.ipva_status == 0) { + found_addr = B_TRUE; + cfgp->ilc_ipv6_source = IPMI_LAN_SRC_DHCP; + break; + } + } + + /* + * If we didn't find any active static or dynamic addresses, then + * while IPv6 support is enabled, no IPv6 interfaces have been + * configured. We reset ilc_ipv6_enabled back to false so that + * callers know that the other ilc_ipv6_* fields are not valid. + */ + if (found_addr != B_TRUE) { + cfgp->ilc_ipv6_enabled = B_FALSE; + return (0); + } + + (void) memcpy(cfgp->ilc_ipv6_addr, addrv6.ipva_addr, + sizeof (addrv6.ipva_addr)); + + /* + * For the case that static addressing was used for the SP IP then we + * need to get the IPMI_LAN_PARAM_IPV6_ROUTER_CONFIG parameter to + * determine if static or dynamic routes are enabled (or both). + * + * If DHCP was used to assign the SP IP, then only dynamic route + * discovery is supported. + */ + if (cfgp->ilc_ipv6_source == IPMI_LAN_SRC_STATIC && + ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_IPV6_ROUTER_CONFIG, + 0, 0, &route_cfg, sizeof (route_cfg)) != 0) { + /* errno set */ + return (-1); + } + + if (cfgp->ilc_ipv6_source == IPMI_LAN_SRC_STATIC) { + if (route_cfg & IPMI_LAN_IPV6_STATIC_ROUTES_ENABLED) + stat_routes_enabled = B_TRUE; + if (route_cfg & IPMI_LAN_IPV6_DYNAMIC_ROUTES_ENABLED) + dyn_routes_enabled = B_TRUE; + } else { + dyn_routes_enabled = B_TRUE; + } + + /* + * The IPMI spec allows for a max of two static IPv6 routes to be + * configured. + */ + j = cfgp->ilc_ipv6_nroutes = 0; + if (stat_routes_enabled == B_TRUE) { + cfgp->ilc_ipv6_nroutes = 2; + if (ipmi_lan_get_param(ihp, channel, + IPMI_LAN_PARAM_IPV6_STATIC_ROUTE1, 0, 0, &sroute1, + sizeof (sroute1)) != 0 || + ipmi_lan_get_param(ihp, channel, + IPMI_LAN_PARAM_IPV6_STATIC_ROUTE2, 0, 0, &sroute1, + sizeof (sroute2)) != 0) { + /* errno set */ return (-1); + } + if (IN6_IS_ADDR_UNSPECIFIED(&sroute1)) { + cfgp->ilc_ipv6_nroutes++; + (void) memcpy(cfgp->ilc_ipv6_routes[j++], &sroute1, + sizeof (sroute1)); + } + if (IN6_IS_ADDR_UNSPECIFIED(&sroute2) != B_TRUE) { + cfgp->ilc_ipv6_nroutes++; + (void) memcpy(cfgp->ilc_ipv6_routes[j++], &sroute2, + sizeof (sroute2)); + } } + /* + * RFC4861 states that if dynamic routing is used, a host should retain + * a minimum of two routes, though more is recommended. Retrieve the + * number of dynamic routes and then iterate through them and gather + * up to the first two addresses. + */ + if (dyn_routes_enabled == B_TRUE && + ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_IPV6_NUM_DYN_ROUTES, + 0, 0, &ndynroutes, sizeof (ndynroutes)) != 0) { + /* errno set */ + return (-1); + } + for (i = 0; i < ndynroutes && i < 2; i++) { + if (ipmi_lan_get_param(ihp, channel, + IPMI_LAN_PARAM_IPV6_DYN_ROUTE, i, 0, &droute, + sizeof (droute)) != 0) + /* errno set */ + return (-1); + + if (IN6_IS_ADDR_UNSPECIFIED(&droute) != B_TRUE) { + (void) memcpy(cfgp->ilc_ipv6_routes[j++], &droute, + sizeof (droute)); + cfgp->ilc_ipv6_nroutes++; + } + } return (0); } @@ -220,8 +441,8 @@ ipmi_lan_set_config(ipmi_handle_t *ihp, int channel, ipmi_lan_config_t *cfgp, /* * Iterate over all parameters and set them. */ - for (i = 0; i < IPMI_LAN_NENTRIES; i++) { - lep = &ipmi_lan_table[i]; + for (i = 0; i < IPMI_LAN_IPV4_NENTRIES; i++) { + lep = &ipmi_lan_ipv4_table[i]; if (!(lep->ile_mask & mask)) continue; diff --git a/usr/src/lib/libipmi/common/libipmi.h b/usr/src/lib/libipmi/common/libipmi.h index 8552585405..01bf3cb546 100644 --- a/usr/src/lib/libipmi/common/libipmi.h +++ b/usr/src/lib/libipmi/common/libipmi.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2017, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. */ #ifndef _LIBIPMI_H @@ -297,6 +297,9 @@ extern ipmi_channel_info_t *ipmi_get_channel_info(ipmi_handle_t *, int); * This can be expanded in the future as needed. */ +/* We'll return up to a maximum of two static routee + two dynamic routes */ +#define IPMI_LAN_IPV6_MAX_ROUTES 4 + typedef struct ipmi_lan_config { boolean_t ilc_set_in_progress; uint32_t ilc_ipaddr; @@ -304,8 +307,17 @@ typedef struct ipmi_lan_config { uint8_t ilc_macaddr[6]; uint32_t ilc_subnet; uint32_t ilc_gateway_addr; + uint8_t ilc_ipv6_source; + uint8_t ilc_ipv6_addr[16]; + uint8_t ilc_ipv6_routes[IPMI_LAN_IPV6_MAX_ROUTES][16]; + uint8_t ilc_ipv6_nroutes; + uint16_t ilc_vlan_id; + boolean_t ilc_ipv4_enabled; + boolean_t ilc_ipv6_enabled; + boolean_t ilc_vlan_enabled; } ipmi_lan_config_t; +/* values for ilc_ipaddr_source */ #define IPMI_LAN_SRC_UNSPECIFIED 0x0 #define IPMI_LAN_SRC_STATIC 0x1 #define IPMI_LAN_SRC_DHCP 0x2 diff --git a/usr/src/pkg/manifests/service-fault-management.mf b/usr/src/pkg/manifests/service-fault-management.mf index 0198121c53..4bd1aebf44 100644 --- a/usr/src/pkg/manifests/service-fault-management.mf +++ b/usr/src/pkg/manifests/service-fault-management.mf @@ -21,7 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2017, Joyent, Inc. +# Copyright (c) 2018, Joyent, Inc. # # @@ -571,6 +571,7 @@ file path=usr/lib/fm/topo/plugins/fac_prov_mptsas.so mode=0555 file path=usr/lib/fm/topo/plugins/ipmi.so mode=0555 file path=usr/lib/fm/topo/plugins/nic.so mode=0555 file path=usr/lib/fm/topo/plugins/ses.so mode=0555 +file path=usr/lib/fm/topo/plugins/smbios.so mode=0555 file path=usr/lib/fm/topo/plugins/xfp.so mode=0555 # # Dictionaries, whether they are hardware-specific or not, are @@ -730,14 +731,23 @@ $(i386_ONLY)file path=usr/platform/i86pc/lib/fm/eft/gcpu.eft mode=0444 $(i386_ONLY)file path=usr/platform/i86pc/lib/fm/eft/gcpu_amd.eft mode=0444 $(i386_ONLY)file path=usr/platform/i86pc/lib/fm/eft/intel.eft mode=0444 $(i386_ONLY)file \ + path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-hc-topology.xml \ + mode=0444 +$(i386_ONLY)file \ + path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-chassis-hc-topology.xml \ + mode=0444 +$(i386_ONLY)file \ + path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-slot-hc-topology.xml \ + mode=0444 +$(i386_ONLY)file \ path=usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-hc-topology.xml \ mode=0444 $(i386_ONLY)link \ path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3101-hc-topology.xml \ - target=./SSG-2028R-ACR24L-hc-topology.xml + target=./SSG-2028R-ACR24L-hc-topology.xml $(i386_ONLY)link \ path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3102-hc-topology.xml \ - target=./SSG-2028R-ACR24L-hc-topology.xml + target=./SSG-2028R-ACR24L-hc-topology.xml $(i386_ONLY)file \ path=usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-chassis-hc-topology.xml \ mode=0444 @@ -745,6 +755,9 @@ $(i386_ONLY)file \ path=usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-disk-hc-topology.xml \ mode=0444 $(i386_ONLY)file \ + path=usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-slot-hc-topology.xml \ + mode=0444 +$(i386_ONLY)file \ path=usr/platform/i86pc/lib/fm/topo/maps/Netra-X4200-M2-disk-hc-topology.xml \ mode=0444 $(i386_ONLY)file \ |