1f41150baSkrishnae /*
2f41150baSkrishnae  * CDDL HEADER START
3f41150baSkrishnae  *
4f41150baSkrishnae  * The contents of this file are subject to the terms of the
5f41150baSkrishnae  * Common Development and Distribution License (the "License").
6f41150baSkrishnae  * You may not use this file except in compliance with the License.
7f41150baSkrishnae  *
8f41150baSkrishnae  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9f41150baSkrishnae  * or http://www.opensolaris.org/os/licensing.
10f41150baSkrishnae  * See the License for the specific language governing permissions
11f41150baSkrishnae  * and limitations under the License.
12f41150baSkrishnae  *
13f41150baSkrishnae  * When distributing Covered Code, include this CDDL HEADER in each
14f41150baSkrishnae  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15f41150baSkrishnae  * If applicable, add the following below this CDDL HEADER, with the
16f41150baSkrishnae  * fields enclosed by brackets "[]" replaced with your own identifying
17f41150baSkrishnae  * information: Portions Copyright [yyyy] [name of copyright owner]
18f41150baSkrishnae  *
19f41150baSkrishnae  * CDDL HEADER END
20f41150baSkrishnae  */
21f41150baSkrishnae 
22f41150baSkrishnae /*
236bc688afSScott M. Carter  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24f41150baSkrishnae  */
25f41150baSkrishnae #include <fm/libtopo.h>
26f41150baSkrishnae #include <sys/fm/util.h>
276bc688afSScott M. Carter #include <sys/types.h>
286bc688afSScott M. Carter #include <sys/stat.h>
296bc688afSScott M. Carter #include <sys/errno.h>
306bc688afSScott M. Carter #include <fcntl.h>
316bc688afSScott M. Carter #include <unistd.h>
326bc688afSScott M. Carter #include <pthread.h>
33f41150baSkrishnae 
34*b0709259SAndy Fiddaman #include <libxml/tree.h>
35*b0709259SAndy Fiddaman #include <libxml/parser.h>
36f41150baSkrishnae #include <libxml/xpathInternals.h>
37f41150baSkrishnae 
384df55fdeSJanie Lu #include "fabric-xlate.h"
39f41150baSkrishnae 
406bc688afSScott M. Carter #define	XMLTOPOFILE "/var/run/fab-xlate-topo.xml"
41f41150baSkrishnae 
424df55fdeSJanie Lu fmd_xprt_t *fab_fmd_xprt;	/* FMD transport layer handle */
434df55fdeSJanie Lu char fab_buf[FM_MAX_CLASS];
44f41150baSkrishnae 
454df55fdeSJanie Lu /* Static FM Topo XML Format and XML XPath Context  */
464df55fdeSJanie Lu static xmlDocPtr	fab_doc = NULL;
474df55fdeSJanie Lu xmlXPathContextPtr	fab_xpathCtx = NULL;
484df55fdeSJanie Lu static int		fab_valid_topo = 0;
496bc688afSScott M. Carter static pthread_mutex_t	fab_lock = PTHREAD_MUTEX_INITIALIZER;
50f41150baSkrishnae 
51f41150baSkrishnae static void
fab_update_topo(fmd_hdl_t * hdl)52f41150baSkrishnae fab_update_topo(fmd_hdl_t *hdl)
53f41150baSkrishnae {
54f41150baSkrishnae 	topo_hdl_t	*thp = NULL;
556bc688afSScott M. Carter 	FILE		*fp = NULL;
56f41150baSkrishnae 	int		err = 0;
576bc688afSScott M. Carter 	int		fd = -1;
58f41150baSkrishnae 
596bc688afSScott M. Carter 	/* Open the temporary file with proper ownership */
606bc688afSScott M. Carter 	while (fd == -1) {
616bc688afSScott M. Carter 		if ((unlink(XMLTOPOFILE) == -1) && (errno != ENOENT)) {
626bc688afSScott M. Carter 			fmd_hdl_debug(hdl, "Failed to remove XML topo file\n");
636bc688afSScott M. Carter 			return;
646bc688afSScott M. Carter 		}
656bc688afSScott M. Carter 		fd = open(XMLTOPOFILE, O_RDWR | O_CREAT | O_EXCL, 0600);
666bc688afSScott M. Carter 		if ((fd == -1) && (errno != EEXIST)) {
676bc688afSScott M. Carter 			fmd_hdl_debug(hdl, "Failed to create XML topo file\n");
686bc688afSScott M. Carter 			return;
696bc688afSScott M. Carter 		}
706bc688afSScott M. Carter 	}
716bc688afSScott M. Carter 
726bc688afSScott M. Carter 	/* Associate a stream with the temporary file */
736bc688afSScott M. Carter 	if ((fp = fdopen(fd, "w")) == NULL) {
746bc688afSScott M. Carter 		fmd_hdl_debug(hdl, "Failed to open XML topo file\n");
756bc688afSScott M. Carter 		goto cleanup;
766bc688afSScott M. Carter 	}
776bc688afSScott M. Carter 
786bc688afSScott M. Carter 	/* Hold topology */
79f41150baSkrishnae 	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) {
80f41150baSkrishnae 		fmd_hdl_debug(hdl, "Failed to hold topo\n");
816bc688afSScott M. Carter 		goto cleanup;
82f41150baSkrishnae 	}
83f41150baSkrishnae 
846bc688afSScott M. Carter 	/* Print topology to XML file */
85f41150baSkrishnae 	if (topo_xml_print(thp, fp, FM_FMRI_SCHEME_HC, &err) < 0) {
86f41150baSkrishnae 		fmd_hdl_debug(hdl, "Failed to get XML topo\n");
876bc688afSScott M. Carter 		fmd_hdl_topo_rele(hdl, thp);
886bc688afSScott M. Carter 		goto cleanup;
89f41150baSkrishnae 	}
90f41150baSkrishnae 
916bc688afSScott M. Carter 	/* Release topology */
92f41150baSkrishnae 	fmd_hdl_topo_rele(hdl, thp);
93f41150baSkrishnae 
946bc688afSScott M. Carter 	/* Reload topology from XML file */
95e8638579Skrishnae 	if (fab_xpathCtx)
96e8638579Skrishnae 		xmlXPathFreeContext(fab_xpathCtx);
97e8638579Skrishnae 	if (fab_doc)
98e8638579Skrishnae 		xmlFreeDoc(fab_doc);
99f41150baSkrishnae 	fab_doc = xmlParseFile(XMLTOPOFILE);
100f41150baSkrishnae 	fab_xpathCtx = xmlXPathNewContext(fab_doc);
101b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 	fab_set_fake_rp(hdl);
102f41150baSkrishnae 	fab_valid_topo = 1;
1036bc688afSScott M. Carter 
1046bc688afSScott M. Carter cleanup:
1056bc688afSScott M. Carter 	if (fp != NULL)
1066bc688afSScott M. Carter 		(void) fclose(fp);
1076bc688afSScott M. Carter 	else if (fd != -1)
1086bc688afSScott M. Carter 		(void) close(fd);
1096bc688afSScott M. Carter 	(void) unlink(XMLTOPOFILE);
110f41150baSkrishnae }
111f41150baSkrishnae 
112f41150baSkrishnae /*ARGSUSED*/
113f41150baSkrishnae static void
fab_recv(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl,const char * class)114f41150baSkrishnae fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
115f41150baSkrishnae {
1164df55fdeSJanie Lu 	nvlist_t *new_nvl;
117f41150baSkrishnae 
1186bc688afSScott M. Carter 	(void) pthread_mutex_lock(&fab_lock);
119f41150baSkrishnae 	if (!fab_valid_topo)
120f41150baSkrishnae 		fab_update_topo(hdl);
1216bc688afSScott M. Carter 	(void) pthread_mutex_unlock(&fab_lock);
122f41150baSkrishnae 
1234df55fdeSJanie Lu 	if (nvlist_dup(nvl, &new_nvl, NV_UNIQUE_NAME) != 0) {
1244df55fdeSJanie Lu 		fmd_hdl_error(hdl, "failed to duplicate event");
1254df55fdeSJanie Lu 		return;
1264df55fdeSJanie Lu 	}
1274df55fdeSJanie Lu 
1284df55fdeSJanie Lu 	if (fmd_nvl_class_match(hdl, new_nvl, "ereport.io.pci.fabric")) {
1294df55fdeSJanie Lu 		fab_xlate_fabric_erpts(hdl, new_nvl, class);
130f41150baSkrishnae 	} else {
1314df55fdeSJanie Lu 		fab_pr(hdl, ep, new_nvl);
1324df55fdeSJanie Lu 		if (fmd_nvl_class_match(hdl, new_nvl,
1334df55fdeSJanie Lu 		    "ereport.io.pciex.rc.epkt")) {
1344df55fdeSJanie Lu 			fab_xlate_epkt_erpts(hdl, new_nvl, class);
1354df55fdeSJanie Lu 		} else {
1364df55fdeSJanie Lu 			fab_xlate_fire_erpts(hdl, new_nvl, class);
1374df55fdeSJanie Lu 		}
138f41150baSkrishnae 	}
1394df55fdeSJanie Lu 
1404df55fdeSJanie Lu 	nvlist_free(new_nvl);
141f41150baSkrishnae }
142f41150baSkrishnae 
143f41150baSkrishnae /* ARGSUSED */
144f41150baSkrishnae static void
fab_topo(fmd_hdl_t * hdl,topo_hdl_t * topo)145f41150baSkrishnae fab_topo(fmd_hdl_t *hdl, topo_hdl_t *topo)
146f41150baSkrishnae {
1476bc688afSScott M. Carter 	(void) pthread_mutex_lock(&fab_lock);
148f41150baSkrishnae 	fab_valid_topo = 0;
1496bc688afSScott M. Carter 	(void) pthread_mutex_unlock(&fab_lock);
150f41150baSkrishnae }
151f41150baSkrishnae 
152f41150baSkrishnae static const fmd_hdl_ops_t fmd_ops = {
153f41150baSkrishnae 	fab_recv,	/* fmdo_recv */
154f41150baSkrishnae 	NULL,		/* fmdo_timeout */
155f41150baSkrishnae 	NULL,		/* fmdo_close */
156f41150baSkrishnae 	NULL,		/* fmdo_stats */
157f41150baSkrishnae 	NULL,		/* fmdo_gc */
158f41150baSkrishnae 	NULL,		/* fmdo_send */
159f41150baSkrishnae 	fab_topo,	/* fmdo_topo */
160f41150baSkrishnae };
161f41150baSkrishnae 
162f41150baSkrishnae static const fmd_hdl_info_t fmd_info = {
163f41150baSkrishnae 	"Fabric Ereport Translater", "1.0", &fmd_ops, NULL
164f41150baSkrishnae };
165f41150baSkrishnae 
166f41150baSkrishnae void
_fmd_init(fmd_hdl_t * hdl)167f41150baSkrishnae _fmd_init(fmd_hdl_t *hdl)
168f41150baSkrishnae {
169f41150baSkrishnae 	if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0)
170f41150baSkrishnae 		return;
171f41150baSkrishnae 
172f41150baSkrishnae 	/* Init libxml */
173f41150baSkrishnae 	xmlInitParser();
174f41150baSkrishnae 
175f41150baSkrishnae 	fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL);
176f41150baSkrishnae 	fmd_hdl_debug(hdl, "Fabric Translater Started\n");
177f41150baSkrishnae 
1784df55fdeSJanie Lu 	fab_setup_master_table();
179f41150baSkrishnae }
180f41150baSkrishnae 
181f41150baSkrishnae void
_fmd_fini(fmd_hdl_t * hdl)182f41150baSkrishnae _fmd_fini(fmd_hdl_t *hdl)
183f41150baSkrishnae {
184f41150baSkrishnae 	/* Fini xpath */
185f41150baSkrishnae 	if (fab_xpathCtx)
186f41150baSkrishnae 		xmlXPathFreeContext(fab_xpathCtx);
187f41150baSkrishnae 	/* Free xml document */
188f41150baSkrishnae 	if (fab_doc)
189f41150baSkrishnae 		xmlFreeDoc(fab_doc);
190f41150baSkrishnae 	/* Fini libxml */
191f41150baSkrishnae 	xmlCleanupParser();
192f41150baSkrishnae 
193f41150baSkrishnae 	fmd_xprt_close(hdl, fab_fmd_xprt);
194f41150baSkrishnae }
195