1733a5356Srb144127 /* 2733a5356Srb144127 * CDDL HEADER START 3733a5356Srb144127 * 4733a5356Srb144127 * The contents of this file are subject to the terms of the 531e37bb4Svn83148 * Common Development and Distribution License (the "License"). 631e37bb4Svn83148 * You may not use this file except in compliance with the License. 7733a5356Srb144127 * 8733a5356Srb144127 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9733a5356Srb144127 * or http://www.opensolaris.org/os/licensing. 10733a5356Srb144127 * See the License for the specific language governing permissions 11733a5356Srb144127 * and limitations under the License. 12733a5356Srb144127 * 13733a5356Srb144127 * When distributing Covered Code, include this CDDL HEADER in each 14733a5356Srb144127 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15733a5356Srb144127 * If applicable, add the following below this CDDL HEADER, with the 16733a5356Srb144127 * fields enclosed by brackets "[]" replaced with your own identifying 17733a5356Srb144127 * information: Portions Copyright [yyyy] [name of copyright owner] 18733a5356Srb144127 * 19733a5356Srb144127 * CDDL HEADER END 20733a5356Srb144127 */ 21733a5356Srb144127 22733a5356Srb144127 /* 23*c5fb5d32SKarl Davis * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24733a5356Srb144127 * Use is subject to license terms. 25733a5356Srb144127 */ 26733a5356Srb144127 27733a5356Srb144127 /* 28733a5356Srb144127 * etm.c FMA Event Transport Module implementation, a plugin of FMD 29733a5356Srb144127 * for sun4v/Ontario 30733a5356Srb144127 * 31733a5356Srb144127 * plugin for sending/receiving FMA events to/from service processor 32733a5356Srb144127 */ 33733a5356Srb144127 34733a5356Srb144127 /* 35733a5356Srb144127 * --------------------------------- includes -------------------------------- 36733a5356Srb144127 */ 37733a5356Srb144127 38733a5356Srb144127 #include <sys/fm/protocol.h> 39733a5356Srb144127 #include <sys/fm/util.h> 4031e37bb4Svn83148 #include <sys/fm/ldom.h> 414b476ed5Sdarudy #include <sys/strlog.h> 424b476ed5Sdarudy #include <sys/syslog.h> 4325351652SVuong Nguyen #include <sys/libds.h> 44b8677b72Srb144127 #include <netinet/in.h> 45b8677b72Srb144127 #include <fm/fmd_api.h> 46733a5356Srb144127 47733a5356Srb144127 #include "etm_xport_api.h" 48733a5356Srb144127 #include "etm_etm_proto.h" 49733a5356Srb144127 #include "etm_impl.h" 5025351652SVuong Nguyen #include "etm_iosvc.h" 5125351652SVuong Nguyen #include "etm_filter.h" 5225351652SVuong Nguyen #include "etm_ckpt.h" 53733a5356Srb144127 54733a5356Srb144127 #include <pthread.h> 55733a5356Srb144127 #include <signal.h> 56733a5356Srb144127 #include <stropts.h> 57733a5356Srb144127 #include <locale.h> 58733a5356Srb144127 #include <strings.h> 59733a5356Srb144127 #include <stdlib.h> 60733a5356Srb144127 #include <unistd.h> 61733a5356Srb144127 #include <limits.h> 62733a5356Srb144127 #include <values.h> 63733a5356Srb144127 #include <alloca.h> 64733a5356Srb144127 #include <errno.h> 6525351652SVuong Nguyen #include <dlfcn.h> 6625351652SVuong Nguyen #include <link.h> 67733a5356Srb144127 #include <fcntl.h> 68733a5356Srb144127 #include <time.h> 69733a5356Srb144127 70733a5356Srb144127 /* 71733a5356Srb144127 * ----------------------------- forward decls ------------------------------- 72733a5356Srb144127 */ 73733a5356Srb144127 74733a5356Srb144127 static void 75733a5356Srb144127 etm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class); 76733a5356Srb144127 7725351652SVuong Nguyen static int 7825351652SVuong Nguyen etm_send(fmd_hdl_t *hdl, fmd_xprt_t *xp, fmd_event_t *event, nvlist_t *nvl); 7925351652SVuong Nguyen 8025351652SVuong Nguyen static void 8125351652SVuong Nguyen etm_send_to_remote_root(void *arg); 8225351652SVuong Nguyen 8325351652SVuong Nguyen static void 8425351652SVuong Nguyen etm_recv_from_remote_root(void *arg); 8525351652SVuong Nguyen 86d279c7bfSVuong Nguyen static void 87d279c7bfSVuong Nguyen etm_ckpt_remove(fmd_hdl_t *hdl, etm_iosvc_q_ele_t *ele); 88d279c7bfSVuong Nguyen 89733a5356Srb144127 /* 90733a5356Srb144127 * ------------------------- data structs for FMD ---------------------------- 91733a5356Srb144127 */ 92733a5356Srb144127 932c07a099SYanmin Sun static const fmd_hdl_ops_t fmd_ops = { 94733a5356Srb144127 etm_recv, /* fmdo_recv */ 95733a5356Srb144127 NULL, /* fmdo_timeout */ 96733a5356Srb144127 NULL, /* fmdo_close */ 97733a5356Srb144127 NULL, /* fmdo_stats */ 98733a5356Srb144127 NULL, /* fmdo_gc */ 9925351652SVuong Nguyen etm_send, /* fmdo_send */ 100733a5356Srb144127 }; 101733a5356Srb144127 102733a5356Srb144127 static const fmd_prop_t fmd_props[] = { 103733a5356Srb144127 { ETM_PROP_NM_XPORT_ADDRS, FMD_TYPE_STRING, "" }, 104733a5356Srb144127 { ETM_PROP_NM_DEBUG_LVL, FMD_TYPE_INT32, "0" }, 105733a5356Srb144127 { ETM_PROP_NM_DEBUG_MAX_EV_CNT, FMD_TYPE_INT32, "-1" }, 1064b476ed5Sdarudy { ETM_PROP_NM_CONSOLE, FMD_TYPE_BOOL, "false" }, 1074b476ed5Sdarudy { ETM_PROP_NM_SYSLOGD, FMD_TYPE_BOOL, "true" }, 1084b476ed5Sdarudy { ETM_PROP_NM_FACILITY, FMD_TYPE_STRING, "LOG_DAEMON" }, 109*c5fb5d32SKarl Davis { ETM_PROP_NM_MAX_RESP_Q_LEN, FMD_TYPE_UINT32, "32" }, 1102ca9f232Srb144127 { ETM_PROP_NM_BAD_ACC_TO_SEC, FMD_TYPE_UINT32, "1" }, 11125351652SVuong Nguyen { ETM_PROP_NM_FMA_RESP_WAIT_TIME, FMD_TYPE_INT32, "240" }, 112733a5356Srb144127 { NULL, 0, NULL } 113733a5356Srb144127 }; 114733a5356Srb144127 1154b476ed5Sdarudy 116733a5356Srb144127 static const fmd_hdl_info_t fmd_info = { 11725351652SVuong Nguyen "FMA Event Transport Module", "1.2", &fmd_ops, fmd_props 118733a5356Srb144127 }; 119733a5356Srb144127 120733a5356Srb144127 /* 121733a5356Srb144127 * ----------------------- private consts and defns -------------------------- 122733a5356Srb144127 */ 123733a5356Srb144127 124733a5356Srb144127 /* misc buffer for variable sized protocol header fields */ 125733a5356Srb144127 126733a5356Srb144127 #define ETM_MISC_BUF_SZ (4 * 1024) 127733a5356Srb144127 12825351652SVuong Nguyen static uint32_t 12925351652SVuong Nguyen etm_ldom_type = LDOM_TYPE_LEGACY; 13025351652SVuong Nguyen 131733a5356Srb144127 /* try limit for IO operations w/ capped exp backoff sleep on retry */ 132733a5356Srb144127 133733a5356Srb144127 /* 134733a5356Srb144127 * Design_Note: ETM will potentially retry forever IO operations that the 135733a5356Srb144127 * transport fails with EAGAIN (aka EWOULDBLOCK) rather than 136733a5356Srb144127 * giving up after some number of seconds. This avoids 137733a5356Srb144127 * dropping FMA events while the service processor is down, 138733a5356Srb144127 * but at the risk of pending fmdo_recv() forever and 139733a5356Srb144127 * overflowing FMD's event queue for ETM. 140733a5356Srb144127 * A future TBD enhancement would be to always recv 141733a5356Srb144127 * and send each ETM msg in a single read/write() to reduce 142733a5356Srb144127 * the risk of failure between ETM msg hdr and body, 143733a5356Srb144127 * assuming the MTU_SZ is large enough. 144733a5356Srb144127 */ 145733a5356Srb144127 146733a5356Srb144127 #define ETM_TRY_MAX_CNT (MAXINT - 1) 147733a5356Srb144127 #define ETM_TRY_BACKOFF_RATE (4) 148733a5356Srb144127 #define ETM_TRY_BACKOFF_CAP (60) 149733a5356Srb144127 150e2ff4ac6Srb144127 /* amount to increment protocol transaction id on each new send */ 151733a5356Srb144127 152733a5356Srb144127 #define ETM_XID_INC (2) 153733a5356Srb144127 154b8677b72Srb144127 typedef struct etm_resp_q_ele { 155b8677b72Srb144127 156b8677b72Srb144127 etm_xport_conn_t rqe_conn; /* open connection to send on */ 157b8677b72Srb144127 etm_proto_v1_pp_t *rqe_hdrp; /* ptr to ETM msg hdr */ 158b8677b72Srb144127 size_t rqe_hdr_sz; /* sizeof ETM msg hdr */ 159b8677b72Srb144127 int32_t rqe_resp_code; /* response code to send */ 160b8677b72Srb144127 161b8677b72Srb144127 struct etm_resp_q_ele *rqe_nextp; /* PRIVATE - next ele ptr */ 162b8677b72Srb144127 163b8677b72Srb144127 } etm_resp_q_ele_t; /* responder queue element */ 164b8677b72Srb144127 165733a5356Srb144127 /* 166733a5356Srb144127 * ---------------------------- global data ---------------------------------- 167733a5356Srb144127 */ 168733a5356Srb144127 16931e37bb4Svn83148 static fmd_hdl_t 17025351652SVuong Nguyen *init_hdl = NULL; /* used in mem allocator and several other places */ 17131e37bb4Svn83148 172733a5356Srb144127 static int 173733a5356Srb144127 etm_debug_lvl = 0; /* debug level: 0 is off, 1 is on, 2 is more, etc */ 174733a5356Srb144127 175733a5356Srb144127 static int 176733a5356Srb144127 etm_debug_max_ev_cnt = -1; /* max allowed event count for debugging */ 177733a5356Srb144127 17800ab1250Srb144127 static fmd_xprt_t 17900ab1250Srb144127 *etm_fmd_xprt = NULL; /* FMD transport layer handle */ 18000ab1250Srb144127 181733a5356Srb144127 static pthread_t 182733a5356Srb144127 etm_svr_tid = NULL; /* thread id of connection acceptance server */ 183733a5356Srb144127 184b8677b72Srb144127 static pthread_t 185b8677b72Srb144127 etm_resp_tid = NULL; /* thread id of msg responder */ 186b8677b72Srb144127 187b8677b72Srb144127 static etm_resp_q_ele_t 188b8677b72Srb144127 *etm_resp_q_head = NULL; /* ptr to cur head of responder queue */ 189b8677b72Srb144127 190b8677b72Srb144127 static etm_resp_q_ele_t 191b8677b72Srb144127 *etm_resp_q_tail = NULL; /* ptr to cur tail of responder queue */ 192b8677b72Srb144127 193b8677b72Srb144127 static uint32_t 194b8677b72Srb144127 etm_resp_q_cur_len = 0; /* cur length (ele cnt) of responder queue */ 195b8677b72Srb144127 196b8677b72Srb144127 static uint32_t 197b8677b72Srb144127 etm_resp_q_max_len = 0; /* max length (ele cnt) of responder queue */ 198b8677b72Srb144127 1992ca9f232Srb144127 static uint32_t 2002ca9f232Srb144127 etm_bad_acc_to_sec = 0; /* sleep timeout (in sec) after bad conn accept */ 2012ca9f232Srb144127 202b8677b72Srb144127 static pthread_mutex_t 203b8677b72Srb144127 etm_resp_q_lock = PTHREAD_MUTEX_INITIALIZER; /* protects responder queue */ 204b8677b72Srb144127 205b8677b72Srb144127 static pthread_cond_t 206b8677b72Srb144127 etm_resp_q_cv = PTHREAD_COND_INITIALIZER; /* nudges msg responder */ 207b8677b72Srb144127 208733a5356Srb144127 static volatile int 209733a5356Srb144127 etm_is_dying = 0; /* bool for dying (killing self) */ 210733a5356Srb144127 211733a5356Srb144127 static uint32_t 212e2ff4ac6Srb144127 etm_xid_cur = 0; /* current transaction id for sends */ 213733a5356Srb144127 214733a5356Srb144127 static uint32_t 215733a5356Srb144127 etm_xid_ping = 0; /* xid of last CONTROL msg sent requesting ping */ 216733a5356Srb144127 217733a5356Srb144127 static uint32_t 218e2ff4ac6Srb144127 etm_xid_ver_negot = 0; /* xid of last CONTROL msg sent requesting ver negot */ 219e2ff4ac6Srb144127 220e2ff4ac6Srb144127 static uint32_t 22125351652SVuong Nguyen etm_xid_posted_logged_ev = 0; 22225351652SVuong Nguyen /* xid of last FMA_EVENT msg/event posted OK to FMD */ 223e2ff4ac6Srb144127 224b8677b72Srb144127 static uint32_t 225b8677b72Srb144127 etm_xid_posted_sa = 0; /* xid of last ALERT msg/event posted OK to syslog */ 226b8677b72Srb144127 227e2ff4ac6Srb144127 static uint8_t 228e2ff4ac6Srb144127 etm_resp_ver = ETM_PROTO_V1; /* proto ver [negotiated] for msg sends */ 229733a5356Srb144127 23025351652SVuong Nguyen static uint32_t 23125351652SVuong Nguyen etm_fma_resp_wait_time = 30; /* time (sec) wait for fma event resp */ 23225351652SVuong Nguyen 2332ae66659Sjrutt static pthread_mutex_t 2342ae66659Sjrutt etm_write_lock = PTHREAD_MUTEX_INITIALIZER; /* for write operations */ 2352ae66659Sjrutt 2364b476ed5Sdarudy static log_ctl_t syslog_ctl; /* log(7D) meta-data for each msg */ 2374b476ed5Sdarudy static int syslog_facility; /* log(7D) facility (part of priority) */ 2384b476ed5Sdarudy static int syslog_logfd = -1; /* log(7D) file descriptor */ 2394b476ed5Sdarudy static int syslog_msgfd = -1; /* sysmsg(7D) file descriptor */ 2404b476ed5Sdarudy static int syslog_file = 0; /* log to syslog_logfd */ 2414b476ed5Sdarudy static int syslog_cons = 0; /* log to syslog_msgfd */ 2424b476ed5Sdarudy 2434b476ed5Sdarudy static const struct facility { 2444b476ed5Sdarudy const char *fac_name; 2454b476ed5Sdarudy int fac_value; 2464b476ed5Sdarudy } syslog_facs[] = { 2474b476ed5Sdarudy { "LOG_DAEMON", LOG_DAEMON }, 2484b476ed5Sdarudy { "LOG_LOCAL0", LOG_LOCAL0 }, 2494b476ed5Sdarudy { "LOG_LOCAL1", LOG_LOCAL1 }, 2504b476ed5Sdarudy { "LOG_LOCAL2", LOG_LOCAL2 }, 2514b476ed5Sdarudy { "LOG_LOCAL3", LOG_LOCAL3 }, 2524b476ed5Sdarudy { "LOG_LOCAL4", LOG_LOCAL4 }, 2534b476ed5Sdarudy { "LOG_LOCAL5", LOG_LOCAL5 }, 2544b476ed5Sdarudy { "LOG_LOCAL6", LOG_LOCAL6 }, 2554b476ed5Sdarudy { "LOG_LOCAL7", LOG_LOCAL7 }, 2564b476ed5Sdarudy { NULL, 0 } 2574b476ed5Sdarudy }; 2584b476ed5Sdarudy 259733a5356Srb144127 static struct stats { 260733a5356Srb144127 261733a5356Srb144127 /* ETM msg counters */ 262733a5356Srb144127 263733a5356Srb144127 fmd_stat_t etm_rd_hdr_fmaevent; 264733a5356Srb144127 fmd_stat_t etm_rd_hdr_control; 2654b476ed5Sdarudy fmd_stat_t etm_rd_hdr_alert; 266733a5356Srb144127 fmd_stat_t etm_rd_hdr_response; 267733a5356Srb144127 fmd_stat_t etm_rd_body_fmaevent; 268733a5356Srb144127 fmd_stat_t etm_rd_body_control; 2694b476ed5Sdarudy fmd_stat_t etm_rd_body_alert; 270733a5356Srb144127 fmd_stat_t etm_rd_body_response; 271733a5356Srb144127 fmd_stat_t etm_wr_hdr_fmaevent; 272733a5356Srb144127 fmd_stat_t etm_wr_hdr_control; 273733a5356Srb144127 fmd_stat_t etm_wr_hdr_response; 274733a5356Srb144127 fmd_stat_t etm_wr_body_fmaevent; 275733a5356Srb144127 fmd_stat_t etm_wr_body_control; 276733a5356Srb144127 fmd_stat_t etm_wr_body_response; 277733a5356Srb144127 278b8677b72Srb144127 fmd_stat_t etm_rd_max_ev_per_msg; 279b8677b72Srb144127 fmd_stat_t etm_wr_max_ev_per_msg; 280b8677b72Srb144127 281b8677b72Srb144127 fmd_stat_t etm_resp_q_cur_len; 282b8677b72Srb144127 fmd_stat_t etm_resp_q_max_len; 283b8677b72Srb144127 284733a5356Srb144127 /* ETM byte counters */ 285733a5356Srb144127 286733a5356Srb144127 fmd_stat_t etm_wr_fmd_bytes; 287733a5356Srb144127 fmd_stat_t etm_rd_fmd_bytes; 288733a5356Srb144127 fmd_stat_t etm_wr_xport_bytes; 289733a5356Srb144127 fmd_stat_t etm_rd_xport_bytes; 290733a5356Srb144127 291733a5356Srb144127 fmd_stat_t etm_magic_drop_bytes; 292733a5356Srb144127 293733a5356Srb144127 /* ETM [dropped] FMA event counters */ 294733a5356Srb144127 295733a5356Srb144127 fmd_stat_t etm_rd_fmd_fmaevent; 296733a5356Srb144127 fmd_stat_t etm_wr_fmd_fmaevent; 297733a5356Srb144127 298733a5356Srb144127 fmd_stat_t etm_rd_drop_fmaevent; 299733a5356Srb144127 fmd_stat_t etm_wr_drop_fmaevent; 300733a5356Srb144127 301e2ff4ac6Srb144127 fmd_stat_t etm_rd_dup_fmaevent; 302e2ff4ac6Srb144127 fmd_stat_t etm_wr_dup_fmaevent; 303e2ff4ac6Srb144127 304b8677b72Srb144127 fmd_stat_t etm_rd_dup_alert; 305b8677b72Srb144127 fmd_stat_t etm_wr_dup_alert; 306b8677b72Srb144127 307b8677b72Srb144127 fmd_stat_t etm_enq_drop_resp_q; 308b8677b72Srb144127 fmd_stat_t etm_deq_drop_resp_q; 309b8677b72Srb144127 310733a5356Srb144127 /* ETM protocol failures */ 311733a5356Srb144127 312733a5356Srb144127 fmd_stat_t etm_magic_bad; 313733a5356Srb144127 fmd_stat_t etm_ver_bad; 314733a5356Srb144127 fmd_stat_t etm_msgtype_bad; 315733a5356Srb144127 fmd_stat_t etm_subtype_bad; 316733a5356Srb144127 fmd_stat_t etm_xid_bad; 317733a5356Srb144127 fmd_stat_t etm_fmaeventlen_bad; 318733a5356Srb144127 fmd_stat_t etm_respcode_bad; 319733a5356Srb144127 fmd_stat_t etm_timeout_bad; 320733a5356Srb144127 fmd_stat_t etm_evlens_bad; 321733a5356Srb144127 322733a5356Srb144127 /* IO operation failures */ 323733a5356Srb144127 324733a5356Srb144127 fmd_stat_t etm_xport_wr_fail; 325733a5356Srb144127 fmd_stat_t etm_xport_rd_fail; 326733a5356Srb144127 fmd_stat_t etm_xport_pk_fail; 327733a5356Srb144127 328733a5356Srb144127 /* IO operation retries */ 329733a5356Srb144127 330733a5356Srb144127 fmd_stat_t etm_xport_wr_retry; 331733a5356Srb144127 fmd_stat_t etm_xport_rd_retry; 332733a5356Srb144127 fmd_stat_t etm_xport_pk_retry; 333733a5356Srb144127 334733a5356Srb144127 /* system and library failures */ 335733a5356Srb144127 336733a5356Srb144127 fmd_stat_t etm_os_nvlist_pack_fail; 337733a5356Srb144127 fmd_stat_t etm_os_nvlist_unpack_fail; 338733a5356Srb144127 fmd_stat_t etm_os_nvlist_size_fail; 339733a5356Srb144127 fmd_stat_t etm_os_pthread_create_fail; 340733a5356Srb144127 341733a5356Srb144127 /* xport API failures */ 342733a5356Srb144127 343733a5356Srb144127 fmd_stat_t etm_xport_get_ev_addrv_fail; 344733a5356Srb144127 fmd_stat_t etm_xport_open_fail; 345733a5356Srb144127 fmd_stat_t etm_xport_close_fail; 346733a5356Srb144127 fmd_stat_t etm_xport_accept_fail; 347733a5356Srb144127 fmd_stat_t etm_xport_open_retry; 348733a5356Srb144127 349733a5356Srb144127 /* FMD entry point bad arguments */ 350733a5356Srb144127 351733a5356Srb144127 fmd_stat_t etm_fmd_init_badargs; 352733a5356Srb144127 fmd_stat_t etm_fmd_fini_badargs; 353733a5356Srb144127 3544b476ed5Sdarudy /* Alert logging errors */ 355b8677b72Srb144127 3564b476ed5Sdarudy fmd_stat_t etm_log_err; 3574b476ed5Sdarudy fmd_stat_t etm_msg_err; 3584b476ed5Sdarudy 3592ca9f232Srb144127 /* miscellaneous stats */ 3602ca9f232Srb144127 3612ca9f232Srb144127 fmd_stat_t etm_reset_xport; 3622ca9f232Srb144127 363733a5356Srb144127 } etm_stats = { 364733a5356Srb144127 365733a5356Srb144127 /* ETM msg counters */ 366733a5356Srb144127 367733a5356Srb144127 { "etm_rd_hdr_fmaevent", FMD_TYPE_UINT64, 368733a5356Srb144127 "ETM fmaevent msg headers rcvd from xport" }, 369733a5356Srb144127 { "etm_rd_hdr_control", FMD_TYPE_UINT64, 370733a5356Srb144127 "ETM control msg headers rcvd from xport" }, 3714b476ed5Sdarudy { "etm_rd_hdr_alert", FMD_TYPE_UINT64, 3724b476ed5Sdarudy "ETM alert msg headers rcvd from xport" }, 373733a5356Srb144127 { "etm_rd_hdr_response", FMD_TYPE_UINT64, 374733a5356Srb144127 "ETM response msg headers rcvd from xport" }, 375733a5356Srb144127 { "etm_rd_body_fmaevent", FMD_TYPE_UINT64, 376733a5356Srb144127 "ETM fmaevent msg bodies rcvd from xport" }, 377733a5356Srb144127 { "etm_rd_body_control", FMD_TYPE_UINT64, 378733a5356Srb144127 "ETM control msg bodies rcvd from xport" }, 3794b476ed5Sdarudy { "etm_rd_body_alert", FMD_TYPE_UINT64, 3804b476ed5Sdarudy "ETM alert msg bodies rcvd from xport" }, 381733a5356Srb144127 { "etm_rd_body_response", FMD_TYPE_UINT64, 382733a5356Srb144127 "ETM response msg bodies rcvd from xport" }, 383733a5356Srb144127 { "etm_wr_hdr_fmaevent", FMD_TYPE_UINT64, 384733a5356Srb144127 "ETM fmaevent msg headers sent to xport" }, 385733a5356Srb144127 { "etm_wr_hdr_control", FMD_TYPE_UINT64, 386733a5356Srb144127 "ETM control msg headers sent to xport" }, 387733a5356Srb144127 { "etm_wr_hdr_response", FMD_TYPE_UINT64, 388733a5356Srb144127 "ETM response msg headers sent to xport" }, 389733a5356Srb144127 { "etm_wr_body_fmaevent", FMD_TYPE_UINT64, 390733a5356Srb144127 "ETM fmaevent msg bodies sent to xport" }, 391733a5356Srb144127 { "etm_wr_body_control", FMD_TYPE_UINT64, 392733a5356Srb144127 "ETM control msg bodies sent to xport" }, 393733a5356Srb144127 { "etm_wr_body_response", FMD_TYPE_UINT64, 394733a5356Srb144127 "ETM response msg bodies sent to xport" }, 395733a5356Srb144127 396b8677b72Srb144127 { "etm_rd_max_ev_per_msg", FMD_TYPE_UINT64, 397b8677b72Srb144127 "max FMA events per ETM msg from xport" }, 398b8677b72Srb144127 { "etm_wr_max_ev_per_msg", FMD_TYPE_UINT64, 399b8677b72Srb144127 "max FMA events per ETM msg to xport" }, 400b8677b72Srb144127 401b8677b72Srb144127 { "etm_resp_q_cur_len", FMD_TYPE_UINT64, 402b8677b72Srb144127 "cur enqueued response msgs to xport" }, 403b8677b72Srb144127 { "etm_resp_q_max_len", FMD_TYPE_UINT64, 404b8677b72Srb144127 "max enqueable response msgs to xport" }, 405b8677b72Srb144127 406733a5356Srb144127 /* ETM byte counters */ 407733a5356Srb144127 408733a5356Srb144127 { "etm_wr_fmd_bytes", FMD_TYPE_UINT64, 409733a5356Srb144127 "bytes of FMA events sent to FMD" }, 410733a5356Srb144127 { "etm_rd_fmd_bytes", FMD_TYPE_UINT64, 411733a5356Srb144127 "bytes of FMA events rcvd from FMD" }, 412733a5356Srb144127 { "etm_wr_xport_bytes", FMD_TYPE_UINT64, 413733a5356Srb144127 "bytes of FMA events sent to xport" }, 414733a5356Srb144127 { "etm_rd_xport_bytes", FMD_TYPE_UINT64, 415733a5356Srb144127 "bytes of FMA events rcvd from xport" }, 416733a5356Srb144127 417733a5356Srb144127 { "etm_magic_drop_bytes", FMD_TYPE_UINT64, 418733a5356Srb144127 "bytes dropped from xport pre magic num" }, 419733a5356Srb144127 420733a5356Srb144127 /* ETM [dropped] FMA event counters */ 421733a5356Srb144127 422733a5356Srb144127 { "etm_rd_fmd_fmaevent", FMD_TYPE_UINT64, 423733a5356Srb144127 "FMA events rcvd from FMD" }, 424733a5356Srb144127 { "etm_wr_fmd_fmaevent", FMD_TYPE_UINT64, 425733a5356Srb144127 "FMA events sent to FMD" }, 426733a5356Srb144127 427733a5356Srb144127 { "etm_rd_drop_fmaevent", FMD_TYPE_UINT64, 428733a5356Srb144127 "dropped FMA events from xport" }, 429733a5356Srb144127 { "etm_wr_drop_fmaevent", FMD_TYPE_UINT64, 430733a5356Srb144127 "dropped FMA events to xport" }, 431733a5356Srb144127 432e2ff4ac6Srb144127 { "etm_rd_dup_fmaevent", FMD_TYPE_UINT64, 433b8677b72Srb144127 "duplicate FMA events rcvd from xport" }, 434e2ff4ac6Srb144127 { "etm_wr_dup_fmaevent", FMD_TYPE_UINT64, 435b8677b72Srb144127 "duplicate FMA events sent to xport" }, 436b8677b72Srb144127 437b8677b72Srb144127 { "etm_rd_dup_alert", FMD_TYPE_UINT64, 438b8677b72Srb144127 "duplicate ALERTs rcvd from xport" }, 439b8677b72Srb144127 { "etm_wr_dup_alert", FMD_TYPE_UINT64, 440b8677b72Srb144127 "duplicate ALERTs sent to xport" }, 441b8677b72Srb144127 442b8677b72Srb144127 { "etm_enq_drop_resp_q", FMD_TYPE_UINT64, 443b8677b72Srb144127 "dropped response msgs on enq" }, 444b8677b72Srb144127 { "etm_deq_drop_resp_q", FMD_TYPE_UINT64, 445b8677b72Srb144127 "dropped response msgs on deq" }, 446e2ff4ac6Srb144127 447733a5356Srb144127 /* ETM protocol failures */ 448733a5356Srb144127 449733a5356Srb144127 { "etm_magic_bad", FMD_TYPE_UINT64, 450733a5356Srb144127 "ETM msgs w/ invalid magic num" }, 451733a5356Srb144127 { "etm_ver_bad", FMD_TYPE_UINT64, 452733a5356Srb144127 "ETM msgs w/ invalid protocol version" }, 453733a5356Srb144127 { "etm_msgtype_bad", FMD_TYPE_UINT64, 454733a5356Srb144127 "ETM msgs w/ invalid message type" }, 455733a5356Srb144127 { "etm_subtype_bad", FMD_TYPE_UINT64, 456733a5356Srb144127 "ETM msgs w/ invalid sub type" }, 457733a5356Srb144127 { "etm_xid_bad", FMD_TYPE_UINT64, 458733a5356Srb144127 "ETM msgs w/ unmatched xid" }, 459733a5356Srb144127 { "etm_fmaeventlen_bad", FMD_TYPE_UINT64, 460733a5356Srb144127 "ETM msgs w/ invalid FMA event length" }, 461733a5356Srb144127 { "etm_respcode_bad", FMD_TYPE_UINT64, 462733a5356Srb144127 "ETM msgs w/ invalid response code" }, 463733a5356Srb144127 { "etm_timeout_bad", FMD_TYPE_UINT64, 464733a5356Srb144127 "ETM msgs w/ invalid timeout value" }, 465733a5356Srb144127 { "etm_evlens_bad", FMD_TYPE_UINT64, 466733a5356Srb144127 "ETM msgs w/ too many event lengths" }, 467733a5356Srb144127 468733a5356Srb144127 /* IO operation failures */ 469733a5356Srb144127 470733a5356Srb144127 { "etm_xport_wr_fail", FMD_TYPE_UINT64, 471733a5356Srb144127 "xport write failures" }, 472733a5356Srb144127 { "etm_xport_rd_fail", FMD_TYPE_UINT64, 473733a5356Srb144127 "xport read failures" }, 474733a5356Srb144127 { "etm_xport_pk_fail", FMD_TYPE_UINT64, 475733a5356Srb144127 "xport peek failures" }, 476733a5356Srb144127 477733a5356Srb144127 /* IO operation retries */ 478733a5356Srb144127 479733a5356Srb144127 { "etm_xport_wr_retry", FMD_TYPE_UINT64, 480733a5356Srb144127 "xport write retries" }, 481733a5356Srb144127 { "etm_xport_rd_retry", FMD_TYPE_UINT64, 482733a5356Srb144127 "xport read retries" }, 483733a5356Srb144127 { "etm_xport_pk_retry", FMD_TYPE_UINT64, 484733a5356Srb144127 "xport peek retries" }, 485733a5356Srb144127 486733a5356Srb144127 /* system and library failures */ 487733a5356Srb144127 488733a5356Srb144127 { "etm_os_nvlist_pack_fail", FMD_TYPE_UINT64, 489733a5356Srb144127 "nvlist_pack failures" }, 490733a5356Srb144127 { "etm_os_nvlist_unpack_fail", FMD_TYPE_UINT64, 491733a5356Srb144127 "nvlist_unpack failures" }, 492733a5356Srb144127 { "etm_os_nvlist_size_fail", FMD_TYPE_UINT64, 493733a5356Srb144127 "nvlist_size failures" }, 494733a5356Srb144127 { "etm_os_pthread_create_fail", FMD_TYPE_UINT64, 495733a5356Srb144127 "pthread_create failures" }, 496733a5356Srb144127 497733a5356Srb144127 /* transport API failures */ 498733a5356Srb144127 499733a5356Srb144127 { "etm_xport_get_ev_addrv_fail", FMD_TYPE_UINT64, 500733a5356Srb144127 "xport get event addrv API failures" }, 501733a5356Srb144127 { "etm_xport_open_fail", FMD_TYPE_UINT64, 502733a5356Srb144127 "xport open API failures" }, 503733a5356Srb144127 { "etm_xport_close_fail", FMD_TYPE_UINT64, 504733a5356Srb144127 "xport close API failures" }, 505733a5356Srb144127 { "etm_xport_accept_fail", FMD_TYPE_UINT64, 506733a5356Srb144127 "xport accept API failures" }, 507733a5356Srb144127 { "etm_xport_open_retry", FMD_TYPE_UINT64, 508733a5356Srb144127 "xport open API retries" }, 509733a5356Srb144127 510733a5356Srb144127 /* FMD entry point bad arguments */ 511733a5356Srb144127 512733a5356Srb144127 { "etm_fmd_init_badargs", FMD_TYPE_UINT64, 513733a5356Srb144127 "bad arguments from fmd_init entry point" }, 514733a5356Srb144127 { "etm_fmd_fini_badargs", FMD_TYPE_UINT64, 5154b476ed5Sdarudy "bad arguments from fmd_fini entry point" }, 5164b476ed5Sdarudy 5174b476ed5Sdarudy /* Alert logging errors */ 518b8677b72Srb144127 5194b476ed5Sdarudy { "etm_log_err", FMD_TYPE_UINT64, 5204b476ed5Sdarudy "failed to log message to log(7D)" }, 5214b476ed5Sdarudy { "etm_msg_err", FMD_TYPE_UINT64, 5222ca9f232Srb144127 "failed to log message to sysmsg(7D)" }, 5232ca9f232Srb144127 5242ca9f232Srb144127 /* miscellaneous stats */ 5252ca9f232Srb144127 5262ca9f232Srb144127 { "etm_reset_xport", FMD_TYPE_UINT64, 5272ca9f232Srb144127 "xport resets after xport API failure" } 528733a5356Srb144127 }; 529733a5356Srb144127 53025351652SVuong Nguyen 53125351652SVuong Nguyen /* 53225351652SVuong Nguyen * -------------------- global data for Root ldom------------------------- 53325351652SVuong Nguyen */ 53425351652SVuong Nguyen 53525351652SVuong Nguyen ldom_hdl_t 53625351652SVuong Nguyen *etm_lhp = NULL; /* ldom pointer */ 53725351652SVuong Nguyen 53825351652SVuong Nguyen static void *etm_dl_hdl = (void *)NULL; 53925351652SVuong Nguyen static const char *etm_dl_path = "libds.so.1"; 54025351652SVuong Nguyen static int etm_dl_mode = (RTLD_NOW | RTLD_LOCAL); 54125351652SVuong Nguyen 54225351652SVuong Nguyen static int(*etm_ds_svc_reg)(ds_capability_t *cap, ds_ops_t *ops) = 54325351652SVuong Nguyen (int (*)(ds_capability_t *cap, ds_ops_t *ops))NULL; 54425351652SVuong Nguyen static int(*etm_ds_clnt_reg)(ds_capability_t *cap, ds_ops_t *ops) = 54525351652SVuong Nguyen (int (*)(ds_capability_t *cap, ds_ops_t *ops))NULL; 54625351652SVuong Nguyen static int(*etm_ds_send_msg)(ds_hdl_t hdl, void *buf, size_t buflen) = 54725351652SVuong Nguyen (int (*)(ds_hdl_t hdl, void *buf, size_t buflen))NULL; 54825351652SVuong Nguyen static int(*etm_ds_recv_msg)(ds_hdl_t hdl, void *buf, size_t buflen, 54925351652SVuong Nguyen size_t *msglen) = 55025351652SVuong Nguyen (int (*)(ds_hdl_t hdl, void *buf, size_t buflen, size_t *msglen))NULL; 55125351652SVuong Nguyen static int (*etm_ds_fini)(void) = (int (*)(void))NULL; 55225351652SVuong Nguyen 55325351652SVuong Nguyen static pthread_mutex_t 55425351652SVuong Nguyen iosvc_list_lock = PTHREAD_MUTEX_INITIALIZER; 55525351652SVuong Nguyen 55625351652SVuong Nguyen static pthread_t 55725351652SVuong Nguyen etm_async_e_tid = NULL; /* thread id of io svc async event handler */ 55825351652SVuong Nguyen 55925351652SVuong Nguyen static etm_proto_v1_ev_hdr_t iosvc_hdr = { 56025351652SVuong Nguyen ETM_PROTO_MAGIC_NUM, /* magic number */ 56125351652SVuong Nguyen ETM_PROTO_V1, /* default to V1, not checked */ 56225351652SVuong Nguyen ETM_MSG_TYPE_FMA_EVENT, /* Root Domain inteoduces only FMA events */ 56325351652SVuong Nguyen 0, /* sub-type */ 56425351652SVuong Nguyen 0, /* pad */ 56525351652SVuong Nguyen 0, /* add the xid at the Q send time */ 56625351652SVuong Nguyen ETM_PROTO_V1_TIMEOUT_NONE, 56725351652SVuong Nguyen 0 /* ev_lens, 0-termed, after 1 FMA event */ 56825351652SVuong Nguyen }; 56925351652SVuong Nguyen 57025351652SVuong Nguyen /* 57125351652SVuong Nguyen * static iosvc_list 57225351652SVuong Nguyen */ 57325351652SVuong Nguyen static etm_iosvc_t iosvc_list[NUM_OF_ROOT_DOMAINS] = { 57425351652SVuong Nguyen {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, 57525351652SVuong Nguyen {"", 0}, {"", 0} 57625351652SVuong Nguyen }; 57725351652SVuong Nguyen 57825351652SVuong Nguyen static etm_iosvc_t io_svc = { 57925351652SVuong Nguyen "\0", /* ldom_name */ 58025351652SVuong Nguyen PTHREAD_COND_INITIALIZER, /* nudges */ 58125351652SVuong Nguyen PTHREAD_MUTEX_INITIALIZER, /* protects the iosvc msg Q */ 58225351652SVuong Nguyen NULL, /* iosvc msg Q head */ 58325351652SVuong Nguyen NULL, /* iosvc msg Q tail */ 58425351652SVuong Nguyen 0, /* msg Q current length */ 58525351652SVuong Nguyen 100, /* msg Q max length */ 58625351652SVuong Nguyen 0, /* current transaction id */ 58725351652SVuong Nguyen 0, /* xid of last event posted to FMD */ 58825351652SVuong Nguyen DS_INVALID_HDL, /* DS handle */ 58925351652SVuong Nguyen NULL, /* fmd xprt handle */ 59025351652SVuong Nguyen NULL, /* tid 4 send to remote RootDomain */ 59125351652SVuong Nguyen NULL, /* tid 4 recv from remote RootDomain */ 59225351652SVuong Nguyen PTHREAD_COND_INITIALIZER, /* nudges etm_send_to_remote_root */ 59325351652SVuong Nguyen PTHREAD_MUTEX_INITIALIZER, /* protects msg_ack_cv */ 59425351652SVuong Nguyen 0, /* send/recv threads are not dying */ 59525351652SVuong Nguyen 0, /* flag for start sending msg Q */ 59625351652SVuong Nguyen 0 /* indicate if the ACK has come */ 59725351652SVuong Nguyen }; 59825351652SVuong Nguyen etm_iosvc_t *io_svc_p = &io_svc; 59925351652SVuong Nguyen 60025351652SVuong Nguyen 60125351652SVuong Nguyen static uint32_t 60225351652SVuong Nguyen flags; /* flags for fmd_xprt_open */ 60325351652SVuong Nguyen 60425351652SVuong Nguyen static etm_async_event_ele_t 60525351652SVuong Nguyen async_event_q[ASYNC_EVENT_Q_SIZE]; /* holds the async events */ 60625351652SVuong Nguyen 60725351652SVuong Nguyen static uint32_t 60825351652SVuong Nguyen etm_async_q_head = 0; /* ptr to cur head of async event queue */ 60925351652SVuong Nguyen 61025351652SVuong Nguyen static uint32_t 61125351652SVuong Nguyen etm_async_q_tail = 0; /* ptr to cur tail of async event queue */ 61225351652SVuong Nguyen 61325351652SVuong Nguyen static uint32_t 61425351652SVuong Nguyen etm_async_q_cur_len = 0; /* cur length (ele cnt) of async event queue */ 61525351652SVuong Nguyen 61625351652SVuong Nguyen static uint32_t 61725351652SVuong Nguyen etm_async_q_max_len = ASYNC_EVENT_Q_SIZE; 61825351652SVuong Nguyen /* max length (ele cnt) of async event queue */ 61925351652SVuong Nguyen 62025351652SVuong Nguyen static pthread_cond_t 62125351652SVuong Nguyen etm_async_event_q_cv = PTHREAD_COND_INITIALIZER; 62225351652SVuong Nguyen /* nudges async event handler */ 62325351652SVuong Nguyen 62425351652SVuong Nguyen static pthread_mutex_t 62525351652SVuong Nguyen etm_async_event_q_lock = PTHREAD_MUTEX_INITIALIZER; 62625351652SVuong Nguyen /* protects async event q */ 62725351652SVuong Nguyen 62825351652SVuong Nguyen static ds_ver_t 62925351652SVuong Nguyen etm_iosvc_vers[] = { { 1, 0} }; 63025351652SVuong Nguyen 63125351652SVuong Nguyen #define ETM_NVERS (sizeof (etm_iosvc_vers) / sizeof (ds_ver_t)) 63225351652SVuong Nguyen 63325351652SVuong Nguyen static ds_capability_t 63425351652SVuong Nguyen iosvc_caps = { 63525351652SVuong Nguyen "ETM", /* svc_id */ 63625351652SVuong Nguyen etm_iosvc_vers, /* vers */ 63725351652SVuong Nguyen ETM_NVERS /* number of vers */ 63825351652SVuong Nguyen }; 63925351652SVuong Nguyen 64025351652SVuong Nguyen static void 64125351652SVuong Nguyen etm_iosvc_reg_handler(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver, 64225351652SVuong Nguyen ds_domain_hdl_t did); 64325351652SVuong Nguyen 64425351652SVuong Nguyen static void 64525351652SVuong Nguyen etm_iosvc_unreg_handler(ds_hdl_t hdl, ds_cb_arg_t arg); 64625351652SVuong Nguyen 64725351652SVuong Nguyen static ds_ops_t 64825351652SVuong Nguyen iosvc_ops = { 64925351652SVuong Nguyen etm_iosvc_reg_handler, /* ds_reg_cb */ 65025351652SVuong Nguyen etm_iosvc_unreg_handler, /* ds_unreg_cb */ 65125351652SVuong Nguyen NULL, /* ds_data_cb */ 65225351652SVuong Nguyen NULL /* cb_arg */ 65325351652SVuong Nguyen }; 65425351652SVuong Nguyen 65525351652SVuong Nguyen 656733a5356Srb144127 /* 657733a5356Srb144127 * -------------------------- support functions ------------------------------ 658733a5356Srb144127 */ 659733a5356Srb144127 660733a5356Srb144127 /* 661733a5356Srb144127 * Design_Note: Each failure worth reporting to FMD should be done using 662733a5356Srb144127 * a single call to fmd_hdl_error() as it logs an FMA event 663733a5356Srb144127 * for each call. Also be aware that all the fmd_hdl_*() 664733a5356Srb144127 * format strings currently use platform specific *printf() 665733a5356Srb144127 * routines; so "%p" under Solaris does not prepend "0x" to 666733a5356Srb144127 * the outputted hex digits, while Linux and VxWorks do. 667733a5356Srb144127 */ 668733a5356Srb144127 66925351652SVuong Nguyen 670733a5356Srb144127 /* 671e2ff4ac6Srb144127 * etm_show_time - display the current time of day (for debugging) using 672e2ff4ac6Srb144127 * the given FMD module handle and annotation string 673e2ff4ac6Srb144127 */ 674e2ff4ac6Srb144127 675e2ff4ac6Srb144127 static void 676e2ff4ac6Srb144127 etm_show_time(fmd_hdl_t *hdl, char *note_str) 677e2ff4ac6Srb144127 { 678e2ff4ac6Srb144127 struct timeval tmv; /* timeval */ 679e2ff4ac6Srb144127 680e2ff4ac6Srb144127 (void) gettimeofday(&tmv, NULL); 681e2ff4ac6Srb144127 fmd_hdl_debug(hdl, "info: %s: cur Unix Epoch time %d.%06d\n", 682e2ff4ac6Srb144127 note_str, tmv.tv_sec, tmv.tv_usec); 683e2ff4ac6Srb144127 684e2ff4ac6Srb144127 } /* etm_show_time() */ 685e2ff4ac6Srb144127 686e2ff4ac6Srb144127 /* 687733a5356Srb144127 * etm_hexdump - hexdump the given buffer (for debugging) using 688733a5356Srb144127 * the given FMD module handle 689733a5356Srb144127 */ 690733a5356Srb144127 691733a5356Srb144127 static void 692733a5356Srb144127 etm_hexdump(fmd_hdl_t *hdl, void *buf, size_t byte_cnt) 693733a5356Srb144127 { 694733a5356Srb144127 uint8_t *bp; /* byte ptr */ 695733a5356Srb144127 int i, j; /* index */ 696733a5356Srb144127 char cb[80]; /* char buf */ 697733a5356Srb144127 unsigned int n; /* a byte of data for sprintf() */ 698733a5356Srb144127 699733a5356Srb144127 bp = buf; 700733a5356Srb144127 j = 0; 701733a5356Srb144127 702733a5356Srb144127 /* 703733a5356Srb144127 * Design_Note: fmd_hdl_debug() auto adds a newline if missing; 704733a5356Srb144127 * hence cb exists to accumulate a longer string. 705733a5356Srb144127 */ 706733a5356Srb144127 707733a5356Srb144127 for (i = 1; i <= byte_cnt; i++) { 708733a5356Srb144127 n = *bp++; 709733a5356Srb144127 (void) sprintf(&cb[j], "%2.2x ", n); 710733a5356Srb144127 j += 3; 711733a5356Srb144127 /* add a newline every 16 bytes or at the buffer's end */ 712733a5356Srb144127 if (((i % 16) == 0) || (i >= byte_cnt)) { 713733a5356Srb144127 cb[j-1] = '\0'; 714733a5356Srb144127 fmd_hdl_debug(hdl, "%s\n", cb); 715733a5356Srb144127 j = 0; 716733a5356Srb144127 } 717733a5356Srb144127 } /* for each byte in the buffer */ 718733a5356Srb144127 719733a5356Srb144127 } /* etm_hexdump() */ 720733a5356Srb144127 721733a5356Srb144127 /* 722733a5356Srb144127 * etm_sleep - sleep the caller for the given number of seconds, 723733a5356Srb144127 * return 0 or -errno value 724733a5356Srb144127 * 725733a5356Srb144127 * Design_Note: To avoid interfering with FMD's signal mask (SIGALRM) 726733a5356Srb144127 * do not use [Solaris] sleep(3C) and instead use 727733a5356Srb144127 * pthread_cond_wait() or nanosleep(), both of which 728733a5356Srb144127 * are POSIX spec-ed to leave signal masks alone. 729733a5356Srb144127 * This is needed for Solaris and Linux (domain and SP). 730733a5356Srb144127 */ 731733a5356Srb144127 732733a5356Srb144127 static int 733733a5356Srb144127 etm_sleep(unsigned sleep_sec) 734733a5356Srb144127 { 735733a5356Srb144127 struct timespec tms; /* for nanosleep() */ 736733a5356Srb144127 737733a5356Srb144127 tms.tv_sec = sleep_sec; 738733a5356Srb144127 tms.tv_nsec = 0; 739733a5356Srb144127 740733a5356Srb144127 if (nanosleep(&tms, NULL) < 0) { 741733a5356Srb144127 /* errno assumed set by above call */ 742733a5356Srb144127 return (-errno); 743733a5356Srb144127 } 744733a5356Srb144127 return (0); 745733a5356Srb144127 746733a5356Srb144127 } /* etm_sleep() */ 747733a5356Srb144127 748733a5356Srb144127 /* 749733a5356Srb144127 * etm_conn_open - open a connection to the given transport address, 750733a5356Srb144127 * return 0 and the opened connection handle 751733a5356Srb144127 * or -errno value 752733a5356Srb144127 * 753733a5356Srb144127 * caveats: the err_substr is used in failure cases for calling 754733a5356Srb144127 * fmd_hdl_error() 755733a5356Srb144127 */ 756733a5356Srb144127 757733a5356Srb144127 static int 758733a5356Srb144127 etm_conn_open(fmd_hdl_t *hdl, char *err_substr, 759733a5356Srb144127 etm_xport_addr_t addr, etm_xport_conn_t *connp) 760733a5356Srb144127 { 761733a5356Srb144127 etm_xport_conn_t conn; /* connection to return */ 762733a5356Srb144127 int nev; /* -errno value */ 763733a5356Srb144127 764733a5356Srb144127 if ((conn = etm_xport_open(hdl, addr)) == NULL) { 765733a5356Srb144127 nev = (-errno); 766733a5356Srb144127 fmd_hdl_error(hdl, "error: %s: errno %d\n", 767733a5356Srb144127 err_substr, errno); 768733a5356Srb144127 etm_stats.etm_xport_open_fail.fmds_value.ui64++; 769733a5356Srb144127 return (nev); 770733a5356Srb144127 } else { 771733a5356Srb144127 *connp = conn; 772733a5356Srb144127 return (0); 773733a5356Srb144127 } 774733a5356Srb144127 } /* etm_conn_open() */ 775733a5356Srb144127 776733a5356Srb144127 /* 777733a5356Srb144127 * etm_conn_close - close the given connection, 778733a5356Srb144127 * return 0 or -errno value 779733a5356Srb144127 * 780733a5356Srb144127 * caveats: the err_substr is used in failure cases for calling 781733a5356Srb144127 * fmd_hdl_error() 782733a5356Srb144127 */ 783733a5356Srb144127 784733a5356Srb144127 static int 785733a5356Srb144127 etm_conn_close(fmd_hdl_t *hdl, char *err_substr, etm_xport_conn_t conn) 786733a5356Srb144127 { 787733a5356Srb144127 int nev; /* -errno value */ 788733a5356Srb144127 789733a5356Srb144127 if (etm_xport_close(hdl, conn) == NULL) { 790733a5356Srb144127 nev = (-errno); 791733a5356Srb144127 fmd_hdl_error(hdl, "warning: %s: errno %d\n", 792733a5356Srb144127 err_substr, errno); 793733a5356Srb144127 etm_stats.etm_xport_close_fail.fmds_value.ui64++; 794733a5356Srb144127 return (nev); 795733a5356Srb144127 } else { 796733a5356Srb144127 return (0); 797733a5356Srb144127 } 798733a5356Srb144127 } /* etm_conn_close() */ 799733a5356Srb144127 800733a5356Srb144127 /* 801733a5356Srb144127 * etm_io_op - perform an IO operation on the given connection 802733a5356Srb144127 * with the given buffer, 803733a5356Srb144127 * accommodating MTU size and retrying op if needed, 804733a5356Srb144127 * return how many bytes actually done by the op 805733a5356Srb144127 * or -errno value 806733a5356Srb144127 * 807733a5356Srb144127 * caveats: the err_substr is used in failure cases for calling 808733a5356Srb144127 * fmd_hdl_error() 809733a5356Srb144127 */ 810733a5356Srb144127 811733a5356Srb144127 static ssize_t 812733a5356Srb144127 etm_io_op(fmd_hdl_t *hdl, char *err_substr, etm_xport_conn_t conn, 813733a5356Srb144127 void *buf, size_t byte_cnt, int io_op) 814733a5356Srb144127 { 815733a5356Srb144127 ssize_t rv; /* ret val / byte count */ 816733a5356Srb144127 ssize_t n; /* gen use */ 817733a5356Srb144127 uint8_t *datap; /* ptr to data */ 818733a5356Srb144127 size_t mtu_sz; /* MTU size in bytes */ 819733a5356Srb144127 int (*io_func_ptr)(fmd_hdl_t *, etm_xport_conn_t, 820733a5356Srb144127 void *, size_t); 821733a5356Srb144127 size_t io_sz; /* byte count for io_func_ptr */ 822733a5356Srb144127 int try_cnt; /* number of tries done */ 823733a5356Srb144127 int sleep_sec; /* exp backoff sleep period in sec */ 824733a5356Srb144127 int sleep_rv; /* ret val from sleeping */ 825733a5356Srb144127 fmd_stat_t io_retry_stat; /* IO retry stat to update */ 826733a5356Srb144127 fmd_stat_t io_fail_stat; /* IO failure stat to update */ 827733a5356Srb144127 828733a5356Srb144127 if ((conn == NULL) || (buf == NULL)) { 829733a5356Srb144127 return (-EINVAL); 830733a5356Srb144127 } 831733a5356Srb144127 switch (io_op) { 832733a5356Srb144127 case ETM_IO_OP_RD: 833733a5356Srb144127 io_func_ptr = etm_xport_read; 834733a5356Srb144127 io_retry_stat = etm_stats.etm_xport_rd_retry; 835733a5356Srb144127 io_fail_stat = etm_stats.etm_xport_rd_fail; 836733a5356Srb144127 break; 837733a5356Srb144127 case ETM_IO_OP_WR: 838733a5356Srb144127 io_func_ptr = etm_xport_write; 839733a5356Srb144127 io_retry_stat = etm_stats.etm_xport_wr_retry; 840733a5356Srb144127 io_fail_stat = etm_stats.etm_xport_wr_fail; 841733a5356Srb144127 break; 842733a5356Srb144127 default: 843733a5356Srb144127 return (-EINVAL); 844733a5356Srb144127 } 845733a5356Srb144127 if (byte_cnt == 0) { 846733a5356Srb144127 return (byte_cnt); /* nop */ 847733a5356Srb144127 } 848733a5356Srb144127 849733a5356Srb144127 /* obtain [current] MTU size */ 850733a5356Srb144127 851733a5356Srb144127 if ((n = etm_xport_get_opt(hdl, conn, ETM_XPORT_OPT_MTU_SZ)) < 0) { 852733a5356Srb144127 mtu_sz = ETM_XPORT_MTU_SZ_DEF; 853733a5356Srb144127 } else { 854733a5356Srb144127 mtu_sz = n; 855733a5356Srb144127 } 856733a5356Srb144127 857733a5356Srb144127 /* loop until all IO done, try limit exceeded, or real failure */ 858733a5356Srb144127 859733a5356Srb144127 rv = 0; 860733a5356Srb144127 datap = buf; 861733a5356Srb144127 while (rv < byte_cnt) { 862733a5356Srb144127 io_sz = MIN((byte_cnt - rv), mtu_sz); 863733a5356Srb144127 try_cnt = 0; 864733a5356Srb144127 sleep_sec = 0; 865733a5356Srb144127 866733a5356Srb144127 /* when give up, return -errno value even if partly done */ 867733a5356Srb144127 868733a5356Srb144127 while ((n = (*io_func_ptr)(hdl, conn, datap, io_sz)) == 869733a5356Srb144127 (-EAGAIN)) { 870733a5356Srb144127 try_cnt++; 871733a5356Srb144127 if (try_cnt > ETM_TRY_MAX_CNT) { 872733a5356Srb144127 rv = n; 873733a5356Srb144127 goto func_ret; 874733a5356Srb144127 } 875733a5356Srb144127 if (etm_is_dying) { 876733a5356Srb144127 rv = (-EINTR); 877733a5356Srb144127 goto func_ret; 878733a5356Srb144127 } 879733a5356Srb144127 if ((sleep_rv = etm_sleep(sleep_sec)) < 0) { 880733a5356Srb144127 rv = sleep_rv; 881733a5356Srb144127 goto func_ret; 882733a5356Srb144127 } 883733a5356Srb144127 sleep_sec = ((sleep_sec == 0) ? 1 : 884733a5356Srb144127 (sleep_sec * ETM_TRY_BACKOFF_RATE)); 885733a5356Srb144127 sleep_sec = MIN(sleep_sec, ETM_TRY_BACKOFF_CAP); 886733a5356Srb144127 io_retry_stat.fmds_value.ui64++; 887733a5356Srb144127 if (etm_debug_lvl >= 1) { 888733a5356Srb144127 fmd_hdl_debug(hdl, "info: retrying io op %d " 889733a5356Srb144127 "due to EAGAIN\n", io_op); 890733a5356Srb144127 } 891733a5356Srb144127 } /* while trying the io operation */ 892733a5356Srb144127 893733a5356Srb144127 if (etm_is_dying) { 894733a5356Srb144127 rv = (-EINTR); 895733a5356Srb144127 goto func_ret; 896733a5356Srb144127 } 897733a5356Srb144127 if (n < 0) { 898733a5356Srb144127 rv = n; 899733a5356Srb144127 goto func_ret; 900733a5356Srb144127 } 901733a5356Srb144127 /* avoid spinning CPU when given 0 bytes but no error */ 902733a5356Srb144127 if (n == 0) { 903733a5356Srb144127 if ((sleep_rv = etm_sleep(ETM_SLEEP_QUIK)) < 0) { 904733a5356Srb144127 rv = sleep_rv; 905733a5356Srb144127 goto func_ret; 906733a5356Srb144127 } 907733a5356Srb144127 } 908733a5356Srb144127 rv += n; 909733a5356Srb144127 datap += n; 910733a5356Srb144127 } /* while still have more data */ 911733a5356Srb144127 912733a5356Srb144127 func_ret: 913733a5356Srb144127 914733a5356Srb144127 if (rv < 0) { 915733a5356Srb144127 io_fail_stat.fmds_value.ui64++; 9162ae66659Sjrutt fmd_hdl_debug(hdl, "error: %s: errno %d\n", 917733a5356Srb144127 err_substr, (int)(-rv)); 918733a5356Srb144127 } 919733a5356Srb144127 if (etm_debug_lvl >= 3) { 920733a5356Srb144127 fmd_hdl_debug(hdl, "info: io op %d ret %d of %d\n", 921733a5356Srb144127 io_op, (int)rv, (int)byte_cnt); 922733a5356Srb144127 } 923733a5356Srb144127 return (rv); 924733a5356Srb144127 925733a5356Srb144127 } /* etm_io_op() */ 926733a5356Srb144127 927733a5356Srb144127 /* 928733a5356Srb144127 * etm_magic_read - read the magic number of an ETM message header 929733a5356Srb144127 * from the given connection into the given buffer, 930733a5356Srb144127 * return 0 or -errno value 931733a5356Srb144127 * 932733a5356Srb144127 * Design_Note: This routine is intended to help protect ETM from protocol 933733a5356Srb144127 * framing errors as might be caused by an SP reset / crash in 934733a5356Srb144127 * the middle of an ETM message send; the connection will be 935733a5356Srb144127 * read from for as many bytes as needed until the magic number 936733a5356Srb144127 * is found using a sliding buffer for comparisons. 937733a5356Srb144127 */ 938733a5356Srb144127 939733a5356Srb144127 static int 940733a5356Srb144127 etm_magic_read(fmd_hdl_t *hdl, etm_xport_conn_t conn, uint32_t *magic_ptr) 941733a5356Srb144127 { 942733a5356Srb144127 int rv; /* ret val */ 943733a5356Srb144127 uint32_t magic_num; /* magic number */ 944733a5356Srb144127 int byte_cnt; /* count of bytes read */ 945733a5356Srb144127 uint8_t buf5[4+1]; /* sliding input buffer */ 946733a5356Srb144127 int i, j; /* indices into buf5 */ 947733a5356Srb144127 ssize_t n; /* gen use */ 948733a5356Srb144127 uint8_t drop_buf[1024]; /* dropped bytes buffer */ 949733a5356Srb144127 950733a5356Srb144127 rv = 0; /* assume success */ 951733a5356Srb144127 magic_num = 0; 952733a5356Srb144127 byte_cnt = 0; 953733a5356Srb144127 j = 0; 954733a5356Srb144127 955733a5356Srb144127 /* magic number bytes are sent in network (big endian) order */ 956733a5356Srb144127 957733a5356Srb144127 while (magic_num != ETM_PROTO_MAGIC_NUM) { 958733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io read on magic", 959733a5356Srb144127 conn, &buf5[j], 1, ETM_IO_OP_RD)) < 0) { 960733a5356Srb144127 rv = n; 961733a5356Srb144127 goto func_ret; 962733a5356Srb144127 } 963733a5356Srb144127 byte_cnt++; 964733a5356Srb144127 j = MIN((j + 1), sizeof (magic_num)); 965733a5356Srb144127 if (byte_cnt < sizeof (magic_num)) { 966733a5356Srb144127 continue; 967733a5356Srb144127 } 968733a5356Srb144127 969733a5356Srb144127 if (byte_cnt > sizeof (magic_num)) { 970733a5356Srb144127 etm_stats.etm_magic_drop_bytes.fmds_value.ui64++; 971733a5356Srb144127 i = MIN(byte_cnt - j - 1, sizeof (drop_buf) - 1); 972733a5356Srb144127 drop_buf[i] = buf5[0]; 973733a5356Srb144127 for (i = 0; i < j; i++) { 974733a5356Srb144127 buf5[i] = buf5[i+1]; 975733a5356Srb144127 } /* for sliding the buffer contents */ 976733a5356Srb144127 } 977733a5356Srb144127 (void) memcpy(&magic_num, &buf5[0], sizeof (magic_num)); 978733a5356Srb144127 magic_num = ntohl(magic_num); 979733a5356Srb144127 } /* for reading bytes until find magic number */ 980733a5356Srb144127 981733a5356Srb144127 func_ret: 982733a5356Srb144127 983733a5356Srb144127 if (byte_cnt != sizeof (magic_num)) { 9842ae66659Sjrutt fmd_hdl_debug(hdl, "warning: bad proto frame " 985733a5356Srb144127 "implies corrupt/lost msg(s)\n"); 986733a5356Srb144127 } 987733a5356Srb144127 if ((byte_cnt > sizeof (magic_num)) && (etm_debug_lvl >= 2)) { 988733a5356Srb144127 i = MIN(byte_cnt - sizeof (magic_num), sizeof (drop_buf)); 989733a5356Srb144127 fmd_hdl_debug(hdl, "info: magic drop hexdump " 990b8677b72Srb144127 "first %d of %d bytes:\n", i, 991b8677b72Srb144127 byte_cnt - sizeof (magic_num)); 992733a5356Srb144127 etm_hexdump(hdl, drop_buf, i); 993733a5356Srb144127 } 994733a5356Srb144127 995733a5356Srb144127 if (rv == 0) { 996733a5356Srb144127 *magic_ptr = magic_num; 997733a5356Srb144127 } 998733a5356Srb144127 return (rv); 999733a5356Srb144127 1000733a5356Srb144127 } /* etm_magic_read() */ 1001733a5356Srb144127 1002733a5356Srb144127 /* 1003733a5356Srb144127 * etm_hdr_read - allocate, read, and validate a [variable sized] 1004733a5356Srb144127 * ETM message header from the given connection, 1005733a5356Srb144127 * return the allocated ETM message header 1006733a5356Srb144127 * (which is guaranteed to be large enough to reuse as a 1007733a5356Srb144127 * RESPONSE msg hdr) and its size 1008733a5356Srb144127 * or NULL and set errno on failure 1009733a5356Srb144127 */ 1010733a5356Srb144127 1011733a5356Srb144127 static void * 1012733a5356Srb144127 etm_hdr_read(fmd_hdl_t *hdl, etm_xport_conn_t conn, size_t *szp) 1013733a5356Srb144127 { 1014733a5356Srb144127 uint8_t *hdrp; /* ptr to header to return */ 1015733a5356Srb144127 size_t hdr_sz; /* sizeof *hdrp */ 1016733a5356Srb144127 etm_proto_v1_pp_t pp; /* protocol preamble */ 1017733a5356Srb144127 etm_proto_v1_ev_hdr_t *ev_hdrp; /* for FMA_EVENT msg */ 1018733a5356Srb144127 etm_proto_v1_ctl_hdr_t *ctl_hdrp; /* for CONTROL msg */ 1019733a5356Srb144127 etm_proto_v1_resp_hdr_t *resp_hdrp; /* for RESPONSE msg */ 10204b476ed5Sdarudy etm_proto_v3_sa_hdr_t *sa_hdrp; /* for ALERT msg */ 1021733a5356Srb144127 uint32_t *lenp; /* ptr to FMA event length */ 1022733a5356Srb144127 ssize_t i, n; /* gen use */ 1023733a5356Srb144127 uint8_t misc_buf[ETM_MISC_BUF_SZ]; /* for var sized hdrs */ 1024733a5356Srb144127 int dummy_int; /* dummy var to appease lint */ 1025733a5356Srb144127 1026733a5356Srb144127 hdrp = NULL; hdr_sz = 0; 1027733a5356Srb144127 1028733a5356Srb144127 /* read the magic number which starts the protocol preamble */ 1029733a5356Srb144127 1030733a5356Srb144127 if ((n = etm_magic_read(hdl, conn, &pp.pp_magic_num)) < 0) { 1031733a5356Srb144127 errno = (-n); 1032733a5356Srb144127 etm_stats.etm_magic_bad.fmds_value.ui64++; 1033733a5356Srb144127 return (NULL); 1034733a5356Srb144127 } 1035733a5356Srb144127 1036733a5356Srb144127 /* read the rest of the protocol preamble all at once */ 1037733a5356Srb144127 1038733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io read on preamble", 1039b8677b72Srb144127 conn, &pp.pp_proto_ver, sizeof (pp) - sizeof (pp.pp_magic_num), 1040733a5356Srb144127 ETM_IO_OP_RD)) < 0) { 1041733a5356Srb144127 errno = (-n); 1042733a5356Srb144127 return (NULL); 1043733a5356Srb144127 } 1044733a5356Srb144127 1045733a5356Srb144127 /* 1046733a5356Srb144127 * Design_Note: The magic number was already network decoded; but 1047733a5356Srb144127 * some other preamble fields also need to be decoded, 1048733a5356Srb144127 * specifically pp_xid and pp_timeout. The rest of the 1049733a5356Srb144127 * preamble fields are byte sized and hence need no 1050733a5356Srb144127 * decoding. 1051733a5356Srb144127 */ 1052733a5356Srb144127 1053733a5356Srb144127 pp.pp_xid = ntohl(pp.pp_xid); 1054733a5356Srb144127 pp.pp_timeout = ntohl(pp.pp_timeout); 1055733a5356Srb144127 1056733a5356Srb144127 /* sanity check the header as best we can */ 1057733a5356Srb144127 1058e2ff4ac6Srb144127 if ((pp.pp_proto_ver < ETM_PROTO_V1) || 10594b476ed5Sdarudy (pp.pp_proto_ver > ETM_PROTO_V3)) { 1060733a5356Srb144127 fmd_hdl_error(hdl, "error: bad proto ver %d\n", 1061733a5356Srb144127 (int)pp.pp_proto_ver); 1062733a5356Srb144127 errno = EPROTO; 1063733a5356Srb144127 etm_stats.etm_ver_bad.fmds_value.ui64++; 1064733a5356Srb144127 return (NULL); 1065733a5356Srb144127 } 1066733a5356Srb144127 1067733a5356Srb144127 dummy_int = pp.pp_msg_type; 1068733a5356Srb144127 if ((dummy_int <= ETM_MSG_TYPE_TOO_LOW) || 1069733a5356Srb144127 (dummy_int >= ETM_MSG_TYPE_TOO_BIG)) { 1070733a5356Srb144127 fmd_hdl_error(hdl, "error: bad msg type %d", dummy_int); 1071733a5356Srb144127 errno = EBADMSG; 1072733a5356Srb144127 etm_stats.etm_msgtype_bad.fmds_value.ui64++; 1073733a5356Srb144127 return (NULL); 1074733a5356Srb144127 } 1075733a5356Srb144127 1076733a5356Srb144127 /* handle [var sized] hdrs for FMA_EVENT, CONTROL, RESPONSE msgs */ 1077733a5356Srb144127 1078733a5356Srb144127 if (pp.pp_msg_type == ETM_MSG_TYPE_FMA_EVENT) { 1079733a5356Srb144127 1080733a5356Srb144127 ev_hdrp = (void*)&misc_buf[0]; 1081733a5356Srb144127 hdr_sz = sizeof (*ev_hdrp); 1082733a5356Srb144127 (void) memcpy(&ev_hdrp->ev_pp, &pp, sizeof (pp)); 1083733a5356Srb144127 1084733a5356Srb144127 /* sanity check the header's timeout */ 1085733a5356Srb144127 1086e2ff4ac6Srb144127 if ((ev_hdrp->ev_pp.pp_proto_ver == ETM_PROTO_V1) && 1087e2ff4ac6Srb144127 (ev_hdrp->ev_pp.pp_timeout != ETM_PROTO_V1_TIMEOUT_NONE)) { 1088733a5356Srb144127 errno = ETIME; 1089733a5356Srb144127 etm_stats.etm_timeout_bad.fmds_value.ui64++; 1090733a5356Srb144127 return (NULL); 1091733a5356Srb144127 } 1092733a5356Srb144127 1093733a5356Srb144127 /* get all FMA event lengths from the header */ 1094733a5356Srb144127 1095733a5356Srb144127 lenp = (uint32_t *)&ev_hdrp->ev_lens[0]; lenp--; 1096733a5356Srb144127 i = -1; /* cnt of length entries preceding 0 */ 1097733a5356Srb144127 do { 1098733a5356Srb144127 i++; lenp++; 1099733a5356Srb144127 if ((sizeof (*ev_hdrp) + (i * sizeof (*lenp))) >= 1100733a5356Srb144127 ETM_MISC_BUF_SZ) { 1101733a5356Srb144127 errno = E2BIG; /* ridiculous size */ 1102733a5356Srb144127 etm_stats.etm_evlens_bad.fmds_value.ui64++; 1103733a5356Srb144127 return (NULL); 1104733a5356Srb144127 } 1105733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io read on event len", 1106b8677b72Srb144127 conn, lenp, sizeof (*lenp), ETM_IO_OP_RD)) < 0) { 1107733a5356Srb144127 errno = (-n); 1108733a5356Srb144127 return (NULL); 1109733a5356Srb144127 } 1110733a5356Srb144127 *lenp = ntohl(*lenp); 1111733a5356Srb144127 1112733a5356Srb144127 } while (*lenp != 0); 1113733a5356Srb144127 i += 0; /* first len already counted by sizeof(ev_hdr) */ 1114733a5356Srb144127 hdr_sz += (i * sizeof (*lenp)); 1115733a5356Srb144127 1116733a5356Srb144127 etm_stats.etm_rd_hdr_fmaevent.fmds_value.ui64++; 1117733a5356Srb144127 1118733a5356Srb144127 } else if (pp.pp_msg_type == ETM_MSG_TYPE_CONTROL) { 1119733a5356Srb144127 1120733a5356Srb144127 ctl_hdrp = (void*)&misc_buf[0]; 1121733a5356Srb144127 hdr_sz = sizeof (*ctl_hdrp); 1122733a5356Srb144127 (void) memcpy(&ctl_hdrp->ctl_pp, &pp, sizeof (pp)); 1123733a5356Srb144127 1124733a5356Srb144127 /* sanity check the header's sub type (control selector) */ 1125733a5356Srb144127 1126733a5356Srb144127 if ((ctl_hdrp->ctl_pp.pp_sub_type <= ETM_CTL_SEL_TOO_LOW) || 1127733a5356Srb144127 (ctl_hdrp->ctl_pp.pp_sub_type >= ETM_CTL_SEL_TOO_BIG)) { 1128733a5356Srb144127 fmd_hdl_error(hdl, "error: bad ctl sub type %d\n", 1129733a5356Srb144127 (int)ctl_hdrp->ctl_pp.pp_sub_type); 1130733a5356Srb144127 errno = EBADMSG; 1131733a5356Srb144127 etm_stats.etm_subtype_bad.fmds_value.ui64++; 1132733a5356Srb144127 return (NULL); 1133733a5356Srb144127 } 1134733a5356Srb144127 1135733a5356Srb144127 /* get the control length */ 1136733a5356Srb144127 1137733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io read on ctl len", 1138b8677b72Srb144127 conn, &ctl_hdrp->ctl_len, sizeof (ctl_hdrp->ctl_len), 1139733a5356Srb144127 ETM_IO_OP_RD)) < 0) { 1140733a5356Srb144127 errno = (-n); 1141733a5356Srb144127 return (NULL); 1142733a5356Srb144127 } 1143733a5356Srb144127 1144733a5356Srb144127 ctl_hdrp->ctl_len = ntohl(ctl_hdrp->ctl_len); 1145733a5356Srb144127 1146733a5356Srb144127 etm_stats.etm_rd_hdr_control.fmds_value.ui64++; 1147733a5356Srb144127 1148733a5356Srb144127 } else if (pp.pp_msg_type == ETM_MSG_TYPE_RESPONSE) { 1149733a5356Srb144127 1150733a5356Srb144127 resp_hdrp = (void*)&misc_buf[0]; 1151733a5356Srb144127 hdr_sz = sizeof (*resp_hdrp); 1152733a5356Srb144127 (void) memcpy(&resp_hdrp->resp_pp, &pp, sizeof (pp)); 1153733a5356Srb144127 1154733a5356Srb144127 /* sanity check the header's timeout */ 1155733a5356Srb144127 1156733a5356Srb144127 if (resp_hdrp->resp_pp.pp_timeout != 1157733a5356Srb144127 ETM_PROTO_V1_TIMEOUT_NONE) { 1158733a5356Srb144127 errno = ETIME; 1159733a5356Srb144127 etm_stats.etm_timeout_bad.fmds_value.ui64++; 1160733a5356Srb144127 return (NULL); 1161733a5356Srb144127 } 1162733a5356Srb144127 1163733a5356Srb144127 /* get the response code and length */ 1164733a5356Srb144127 1165733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io read on resp code+len", 1166733a5356Srb144127 conn, &resp_hdrp->resp_code, 1167b8677b72Srb144127 sizeof (resp_hdrp->resp_code) 1168b8677b72Srb144127 + sizeof (resp_hdrp->resp_len), 1169733a5356Srb144127 ETM_IO_OP_RD)) < 0) { 1170733a5356Srb144127 errno = (-n); 1171733a5356Srb144127 return (NULL); 1172733a5356Srb144127 } 1173733a5356Srb144127 1174733a5356Srb144127 resp_hdrp->resp_code = ntohl(resp_hdrp->resp_code); 1175733a5356Srb144127 resp_hdrp->resp_len = ntohl(resp_hdrp->resp_len); 1176733a5356Srb144127 1177733a5356Srb144127 etm_stats.etm_rd_hdr_response.fmds_value.ui64++; 1178733a5356Srb144127 11794b476ed5Sdarudy } else if (pp.pp_msg_type == ETM_MSG_TYPE_ALERT) { 11804b476ed5Sdarudy 11814b476ed5Sdarudy sa_hdrp = (void*)&misc_buf[0]; 11824b476ed5Sdarudy hdr_sz = sizeof (*sa_hdrp); 11834b476ed5Sdarudy (void) memcpy(&sa_hdrp->sa_pp, &pp, sizeof (pp)); 11844b476ed5Sdarudy 11854b476ed5Sdarudy /* sanity check the header's protocol version */ 11864b476ed5Sdarudy 11874b476ed5Sdarudy if (sa_hdrp->sa_pp.pp_proto_ver != ETM_PROTO_V3) { 11884b476ed5Sdarudy errno = EPROTO; 11894b476ed5Sdarudy etm_stats.etm_ver_bad.fmds_value.ui64++; 11904b476ed5Sdarudy return (NULL); 11914b476ed5Sdarudy } 11924b476ed5Sdarudy 11934b476ed5Sdarudy /* get the priority and length */ 11944b476ed5Sdarudy 11954b476ed5Sdarudy if ((n = etm_io_op(hdl, "bad io read on sa priority+len", 11964b476ed5Sdarudy conn, &sa_hdrp->sa_priority, 1197b8677b72Srb144127 sizeof (sa_hdrp->sa_priority) 1198b8677b72Srb144127 + sizeof (sa_hdrp->sa_len), 11994b476ed5Sdarudy ETM_IO_OP_RD)) < 0) { 12004b476ed5Sdarudy errno = (-n); 12014b476ed5Sdarudy return (NULL); 12024b476ed5Sdarudy } 12034b476ed5Sdarudy 12044b476ed5Sdarudy sa_hdrp->sa_priority = ntohl(sa_hdrp->sa_priority); 12054b476ed5Sdarudy sa_hdrp->sa_len = ntohl(sa_hdrp->sa_len); 12064b476ed5Sdarudy 12074b476ed5Sdarudy etm_stats.etm_rd_hdr_alert.fmds_value.ui64++; 12084b476ed5Sdarudy 12094b476ed5Sdarudy } /* whether we have FMA_EVENT, ALERT, CONTROL, or RESPONSE msg */ 1210733a5356Srb144127 1211733a5356Srb144127 /* 1212733a5356Srb144127 * choose a header size that allows hdr reuse for RESPONSE msgs, 1213733a5356Srb144127 * allocate and populate the message header, and 1214733a5356Srb144127 * return alloc size to caller for later free of hdrp 1215733a5356Srb144127 */ 1216733a5356Srb144127 1217733a5356Srb144127 hdr_sz = MAX(hdr_sz, sizeof (*resp_hdrp)); 1218733a5356Srb144127 hdrp = fmd_hdl_zalloc(hdl, hdr_sz, FMD_SLEEP); 1219733a5356Srb144127 (void) memcpy(hdrp, misc_buf, hdr_sz); 1220733a5356Srb144127 1221733a5356Srb144127 if (etm_debug_lvl >= 3) { 1222b8677b72Srb144127 fmd_hdl_debug(hdl, "info: msg hdr hexdump %d bytes:\n", hdr_sz); 1223733a5356Srb144127 etm_hexdump(hdl, hdrp, hdr_sz); 1224733a5356Srb144127 } 1225733a5356Srb144127 *szp = hdr_sz; 1226733a5356Srb144127 return (hdrp); 1227733a5356Srb144127 1228733a5356Srb144127 } /* etm_hdr_read() */ 1229733a5356Srb144127 1230733a5356Srb144127 /* 1231733a5356Srb144127 * etm_hdr_write - create and write a [variable sized] ETM message header 1232733a5356Srb144127 * to the given connection appropriate for the given FMA event 1233733a5356Srb144127 * and type of nvlist encoding, 1234733a5356Srb144127 * return the allocated ETM message header and its size 1235733a5356Srb144127 * or NULL and set errno on failure 1236733a5356Srb144127 */ 1237733a5356Srb144127 1238733a5356Srb144127 static void* 1239733a5356Srb144127 etm_hdr_write(fmd_hdl_t *hdl, etm_xport_conn_t conn, nvlist_t *evp, 1240733a5356Srb144127 int encoding, size_t *szp) 1241733a5356Srb144127 { 1242733a5356Srb144127 etm_proto_v1_ev_hdr_t *hdrp; /* for FMA_EVENT msg */ 1243733a5356Srb144127 size_t hdr_sz; /* sizeof *hdrp */ 1244733a5356Srb144127 uint32_t *lenp; /* ptr to FMA event length */ 1245733a5356Srb144127 size_t evsz; /* packed FMA event size */ 1246733a5356Srb144127 ssize_t n; /* gen use */ 1247733a5356Srb144127 1248733a5356Srb144127 /* allocate and populate the message header for 1 FMA event */ 1249733a5356Srb144127 1250733a5356Srb144127 hdr_sz = sizeof (*hdrp) + (1 * sizeof (hdrp->ev_lens[0])); 1251733a5356Srb144127 1252733a5356Srb144127 hdrp = fmd_hdl_zalloc(hdl, hdr_sz, FMD_SLEEP); 1253733a5356Srb144127 1254733a5356Srb144127 /* 1255e2ff4ac6Srb144127 * Design_Note: Although the ETM protocol supports it, we do not (yet) 1256e2ff4ac6Srb144127 * want responses/ACKs on FMA events that we send. All 1257e2ff4ac6Srb144127 * such messages are sent with ETM_PROTO_V1_TIMEOUT_NONE. 1258733a5356Srb144127 */ 1259733a5356Srb144127 1260733a5356Srb144127 hdrp->ev_pp.pp_magic_num = ETM_PROTO_MAGIC_NUM; 1261733a5356Srb144127 hdrp->ev_pp.pp_magic_num = htonl(hdrp->ev_pp.pp_magic_num); 1262733a5356Srb144127 hdrp->ev_pp.pp_proto_ver = ETM_PROTO_V1; 1263733a5356Srb144127 hdrp->ev_pp.pp_msg_type = ETM_MSG_TYPE_FMA_EVENT; 1264733a5356Srb144127 hdrp->ev_pp.pp_sub_type = 0; 1265733a5356Srb144127 hdrp->ev_pp.pp_rsvd_pad = 0; 1266733a5356Srb144127 hdrp->ev_pp.pp_xid = etm_xid_cur; 1267733a5356Srb144127 hdrp->ev_pp.pp_xid = htonl(hdrp->ev_pp.pp_xid); 1268733a5356Srb144127 etm_xid_cur += ETM_XID_INC; 1269733a5356Srb144127 hdrp->ev_pp.pp_timeout = ETM_PROTO_V1_TIMEOUT_NONE; 1270733a5356Srb144127 hdrp->ev_pp.pp_timeout = htonl(hdrp->ev_pp.pp_timeout); 1271733a5356Srb144127 1272733a5356Srb144127 lenp = &hdrp->ev_lens[0]; 1273733a5356Srb144127 1274733a5356Srb144127 if ((n = nvlist_size(evp, &evsz, encoding)) != 0) { 1275733a5356Srb144127 errno = n; 1276733a5356Srb144127 fmd_hdl_free(hdl, hdrp, hdr_sz); 1277733a5356Srb144127 etm_stats.etm_os_nvlist_size_fail.fmds_value.ui64++; 1278733a5356Srb144127 return (NULL); 1279733a5356Srb144127 } 1280733a5356Srb144127 1281733a5356Srb144127 /* indicate 1 FMA event, network encode its length, and 0-terminate */ 1282733a5356Srb144127 1283b8677b72Srb144127 etm_stats.etm_wr_max_ev_per_msg.fmds_value.ui64 = 1; 1284b8677b72Srb144127 1285733a5356Srb144127 *lenp = evsz; *lenp = htonl(*lenp); lenp++; 1286733a5356Srb144127 *lenp = 0; *lenp = htonl(*lenp); lenp++; 1287733a5356Srb144127 1288733a5356Srb144127 /* 1289733a5356Srb144127 * write the network encoded header to the transport, and 1290733a5356Srb144127 * return alloc size to caller for later free 1291733a5356Srb144127 */ 1292733a5356Srb144127 1293733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io write on event hdr", 1294733a5356Srb144127 conn, hdrp, hdr_sz, ETM_IO_OP_WR)) < 0) { 1295733a5356Srb144127 errno = (-n); 1296733a5356Srb144127 fmd_hdl_free(hdl, hdrp, hdr_sz); 1297733a5356Srb144127 return (NULL); 1298733a5356Srb144127 } 1299733a5356Srb144127 1300733a5356Srb144127 *szp = hdr_sz; 1301733a5356Srb144127 return (hdrp); 1302733a5356Srb144127 1303733a5356Srb144127 } /* etm_hdr_write() */ 1304733a5356Srb144127 1305733a5356Srb144127 /* 1306733a5356Srb144127 * etm_post_to_fmd - post the given FMA event to FMD 130700ab1250Srb144127 * via a FMD transport API call, 1308733a5356Srb144127 * return 0 or -errno value 1309733a5356Srb144127 * 131000ab1250Srb144127 * caveats: the FMA event (evp) is freed by FMD, 131100ab1250Srb144127 * thus callers of this function should 131200ab1250Srb144127 * immediately discard any ptr they have to the 131300ab1250Srb144127 * nvlist without freeing or dereferencing it 1314733a5356Srb144127 */ 1315733a5356Srb144127 1316733a5356Srb144127 static int 131725351652SVuong Nguyen etm_post_to_fmd(fmd_hdl_t *hdl, fmd_xprt_t *fmd_xprt, nvlist_t *evp) 1318733a5356Srb144127 { 131900ab1250Srb144127 ssize_t ev_sz; /* sizeof *evp */ 1320733a5356Srb144127 132100ab1250Srb144127 (void) nvlist_size(evp, (size_t *)&ev_sz, NV_ENCODE_XDR); 1322733a5356Srb144127 1323e2ff4ac6Srb144127 if (etm_debug_lvl >= 2) { 1324e2ff4ac6Srb144127 etm_show_time(hdl, "ante ev post"); 1325e2ff4ac6Srb144127 } 132625351652SVuong Nguyen fmd_xprt_post(hdl, fmd_xprt, evp, 0); 1327733a5356Srb144127 etm_stats.etm_wr_fmd_fmaevent.fmds_value.ui64++; 132800ab1250Srb144127 etm_stats.etm_wr_fmd_bytes.fmds_value.ui64 += ev_sz; 1329733a5356Srb144127 if (etm_debug_lvl >= 1) { 133000ab1250Srb144127 fmd_hdl_debug(hdl, "info: event %p post ok to FMD\n", evp); 1331733a5356Srb144127 } 1332e2ff4ac6Srb144127 if (etm_debug_lvl >= 2) { 1333e2ff4ac6Srb144127 etm_show_time(hdl, "post ev post"); 1334e2ff4ac6Srb144127 } 133500ab1250Srb144127 return (0); 1336733a5356Srb144127 1337733a5356Srb144127 } /* etm_post_to_fmd() */ 1338733a5356Srb144127 1339733a5356Srb144127 /* 13404b476ed5Sdarudy * Ideally we would just use syslog(3C) for outputting our messages. 13414b476ed5Sdarudy * Unfortunately, as this module is running within the FMA daemon context, 13424b476ed5Sdarudy * that would create the situation where this module's openlog() would 13434b476ed5Sdarudy * have the monopoly on syslog(3C) for the daemon and all its modules. 13444b476ed5Sdarudy * To avoid that situation, this module uses the same logic as the 13454b476ed5Sdarudy * syslog-msgs FM module to directly call into the log(7D) and sysmsg(7D) 13464b476ed5Sdarudy * devices for syslog and console. 13474b476ed5Sdarudy */ 13484b476ed5Sdarudy 13494b476ed5Sdarudy static int 13504b476ed5Sdarudy etm_post_to_syslog(fmd_hdl_t *hdl, uint32_t priority, uint32_t body_sz, 13514b476ed5Sdarudy uint8_t *body_buf) 13524b476ed5Sdarudy { 13534b476ed5Sdarudy char *sysmessage; /* Formatted message */ 13544b476ed5Sdarudy size_t formatlen; /* maximum length of sysmessage */ 13554b476ed5Sdarudy struct strbuf ctl, dat; /* structs pushed to the logfd */ 13564b476ed5Sdarudy uint32_t msgid; /* syslog message ID number */ 13574b476ed5Sdarudy 13584b476ed5Sdarudy if ((syslog_file == 0) && (syslog_cons == 0)) { 13594b476ed5Sdarudy return (0); 13604b476ed5Sdarudy } 13614b476ed5Sdarudy 13624b476ed5Sdarudy if (etm_debug_lvl >= 2) { 13634b476ed5Sdarudy etm_show_time(hdl, "ante syslog post"); 13644b476ed5Sdarudy } 13654b476ed5Sdarudy 13664b476ed5Sdarudy formatlen = body_sz + 64; /* +64 for prefix strings added below */ 13674b476ed5Sdarudy sysmessage = fmd_hdl_zalloc(hdl, formatlen, FMD_SLEEP); 13684b476ed5Sdarudy 13694b476ed5Sdarudy if (syslog_file) { 13704b476ed5Sdarudy STRLOG_MAKE_MSGID(body_buf, msgid); 13714b476ed5Sdarudy (void) snprintf(sysmessage, formatlen, 13724b476ed5Sdarudy "SC Alert: [ID %u FACILITY_AND_PRIORITY] %s", msgid, 13734b476ed5Sdarudy body_buf); 13744b476ed5Sdarudy 13754b476ed5Sdarudy syslog_ctl.pri = syslog_facility | priority; 13764b476ed5Sdarudy 13774b476ed5Sdarudy ctl.buf = (void *)&syslog_ctl; 13784b476ed5Sdarudy ctl.len = sizeof (syslog_ctl); 13794b476ed5Sdarudy 13804b476ed5Sdarudy dat.buf = sysmessage; 13814b476ed5Sdarudy dat.len = strlen(sysmessage) + 1; 13824b476ed5Sdarudy 13834b476ed5Sdarudy if (putmsg(syslog_logfd, &ctl, &dat, 0) != 0) { 13844b476ed5Sdarudy fmd_hdl_debug(hdl, "putmsg failed: %s\n", 13854b476ed5Sdarudy strerror(errno)); 13864b476ed5Sdarudy etm_stats.etm_log_err.fmds_value.ui64++; 13874b476ed5Sdarudy } 13884b476ed5Sdarudy } 13894b476ed5Sdarudy 13904b476ed5Sdarudy if (syslog_cons) { 13914b476ed5Sdarudy (void) snprintf(sysmessage, formatlen, 13924b476ed5Sdarudy "SC Alert: %s\r\n", body_buf); 13934b476ed5Sdarudy 13944b476ed5Sdarudy dat.buf = sysmessage; 13954b476ed5Sdarudy dat.len = strlen(sysmessage) + 1; 13964b476ed5Sdarudy 13974b476ed5Sdarudy if (write(syslog_msgfd, dat.buf, dat.len) != dat.len) { 13984b476ed5Sdarudy fmd_hdl_debug(hdl, "write failed: %s\n", 13994b476ed5Sdarudy strerror(errno)); 14004b476ed5Sdarudy etm_stats.etm_msg_err.fmds_value.ui64++; 14014b476ed5Sdarudy } 14024b476ed5Sdarudy } 14034b476ed5Sdarudy 14044b476ed5Sdarudy fmd_hdl_free(hdl, sysmessage, formatlen); 14054b476ed5Sdarudy 14064b476ed5Sdarudy if (etm_debug_lvl >= 2) { 14074b476ed5Sdarudy etm_show_time(hdl, "post syslog post"); 14084b476ed5Sdarudy } 14094b476ed5Sdarudy 14104b476ed5Sdarudy return (0); 14114b476ed5Sdarudy } 14124b476ed5Sdarudy 14134b476ed5Sdarudy 14144b476ed5Sdarudy /* 1415733a5356Srb144127 * etm_req_ver_negot - send an ETM control message to the other end requesting 1416733a5356Srb144127 * that the ETM protocol version be negotiated/set 1417733a5356Srb144127 */ 1418733a5356Srb144127 1419733a5356Srb144127 static void 1420733a5356Srb144127 etm_req_ver_negot(fmd_hdl_t *hdl) 1421733a5356Srb144127 { 1422733a5356Srb144127 etm_xport_addr_t *addrv; /* default dst addr(s) */ 1423733a5356Srb144127 etm_xport_conn_t conn; /* connection to other end */ 1424733a5356Srb144127 etm_proto_v1_ctl_hdr_t *ctl_hdrp; /* for CONTROL msg */ 1425733a5356Srb144127 size_t hdr_sz; /* sizeof header */ 1426733a5356Srb144127 uint8_t *body_buf; /* msg body buffer */ 1427733a5356Srb144127 uint32_t body_sz; /* sizeof *body_buf */ 1428733a5356Srb144127 ssize_t i; /* gen use */ 1429733a5356Srb144127 1430733a5356Srb144127 /* populate an ETM control msg to send */ 1431733a5356Srb144127 1432733a5356Srb144127 hdr_sz = sizeof (*ctl_hdrp); 14334b476ed5Sdarudy body_sz = (3 + 1); /* version bytes plus null byte */ 1434733a5356Srb144127 1435733a5356Srb144127 ctl_hdrp = fmd_hdl_zalloc(hdl, hdr_sz + body_sz, FMD_SLEEP); 1436733a5356Srb144127 1437733a5356Srb144127 ctl_hdrp->ctl_pp.pp_magic_num = htonl(ETM_PROTO_MAGIC_NUM); 1438733a5356Srb144127 ctl_hdrp->ctl_pp.pp_proto_ver = ETM_PROTO_V1; 1439733a5356Srb144127 ctl_hdrp->ctl_pp.pp_msg_type = ETM_MSG_TYPE_CONTROL; 1440e2ff4ac6Srb144127 ctl_hdrp->ctl_pp.pp_sub_type = ETM_CTL_SEL_VER_NEGOT_REQ; 1441733a5356Srb144127 ctl_hdrp->ctl_pp.pp_rsvd_pad = 0; 1442e2ff4ac6Srb144127 etm_xid_ver_negot = etm_xid_cur; 1443733a5356Srb144127 etm_xid_cur += ETM_XID_INC; 1444e2ff4ac6Srb144127 ctl_hdrp->ctl_pp.pp_xid = htonl(etm_xid_ver_negot); 1445733a5356Srb144127 ctl_hdrp->ctl_pp.pp_timeout = htonl(ETM_PROTO_V1_TIMEOUT_FOREVER); 1446733a5356Srb144127 ctl_hdrp->ctl_len = htonl(body_sz); 1447733a5356Srb144127 1448733a5356Srb144127 body_buf = (void*)&ctl_hdrp->ctl_len; 1449733a5356Srb144127 body_buf += sizeof (ctl_hdrp->ctl_len); 14504b476ed5Sdarudy *body_buf++ = ETM_PROTO_V3; 1451e2ff4ac6Srb144127 *body_buf++ = ETM_PROTO_V2; 1452733a5356Srb144127 *body_buf++ = ETM_PROTO_V1; 1453733a5356Srb144127 *body_buf++ = '\0'; 1454733a5356Srb144127 1455733a5356Srb144127 /* 1456733a5356Srb144127 * open and close a connection to send the ETM control msg 1457733a5356Srb144127 * to any/all of the default dst addrs 1458733a5356Srb144127 */ 1459733a5356Srb144127 1460733a5356Srb144127 if ((addrv = etm_xport_get_ev_addrv(hdl, NULL)) == NULL) { 1461733a5356Srb144127 fmd_hdl_error(hdl, 1462733a5356Srb144127 "error: bad ctl dst addrs errno %d\n", errno); 1463733a5356Srb144127 etm_stats.etm_xport_get_ev_addrv_fail.fmds_value.ui64++; 1464733a5356Srb144127 goto func_ret; 1465733a5356Srb144127 } 1466733a5356Srb144127 1467733a5356Srb144127 for (i = 0; addrv[i] != NULL; i++) { 1468733a5356Srb144127 1469733a5356Srb144127 if (etm_conn_open(hdl, "bad conn open during ver negot", 1470733a5356Srb144127 addrv[i], &conn) < 0) { 1471733a5356Srb144127 continue; 1472733a5356Srb144127 } 1473733a5356Srb144127 if (etm_io_op(hdl, "bad io write on ctl hdr+body", 1474b8677b72Srb144127 conn, ctl_hdrp, hdr_sz + body_sz, ETM_IO_OP_WR) >= 0) { 1475733a5356Srb144127 etm_stats.etm_wr_hdr_control.fmds_value.ui64++; 1476733a5356Srb144127 etm_stats.etm_wr_body_control.fmds_value.ui64++; 1477733a5356Srb144127 } 1478733a5356Srb144127 (void) etm_conn_close(hdl, "bad conn close during ver negot", 1479733a5356Srb144127 conn); 1480733a5356Srb144127 1481733a5356Srb144127 } /* foreach dst addr */ 1482733a5356Srb144127 1483733a5356Srb144127 func_ret: 1484733a5356Srb144127 1485733a5356Srb144127 if (addrv != NULL) { 1486733a5356Srb144127 etm_xport_free_addrv(hdl, addrv); 1487733a5356Srb144127 } 1488733a5356Srb144127 fmd_hdl_free(hdl, ctl_hdrp, hdr_sz + body_sz); 1489733a5356Srb144127 1490733a5356Srb144127 } /* etm_req_ver_negot() */ 1491733a5356Srb144127 149225351652SVuong Nguyen 149325351652SVuong Nguyen 149425351652SVuong Nguyen /* 149525351652SVuong Nguyen * etm_iosvc_msg_enq - add element to tail of ETM iosvc msg queue 149625351652SVuong Nguyen * etm_iosvc_msg_deq - del element from head of ETM iosvc msg queue 149725351652SVuong Nguyen * need to grab the mutex lock before calling this routine 149825351652SVuong Nguyen * return >0 for success, or -errno value 149925351652SVuong Nguyen */ 150025351652SVuong Nguyen static int 150125351652SVuong Nguyen etm_iosvc_msg_enq(fmd_hdl_t *hdl, etm_iosvc_t *iosvc, etm_iosvc_q_ele_t *msgp) 150225351652SVuong Nguyen { 150325351652SVuong Nguyen etm_iosvc_q_ele_t *newp; /* ptr to new msg q ele */ 150425351652SVuong Nguyen 150525351652SVuong Nguyen if (iosvc->msg_q_cur_len >= iosvc->msg_q_max_len) { 150625351652SVuong Nguyen fmd_hdl_debug(hdl, "warning: enq to full msg queue\n"); 150725351652SVuong Nguyen return (-E2BIG); 150825351652SVuong Nguyen } 150925351652SVuong Nguyen 151025351652SVuong Nguyen newp = fmd_hdl_zalloc(hdl, sizeof (*newp), FMD_SLEEP); 151125351652SVuong Nguyen (void) memcpy(newp, msgp, sizeof (*newp)); 151225351652SVuong Nguyen newp->msg_nextp = NULL; 151325351652SVuong Nguyen 151425351652SVuong Nguyen if (iosvc->msg_q_cur_len == 0) { 151525351652SVuong Nguyen iosvc->msg_q_head = newp; 151625351652SVuong Nguyen } else { 151725351652SVuong Nguyen iosvc->msg_q_tail->msg_nextp = newp; 151825351652SVuong Nguyen } 151925351652SVuong Nguyen 152025351652SVuong Nguyen iosvc->msg_q_tail = newp; 152125351652SVuong Nguyen iosvc->msg_q_cur_len++; 152225351652SVuong Nguyen fmd_hdl_debug(hdl, "info: current msg queue length %d\n", 152325351652SVuong Nguyen iosvc->msg_q_cur_len); 152425351652SVuong Nguyen 152525351652SVuong Nguyen return (1); 152625351652SVuong Nguyen 152725351652SVuong Nguyen } /* etm_iosvc_msg_enq() */ 152825351652SVuong Nguyen 152925351652SVuong Nguyen static int 153025351652SVuong Nguyen etm_iosvc_msg_deq(fmd_hdl_t *hdl, etm_iosvc_t *iosvc, etm_iosvc_q_ele_t *msgp) 153125351652SVuong Nguyen { 153225351652SVuong Nguyen etm_iosvc_q_ele_t *oldp; /* ptr to old msg q ele */ 153325351652SVuong Nguyen 153425351652SVuong Nguyen if (iosvc->msg_q_cur_len == 0) { 153525351652SVuong Nguyen fmd_hdl_debug(hdl, "warning: deq from empty responder queue\n"); 153625351652SVuong Nguyen return (-ENOENT); 153725351652SVuong Nguyen } 153825351652SVuong Nguyen 153925351652SVuong Nguyen (void) memcpy(msgp, iosvc->msg_q_head, sizeof (*msgp)); 154025351652SVuong Nguyen msgp->msg_nextp = NULL; 154125351652SVuong Nguyen 154225351652SVuong Nguyen oldp = iosvc->msg_q_head; 154325351652SVuong Nguyen iosvc->msg_q_head = iosvc->msg_q_head->msg_nextp; 154425351652SVuong Nguyen 154525351652SVuong Nguyen /* 154625351652SVuong Nguyen * free the mem alloc-ed in etm_iosvc_msg_enq() 154725351652SVuong Nguyen */ 154825351652SVuong Nguyen fmd_hdl_free(hdl, oldp, sizeof (*oldp)); 154925351652SVuong Nguyen 155025351652SVuong Nguyen iosvc->msg_q_cur_len--; 155125351652SVuong Nguyen if (iosvc->msg_q_cur_len == 0) { 155225351652SVuong Nguyen iosvc->msg_q_tail = NULL; 155325351652SVuong Nguyen } 155425351652SVuong Nguyen 155525351652SVuong Nguyen return (1); 155625351652SVuong Nguyen 155725351652SVuong Nguyen } /* etm_iosvc_msg_deq() */ 155825351652SVuong Nguyen 155925351652SVuong Nguyen 156025351652SVuong Nguyen /* 156125351652SVuong Nguyen * etm_msg_enq_head(): 156225351652SVuong Nguyen * enq the msg to the head of the Q. 156325351652SVuong Nguyen * If the Q is full, drop the msg at the tail then enq the msg at head. 156425351652SVuong Nguyen * need to grab mutex lock iosvc->msg_q_lock before calling this routine. 156525351652SVuong Nguyen */ 156625351652SVuong Nguyen static void 156725351652SVuong Nguyen etm_msg_enq_head(fmd_hdl_t *fmd_hdl, etm_iosvc_t *iosvc, 156825351652SVuong Nguyen etm_iosvc_q_ele_t *msg_ele) 156925351652SVuong Nguyen { 157025351652SVuong Nguyen 157125351652SVuong Nguyen etm_iosvc_q_ele_t *newp; /* iosvc msg ele ptr */ 157225351652SVuong Nguyen 157325351652SVuong Nguyen if (iosvc->msg_q_cur_len >= iosvc->msg_q_max_len) { 157425351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 157525351652SVuong Nguyen "warning: add to head of a full msg queue." 157625351652SVuong Nguyen " Drop the msg at the tail\n"); 157725351652SVuong Nguyen /* 157825351652SVuong Nguyen * drop the msg at the tail 157925351652SVuong Nguyen */ 158025351652SVuong Nguyen newp = iosvc->msg_q_head; 158125351652SVuong Nguyen while (newp->msg_nextp != iosvc->msg_q_tail) { 158225351652SVuong Nguyen newp = newp->msg_nextp; 158325351652SVuong Nguyen } 158425351652SVuong Nguyen 158525351652SVuong Nguyen /* 158625351652SVuong Nguyen * free the msg in iosvc->msg_q_tail->msg 158725351652SVuong Nguyen * free the mem pointed to by iosvc->msg_q_tail 158825351652SVuong Nguyen */ 158925351652SVuong Nguyen fmd_hdl_free(fmd_hdl, iosvc->msg_q_tail->msg, 159025351652SVuong Nguyen iosvc->msg_q_tail->msg_size); 159125351652SVuong Nguyen fmd_hdl_free(fmd_hdl, iosvc->msg_q_tail, sizeof (*newp)); 159225351652SVuong Nguyen iosvc->msg_q_tail = newp; 159325351652SVuong Nguyen iosvc->msg_q_tail->msg_nextp = NULL; 159425351652SVuong Nguyen iosvc->msg_q_cur_len--; 159525351652SVuong Nguyen } 159625351652SVuong Nguyen 159725351652SVuong Nguyen /* 159825351652SVuong Nguyen * enq the msg to the head 159925351652SVuong Nguyen */ 160025351652SVuong Nguyen newp = fmd_hdl_zalloc(fmd_hdl, sizeof (*newp), FMD_SLEEP); 160125351652SVuong Nguyen (void) memcpy(newp, msg_ele, sizeof (*newp)); 160225351652SVuong Nguyen if (iosvc->msg_q_cur_len == 0) { 160325351652SVuong Nguyen newp->msg_nextp = NULL; 160425351652SVuong Nguyen iosvc->msg_q_tail = newp; 160525351652SVuong Nguyen } else { 160625351652SVuong Nguyen newp->msg_nextp = iosvc->msg_q_head; 160725351652SVuong Nguyen } 160825351652SVuong Nguyen iosvc->msg_q_head = newp; 160925351652SVuong Nguyen iosvc->msg_q_cur_len++; 161025351652SVuong Nguyen } /* etm_msg_enq_head() */ 161125351652SVuong Nguyen 161225351652SVuong Nguyen /* 1613d279c7bfSVuong Nguyen * etm_iosvc_cleanup(): 1614d279c7bfSVuong Nguyen * Clean up an iosvc structure 1615d279c7bfSVuong Nguyen * 1) close the fmd_xprt if it has not been closed 1616d279c7bfSVuong Nguyen * 2) Terminate the send/revc threads 1617d279c7bfSVuong Nguyen * 3) If the clean_msg_q flag is set, free all fma events in the queue. In 1618d279c7bfSVuong Nguyen * addition, if the chpt_remove flag is set, delete the checkpoint so that 1619d279c7bfSVuong Nguyen * the events are not persisted. 162025351652SVuong Nguyen */ 162125351652SVuong Nguyen static void 1622d279c7bfSVuong Nguyen etm_iosvc_cleanup(fmd_hdl_t *fmd_hdl, etm_iosvc_t *iosvc, boolean_t clean_msg_q, 1623d279c7bfSVuong Nguyen boolean_t ckpt_remove) 162425351652SVuong Nguyen { 162525351652SVuong Nguyen 162625351652SVuong Nguyen etm_iosvc_q_ele_t msg_ele; /* io svc msg Q ele */ 162725351652SVuong Nguyen 162825351652SVuong Nguyen iosvc->thr_is_dying = 1; 162925351652SVuong Nguyen 16302c07a099SYanmin Sun iosvc->ds_hdl = DS_INVALID_HDL; 16312c07a099SYanmin Sun if (iosvc->fmd_xprt != NULL) { 16322c07a099SYanmin Sun fmd_xprt_close(fmd_hdl, iosvc->fmd_xprt); 16332c07a099SYanmin Sun iosvc->fmd_xprt = NULL; 16342c07a099SYanmin Sun } /* if fmd-xprt has been opened */ 16352c07a099SYanmin Sun 163625351652SVuong Nguyen if (iosvc->send_tid != NULL) { 163725351652SVuong Nguyen fmd_thr_signal(fmd_hdl, iosvc->send_tid); 163825351652SVuong Nguyen fmd_thr_destroy(fmd_hdl, iosvc->send_tid); 163925351652SVuong Nguyen iosvc->send_tid = NULL; 164025351652SVuong Nguyen } /* if io svc send thread was created ok */ 164125351652SVuong Nguyen 164225351652SVuong Nguyen if (iosvc->recv_tid != NULL) { 164325351652SVuong Nguyen fmd_thr_signal(fmd_hdl, iosvc->recv_tid); 164425351652SVuong Nguyen fmd_thr_destroy(fmd_hdl, iosvc->recv_tid); 164525351652SVuong Nguyen iosvc->recv_tid = NULL; 164625351652SVuong Nguyen } /* if root domain recv thread was created */ 164725351652SVuong Nguyen 16482c07a099SYanmin Sun 16492c07a099SYanmin Sun if (clean_msg_q) { 165025351652SVuong Nguyen iosvc->ldom_name[0] = '\0'; 165125351652SVuong Nguyen 165225351652SVuong Nguyen (void) pthread_mutex_lock(&iosvc->msg_q_lock); 165325351652SVuong Nguyen while (iosvc->msg_q_cur_len > 0) { 165425351652SVuong Nguyen (void) etm_iosvc_msg_deq(fmd_hdl, iosvc, &msg_ele); 1655d279c7bfSVuong Nguyen if (ckpt_remove == B_TRUE && 1656d279c7bfSVuong Nguyen msg_ele.ckpt_flag != ETM_CKPT_NOOP) { 1657d279c7bfSVuong Nguyen etm_ckpt_remove(fmd_hdl, &msg_ele); 1658d279c7bfSVuong Nguyen } 165925351652SVuong Nguyen fmd_hdl_free(fmd_hdl, msg_ele.msg, msg_ele.msg_size); 166025351652SVuong Nguyen } 166125351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc->msg_q_lock); 16622c07a099SYanmin Sun } 166325351652SVuong Nguyen 166425351652SVuong Nguyen return; 166525351652SVuong Nguyen 166625351652SVuong Nguyen } /* etm_iosvc_cleanup() */ 166725351652SVuong Nguyen 166825351652SVuong Nguyen /* 166925351652SVuong Nguyen * etm_iosvc_lookup(using ldom_name or ds_hdl when ldom_name is empty) 167025351652SVuong Nguyen * not found, create one, add to iosvc_list 167125351652SVuong Nguyen */ 167225351652SVuong Nguyen etm_iosvc_t * 167325351652SVuong Nguyen etm_iosvc_lookup(fmd_hdl_t *fmd_hdl, char *ldom_name, ds_hdl_t ds_hdl, 167425351652SVuong Nguyen boolean_t iosvc_create) 167525351652SVuong Nguyen { 167625351652SVuong Nguyen uint32_t i; /* for loop var */ 167725351652SVuong Nguyen int32_t first_empty_slot = -1; /* remember that */ 167825351652SVuong Nguyen 167925351652SVuong Nguyen for (i = 0; i < NUM_OF_ROOT_DOMAINS; i++) { 168025351652SVuong Nguyen if (ldom_name[0] == '\0') { 168125351652SVuong Nguyen /* 168225351652SVuong Nguyen * search by hdl passed in 168325351652SVuong Nguyen * the only time this is used is at ds_unreg_cb time. 168425351652SVuong Nguyen * there is no ldom name, only the valid ds_hdl. 168525351652SVuong Nguyen * find an iosvc with the matching ds_hdl. 168625351652SVuong Nguyen * ignore the iosvc_create flag, should never need to 168725351652SVuong Nguyen * create an iosvc for ds_unreg_cb 168825351652SVuong Nguyen */ 168925351652SVuong Nguyen if (ds_hdl == iosvc_list[i].ds_hdl) { 169025351652SVuong Nguyen if (etm_debug_lvl >= 2) { 169125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 169225351652SVuong Nguyen "info: found an iosvc at slot %d w/ ds_hdl %d \n", 169325351652SVuong Nguyen i, iosvc_list[i].ds_hdl); 169425351652SVuong Nguyen } 169525351652SVuong Nguyen if (iosvc_list[i].ldom_name[0] != '\0') 169625351652SVuong Nguyen if (etm_debug_lvl >= 2) { 169725351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 169825351652SVuong Nguyen "info: found an iosvc w/ ldom_name %s \n", 169925351652SVuong Nguyen iosvc_list[i].ldom_name); 170025351652SVuong Nguyen } 170125351652SVuong Nguyen return (&iosvc_list[i]); 170225351652SVuong Nguyen } else { 170325351652SVuong Nguyen continue; 170425351652SVuong Nguyen } 170525351652SVuong Nguyen } else if (iosvc_list[i].ldom_name[0] != '\0') { 170625351652SVuong Nguyen /* 170725351652SVuong Nguyen * this is an non-empty iosvc structure slot 170825351652SVuong Nguyen */ 170925351652SVuong Nguyen if (strcmp(ldom_name, iosvc_list[i].ldom_name) == 0) { 171025351652SVuong Nguyen /* 171125351652SVuong Nguyen * found an iosvc structure that matches the 171225351652SVuong Nguyen * passed in ldom_name, return the ptr 171325351652SVuong Nguyen */ 171425351652SVuong Nguyen if (etm_debug_lvl >= 2) { 171525351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: found an " 171625351652SVuong Nguyen "iosvc at slot %d w/ ds_hdl %d \n", 171725351652SVuong Nguyen i, iosvc_list[i].ds_hdl); 171825351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: found an " 171925351652SVuong Nguyen "iosvc w/ ldom_name %s \n", 172025351652SVuong Nguyen iosvc_list[i].ldom_name); 172125351652SVuong Nguyen } 172225351652SVuong Nguyen return (&iosvc_list[i]); 172325351652SVuong Nguyen } else { 172425351652SVuong Nguyen /* 172525351652SVuong Nguyen * non-empty slot with no-matching name, 172625351652SVuong Nguyen * move on to next slot. 172725351652SVuong Nguyen */ 172825351652SVuong Nguyen continue; 172925351652SVuong Nguyen } 173025351652SVuong Nguyen } else { 173125351652SVuong Nguyen /* 173225351652SVuong Nguyen * found the 1st slot with ldom name being empty 173325351652SVuong Nguyen * remember the slot #, will be used for creating one 173425351652SVuong Nguyen */ 173525351652SVuong Nguyen if (first_empty_slot == -1) { 173625351652SVuong Nguyen first_empty_slot = i; 173725351652SVuong Nguyen } 173825351652SVuong Nguyen } 173925351652SVuong Nguyen } 174025351652SVuong Nguyen if (iosvc_create == B_TRUE && first_empty_slot >= 0) { 174125351652SVuong Nguyen /* 174225351652SVuong Nguyen * this is the case we need to add an iosvc at first_empty_slot 174325351652SVuong Nguyen * for the ldom_name at iosvc_list[first_empty_slot] 174425351652SVuong Nguyen */ 174525351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 174625351652SVuong Nguyen "info: create an iosvc with ldom name %s\n", 174725351652SVuong Nguyen ldom_name); 174825351652SVuong Nguyen i = first_empty_slot; 174925351652SVuong Nguyen (void) memcpy(&iosvc_list[i], &io_svc, sizeof (etm_iosvc_t)); 175025351652SVuong Nguyen (void) strcpy(iosvc_list[i].ldom_name, ldom_name); 175125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: iosvc #%d has ldom name %s\n", 175225351652SVuong Nguyen i, iosvc_list[i].ldom_name); 175325351652SVuong Nguyen return (&iosvc_list[i]); 175425351652SVuong Nguyen } else { 175525351652SVuong Nguyen return (NULL); 175625351652SVuong Nguyen } 175725351652SVuong Nguyen 175825351652SVuong Nguyen } /* etm_iosvc_lookup() */ 175925351652SVuong Nguyen 176025351652SVuong Nguyen 176125351652SVuong Nguyen /* 176225351652SVuong Nguyen * etm_ckpt_remove: 176325351652SVuong Nguyen * remove the ckpt for the iosvc element 176425351652SVuong Nguyen */ 176525351652SVuong Nguyen static void 176625351652SVuong Nguyen etm_ckpt_remove(fmd_hdl_t *hdl, etm_iosvc_q_ele_t *ele) { 176725351652SVuong Nguyen int err; /* temp error */ 176825351652SVuong Nguyen nvlist_t *evp = NULL; /* event pointer */ 176925351652SVuong Nguyen etm_proto_v1_ev_hdr_t *hdrp; /* hdr for FMA_EVENT */ 177025351652SVuong Nguyen char *buf; /* packed event pointer */ 177125351652SVuong Nguyen 177225351652SVuong Nguyen if ((ele->ckpt_flag == ETM_CKPT_NOOP) || 177325351652SVuong Nguyen (etm_ldom_type != LDOM_TYPE_CONTROL)) { 177425351652SVuong Nguyen return; 177525351652SVuong Nguyen } 177625351652SVuong Nguyen 177725351652SVuong Nguyen /* the pointer to the packed event in the etm message */ 177825351652SVuong Nguyen hdrp = (etm_proto_v1_ev_hdr_t *)((ptrdiff_t)ele->msg); 177925351652SVuong Nguyen buf = (char *)((ptrdiff_t)hdrp + sizeof (*hdrp) 178025351652SVuong Nguyen + (1 * sizeof (hdrp->ev_lens[0]))); 178125351652SVuong Nguyen 178225351652SVuong Nguyen /* unpack it, then uncheckpoited it */ 178325351652SVuong Nguyen if ((err = nvlist_unpack(buf, hdrp->ev_lens[0], &evp, 0)) != 0) { 178425351652SVuong Nguyen fmd_hdl_debug(hdl, "failed to unpack event(rc=%d)\n", err); 178525351652SVuong Nguyen return; 178625351652SVuong Nguyen } 178725351652SVuong Nguyen (void) etm_ckpt_delete(hdl, evp); 178825351652SVuong Nguyen nvlist_free(evp); 178925351652SVuong Nguyen } 179025351652SVuong Nguyen 179125351652SVuong Nguyen /* 179225351652SVuong Nguyen * etm_send_ds_msg() 179325351652SVuong Nguyen * call ds_send_msg() to send the msg passed in. 179425351652SVuong Nguyen * timedcond_wait for the ACK to come back. 179525351652SVuong Nguyen * if the ACK doesn't come in the specified time, retrun -EAGAIN. 179625351652SVuong Nguyen * other wise, return 1. 179725351652SVuong Nguyen */ 179825351652SVuong Nguyen int 179925351652SVuong Nguyen etm_send_ds_msg(fmd_hdl_t *fmd_hdl, boolean_t ckpt_remove, etm_iosvc_t *iosvc, 180025351652SVuong Nguyen etm_iosvc_q_ele_t *msg_ele, etm_proto_v1_ev_hdr_t *evhdrp) 180125351652SVuong Nguyen { 180225351652SVuong Nguyen uint32_t rc; /* for return code */ 180325351652SVuong Nguyen 180425351652SVuong Nguyen struct timeval tv; 180525351652SVuong Nguyen struct timespec timeout; 180625351652SVuong Nguyen 180725351652SVuong Nguyen 180825351652SVuong Nguyen /* 180925351652SVuong Nguyen * call ds_send_msg(). Return (-EAGAIN) if not successful 181025351652SVuong Nguyen */ 181125351652SVuong Nguyen if ((rc = (*etm_ds_send_msg)(iosvc->ds_hdl, msg_ele->msg, 181225351652SVuong Nguyen msg_ele->msg_size)) != 0) { 181325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: ds_send_msg rc %d xid %d\n", 181425351652SVuong Nguyen rc, evhdrp->ev_pp.pp_xid); 181525351652SVuong Nguyen return (-EAGAIN); 181625351652SVuong Nguyen } 181725351652SVuong Nguyen 181825351652SVuong Nguyen /* 181925351652SVuong Nguyen * wait on the cv for resp msg for cur_send_xid 182025351652SVuong Nguyen */ 182125351652SVuong Nguyen (void *) pthread_mutex_lock(&iosvc->msg_ack_lock); 182225351652SVuong Nguyen 182325351652SVuong Nguyen (void) gettimeofday(&tv, 0); 182425351652SVuong Nguyen timeout.tv_sec = tv.tv_sec + etm_fma_resp_wait_time; 182525351652SVuong Nguyen timeout.tv_nsec = 0; 182625351652SVuong Nguyen 182725351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: waiting on msg_ack_cv for ldom %s\n", 182825351652SVuong Nguyen iosvc->ldom_name); 182925351652SVuong Nguyen rc = pthread_cond_timedwait(&iosvc->msg_ack_cv, &iosvc->msg_ack_lock, 183025351652SVuong Nguyen &timeout); 183125351652SVuong Nguyen (void *) pthread_mutex_unlock(&iosvc->msg_ack_lock); 183225351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: msg_ack_cv returns with rc %d\n", rc); 183325351652SVuong Nguyen 183425351652SVuong Nguyen /* 183525351652SVuong Nguyen * check to see if ack_ok is non-zero 183625351652SVuong Nguyen * if non-zero, resp msg has been received 183725351652SVuong Nguyen */ 183825351652SVuong Nguyen if (iosvc->ack_ok != 0) { 183925351652SVuong Nguyen /* 184025351652SVuong Nguyen * ACK came ok, this send is successful, 184125351652SVuong Nguyen * tell the caller ready to send next. 184225351652SVuong Nguyen * free mem alloc-ed in 184325351652SVuong Nguyen * etm_pack_ds_msg 184425351652SVuong Nguyen */ 184525351652SVuong Nguyen if (ckpt_remove == B_TRUE && 184625351652SVuong Nguyen etm_ldom_type == LDOM_TYPE_CONTROL) { 184725351652SVuong Nguyen etm_ckpt_remove(fmd_hdl, msg_ele); 184825351652SVuong Nguyen } 184925351652SVuong Nguyen fmd_hdl_free(fmd_hdl, msg_ele->msg, msg_ele->msg_size); 185025351652SVuong Nguyen iosvc->cur_send_xid++; 185125351652SVuong Nguyen return (1); 185225351652SVuong Nguyen } else { 185325351652SVuong Nguyen /* 185425351652SVuong Nguyen * the ACK did not come on time 185525351652SVuong Nguyen * tell the caller to resend cur_send_xid 185625351652SVuong Nguyen */ 185725351652SVuong Nguyen return (-EAGAIN); 185825351652SVuong Nguyen } /* iosvc->ack_ok != 0 */ 185925351652SVuong Nguyen } /* etm_send_ds_msg() */ 186025351652SVuong Nguyen 186125351652SVuong Nguyen /* 186225351652SVuong Nguyen * both events from fmdo_send entry point and from SP are using the 186325351652SVuong Nguyen * etm_proto_v1_ev_hdr_t as its header and it will be the same header for all 186425351652SVuong Nguyen * ds send/recv msgs. 186525351652SVuong Nguyen * Idealy, we should use the hdr coming with the SP FMA event. Since fmdo_send 186625351652SVuong Nguyen * entry point can be called before FMA events from SP, we can't rely on 186725351652SVuong Nguyen * the SP FMA event hdr. Use the static hdr for packing ds msgs for fmdo_send 186825351652SVuong Nguyen * events. 186925351652SVuong Nguyen * return >0 for success, or -errno value 187025351652SVuong Nguyen * Design assumption: there is one FMA event per ds msg 187125351652SVuong Nguyen */ 187225351652SVuong Nguyen int 187325351652SVuong Nguyen etm_pack_ds_msg(fmd_hdl_t *fmd_hdl, etm_iosvc_t *iosvc, 187425351652SVuong Nguyen etm_proto_v1_ev_hdr_t *ev_hdrp, size_t hdr_sz, nvlist_t *evp, 187525351652SVuong Nguyen etm_pack_msg_type_t msg_type, uint_t ckpt_opt) 187625351652SVuong Nguyen { 187725351652SVuong Nguyen etm_proto_v1_ev_hdr_t *hdrp; /* for FMA_EVENT msg */ 187825351652SVuong Nguyen uint32_t *lenp; /* ptr to FMA event length */ 187925351652SVuong Nguyen size_t evsz; /* packed FMA event size */ 188025351652SVuong Nguyen char *buf; 188125351652SVuong Nguyen uint32_t rc; /* for return code */ 188225351652SVuong Nguyen char *msg; /* body of msg to be Qed */ 188325351652SVuong Nguyen 188425351652SVuong Nguyen etm_iosvc_q_ele_t msg_ele; /* io svc msg Q ele */ 188525351652SVuong Nguyen etm_proto_v1_ev_hdr_t *evhdrp; 188625351652SVuong Nguyen 188725351652SVuong Nguyen 188825351652SVuong Nguyen if (ev_hdrp == NULL) { 188925351652SVuong Nguyen hdrp = &iosvc_hdr; 189025351652SVuong Nguyen } else { 189125351652SVuong Nguyen hdrp = ev_hdrp; 189225351652SVuong Nguyen } 189325351652SVuong Nguyen 189425351652SVuong Nguyen /* 189525351652SVuong Nguyen * determine hdr_sz if 0, otherwise use the one passed in hdr_sz 189625351652SVuong Nguyen */ 189725351652SVuong Nguyen 189825351652SVuong Nguyen if (hdr_sz == 0) { 189925351652SVuong Nguyen hdr_sz = sizeof (*hdrp) + (1 * sizeof (hdrp->ev_lens[0])); 190025351652SVuong Nguyen } 190125351652SVuong Nguyen 190225351652SVuong Nguyen /* 190325351652SVuong Nguyen * determine evp size 190425351652SVuong Nguyen */ 190525351652SVuong Nguyen (void) nvlist_size(evp, &evsz, NV_ENCODE_XDR); 190625351652SVuong Nguyen 190725351652SVuong Nguyen /* indicate 1 FMA event, no network encoding, and 0-terminate */ 190825351652SVuong Nguyen lenp = &hdrp->ev_lens[0]; 190925351652SVuong Nguyen *lenp = evsz; 191025351652SVuong Nguyen 191125351652SVuong Nguyen /* 191225351652SVuong Nguyen * now the total of mem needs to be alloc-ed/ds msg size is 191325351652SVuong Nguyen * hdr_sz + evsz 191425351652SVuong Nguyen * msg will be freed in etm_send_to_remote_root() after ds_send_msg() 191525351652SVuong Nguyen */ 191625351652SVuong Nguyen msg = fmd_hdl_zalloc(fmd_hdl, hdr_sz + evsz, FMD_SLEEP); 191725351652SVuong Nguyen 191825351652SVuong Nguyen 191925351652SVuong Nguyen /* 192025351652SVuong Nguyen * copy hdr, 0 terminate the length vector, and then evp 192125351652SVuong Nguyen */ 192225351652SVuong Nguyen (void) memcpy(msg, hdrp, sizeof (*hdrp)); 192325351652SVuong Nguyen hdrp = (etm_proto_v1_ev_hdr_t *)((ptrdiff_t)msg); 192425351652SVuong Nguyen lenp = &hdrp->ev_lens[0]; 192525351652SVuong Nguyen lenp++; 192625351652SVuong Nguyen *lenp = 0; 192725351652SVuong Nguyen 192825351652SVuong Nguyen buf = fmd_hdl_zalloc(fmd_hdl, evsz, FMD_SLEEP); 192925351652SVuong Nguyen (void) nvlist_pack(evp, (char **)&buf, &evsz, NV_ENCODE_XDR, 0); 193025351652SVuong Nguyen (void) memcpy(msg + hdr_sz, buf, evsz); 193125351652SVuong Nguyen fmd_hdl_free(fmd_hdl, buf, evsz); 193225351652SVuong Nguyen 193325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: hdr_sz= %d evsz= %d in etm_pack_ds_msg" 193425351652SVuong Nguyen "for ldom %s\n", hdr_sz, evsz, iosvc->ldom_name); 193525351652SVuong Nguyen msg_ele.msg = msg; 193625351652SVuong Nguyen msg_ele.msg_size = hdr_sz + evsz; 193725351652SVuong Nguyen msg_ele.ckpt_flag = ckpt_opt; 193825351652SVuong Nguyen 193925351652SVuong Nguyen /* 194025351652SVuong Nguyen * decide what to do with the msg: 194125351652SVuong Nguyen * if SP ereports (msg_type == SP_MSG), always enq the msg 194225351652SVuong Nguyen * if not SP ereports, ie, fmd xprt control msgs, enq it _only_ after 194325351652SVuong Nguyen * resource.fm.xprt.run has been sent (which sets start_sending_Q to 1) 194425351652SVuong Nguyen */ 194525351652SVuong Nguyen if ((msg_type == SP_MSG) || 194625351652SVuong Nguyen (msg_type != SP_MSG) && (iosvc->start_sending_Q == 1)) { 194725351652SVuong Nguyen /* 194825351652SVuong Nguyen * this is the case when the msg needs to be enq-ed 194925351652SVuong Nguyen */ 195025351652SVuong Nguyen (void) pthread_mutex_lock(&iosvc->msg_q_lock); 195125351652SVuong Nguyen rc = etm_iosvc_msg_enq(fmd_hdl, iosvc, &msg_ele); 195225351652SVuong Nguyen if ((rc > 0) && (ckpt_opt & ETM_CKPT_SAVE) && 195325351652SVuong Nguyen (etm_ldom_type == LDOM_TYPE_CONTROL)) { 195425351652SVuong Nguyen (void) etm_ckpt_add(fmd_hdl, evp); 195525351652SVuong Nguyen } 195625351652SVuong Nguyen if (iosvc->msg_q_cur_len == 1) 195725351652SVuong Nguyen (void) pthread_cond_signal(&iosvc->msg_q_cv); 195825351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc->msg_q_lock); 195925351652SVuong Nguyen } else { 196025351652SVuong Nguyen /* 196125351652SVuong Nguyen * fmd RDWR xprt procotol startup msgs, send it now! 196225351652SVuong Nguyen */ 196325351652SVuong Nguyen iosvc->ack_ok = 0; 196425351652SVuong Nguyen evhdrp = (etm_proto_v1_ev_hdr_t *)((ptrdiff_t)msg_ele.msg); 196525351652SVuong Nguyen evhdrp->ev_pp.pp_xid = iosvc->cur_send_xid + 1; 196625351652SVuong Nguyen while (!iosvc->ack_ok && iosvc->ds_hdl != DS_INVALID_HDL && 196725351652SVuong Nguyen !etm_is_dying) { 196825351652SVuong Nguyen if (etm_send_ds_msg(fmd_hdl, B_FALSE, iosvc, &msg_ele, 196925351652SVuong Nguyen evhdrp) < 0) { 197025351652SVuong Nguyen continue; 197125351652SVuong Nguyen } 197225351652SVuong Nguyen } 197325351652SVuong Nguyen if (msg_type == FMD_XPRT_RUN_MSG) 197425351652SVuong Nguyen iosvc->start_sending_Q = 1; 197525351652SVuong Nguyen } 197625351652SVuong Nguyen 197725351652SVuong Nguyen return (rc); 197825351652SVuong Nguyen 197925351652SVuong Nguyen } /* etm_pack_ds_msg() */ 198025351652SVuong Nguyen 1981733a5356Srb144127 /* 1982b8677b72Srb144127 * Design_Note: For all etm_resp_q_*() functions and etm_resp_q_* globals, 1983b8677b72Srb144127 * the mutex etm_resp_q_lock must be held by the caller. 1984e2ff4ac6Srb144127 */ 1985e2ff4ac6Srb144127 1986e2ff4ac6Srb144127 /* 1987b8677b72Srb144127 * etm_resp_q_enq - add element to tail of ETM responder queue 1988b8677b72Srb144127 * etm_resp_q_deq - del element from head of ETM responder queue 1989b8677b72Srb144127 * 1990b8677b72Srb144127 * return >0 for success, or -errno value 1991b8677b72Srb144127 */ 1992b8677b72Srb144127 1993b8677b72Srb144127 static int 1994b8677b72Srb144127 etm_resp_q_enq(fmd_hdl_t *hdl, etm_resp_q_ele_t *rqep) 1995b8677b72Srb144127 { 1996b8677b72Srb144127 etm_resp_q_ele_t *newp; /* ptr to new resp q ele */ 1997b8677b72Srb144127 1998b8677b72Srb144127 if (etm_resp_q_cur_len >= etm_resp_q_max_len) { 1999b8677b72Srb144127 fmd_hdl_debug(hdl, "warning: enq to full responder queue\n"); 2000b8677b72Srb144127 etm_stats.etm_enq_drop_resp_q.fmds_value.ui64++; 2001b8677b72Srb144127 return (-E2BIG); 2002b8677b72Srb144127 } 2003b8677b72Srb144127 2004b8677b72Srb144127 newp = fmd_hdl_zalloc(hdl, sizeof (*newp), FMD_SLEEP); 2005b8677b72Srb144127 (void) memcpy(newp, rqep, sizeof (*newp)); 2006b8677b72Srb144127 newp->rqe_nextp = NULL; 2007b8677b72Srb144127 2008b8677b72Srb144127 if (etm_resp_q_cur_len == 0) { 2009b8677b72Srb144127 etm_resp_q_head = newp; 2010b8677b72Srb144127 } else { 2011b8677b72Srb144127 etm_resp_q_tail->rqe_nextp = newp; 2012b8677b72Srb144127 } 2013b8677b72Srb144127 etm_resp_q_tail = newp; 2014b8677b72Srb144127 etm_resp_q_cur_len++; 2015b8677b72Srb144127 etm_stats.etm_resp_q_cur_len.fmds_value.ui64 = etm_resp_q_cur_len; 2016b8677b72Srb144127 2017b8677b72Srb144127 return (1); 2018b8677b72Srb144127 2019b8677b72Srb144127 } /* etm_resp_q_enq() */ 2020b8677b72Srb144127 2021b8677b72Srb144127 static int 2022b8677b72Srb144127 etm_resp_q_deq(fmd_hdl_t *hdl, etm_resp_q_ele_t *rqep) 2023b8677b72Srb144127 { 2024b8677b72Srb144127 etm_resp_q_ele_t *oldp; /* ptr to old resp q ele */ 2025b8677b72Srb144127 2026b8677b72Srb144127 if (etm_resp_q_cur_len == 0) { 2027b8677b72Srb144127 fmd_hdl_debug(hdl, "warning: deq from empty responder queue\n"); 2028b8677b72Srb144127 etm_stats.etm_deq_drop_resp_q.fmds_value.ui64++; 2029b8677b72Srb144127 return (-ENOENT); 2030b8677b72Srb144127 } 2031b8677b72Srb144127 2032b8677b72Srb144127 (void) memcpy(rqep, etm_resp_q_head, sizeof (*rqep)); 2033b8677b72Srb144127 rqep->rqe_nextp = NULL; 2034b8677b72Srb144127 2035b8677b72Srb144127 oldp = etm_resp_q_head; 2036b8677b72Srb144127 etm_resp_q_head = etm_resp_q_head->rqe_nextp; 2037b8677b72Srb144127 fmd_hdl_free(hdl, oldp, sizeof (*oldp)); 2038b8677b72Srb144127 2039b8677b72Srb144127 etm_resp_q_cur_len--; 2040b8677b72Srb144127 etm_stats.etm_resp_q_cur_len.fmds_value.ui64 = etm_resp_q_cur_len; 2041b8677b72Srb144127 if (etm_resp_q_cur_len == 0) { 2042b8677b72Srb144127 etm_resp_q_tail = NULL; 2043b8677b72Srb144127 } 2044b8677b72Srb144127 2045b8677b72Srb144127 return (1); 2046b8677b72Srb144127 2047b8677b72Srb144127 } /* etm_resp_q_deq() */ 2048b8677b72Srb144127 2049b8677b72Srb144127 /* 2050b8677b72Srb144127 * etm_maybe_enq_response - check the given message header to see 2051e2ff4ac6Srb144127 * whether a response has been requested, 2052b8677b72Srb144127 * if so then enqueue the given connection 2053b8677b72Srb144127 * and header for later transport by the 2054b8677b72Srb144127 * responder thread as an ETM response msg, 2055b8677b72Srb144127 * return 0 for nop, >0 success, or -errno value 2056e2ff4ac6Srb144127 */ 2057e2ff4ac6Srb144127 2058e2ff4ac6Srb144127 static ssize_t 2059b8677b72Srb144127 etm_maybe_enq_response(fmd_hdl_t *hdl, etm_xport_conn_t conn, 2060b8677b72Srb144127 void *hdrp, uint32_t hdr_sz, int32_t resp_code) 2061e2ff4ac6Srb144127 { 2062e2ff4ac6Srb144127 ssize_t rv; /* ret val */ 2063e2ff4ac6Srb144127 etm_proto_v1_pp_t *ppp; /* protocol preamble ptr */ 2064e2ff4ac6Srb144127 uint8_t orig_msg_type; /* orig hdr's message type */ 2065e2ff4ac6Srb144127 uint32_t orig_timeout; /* orig hdr's timeout */ 2066b8677b72Srb144127 etm_resp_q_ele_t rqe; /* responder queue ele */ 2067e2ff4ac6Srb144127 2068e2ff4ac6Srb144127 ppp = hdrp; 2069e2ff4ac6Srb144127 orig_msg_type = ppp->pp_msg_type; 2070e2ff4ac6Srb144127 orig_timeout = ppp->pp_timeout; 2071e2ff4ac6Srb144127 2072e2ff4ac6Srb144127 /* bail out now if no response is to be sent */ 2073e2ff4ac6Srb144127 2074e2ff4ac6Srb144127 if (orig_timeout == ETM_PROTO_V1_TIMEOUT_NONE) { 2075e2ff4ac6Srb144127 return (0); 2076e2ff4ac6Srb144127 } /* if a nop */ 2077e2ff4ac6Srb144127 2078e2ff4ac6Srb144127 if ((orig_msg_type != ETM_MSG_TYPE_FMA_EVENT) && 20794b476ed5Sdarudy (orig_msg_type != ETM_MSG_TYPE_ALERT) && 2080e2ff4ac6Srb144127 (orig_msg_type != ETM_MSG_TYPE_CONTROL)) { 2081b8677b72Srb144127 fmd_hdl_debug(hdl, "warning: bad msg type 0x%x\n", 2082b8677b72Srb144127 orig_msg_type); 2083e2ff4ac6Srb144127 return (-EINVAL); 2084e2ff4ac6Srb144127 } /* if inappropriate hdr for a response msg */ 2085e2ff4ac6Srb144127 2086b8677b72Srb144127 /* 2087b8677b72Srb144127 * enqueue the msg hdr and nudge the responder thread 2088b8677b72Srb144127 * if the responder queue was previously empty 2089b8677b72Srb144127 */ 2090b8677b72Srb144127 2091b8677b72Srb144127 rqe.rqe_conn = conn; 2092b8677b72Srb144127 rqe.rqe_hdrp = hdrp; 2093b8677b72Srb144127 rqe.rqe_hdr_sz = hdr_sz; 2094b8677b72Srb144127 rqe.rqe_resp_code = resp_code; 2095b8677b72Srb144127 2096b8677b72Srb144127 (void) pthread_mutex_lock(&etm_resp_q_lock); 2097*c5fb5d32SKarl Davis 2098*c5fb5d32SKarl Davis if (etm_resp_q_cur_len == etm_resp_q_max_len) 2099*c5fb5d32SKarl Davis (void) pthread_cond_wait(&etm_resp_q_cv, &etm_resp_q_lock); 2100*c5fb5d32SKarl Davis 2101b8677b72Srb144127 rv = etm_resp_q_enq(hdl, &rqe); 2102b8677b72Srb144127 if (etm_resp_q_cur_len == 1) 2103b8677b72Srb144127 (void) pthread_cond_signal(&etm_resp_q_cv); 2104b8677b72Srb144127 (void) pthread_mutex_unlock(&etm_resp_q_lock); 2105b8677b72Srb144127 2106b8677b72Srb144127 return (rv); 2107b8677b72Srb144127 2108b8677b72Srb144127 } /* etm_maybe_enq_response() */ 2109b8677b72Srb144127 2110b8677b72Srb144127 /* 2111b8677b72Srb144127 * Design_Note: We rely on the fact that all message types have 2112b8677b72Srb144127 * a common protocol preamble; if this fact should 2113b8677b72Srb144127 * ever change it may break the code below. We also 2114b8677b72Srb144127 * rely on the fact that FMA_EVENT and CONTROL headers 2115b8677b72Srb144127 * returned by etm_hdr_read() will be sized large enough 2116b8677b72Srb144127 * to reuse them as RESPONSE headers if the remote endpt 2117b8677b72Srb144127 * asked for a response via the pp_timeout field. 2118b8677b72Srb144127 */ 2119b8677b72Srb144127 2120b8677b72Srb144127 /* 2121b8677b72Srb144127 * etm_send_response - use the given message header and response code 2122b8677b72Srb144127 * to construct an appropriate response message, 2123b8677b72Srb144127 * and send it back on the given connection, 2124b8677b72Srb144127 * return >0 for success, or -errno value 2125b8677b72Srb144127 */ 2126b8677b72Srb144127 2127b8677b72Srb144127 static ssize_t 2128b8677b72Srb144127 etm_send_response(fmd_hdl_t *hdl, etm_xport_conn_t conn, 2129b8677b72Srb144127 void *hdrp, int32_t resp_code) 2130b8677b72Srb144127 { 2131b8677b72Srb144127 ssize_t rv; /* ret val */ 2132b8677b72Srb144127 etm_proto_v1_pp_t *ppp; /* protocol preamble ptr */ 2133b8677b72Srb144127 etm_proto_v1_resp_hdr_t *resp_hdrp; /* for RESPONSE msg */ 2134b8677b72Srb144127 uint8_t resp_body[4]; /* response body if needed */ 2135b8677b72Srb144127 uint8_t *resp_msg; /* response hdr+body */ 2136b8677b72Srb144127 size_t hdr_sz; /* sizeof response hdr */ 2137b8677b72Srb144127 uint8_t orig_msg_type; /* orig hdr's message type */ 2138b8677b72Srb144127 2139b8677b72Srb144127 ppp = hdrp; 2140b8677b72Srb144127 orig_msg_type = ppp->pp_msg_type; 2141e2ff4ac6Srb144127 2142e2ff4ac6Srb144127 if (etm_debug_lvl >= 2) { 2143e2ff4ac6Srb144127 etm_show_time(hdl, "ante resp send"); 2144e2ff4ac6Srb144127 } 2145e2ff4ac6Srb144127 2146b8677b72Srb144127 /* reuse the given header as a response header */ 2147b8677b72Srb144127 2148e2ff4ac6Srb144127 resp_hdrp = hdrp; 2149e2ff4ac6Srb144127 resp_hdrp->resp_code = resp_code; 2150e2ff4ac6Srb144127 resp_hdrp->resp_len = 0; /* default is empty body */ 2151e2ff4ac6Srb144127 2152e2ff4ac6Srb144127 if ((orig_msg_type == ETM_MSG_TYPE_CONTROL) && 2153e2ff4ac6Srb144127 (ppp->pp_sub_type == ETM_CTL_SEL_VER_NEGOT_REQ)) { 2154e2ff4ac6Srb144127 resp_body[0] = ETM_PROTO_V2; 21554b476ed5Sdarudy resp_body[1] = ETM_PROTO_V3; 21564b476ed5Sdarudy resp_body[2] = 0; 21574b476ed5Sdarudy resp_hdrp->resp_len = 3; 2158e2ff4ac6Srb144127 } /* if should send our/negotiated proto ver in resp body */ 2159e2ff4ac6Srb144127 2160e2ff4ac6Srb144127 /* respond with the proto ver that was negotiated */ 2161e2ff4ac6Srb144127 2162e2ff4ac6Srb144127 resp_hdrp->resp_pp.pp_proto_ver = etm_resp_ver; 2163e2ff4ac6Srb144127 resp_hdrp->resp_pp.pp_msg_type = ETM_MSG_TYPE_RESPONSE; 2164e2ff4ac6Srb144127 resp_hdrp->resp_pp.pp_timeout = ETM_PROTO_V1_TIMEOUT_NONE; 2165e2ff4ac6Srb144127 2166e2ff4ac6Srb144127 /* 2167e2ff4ac6Srb144127 * send the whole response msg in one write, header and body; 2168e2ff4ac6Srb144127 * avoid the alloc-and-copy if we can reuse the hdr as the msg, 2169b8677b72Srb144127 * ie, if the body is empty. update the response stats. 2170e2ff4ac6Srb144127 */ 2171e2ff4ac6Srb144127 2172e2ff4ac6Srb144127 hdr_sz = sizeof (etm_proto_v1_resp_hdr_t); 2173e2ff4ac6Srb144127 2174e2ff4ac6Srb144127 resp_msg = hdrp; 2175e2ff4ac6Srb144127 if (resp_hdrp->resp_len > 0) { 2176e2ff4ac6Srb144127 resp_msg = fmd_hdl_zalloc(hdl, hdr_sz + resp_hdrp->resp_len, 2177e2ff4ac6Srb144127 FMD_SLEEP); 2178e2ff4ac6Srb144127 (void) memcpy(resp_msg, resp_hdrp, hdr_sz); 2179e2ff4ac6Srb144127 (void) memcpy(resp_msg + hdr_sz, resp_body, 2180e2ff4ac6Srb144127 resp_hdrp->resp_len); 2181e2ff4ac6Srb144127 } 2182e2ff4ac6Srb144127 21832ae66659Sjrutt (void) pthread_mutex_lock(&etm_write_lock); 2184b8677b72Srb144127 rv = etm_io_op(hdl, "bad io write on resp msg", conn, 2185b8677b72Srb144127 resp_msg, hdr_sz + resp_hdrp->resp_len, ETM_IO_OP_WR); 21862ae66659Sjrutt (void) pthread_mutex_unlock(&etm_write_lock); 2187b8677b72Srb144127 if (rv < 0) { 2188e2ff4ac6Srb144127 goto func_ret; 2189e2ff4ac6Srb144127 } 2190e2ff4ac6Srb144127 2191e2ff4ac6Srb144127 etm_stats.etm_wr_hdr_response.fmds_value.ui64++; 2192e2ff4ac6Srb144127 etm_stats.etm_wr_body_response.fmds_value.ui64++; 2193e2ff4ac6Srb144127 2194e2ff4ac6Srb144127 fmd_hdl_debug(hdl, "info: sent V%u RESPONSE msg to xport " 2195e2ff4ac6Srb144127 "xid 0x%x code %d len %u\n", 2196e2ff4ac6Srb144127 (unsigned int)resp_hdrp->resp_pp.pp_proto_ver, 2197e2ff4ac6Srb144127 resp_hdrp->resp_pp.pp_xid, resp_hdrp->resp_code, 2198e2ff4ac6Srb144127 resp_hdrp->resp_len); 2199e2ff4ac6Srb144127 func_ret: 2200e2ff4ac6Srb144127 2201e2ff4ac6Srb144127 if (resp_hdrp->resp_len > 0) { 2202e2ff4ac6Srb144127 fmd_hdl_free(hdl, resp_msg, hdr_sz + resp_hdrp->resp_len); 2203e2ff4ac6Srb144127 } 2204e2ff4ac6Srb144127 if (etm_debug_lvl >= 2) { 2205e2ff4ac6Srb144127 etm_show_time(hdl, "post resp send"); 2206e2ff4ac6Srb144127 } 2207e2ff4ac6Srb144127 return (rv); 2208e2ff4ac6Srb144127 2209b8677b72Srb144127 } /* etm_send_response() */ 2210e2ff4ac6Srb144127 2211e2ff4ac6Srb144127 /* 22122ca9f232Srb144127 * etm_reset_xport - reset the transport layer (via fini;init) 22132ca9f232Srb144127 * presumably for an error condition we cannot 22142ca9f232Srb144127 * otherwise recover from (ex: hung LDC channel) 22152ca9f232Srb144127 * 22162ca9f232Srb144127 * caveats - no checking/locking is done to ensure an existing connection 22172ca9f232Srb144127 * is idle during an xport reset; we don't want to deadlock 22182ca9f232Srb144127 * and presumably the transport is stuck/unusable anyway 22192ca9f232Srb144127 */ 22202ca9f232Srb144127 22212ca9f232Srb144127 static void 22222ca9f232Srb144127 etm_reset_xport(fmd_hdl_t *hdl) 22232ca9f232Srb144127 { 22242ca9f232Srb144127 (void) etm_xport_fini(hdl); 22252ca9f232Srb144127 (void) etm_xport_init(hdl); 22262ca9f232Srb144127 etm_stats.etm_reset_xport.fmds_value.ui64++; 22272ca9f232Srb144127 22282ca9f232Srb144127 } /* etm_reset_xport() */ 22292ca9f232Srb144127 22302ca9f232Srb144127 /* 2231733a5356Srb144127 * etm_handle_new_conn - receive an ETM message sent from the other end via 2232733a5356Srb144127 * the given open connection, pull out any FMA events 2233733a5356Srb144127 * and post them to the local FMD (or handle any ETM 2234733a5356Srb144127 * control or response msg); when done, close the 2235733a5356Srb144127 * connection 2236733a5356Srb144127 */ 2237733a5356Srb144127 2238733a5356Srb144127 static void 2239733a5356Srb144127 etm_handle_new_conn(fmd_hdl_t *hdl, etm_xport_conn_t conn) 2240733a5356Srb144127 { 2241733a5356Srb144127 etm_proto_v1_ev_hdr_t *ev_hdrp; /* for FMA_EVENT msg */ 2242733a5356Srb144127 etm_proto_v1_ctl_hdr_t *ctl_hdrp; /* for CONTROL msg */ 2243733a5356Srb144127 etm_proto_v1_resp_hdr_t *resp_hdrp; /* for RESPONSE msg */ 22444b476ed5Sdarudy etm_proto_v3_sa_hdr_t *sa_hdrp; /* for ALERT msg */ 224525351652SVuong Nguyen etm_iosvc_t *iosvc; /* iosvc data structure */ 2246e2ff4ac6Srb144127 int32_t resp_code; /* response code */ 2247b8677b72Srb144127 ssize_t enq_rv; /* resp_q enqueue status */ 2248733a5356Srb144127 size_t hdr_sz; /* sizeof header */ 224925351652SVuong Nguyen size_t evsz; /* FMA event size */ 2250733a5356Srb144127 uint8_t *body_buf; /* msg body buffer */ 2251733a5356Srb144127 uint32_t body_sz; /* sizeof body_buf */ 2252e2ff4ac6Srb144127 uint32_t ev_cnt; /* count of FMA events */ 2253733a5356Srb144127 uint8_t *bp; /* byte ptr within body_buf */ 2254733a5356Srb144127 nvlist_t *evp; /* ptr to unpacked FMA event */ 2255733a5356Srb144127 char *class; /* FMA event class */ 2256733a5356Srb144127 ssize_t i, n; /* gen use */ 22572ca9f232Srb144127 int should_reset_xport; /* bool to reset xport */ 225825351652SVuong Nguyen char ldom_name[MAX_LDOM_NAME]; /* ldom name */ 225925351652SVuong Nguyen int rc; /* return code */ 226025351652SVuong Nguyen uint64_t did; /* domain id */ 226125351652SVuong Nguyen 2262733a5356Srb144127 2263e2ff4ac6Srb144127 if (etm_debug_lvl >= 2) { 2264e2ff4ac6Srb144127 etm_show_time(hdl, "ante conn handle"); 2265e2ff4ac6Srb144127 } 2266733a5356Srb144127 fmd_hdl_debug(hdl, "info: handling new conn %p\n", conn); 2267733a5356Srb144127 22682ca9f232Srb144127 should_reset_xport = 0; 2269733a5356Srb144127 ev_hdrp = NULL; 2270733a5356Srb144127 ctl_hdrp = NULL; 2271733a5356Srb144127 resp_hdrp = NULL; 22724b476ed5Sdarudy sa_hdrp = NULL; 2273733a5356Srb144127 body_buf = NULL; 2274733a5356Srb144127 class = NULL; 2275733a5356Srb144127 evp = NULL; 2276e2ff4ac6Srb144127 resp_code = 0; /* default is success */ 2277b8677b72Srb144127 enq_rv = 0; /* default is nop, ie, did not enqueue */ 2278733a5356Srb144127 2279733a5356Srb144127 /* read a network decoded message header from the connection */ 2280733a5356Srb144127 2281733a5356Srb144127 if ((ev_hdrp = etm_hdr_read(hdl, conn, &hdr_sz)) == NULL) { 2282733a5356Srb144127 /* errno assumed set by above call */ 22832ca9f232Srb144127 should_reset_xport = (errno == ENOTACTIVE); 22842ae66659Sjrutt fmd_hdl_debug(hdl, "error: FMA event dropped: " 2285733a5356Srb144127 "bad hdr read errno %d\n", errno); 2286733a5356Srb144127 etm_stats.etm_rd_drop_fmaevent.fmds_value.ui64++; 2287733a5356Srb144127 goto func_ret; 2288733a5356Srb144127 } 2289733a5356Srb144127 2290733a5356Srb144127 /* 2291733a5356Srb144127 * handle the message based on its preamble pp_msg_type 2292733a5356Srb144127 * which is known to be valid from etm_hdr_read() checks 2293733a5356Srb144127 */ 2294733a5356Srb144127 2295733a5356Srb144127 if (ev_hdrp->ev_pp.pp_msg_type == ETM_MSG_TYPE_FMA_EVENT) { 2296733a5356Srb144127 2297733a5356Srb144127 fmd_hdl_debug(hdl, "info: rcvd FMA_EVENT msg from xport\n"); 2298733a5356Srb144127 2299733a5356Srb144127 /* allocate buf large enough for whole body / all FMA events */ 2300733a5356Srb144127 2301733a5356Srb144127 body_sz = 0; 2302733a5356Srb144127 for (i = 0; ev_hdrp->ev_lens[i] != 0; i++) { 2303733a5356Srb144127 body_sz += ev_hdrp->ev_lens[i]; 2304733a5356Srb144127 } /* for summing sizes of all FMA events */ 2305b8677b72Srb144127 if (i > etm_stats.etm_rd_max_ev_per_msg.fmds_value.ui64) 2306b8677b72Srb144127 etm_stats.etm_rd_max_ev_per_msg.fmds_value.ui64 = i; 2307e2ff4ac6Srb144127 ev_cnt = i; 2308733a5356Srb144127 2309733a5356Srb144127 if (etm_debug_lvl >= 1) { 2310e2ff4ac6Srb144127 fmd_hdl_debug(hdl, "info: event lengths %u sum %u\n", 2311e2ff4ac6Srb144127 ev_cnt, body_sz); 2312733a5356Srb144127 } 2313733a5356Srb144127 2314733a5356Srb144127 body_buf = fmd_hdl_zalloc(hdl, body_sz, FMD_SLEEP); 2315733a5356Srb144127 2316733a5356Srb144127 /* read all the FMA events at once */ 2317733a5356Srb144127 2318733a5356Srb144127 if ((n = etm_io_op(hdl, "FMA event dropped: " 2319b8677b72Srb144127 "bad io read on event bodies", conn, body_buf, body_sz, 2320733a5356Srb144127 ETM_IO_OP_RD)) < 0) { 23212ca9f232Srb144127 should_reset_xport = (n == -ENOTACTIVE); 2322733a5356Srb144127 etm_stats.etm_rd_drop_fmaevent.fmds_value.ui64++; 2323733a5356Srb144127 goto func_ret; 2324733a5356Srb144127 } 2325733a5356Srb144127 2326733a5356Srb144127 etm_stats.etm_rd_xport_bytes.fmds_value.ui64 += body_sz; 2327e2ff4ac6Srb144127 etm_stats.etm_rd_body_fmaevent.fmds_value.ui64 += ev_cnt; 2328733a5356Srb144127 2329b8677b72Srb144127 /* 2330b8677b72Srb144127 * now that we've read the entire ETM msg from the conn, 2331b8677b72Srb144127 * which avoids later ETM protocol framing errors if we didn't, 2332b8677b72Srb144127 * check for dup msg/xid against last good FMD posting, 2333b8677b72Srb144127 * if a dup then resend response but skip repost to FMD 2334b8677b72Srb144127 */ 2335b8677b72Srb144127 233625351652SVuong Nguyen if (ev_hdrp->ev_pp.pp_xid == etm_xid_posted_logged_ev) { 2337b8677b72Srb144127 enq_rv = etm_maybe_enq_response(hdl, conn, 2338b8677b72Srb144127 ev_hdrp, hdr_sz, 0); 2339b8677b72Srb144127 fmd_hdl_debug(hdl, "info: skipping dup FMA event post " 234025351652SVuong Nguyen "xid 0x%x\n", etm_xid_posted_logged_ev); 2341b8677b72Srb144127 etm_stats.etm_rd_dup_fmaevent.fmds_value.ui64++; 2342b8677b72Srb144127 goto func_ret; 2343b8677b72Srb144127 } 2344b8677b72Srb144127 2345733a5356Srb144127 /* unpack each FMA event and post it to FMD */ 2346733a5356Srb144127 2347733a5356Srb144127 bp = body_buf; 23482ae66659Sjrutt for (i = 0; i < ev_cnt; i++) { 2349733a5356Srb144127 if ((n = nvlist_unpack((char *)bp, 2350733a5356Srb144127 ev_hdrp->ev_lens[i], &evp, 0)) != 0) { 2351e2ff4ac6Srb144127 resp_code = (-n); 2352b8677b72Srb144127 enq_rv = etm_maybe_enq_response(hdl, conn, 2353b8677b72Srb144127 ev_hdrp, hdr_sz, resp_code); 2354733a5356Srb144127 fmd_hdl_error(hdl, "error: FMA event dropped: " 2355b8677b72Srb144127 "bad event body unpack errno %d\n", n); 2356733a5356Srb144127 if (etm_debug_lvl >= 2) { 2357733a5356Srb144127 fmd_hdl_debug(hdl, "info: FMA event " 2358733a5356Srb144127 "hexdump %d bytes:\n", 2359733a5356Srb144127 ev_hdrp->ev_lens[i]); 2360733a5356Srb144127 etm_hexdump(hdl, bp, 2361733a5356Srb144127 ev_hdrp->ev_lens[i]); 2362733a5356Srb144127 } 2363733a5356Srb144127 etm_stats.etm_os_nvlist_unpack_fail.fmds_value. 2364733a5356Srb144127 ui64++; 2365733a5356Srb144127 etm_stats.etm_rd_drop_fmaevent.fmds_value. 2366733a5356Srb144127 ui64++; 2367733a5356Srb144127 bp += ev_hdrp->ev_lens[i]; 2368733a5356Srb144127 continue; 2369733a5356Srb144127 } 237025351652SVuong Nguyen 2371733a5356Srb144127 if (etm_debug_lvl >= 1) { 2372733a5356Srb144127 (void) nvlist_lookup_string(evp, FM_CLASS, 2373733a5356Srb144127 &class); 2374733a5356Srb144127 if (class == NULL) { 2375733a5356Srb144127 class = "NULL"; 2376733a5356Srb144127 } 2377733a5356Srb144127 fmd_hdl_debug(hdl, "info: FMA event %p " 2378733a5356Srb144127 "class %s\n", evp, class); 2379733a5356Srb144127 } 238025351652SVuong Nguyen 238125351652SVuong Nguyen rc = nvlist_size(evp, &evsz, NV_ENCODE_XDR); 238225351652SVuong Nguyen fmd_hdl_debug(hdl, 238325351652SVuong Nguyen "info: evp size before pack ds msg %d\n", evsz); 238425351652SVuong Nguyen ldom_name[0] = '\0'; 238525351652SVuong Nguyen rc = etm_filter_find_ldom_id(hdl, evp, ldom_name, 238625351652SVuong Nguyen MAX_LDOM_NAME, &did); 238725351652SVuong Nguyen 238825351652SVuong Nguyen /* 238925351652SVuong Nguyen * if rc is zero and the ldom_name is not "primary", 239025351652SVuong Nguyen * the evp belongs to a root domain, put the evp in an 239125351652SVuong Nguyen * outgoing etm queue, 239225351652SVuong Nguyen * in all other cases, whether ldom_name is primary or 239325351652SVuong Nguyen * can't find a ldom name, call etm_post_to_fmd 239425351652SVuong Nguyen */ 239525351652SVuong Nguyen if ((rc == 0) && strcmp(ldom_name, "primary") && 239625351652SVuong Nguyen strcmp(ldom_name, "")) { 239725351652SVuong Nguyen /* 239825351652SVuong Nguyen * use the ldom_name, guaranteered at this point 239925351652SVuong Nguyen * to be a valid ldom name/non-NULL, to find the 240025351652SVuong Nguyen * iosvc data. 240125351652SVuong Nguyen * add an iosvc struct if can not find one 240225351652SVuong Nguyen */ 240325351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc_list_lock); 240425351652SVuong Nguyen iosvc = etm_iosvc_lookup(hdl, ldom_name, 240525351652SVuong Nguyen DS_INVALID_HDL, B_TRUE); 240625351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc_list_lock); 240725351652SVuong Nguyen if (iosvc == NULL) { 240825351652SVuong Nguyen fmd_hdl_debug(hdl, 240925351652SVuong Nguyen "error: can't find iosvc for ldom " 241025351652SVuong Nguyen "name %s\n", ldom_name); 241125351652SVuong Nguyen } else { 241225351652SVuong Nguyen resp_code = 0; 241325351652SVuong Nguyen (void) etm_pack_ds_msg(hdl, iosvc, 241425351652SVuong Nguyen ev_hdrp, hdr_sz, evp, 241525351652SVuong Nguyen SP_MSG, ETM_CKPT_SAVE); 241625351652SVuong Nguyen /* 241725351652SVuong Nguyen * call the new fmd_xprt_log() 241825351652SVuong Nguyen */ 241925351652SVuong Nguyen fmd_xprt_log(hdl, etm_fmd_xprt, evp, 0); 242025351652SVuong Nguyen etm_xid_posted_logged_ev = 242125351652SVuong Nguyen ev_hdrp->ev_pp.pp_xid; 2422b8677b72Srb144127 } 242325351652SVuong Nguyen } else { 242425351652SVuong Nguyen /* 242525351652SVuong Nguyen * post the fma event to the control fmd 242625351652SVuong Nguyen */ 242725351652SVuong Nguyen resp_code = etm_post_to_fmd(hdl, etm_fmd_xprt, 242825351652SVuong Nguyen evp); 242925351652SVuong Nguyen if (resp_code >= 0) { 243025351652SVuong Nguyen etm_xid_posted_logged_ev = 243125351652SVuong Nguyen ev_hdrp->ev_pp.pp_xid; 243225351652SVuong Nguyen } 243325351652SVuong Nguyen } 243425351652SVuong Nguyen 243500ab1250Srb144127 evp = NULL; 2436b8677b72Srb144127 enq_rv = etm_maybe_enq_response(hdl, conn, 2437b8677b72Srb144127 ev_hdrp, hdr_sz, resp_code); 2438733a5356Srb144127 bp += ev_hdrp->ev_lens[i]; 2439733a5356Srb144127 } /* foreach FMA event in the body buffer */ 2440733a5356Srb144127 2441733a5356Srb144127 } else if (ev_hdrp->ev_pp.pp_msg_type == ETM_MSG_TYPE_CONTROL) { 2442733a5356Srb144127 2443733a5356Srb144127 ctl_hdrp = (void*)ev_hdrp; 2444733a5356Srb144127 2445733a5356Srb144127 fmd_hdl_debug(hdl, "info: rcvd CONTROL msg from xport\n"); 2446733a5356Srb144127 if (etm_debug_lvl >= 1) { 2447733a5356Srb144127 fmd_hdl_debug(hdl, "info: ctl sel %d xid 0x%x\n", 2448733a5356Srb144127 (int)ctl_hdrp->ctl_pp.pp_sub_type, 2449733a5356Srb144127 ctl_hdrp->ctl_pp.pp_xid); 2450733a5356Srb144127 } 2451733a5356Srb144127 2452733a5356Srb144127 /* 2453e2ff4ac6Srb144127 * if we have a VER_NEGOT_REQ read the body and validate 2454733a5356Srb144127 * the protocol version set contained therein, 2455733a5356Srb144127 * otherwise we have a PING_REQ (which has no body) 2456733a5356Srb144127 * and we [also] fall thru to the code which sends a 2457733a5356Srb144127 * response msg if the pp_timeout field requested one 2458733a5356Srb144127 */ 2459733a5356Srb144127 2460e2ff4ac6Srb144127 if (ctl_hdrp->ctl_pp.pp_sub_type == ETM_CTL_SEL_VER_NEGOT_REQ) { 2461733a5356Srb144127 2462733a5356Srb144127 body_sz = ctl_hdrp->ctl_len; 2463733a5356Srb144127 body_buf = fmd_hdl_zalloc(hdl, body_sz, FMD_SLEEP); 2464733a5356Srb144127 2465733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io read on ctl body", 2466b8677b72Srb144127 conn, body_buf, body_sz, ETM_IO_OP_RD)) < 0) { 24672ca9f232Srb144127 should_reset_xport = (n == -ENOTACTIVE); 2468733a5356Srb144127 goto func_ret; 2469733a5356Srb144127 } 2470733a5356Srb144127 2471e2ff4ac6Srb144127 /* complain if version set completely incompatible */ 2472733a5356Srb144127 2473733a5356Srb144127 for (i = 0; i < body_sz; i++) { 2474e2ff4ac6Srb144127 if ((body_buf[i] == ETM_PROTO_V1) || 24754b476ed5Sdarudy (body_buf[i] == ETM_PROTO_V2) || 24764b476ed5Sdarudy (body_buf[i] == ETM_PROTO_V3)) { 2477733a5356Srb144127 break; 2478733a5356Srb144127 } 2479733a5356Srb144127 } 2480e2ff4ac6Srb144127 if (i >= body_sz) { 2481733a5356Srb144127 etm_stats.etm_ver_bad.fmds_value.ui64++; 2482e2ff4ac6Srb144127 resp_code = (-EPROTO); 2483733a5356Srb144127 } 2484733a5356Srb144127 2485733a5356Srb144127 } /* if got version set request */ 2486733a5356Srb144127 2487733a5356Srb144127 etm_stats.etm_rd_body_control.fmds_value.ui64++; 2488733a5356Srb144127 2489b8677b72Srb144127 enq_rv = etm_maybe_enq_response(hdl, conn, 2490b8677b72Srb144127 ctl_hdrp, hdr_sz, resp_code); 2491733a5356Srb144127 2492733a5356Srb144127 } else if (ev_hdrp->ev_pp.pp_msg_type == ETM_MSG_TYPE_RESPONSE) { 2493733a5356Srb144127 2494733a5356Srb144127 resp_hdrp = (void*)ev_hdrp; 2495733a5356Srb144127 2496733a5356Srb144127 fmd_hdl_debug(hdl, "info: rcvd RESPONSE msg from xport\n"); 2497733a5356Srb144127 if (etm_debug_lvl >= 1) { 2498733a5356Srb144127 fmd_hdl_debug(hdl, "info: resp xid 0x%x\n", 2499733a5356Srb144127 (int)resp_hdrp->resp_pp.pp_xid); 2500733a5356Srb144127 } 2501733a5356Srb144127 2502733a5356Srb144127 body_sz = resp_hdrp->resp_len; 2503733a5356Srb144127 body_buf = fmd_hdl_zalloc(hdl, body_sz, FMD_SLEEP); 2504733a5356Srb144127 2505733a5356Srb144127 if ((n = etm_io_op(hdl, "bad io read on resp len", 2506733a5356Srb144127 conn, body_buf, body_sz, ETM_IO_OP_RD)) < 0) { 25072ca9f232Srb144127 should_reset_xport = (n == -ENOTACTIVE); 2508733a5356Srb144127 goto func_ret; 2509733a5356Srb144127 } 2510733a5356Srb144127 2511733a5356Srb144127 etm_stats.etm_rd_body_response.fmds_value.ui64++; 2512733a5356Srb144127 2513733a5356Srb144127 /* 2514e2ff4ac6Srb144127 * look up the xid to interpret the response body 2515733a5356Srb144127 * 2516e2ff4ac6Srb144127 * ping is a nop; for ver negot confirm that a supported 2517e2ff4ac6Srb144127 * protocol version was negotiated and remember which one 2518733a5356Srb144127 */ 2519733a5356Srb144127 2520733a5356Srb144127 if ((resp_hdrp->resp_pp.pp_xid != etm_xid_ping) && 2521e2ff4ac6Srb144127 (resp_hdrp->resp_pp.pp_xid != etm_xid_ver_negot)) { 2522733a5356Srb144127 etm_stats.etm_xid_bad.fmds_value.ui64++; 2523733a5356Srb144127 goto func_ret; 2524733a5356Srb144127 } 2525733a5356Srb144127 2526e2ff4ac6Srb144127 if (resp_hdrp->resp_pp.pp_xid == etm_xid_ver_negot) { 2527e2ff4ac6Srb144127 if ((body_buf[0] < ETM_PROTO_V1) || 25284b476ed5Sdarudy (body_buf[0] > ETM_PROTO_V3)) { 2529733a5356Srb144127 etm_stats.etm_ver_bad.fmds_value.ui64++; 2530733a5356Srb144127 goto func_ret; 2531733a5356Srb144127 } 2532e2ff4ac6Srb144127 etm_resp_ver = body_buf[0]; 2533e2ff4ac6Srb144127 } /* if have resp to last req to negotiate proto ver */ 2534733a5356Srb144127 25354b476ed5Sdarudy } else if (ev_hdrp->ev_pp.pp_msg_type == ETM_MSG_TYPE_ALERT) { 25364b476ed5Sdarudy 25374b476ed5Sdarudy sa_hdrp = (void*)ev_hdrp; 25384b476ed5Sdarudy 25394b476ed5Sdarudy fmd_hdl_debug(hdl, "info: rcvd ALERT msg from xport\n"); 25404b476ed5Sdarudy if (etm_debug_lvl >= 1) { 25414b476ed5Sdarudy fmd_hdl_debug(hdl, "info: sa sel %d xid 0x%x\n", 25424b476ed5Sdarudy (int)sa_hdrp->sa_pp.pp_sub_type, 25434b476ed5Sdarudy sa_hdrp->sa_pp.pp_xid); 25444b476ed5Sdarudy } 25454b476ed5Sdarudy 25464b476ed5Sdarudy body_sz = sa_hdrp->sa_len; 25474b476ed5Sdarudy body_buf = fmd_hdl_zalloc(hdl, body_sz, FMD_SLEEP); 25484b476ed5Sdarudy 25494b476ed5Sdarudy if ((n = etm_io_op(hdl, "bad io read on sa body", 2550b8677b72Srb144127 conn, body_buf, body_sz, ETM_IO_OP_RD)) < 0) { 25512ca9f232Srb144127 should_reset_xport = (n == -ENOTACTIVE); 25524b476ed5Sdarudy goto func_ret; 25534b476ed5Sdarudy } 25544b476ed5Sdarudy 25554b476ed5Sdarudy etm_stats.etm_rd_body_alert.fmds_value.ui64++; 25564b476ed5Sdarudy 2557b8677b72Srb144127 /* 2558b8677b72Srb144127 * now that we've read the entire ETM msg from the conn, 2559b8677b72Srb144127 * which avoids later ETM protocol framing errors if we didn't, 2560b8677b72Srb144127 * check for dup msg/xid against last good syslog posting, 2561b8677b72Srb144127 * if a dup then resend response but skip repost to syslog 2562b8677b72Srb144127 */ 2563b8677b72Srb144127 2564b8677b72Srb144127 if (sa_hdrp->sa_pp.pp_xid == etm_xid_posted_sa) { 2565b8677b72Srb144127 enq_rv = etm_maybe_enq_response(hdl, conn, 2566b8677b72Srb144127 sa_hdrp, hdr_sz, 0); 2567b8677b72Srb144127 fmd_hdl_debug(hdl, "info: skipping dup ALERT post " 2568b8677b72Srb144127 "xid 0x%x\n", etm_xid_posted_sa); 2569b8677b72Srb144127 etm_stats.etm_rd_dup_alert.fmds_value.ui64++; 2570b8677b72Srb144127 goto func_ret; 2571b8677b72Srb144127 } 2572b8677b72Srb144127 25734b476ed5Sdarudy resp_code = etm_post_to_syslog(hdl, sa_hdrp->sa_priority, 25744b476ed5Sdarudy body_sz, body_buf); 2575b8677b72Srb144127 if (resp_code >= 0) { 2576b8677b72Srb144127 etm_xid_posted_sa = sa_hdrp->sa_pp.pp_xid; 2577b8677b72Srb144127 } 2578b8677b72Srb144127 enq_rv = etm_maybe_enq_response(hdl, conn, 2579b8677b72Srb144127 sa_hdrp, hdr_sz, resp_code); 25804b476ed5Sdarudy } /* whether we have a FMA_EVENT, CONTROL, RESPONSE or ALERT msg */ 2581733a5356Srb144127 2582733a5356Srb144127 func_ret: 2583733a5356Srb144127 2584e2ff4ac6Srb144127 if (etm_debug_lvl >= 2) { 2585e2ff4ac6Srb144127 etm_show_time(hdl, "post conn handle"); 2586733a5356Srb144127 } 2587b8677b72Srb144127 2588b8677b72Srb144127 /* 2589b8677b72Srb144127 * if no responder ele was enqueued, close the conn now 2590b8677b72Srb144127 * and free the ETM msg hdr; the ETM msg body is not needed 2591b8677b72Srb144127 * by the responder thread and should always be freed here 2592b8677b72Srb144127 */ 2593b8677b72Srb144127 2594b8677b72Srb144127 if (enq_rv <= 0) { 2595b8677b72Srb144127 (void) etm_conn_close(hdl, "bad conn close after msg recv", 2596b8677b72Srb144127 conn); 2597733a5356Srb144127 if (ev_hdrp != NULL) { 2598733a5356Srb144127 fmd_hdl_free(hdl, ev_hdrp, hdr_sz); 2599733a5356Srb144127 } 2600b8677b72Srb144127 } 2601733a5356Srb144127 if (body_buf != NULL) { 2602733a5356Srb144127 fmd_hdl_free(hdl, body_buf, body_sz); 2603733a5356Srb144127 } 26042ca9f232Srb144127 if (should_reset_xport) { 26052ca9f232Srb144127 etm_reset_xport(hdl); 26062ca9f232Srb144127 } 2607733a5356Srb144127 } /* etm_handle_new_conn() */ 2608733a5356Srb144127 2609733a5356Srb144127 /* 26102ca9f232Srb144127 * etm_handle_bad_accept - recover from a failed connection acceptance 26112ca9f232Srb144127 */ 26122ca9f232Srb144127 26132ca9f232Srb144127 static void 26142ca9f232Srb144127 etm_handle_bad_accept(fmd_hdl_t *hdl, int nev) 26152ca9f232Srb144127 { 26162ca9f232Srb144127 int should_reset_xport; /* bool to reset xport */ 26172ca9f232Srb144127 26182ca9f232Srb144127 should_reset_xport = (nev == -ENOTACTIVE); 26192ca9f232Srb144127 fmd_hdl_debug(hdl, "error: bad conn accept errno %d\n", (-nev)); 26202ca9f232Srb144127 etm_stats.etm_xport_accept_fail.fmds_value.ui64++; 26212ca9f232Srb144127 (void) etm_sleep(etm_bad_acc_to_sec); /* avoid spinning CPU */ 26222ca9f232Srb144127 if (should_reset_xport) { 26232ca9f232Srb144127 etm_reset_xport(hdl); 26242ca9f232Srb144127 } 26252ca9f232Srb144127 } /* etm_handle_bad_accept() */ 26262ca9f232Srb144127 26272ca9f232Srb144127 /* 2628733a5356Srb144127 * etm_server - loop forever accepting new connections 2629733a5356Srb144127 * using the given FMD handle, 2630733a5356Srb144127 * handling any ETM msgs sent from the other side 2631733a5356Srb144127 * via each such connection 2632733a5356Srb144127 */ 2633733a5356Srb144127 2634733a5356Srb144127 static void 2635733a5356Srb144127 etm_server(void *arg) 2636733a5356Srb144127 { 2637733a5356Srb144127 etm_xport_conn_t conn; /* connection handle */ 26382ca9f232Srb144127 int nev; /* -errno val */ 2639733a5356Srb144127 fmd_hdl_t *hdl; /* FMD handle */ 2640733a5356Srb144127 2641733a5356Srb144127 hdl = arg; 2642733a5356Srb144127 2643733a5356Srb144127 fmd_hdl_debug(hdl, "info: connection server starting\n"); 2644733a5356Srb144127 264525351652SVuong Nguyen /* 264625351652SVuong Nguyen * Restore the checkpointed events and dispatch them before starting to 264725351652SVuong Nguyen * receive more events from the sp. 264825351652SVuong Nguyen */ 264925351652SVuong Nguyen etm_ckpt_recover(hdl); 265025351652SVuong Nguyen 2651733a5356Srb144127 while (!etm_is_dying) { 265200ab1250Srb144127 2653733a5356Srb144127 if ((conn = etm_xport_accept(hdl, NULL)) == NULL) { 2654733a5356Srb144127 /* errno assumed set by above call */ 26552ca9f232Srb144127 nev = (-errno); 2656733a5356Srb144127 if (etm_is_dying) { 2657733a5356Srb144127 break; 2658733a5356Srb144127 } 26592ca9f232Srb144127 etm_handle_bad_accept(hdl, nev); 2660733a5356Srb144127 continue; 2661733a5356Srb144127 } 2662733a5356Srb144127 2663b8677b72Srb144127 /* handle the new message/connection, closing it when done */ 2664733a5356Srb144127 2665733a5356Srb144127 etm_handle_new_conn(hdl, conn); 2666733a5356Srb144127 2667733a5356Srb144127 } /* while accepting new connections until ETM dies */ 2668733a5356Srb144127 2669733a5356Srb144127 /* ETM is dying (probably due to "fmadm unload etm") */ 2670733a5356Srb144127 2671733a5356Srb144127 fmd_hdl_debug(hdl, "info: connection server is dying\n"); 2672b8677b72Srb144127 2673733a5356Srb144127 } /* etm_server() */ 2674733a5356Srb144127 2675b8677b72Srb144127 /* 2676b8677b72Srb144127 * etm_responder - loop forever waiting for new responder queue elements 2677b8677b72Srb144127 * to be enqueued, for each one constructing and sending 2678b8677b72Srb144127 * an ETM response msg to the other side, and closing its 2679b8677b72Srb144127 * associated connection when appropriate 2680b8677b72Srb144127 * 2681b8677b72Srb144127 * this thread exists to ensure that the etm_server() thread 2682b8677b72Srb144127 * never pends indefinitely waiting on the xport write lock, and is 2683b8677b72Srb144127 * hence always available to accept new connections and handle 2684b8677b72Srb144127 * incoming messages 2685b8677b72Srb144127 * 2686b8677b72Srb144127 * this design relies on the fact that each connection accepted and 2687b8677b72Srb144127 * returned by the ETM xport layer is unique, and each can be closed 2688b8677b72Srb144127 * independently of the others while multiple connections are 2689b8677b72Srb144127 * outstanding 2690b8677b72Srb144127 */ 2691b8677b72Srb144127 2692b8677b72Srb144127 static void 2693b8677b72Srb144127 etm_responder(void *arg) 2694b8677b72Srb144127 { 2695b8677b72Srb144127 ssize_t n; /* gen use */ 2696b8677b72Srb144127 fmd_hdl_t *hdl; /* FMD handle */ 2697b8677b72Srb144127 etm_resp_q_ele_t rqe; /* responder queue ele */ 2698b8677b72Srb144127 2699b8677b72Srb144127 hdl = arg; 2700b8677b72Srb144127 2701b8677b72Srb144127 fmd_hdl_debug(hdl, "info: responder server starting\n"); 2702b8677b72Srb144127 2703b8677b72Srb144127 while (!etm_is_dying) { 2704b8677b72Srb144127 2705b8677b72Srb144127 (void) pthread_mutex_lock(&etm_resp_q_lock); 2706b8677b72Srb144127 2707b8677b72Srb144127 while (etm_resp_q_cur_len == 0) { 2708b8677b72Srb144127 (void) pthread_cond_wait(&etm_resp_q_cv, 2709b8677b72Srb144127 &etm_resp_q_lock); 2710b8677b72Srb144127 if (etm_is_dying) { 2711b8677b72Srb144127 (void) pthread_mutex_unlock(&etm_resp_q_lock); 2712b8677b72Srb144127 goto func_ret; 2713b8677b72Srb144127 } 2714b8677b72Srb144127 } /* while the responder queue is empty, wait to be nudged */ 2715b8677b72Srb144127 2716b8677b72Srb144127 /* 2717b8677b72Srb144127 * for every responder ele that has been enqueued, 2718b8677b72Srb144127 * dequeue and send it as an ETM response msg, 2719b8677b72Srb144127 * closing its associated conn and freeing its hdr 2720b8677b72Srb144127 * 2721b8677b72Srb144127 * enter the queue draining loop holding the responder 2722b8677b72Srb144127 * queue lock, but do not hold the lock indefinitely 2723b8677b72Srb144127 * (the actual send may pend us indefinitely), 2724b8677b72Srb144127 * so that other threads will never pend for long 2725b8677b72Srb144127 * trying to enqueue a new element 2726b8677b72Srb144127 */ 2727b8677b72Srb144127 2728b8677b72Srb144127 while (etm_resp_q_cur_len > 0) { 2729b8677b72Srb144127 2730b8677b72Srb144127 (void) etm_resp_q_deq(hdl, &rqe); 2731*c5fb5d32SKarl Davis 2732*c5fb5d32SKarl Davis if ((etm_resp_q_cur_len + 1) == etm_resp_q_max_len) 2733*c5fb5d32SKarl Davis (void) pthread_cond_signal(&etm_resp_q_cv); 2734*c5fb5d32SKarl Davis 2735b8677b72Srb144127 (void) pthread_mutex_unlock(&etm_resp_q_lock); 2736b8677b72Srb144127 2737b8677b72Srb144127 if ((n = etm_send_response(hdl, rqe.rqe_conn, 2738b8677b72Srb144127 rqe.rqe_hdrp, rqe.rqe_resp_code)) < 0) { 2739b8677b72Srb144127 fmd_hdl_error(hdl, "error: bad resp send " 2740b8677b72Srb144127 "errno %d\n", (-n)); 2741b8677b72Srb144127 } 2742b8677b72Srb144127 2743b8677b72Srb144127 (void) etm_conn_close(hdl, "bad conn close after resp", 2744b8677b72Srb144127 rqe.rqe_conn); 2745b8677b72Srb144127 fmd_hdl_free(hdl, rqe.rqe_hdrp, rqe.rqe_hdr_sz); 2746b8677b72Srb144127 2747b8677b72Srb144127 if (etm_is_dying) { 2748b8677b72Srb144127 goto func_ret; 2749b8677b72Srb144127 } 2750b8677b72Srb144127 (void) pthread_mutex_lock(&etm_resp_q_lock); 2751b8677b72Srb144127 2752b8677b72Srb144127 } /* while draining the responder queue */ 2753b8677b72Srb144127 2754b8677b72Srb144127 (void) pthread_mutex_unlock(&etm_resp_q_lock); 2755b8677b72Srb144127 2756b8677b72Srb144127 } /* while awaiting and sending resp msgs until ETM dies */ 2757b8677b72Srb144127 2758b8677b72Srb144127 func_ret: 2759b8677b72Srb144127 2760b8677b72Srb144127 /* ETM is dying (probably due to "fmadm unload etm") */ 2761b8677b72Srb144127 2762b8677b72Srb144127 fmd_hdl_debug(hdl, "info: responder server is dying\n"); 2763b8677b72Srb144127 2764b8677b72Srb144127 (void) pthread_mutex_lock(&etm_resp_q_lock); 2765b8677b72Srb144127 if (etm_resp_q_cur_len > 0) { 2766b8677b72Srb144127 fmd_hdl_error(hdl, "warning: %d response msgs dropped\n", 2767b8677b72Srb144127 (int)etm_resp_q_cur_len); 2768b8677b72Srb144127 while (etm_resp_q_cur_len > 0) { 2769b8677b72Srb144127 (void) etm_resp_q_deq(hdl, &rqe); 2770b8677b72Srb144127 (void) etm_conn_close(hdl, "bad conn close after deq", 2771b8677b72Srb144127 rqe.rqe_conn); 2772b8677b72Srb144127 fmd_hdl_free(hdl, rqe.rqe_hdrp, rqe.rqe_hdr_sz); 2773b8677b72Srb144127 } 2774b8677b72Srb144127 } 2775b8677b72Srb144127 (void) pthread_mutex_unlock(&etm_resp_q_lock); 2776b8677b72Srb144127 2777b8677b72Srb144127 } /* etm_responder() */ 2778b8677b72Srb144127 277931e37bb4Svn83148 static void * 278031e37bb4Svn83148 etm_init_alloc(size_t size) 278131e37bb4Svn83148 { 278231e37bb4Svn83148 return (fmd_hdl_alloc(init_hdl, size, FMD_SLEEP)); 278331e37bb4Svn83148 } 278431e37bb4Svn83148 278531e37bb4Svn83148 static void 278631e37bb4Svn83148 etm_init_free(void *addr, size_t size) 278731e37bb4Svn83148 { 278831e37bb4Svn83148 fmd_hdl_free(init_hdl, addr, size); 278931e37bb4Svn83148 } 279031e37bb4Svn83148 2791733a5356Srb144127 /* 279225351652SVuong Nguyen * ---------------------root ldom support functions ----------------------- 279325351652SVuong Nguyen */ 279425351652SVuong Nguyen 279525351652SVuong Nguyen /* 279625351652SVuong Nguyen * use a static array async_event_q instead of dynamicaly allocated mem queue 279725351652SVuong Nguyen * for etm_async_q_enq and etm_async_q_deq. 279825351652SVuong Nguyen * This is not running in an fmd aux thread, can't use the fmd_hdl_* funcs. 279925351652SVuong Nguyen * caller needs to grab the mutex lock before calling this func. 280025351652SVuong Nguyen * return >0 for success, or -errno value 280125351652SVuong Nguyen */ 280225351652SVuong Nguyen static int 280325351652SVuong Nguyen etm_async_q_enq(etm_async_event_ele_t *async_e) 280425351652SVuong Nguyen { 280525351652SVuong Nguyen 280625351652SVuong Nguyen if (etm_async_q_cur_len >= etm_async_q_max_len) { 280725351652SVuong Nguyen /* etm_stats.etm_enq_drop_async_q.fmds_value.ui64++; */ 280825351652SVuong Nguyen return (-E2BIG); 280925351652SVuong Nguyen } 281025351652SVuong Nguyen 281125351652SVuong Nguyen (void) memcpy(&async_event_q[etm_async_q_tail], async_e, 281225351652SVuong Nguyen sizeof (*async_e)); 281325351652SVuong Nguyen 281425351652SVuong Nguyen etm_async_q_tail++; 281525351652SVuong Nguyen if (etm_async_q_tail == etm_async_q_max_len) { 281625351652SVuong Nguyen etm_async_q_tail = 0; 281725351652SVuong Nguyen } 281825351652SVuong Nguyen etm_async_q_cur_len++; 281925351652SVuong Nguyen 282025351652SVuong Nguyen /* etm_stats.etm_async_q_cur_len.fmds_value.ui64 = etm_async_q_cur_len; */ 282125351652SVuong Nguyen 282225351652SVuong Nguyen return (1); 282325351652SVuong Nguyen 282425351652SVuong Nguyen } /* etm_async_q_enq() */ 282525351652SVuong Nguyen 282625351652SVuong Nguyen 282725351652SVuong Nguyen static int 282825351652SVuong Nguyen etm_async_q_deq(etm_async_event_ele_t *async_e) 282925351652SVuong Nguyen { 283025351652SVuong Nguyen 283125351652SVuong Nguyen if (etm_async_q_cur_len == 0) { 283225351652SVuong Nguyen /* etm_stats.etm_deq_drop_async_q.fmds_value.ui64++; */ 283325351652SVuong Nguyen return (-ENOENT); 283425351652SVuong Nguyen } 283525351652SVuong Nguyen 283625351652SVuong Nguyen (void) memcpy(async_e, &async_event_q[etm_async_q_head], 283725351652SVuong Nguyen sizeof (*async_e)); 283825351652SVuong Nguyen 283925351652SVuong Nguyen etm_async_q_head++; 284025351652SVuong Nguyen if (etm_async_q_head == etm_async_q_max_len) { 284125351652SVuong Nguyen etm_async_q_head = 0; 284225351652SVuong Nguyen } 284325351652SVuong Nguyen etm_async_q_cur_len--; 284425351652SVuong Nguyen 284525351652SVuong Nguyen return (1); 284625351652SVuong Nguyen } /* etm_async_q_deq */ 284725351652SVuong Nguyen 284825351652SVuong Nguyen 284925351652SVuong Nguyen /* 28502c07a099SYanmin Sun * setting up the fields in iosvc at DS_REG_CB time 28512c07a099SYanmin Sun */ 28522c07a099SYanmin Sun void 28532c07a099SYanmin Sun etm_iosvc_setup(fmd_hdl_t *fmd_hdl, etm_iosvc_t *iosvc, 28542c07a099SYanmin Sun etm_async_event_ele_t *async_e) 28552c07a099SYanmin Sun { 28562c07a099SYanmin Sun iosvc->ds_hdl = async_e->ds_hdl; 28572c07a099SYanmin Sun iosvc->cur_send_xid = 0; 28582c07a099SYanmin Sun iosvc->xid_posted_ev = 0; 28592c07a099SYanmin Sun iosvc->start_sending_Q = 0; 28602c07a099SYanmin Sun 28612c07a099SYanmin Sun /* 28622c07a099SYanmin Sun * open the fmd xprt if it 28632c07a099SYanmin Sun * hasn't been previously opened 28642c07a099SYanmin Sun */ 28652c07a099SYanmin Sun fmd_hdl_debug(fmd_hdl, "info: before fmd_xprt_open ldom_name is %s\n", 28662c07a099SYanmin Sun async_e->ldom_name); 28672c07a099SYanmin Sun 28682c07a099SYanmin Sun if (iosvc->fmd_xprt == NULL) { 28692c07a099SYanmin Sun iosvc->fmd_xprt = fmd_xprt_open(fmd_hdl, flags, NULL, iosvc); 28702c07a099SYanmin Sun } 28712c07a099SYanmin Sun 28722c07a099SYanmin Sun iosvc->thr_is_dying = 0; 28732c07a099SYanmin Sun if (iosvc->recv_tid == NULL) { 28742c07a099SYanmin Sun iosvc->recv_tid = fmd_thr_create(fmd_hdl, 28752c07a099SYanmin Sun etm_recv_from_remote_root, iosvc); 28762c07a099SYanmin Sun } 28772c07a099SYanmin Sun if (iosvc->send_tid == NULL) { 28782c07a099SYanmin Sun iosvc->send_tid = fmd_thr_create(fmd_hdl, 28792c07a099SYanmin Sun etm_send_to_remote_root, iosvc); 28802c07a099SYanmin Sun } 28812c07a099SYanmin Sun } /* etm_iosvc_setup() */ 28822c07a099SYanmin Sun 28832c07a099SYanmin Sun 28842c07a099SYanmin Sun /* 288525351652SVuong Nguyen * ds userland interface ds_reg_cb callback func 288625351652SVuong Nguyen */ 288725351652SVuong Nguyen 288825351652SVuong Nguyen /* ARGSUSED */ 288925351652SVuong Nguyen static void 289025351652SVuong Nguyen etm_iosvc_reg_handler(ds_hdl_t ds_hdl, ds_cb_arg_t arg, ds_ver_t *ver, 289125351652SVuong Nguyen ds_domain_hdl_t dhdl) 289225351652SVuong Nguyen { 289325351652SVuong Nguyen etm_async_event_ele_t async_ele; 289425351652SVuong Nguyen 289525351652SVuong Nguyen 289625351652SVuong Nguyen /* 289725351652SVuong Nguyen * do version check here. 289825351652SVuong Nguyen * checked the ver received here against etm_iosvc_vers here 289925351652SVuong Nguyen */ 290025351652SVuong Nguyen if (etm_iosvc_vers[0].major != ver->major || 290125351652SVuong Nguyen etm_iosvc_vers[0].minor != ver->minor) { 290225351652SVuong Nguyen /* 290325351652SVuong Nguyen * can't log an fmd debug msg, 290425351652SVuong Nguyen * not running in an fmd aux thread 290525351652SVuong Nguyen */ 290625351652SVuong Nguyen return; 290725351652SVuong Nguyen } 290825351652SVuong Nguyen 290925351652SVuong Nguyen /* 291025351652SVuong Nguyen * the callback should have a valid ldom_name 291125351652SVuong Nguyen * can't log fmd debugging msg here since this is not in an fmd aux 291225351652SVuong Nguyen * thread. log fmd debug msg in etm_async_event_handle() 291325351652SVuong Nguyen */ 291425351652SVuong Nguyen async_ele.ds_hdl = ds_hdl; 291525351652SVuong Nguyen async_ele.dhdl = dhdl; 291625351652SVuong Nguyen async_ele.ldom_name[0] = '\0'; 291725351652SVuong Nguyen async_ele.event_type = ETM_ASYNC_EVENT_DS_REG_CB; 291825351652SVuong Nguyen (void) pthread_mutex_lock(&etm_async_event_q_lock); 291925351652SVuong Nguyen (void) etm_async_q_enq(&async_ele); 292025351652SVuong Nguyen if (etm_async_q_cur_len == 1) 292125351652SVuong Nguyen (void) pthread_cond_signal(&etm_async_event_q_cv); 292225351652SVuong Nguyen (void) pthread_mutex_unlock(&etm_async_event_q_lock); 292325351652SVuong Nguyen 292425351652SVuong Nguyen } /* etm_iosvc_reg_handler */ 292525351652SVuong Nguyen 292625351652SVuong Nguyen 292725351652SVuong Nguyen /* 292825351652SVuong Nguyen * ds userland interface ds_unreg_cb callback func 292925351652SVuong Nguyen */ 293025351652SVuong Nguyen 293125351652SVuong Nguyen /*ARGSUSED*/ 293225351652SVuong Nguyen static void 293325351652SVuong Nguyen etm_iosvc_unreg_handler(ds_hdl_t hdl, ds_cb_arg_t arg) 293425351652SVuong Nguyen { 293525351652SVuong Nguyen etm_async_event_ele_t async_ele; 293625351652SVuong Nguyen 293725351652SVuong Nguyen /* 293825351652SVuong Nguyen * fill in async_ele and enqueue async_ele 293925351652SVuong Nguyen */ 294025351652SVuong Nguyen async_ele.ldom_name[0] = '\0'; 294125351652SVuong Nguyen async_ele.ds_hdl = hdl; 294225351652SVuong Nguyen async_ele.event_type = ETM_ASYNC_EVENT_DS_UNREG_CB; 294325351652SVuong Nguyen (void) pthread_mutex_lock(&etm_async_event_q_lock); 294425351652SVuong Nguyen (void) etm_async_q_enq(&async_ele); 294525351652SVuong Nguyen if (etm_async_q_cur_len == 1) 294625351652SVuong Nguyen (void) pthread_cond_signal(&etm_async_event_q_cv); 294725351652SVuong Nguyen (void) pthread_mutex_unlock(&etm_async_event_q_lock); 294825351652SVuong Nguyen } /* etm_iosvc_unreg_handler */ 294925351652SVuong Nguyen 295025351652SVuong Nguyen /* 295125351652SVuong Nguyen * ldom event registration callback func 295225351652SVuong Nguyen */ 295325351652SVuong Nguyen 295425351652SVuong Nguyen /* ARGSUSED */ 295525351652SVuong Nguyen static void 295625351652SVuong Nguyen ldom_event_handler(char *ldom_name, ldom_event_t event, ldom_cb_arg_t data) 295725351652SVuong Nguyen { 295825351652SVuong Nguyen etm_async_event_ele_t async_ele; 295925351652SVuong Nguyen 296025351652SVuong Nguyen /* 296125351652SVuong Nguyen * the callback will have a valid ldom_name 296225351652SVuong Nguyen */ 296325351652SVuong Nguyen async_ele.ldom_name[0] = '\0'; 296425351652SVuong Nguyen if (ldom_name) 296525351652SVuong Nguyen (void) strcpy(async_ele.ldom_name, ldom_name); 296625351652SVuong Nguyen async_ele.ds_hdl = DS_INVALID_HDL; 296725351652SVuong Nguyen 296825351652SVuong Nguyen /* 296925351652SVuong Nguyen * fill in async_ele and enq async_ele 297025351652SVuong Nguyen */ 297125351652SVuong Nguyen switch (event) { 297225351652SVuong Nguyen case LDOM_EVENT_BIND: 297325351652SVuong Nguyen async_ele.event_type = ETM_ASYNC_EVENT_LDOM_BIND; 297425351652SVuong Nguyen break; 297525351652SVuong Nguyen case LDOM_EVENT_UNBIND: 297625351652SVuong Nguyen async_ele.event_type = ETM_ASYNC_EVENT_LDOM_UNBIND; 297725351652SVuong Nguyen break; 297825351652SVuong Nguyen case LDOM_EVENT_ADD: 297925351652SVuong Nguyen async_ele.event_type = ETM_ASYNC_EVENT_LDOM_ADD; 298025351652SVuong Nguyen break; 298125351652SVuong Nguyen case LDOM_EVENT_REMOVE: 298225351652SVuong Nguyen async_ele.event_type = ETM_ASYNC_EVENT_LDOM_REMOVE; 298325351652SVuong Nguyen break; 298425351652SVuong Nguyen default: 298525351652SVuong Nguyen /* 298625351652SVuong Nguyen * for all other ldom events, do nothing 298725351652SVuong Nguyen */ 298825351652SVuong Nguyen return; 298925351652SVuong Nguyen } /* switch (event) */ 299025351652SVuong Nguyen 299125351652SVuong Nguyen (void) pthread_mutex_lock(&etm_async_event_q_lock); 299225351652SVuong Nguyen (void) etm_async_q_enq(&async_ele); 299325351652SVuong Nguyen if (etm_async_q_cur_len == 1) 299425351652SVuong Nguyen (void) pthread_cond_signal(&etm_async_event_q_cv); 299525351652SVuong Nguyen (void) pthread_mutex_unlock(&etm_async_event_q_lock); 299625351652SVuong Nguyen 299725351652SVuong Nguyen } /* ldom_event_handler */ 299825351652SVuong Nguyen 299925351652SVuong Nguyen 300025351652SVuong Nguyen /* 300125351652SVuong Nguyen * This is running as an fmd aux thread. 300225351652SVuong Nguyen * This is the func that actually handle the events, which include: 300325351652SVuong Nguyen * 1. ldom events. ldom events are on Control Domain only 300425351652SVuong Nguyen * 2. any DS userland callback funcs 300525351652SVuong Nguyen * these events are already Q-ed in the async_event_ele_q 300625351652SVuong Nguyen * deQ and process the events accordingly 300725351652SVuong Nguyen */ 300825351652SVuong Nguyen static void 300925351652SVuong Nguyen etm_async_event_handler(void *arg) 301025351652SVuong Nguyen { 301125351652SVuong Nguyen 301225351652SVuong Nguyen fmd_hdl_t *fmd_hdl = (fmd_hdl_t *)arg; 301325351652SVuong Nguyen etm_iosvc_t *iosvc; /* ptr 2 iosvc struct */ 301425351652SVuong Nguyen etm_async_event_ele_t async_e; 301525351652SVuong Nguyen 301625351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: etm_async_event_handler starting\n"); 301725351652SVuong Nguyen /* 301825351652SVuong Nguyen * handle etm is not dying and Q len > 0 301925351652SVuong Nguyen */ 302025351652SVuong Nguyen while (!etm_is_dying) { 302125351652SVuong Nguyen /* 302225351652SVuong Nguyen * grab the lock to check the Q len 302325351652SVuong Nguyen */ 302425351652SVuong Nguyen (void) pthread_mutex_lock(&etm_async_event_q_lock); 302525351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: etm_async_q_cur_len %d\n", 302625351652SVuong Nguyen etm_async_q_cur_len); 302725351652SVuong Nguyen 302825351652SVuong Nguyen while (etm_async_q_cur_len > 0) { 302925351652SVuong Nguyen (void) etm_async_q_deq(&async_e); 303025351652SVuong Nguyen (void) pthread_mutex_unlock(&etm_async_event_q_lock); 303125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 303225351652SVuong Nguyen "info: processing an async event type %d ds_hdl" 303325351652SVuong Nguyen " %d\n", async_e.event_type, async_e.ds_hdl); 303425351652SVuong Nguyen if (async_e.ldom_name[0] != '\0') { 303525351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 303625351652SVuong Nguyen "info: procssing async evt ldom_name %s\n", 303725351652SVuong Nguyen async_e.ldom_name); 303825351652SVuong Nguyen } 303925351652SVuong Nguyen 304025351652SVuong Nguyen /* 304125351652SVuong Nguyen * at this point, if async_e.ldom_name is not NULL, 304225351652SVuong Nguyen * we have a valid iosvc strcut ptr. 304325351652SVuong Nguyen * the only time async_e.ldom_name is NULL is at 304425351652SVuong Nguyen * ds_unreg_cb() 304525351652SVuong Nguyen */ 304625351652SVuong Nguyen switch (async_e.event_type) { 304725351652SVuong Nguyen case ETM_ASYNC_EVENT_LDOM_UNBIND: 304825351652SVuong Nguyen case ETM_ASYNC_EVENT_LDOM_REMOVE: 304925351652SVuong Nguyen /* 305025351652SVuong Nguyen * we have a valid ldom_name, 305125351652SVuong Nguyen * etm_lookup_struct(ldom_name) 305225351652SVuong Nguyen * do nothing if can't find an iosvc 305325351652SVuong Nguyen * no iosvc clean up to do 305425351652SVuong Nguyen */ 305525351652SVuong Nguyen (void) pthread_mutex_lock( 305625351652SVuong Nguyen &iosvc_list_lock); 305725351652SVuong Nguyen iosvc = etm_iosvc_lookup(fmd_hdl, 305825351652SVuong Nguyen async_e.ldom_name, 305925351652SVuong Nguyen async_e.ds_hdl, B_FALSE); 306025351652SVuong Nguyen if (iosvc == NULL) { 306125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 306225351652SVuong Nguyen "error: can't find iosvc for ldom " 306325351652SVuong Nguyen "name %s\n", 306425351652SVuong Nguyen async_e.ldom_name); 306525351652SVuong Nguyen (void) pthread_mutex_unlock( 306625351652SVuong Nguyen &iosvc_list_lock); 306725351652SVuong Nguyen break; 306825351652SVuong Nguyen } 3069d279c7bfSVuong Nguyen /* 3070d279c7bfSVuong Nguyen * Clean up the queue, delete all messages and 3071d279c7bfSVuong Nguyen * do not persist checkpointed fma events. 3072d279c7bfSVuong Nguyen */ 3073d279c7bfSVuong Nguyen etm_iosvc_cleanup(fmd_hdl, iosvc, B_TRUE, 3074d279c7bfSVuong Nguyen B_TRUE); 307525351652SVuong Nguyen (void) pthread_mutex_unlock( 307625351652SVuong Nguyen &iosvc_list_lock); 307725351652SVuong Nguyen break; 307825351652SVuong Nguyen 307925351652SVuong Nguyen case ETM_ASYNC_EVENT_LDOM_BIND: 308025351652SVuong Nguyen 308125351652SVuong Nguyen /* 308225351652SVuong Nguyen * create iosvc if it has not been 308325351652SVuong Nguyen * created 308425351652SVuong Nguyen * async_e.ds_hdl is invalid 308525351652SVuong Nguyen * async_e.ldom_name is valid ldom_name 308625351652SVuong Nguyen */ 308725351652SVuong Nguyen (void) pthread_mutex_lock( 308825351652SVuong Nguyen &iosvc_list_lock); 308925351652SVuong Nguyen iosvc = etm_iosvc_lookup(fmd_hdl, 309025351652SVuong Nguyen async_e.ldom_name, 309125351652SVuong Nguyen async_e.ds_hdl, B_TRUE); 309225351652SVuong Nguyen if (iosvc == NULL) { 309325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 309425351652SVuong Nguyen "error: can't create iosvc for " 309525351652SVuong Nguyen "async evnt %d\n", 309625351652SVuong Nguyen async_e.event_type); 309725351652SVuong Nguyen (void) pthread_mutex_unlock( 309825351652SVuong Nguyen &iosvc_list_lock); 309925351652SVuong Nguyen break; 310025351652SVuong Nguyen } 310125351652SVuong Nguyen (void) strcpy(iosvc->ldom_name, 310225351652SVuong Nguyen async_e.ldom_name); 310325351652SVuong Nguyen iosvc->ds_hdl = async_e.ds_hdl; 310425351652SVuong Nguyen (void) pthread_mutex_unlock( 310525351652SVuong Nguyen &iosvc_list_lock); 310625351652SVuong Nguyen break; 310725351652SVuong Nguyen 310825351652SVuong Nguyen case ETM_ASYNC_EVENT_DS_REG_CB: 310925351652SVuong Nguyen if (etm_ldom_type == LDOM_TYPE_CONTROL) { 311025351652SVuong Nguyen /* 311125351652SVuong Nguyen * find the root ldom name from 311225351652SVuong Nguyen * ldom domain hdl/id 311325351652SVuong Nguyen */ 311425351652SVuong Nguyen if (etm_filter_find_ldom_name( 311525351652SVuong Nguyen fmd_hdl, async_e.dhdl, 311625351652SVuong Nguyen async_e.ldom_name, 311725351652SVuong Nguyen MAX_LDOM_NAME) != 0) { 311825351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 311925351652SVuong Nguyen "error: can't find root " 312025351652SVuong Nguyen "domain name from did %d\n", 312125351652SVuong Nguyen async_e.dhdl); 312225351652SVuong Nguyen break; 312325351652SVuong Nguyen } else { 312425351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 312525351652SVuong Nguyen "info: etm_filter_find_" 312625351652SVuong Nguyen "ldom_name returned %s\n", 312725351652SVuong Nguyen async_e.ldom_name); 312825351652SVuong Nguyen } 312925351652SVuong Nguyen /* 313025351652SVuong Nguyen * now we should have a valid 313125351652SVuong Nguyen * root domain name. 313225351652SVuong Nguyen * lookup the iosvc struct 313325351652SVuong Nguyen * associated with the ldom_name 313425351652SVuong Nguyen * and init the iosvc struct 313525351652SVuong Nguyen */ 313625351652SVuong Nguyen (void) pthread_mutex_lock( 313725351652SVuong Nguyen &iosvc_list_lock); 313825351652SVuong Nguyen iosvc = etm_iosvc_lookup( 313925351652SVuong Nguyen fmd_hdl, async_e.ldom_name, 314025351652SVuong Nguyen async_e.ds_hdl, B_TRUE); 314125351652SVuong Nguyen if (iosvc == NULL) { 314225351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 314325351652SVuong Nguyen "error: can't create iosvc " 314425351652SVuong Nguyen "for async evnt %d\n", 314525351652SVuong Nguyen async_e.event_type); 314625351652SVuong Nguyen (void) pthread_mutex_unlock( 314725351652SVuong Nguyen &iosvc_list_lock); 314825351652SVuong Nguyen break; 314925351652SVuong Nguyen } 315025351652SVuong Nguyen 31512c07a099SYanmin Sun etm_iosvc_setup(fmd_hdl, iosvc, 31522c07a099SYanmin Sun &async_e); 315325351652SVuong Nguyen (void) pthread_mutex_unlock( 315425351652SVuong Nguyen &iosvc_list_lock); 315525351652SVuong Nguyen } else { 315625351652SVuong Nguyen iosvc = &io_svc; 315725351652SVuong Nguyen (void) strcpy(iosvc->ldom_name, 315825351652SVuong Nguyen async_e.ldom_name); 315925351652SVuong Nguyen 31602c07a099SYanmin Sun etm_iosvc_setup(fmd_hdl, iosvc, 31612c07a099SYanmin Sun &async_e); 316225351652SVuong Nguyen } 316325351652SVuong Nguyen break; 316425351652SVuong Nguyen 316525351652SVuong Nguyen case ETM_ASYNC_EVENT_DS_UNREG_CB: 316625351652SVuong Nguyen /* 316725351652SVuong Nguyen * decide which iosvc struct to perform 316825351652SVuong Nguyen * this UNREG callback on. 316925351652SVuong Nguyen */ 317025351652SVuong Nguyen if (etm_ldom_type == LDOM_TYPE_CONTROL) { 317125351652SVuong Nguyen (void) pthread_mutex_lock( 317225351652SVuong Nguyen &iosvc_list_lock); 317325351652SVuong Nguyen /* 317425351652SVuong Nguyen * lookup the iosvc struct w/ 317525351652SVuong Nguyen * ds_hdl 317625351652SVuong Nguyen */ 317725351652SVuong Nguyen iosvc = etm_iosvc_lookup( 317825351652SVuong Nguyen fmd_hdl, async_e.ldom_name, 317925351652SVuong Nguyen async_e.ds_hdl, B_FALSE); 318025351652SVuong Nguyen if (iosvc == NULL) { 318125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 318225351652SVuong Nguyen "error: can't find iosvc " 318325351652SVuong Nguyen "for async evnt %d\n", 318425351652SVuong Nguyen async_e.event_type); 318525351652SVuong Nguyen (void) pthread_mutex_unlock( 318625351652SVuong Nguyen &iosvc_list_lock); 318725351652SVuong Nguyen break; 318825351652SVuong Nguyen } 318925351652SVuong Nguyen 319025351652SVuong Nguyen /* 319125351652SVuong Nguyen * ds_hdl and fmd_xprt_open 319225351652SVuong Nguyen * go hand to hand together 319325351652SVuong Nguyen * after unreg_cb, 319425351652SVuong Nguyen * ds_hdl is INVALID and 319525351652SVuong Nguyen * fmd_xprt is closed. 319625351652SVuong Nguyen * the ldom name and the msg Q 319725351652SVuong Nguyen * remains in iosvc_list 319825351652SVuong Nguyen */ 319925351652SVuong Nguyen if (iosvc->ldom_name != '\0') 320025351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 320125351652SVuong Nguyen "info: iosvc w/ ldom_name " 320225351652SVuong Nguyen "%s \n", iosvc->ldom_name); 320325351652SVuong Nguyen 320425351652SVuong Nguyen /* 32052c07a099SYanmin Sun * destroy send/recv threads and 32062c07a099SYanmin Sun * other clean up on Control side. 320725351652SVuong Nguyen */ 32082c07a099SYanmin Sun etm_iosvc_cleanup(fmd_hdl, iosvc, 3209d279c7bfSVuong Nguyen B_FALSE, B_FALSE); 321025351652SVuong Nguyen (void) pthread_mutex_unlock( 321125351652SVuong Nguyen &iosvc_list_lock); 321225351652SVuong Nguyen } else { 321325351652SVuong Nguyen iosvc = &io_svc; 321425351652SVuong Nguyen /* 32152c07a099SYanmin Sun * destroy send/recv threads and 32162c07a099SYanmin Sun * then clean up on Root side. 321725351652SVuong Nguyen */ 32182c07a099SYanmin Sun etm_iosvc_cleanup(fmd_hdl, iosvc, 3219d279c7bfSVuong Nguyen B_FALSE, B_FALSE); 322025351652SVuong Nguyen } 322125351652SVuong Nguyen break; 322225351652SVuong Nguyen 322325351652SVuong Nguyen default: 322425351652SVuong Nguyen /* 322525351652SVuong Nguyen * for all other events, etm doesn't care. 322625351652SVuong Nguyen * already logged an fmd info msg w/ 322725351652SVuong Nguyen * the event type. Do nothing here. 322825351652SVuong Nguyen */ 322925351652SVuong Nguyen break; 323025351652SVuong Nguyen } /* switch (async_e.event_type) */ 323125351652SVuong Nguyen 323225351652SVuong Nguyen if (etm_ldom_type == LDOM_TYPE_CONTROL) { 323325351652SVuong Nguyen etm_filter_handle_ldom_event(fmd_hdl, 323425351652SVuong Nguyen async_e.event_type, async_e.ldom_name); 323525351652SVuong Nguyen } 323625351652SVuong Nguyen 323725351652SVuong Nguyen /* 323825351652SVuong Nguyen * grab the lock to check the q length again 323925351652SVuong Nguyen */ 324025351652SVuong Nguyen (void) pthread_mutex_lock(&etm_async_event_q_lock); 324125351652SVuong Nguyen 324225351652SVuong Nguyen if (etm_is_dying) { 324325351652SVuong Nguyen break; 324425351652SVuong Nguyen } 324525351652SVuong Nguyen } /* etm_async_q_cur_len */ 324625351652SVuong Nguyen 324725351652SVuong Nguyen /* 324825351652SVuong Nguyen * we have the mutex lock at this point, whether 324925351652SVuong Nguyen * . etm_is_dying and/or 325025351652SVuong Nguyen * . q_len == 0 325125351652SVuong Nguyen */ 325225351652SVuong Nguyen if (!etm_is_dying && etm_async_q_cur_len == 0) { 325325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 325425351652SVuong Nguyen "info: cond wait on async_event_q_cv\n"); 325525351652SVuong Nguyen (void) pthread_cond_wait(&etm_async_event_q_cv, 325625351652SVuong Nguyen &etm_async_event_q_lock); 325725351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 325825351652SVuong Nguyen "info: cond wait on async_event_q_cv rtns\n"); 325925351652SVuong Nguyen } 326025351652SVuong Nguyen (void) pthread_mutex_unlock(&etm_async_event_q_lock); 326125351652SVuong Nguyen } /* etm_is_dying */ 326225351652SVuong Nguyen 326325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 326425351652SVuong Nguyen "info: etm async event handler thread exiting\n"); 326525351652SVuong Nguyen 326625351652SVuong Nguyen } /* etm_async_event_handler */ 326725351652SVuong Nguyen 326825351652SVuong Nguyen /* 326925351652SVuong Nguyen * deQ what's in iosvc msg Q 327025351652SVuong Nguyen * send iosvc_msgp to the remote io svc ldom by calling ds_send_msg() 327125351652SVuong Nguyen * the iosvc_msgp already has the packed msg, which is hdr + 1 fma event 327225351652SVuong Nguyen */ 327325351652SVuong Nguyen static void 327425351652SVuong Nguyen etm_send_to_remote_root(void *arg) 327525351652SVuong Nguyen { 327625351652SVuong Nguyen 327725351652SVuong Nguyen etm_iosvc_t *iosvc = (etm_iosvc_t *)arg; /* iosvc ptr */ 327825351652SVuong Nguyen etm_iosvc_q_ele_t msg_ele; /* iosvc msg ele */ 327925351652SVuong Nguyen etm_proto_v1_ev_hdr_t *ev_hdrp; /* hdr for FMA_EVENT */ 328025351652SVuong Nguyen fmd_hdl_t *fmd_hdl = init_hdl; /* fmd handle */ 328125351652SVuong Nguyen 328225351652SVuong Nguyen 328325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 328425351652SVuong Nguyen "info: send to remote iosvc starting w/ ldom_name %s\n", 328525351652SVuong Nguyen iosvc->ldom_name); 328625351652SVuong Nguyen 328725351652SVuong Nguyen /* 328825351652SVuong Nguyen * loop forever until etm_is_dying or thr_is_dying 328925351652SVuong Nguyen */ 329025351652SVuong Nguyen while (!etm_is_dying && !iosvc->thr_is_dying) { 329125351652SVuong Nguyen if (iosvc->ds_hdl != DS_INVALID_HDL && 329225351652SVuong Nguyen iosvc->start_sending_Q > 0) { 329325351652SVuong Nguyen (void) pthread_mutex_lock(&iosvc->msg_q_lock); 329425351652SVuong Nguyen while (iosvc->msg_q_cur_len > 0 && 329525351652SVuong Nguyen iosvc->ds_hdl != DS_INVALID_HDL) { 329625351652SVuong Nguyen (void) etm_iosvc_msg_deq(fmd_hdl, iosvc, 329725351652SVuong Nguyen &msg_ele); 329825351652SVuong Nguyen if (etm_debug_lvl >= 3) { 329925351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: valid " 330025351652SVuong Nguyen "ds_hdl before ds_send_msg \n"); 330125351652SVuong Nguyen } 330225351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc->msg_q_lock); 330325351652SVuong Nguyen 330425351652SVuong Nguyen iosvc->ack_ok = 0; 330525351652SVuong Nguyen ev_hdrp = (etm_proto_v1_ev_hdr_t *) 330625351652SVuong Nguyen ((ptrdiff_t)msg_ele.msg); 330725351652SVuong Nguyen ev_hdrp->ev_pp.pp_xid = iosvc->cur_send_xid + 1; 330825351652SVuong Nguyen while (!iosvc->ack_ok && 330925351652SVuong Nguyen iosvc->ds_hdl != DS_INVALID_HDL && 331025351652SVuong Nguyen !etm_is_dying) { 331125351652SVuong Nguyen /* 331225351652SVuong Nguyen * call ds_send_msg() to send the msg, 331325351652SVuong Nguyen * wait for the recv end to send the 331425351652SVuong Nguyen * resp msg back. 331525351652SVuong Nguyen * If resp msg is recv-ed, ack_ok 331625351652SVuong Nguyen * will be set to 1. 331725351652SVuong Nguyen * otherwise, retry. 331825351652SVuong Nguyen */ 331925351652SVuong Nguyen if (etm_send_ds_msg(fmd_hdl, B_TRUE, 332025351652SVuong Nguyen iosvc, &msg_ele, ev_hdrp) < 0) { 332125351652SVuong Nguyen continue; 332225351652SVuong Nguyen } 332325351652SVuong Nguyen 332425351652SVuong Nguyen if (etm_is_dying || iosvc->thr_is_dying) 332525351652SVuong Nguyen break; 332625351652SVuong Nguyen } 332725351652SVuong Nguyen 332825351652SVuong Nguyen /* 332925351652SVuong Nguyen * if out of the while loop but !ack_ok, ie, 333025351652SVuong Nguyen * ds_hdl becomes invalid at some point 333125351652SVuong Nguyen * while waiting the resp msg, we need to put 333225351652SVuong Nguyen * the msg back to the head of the Q. 333325351652SVuong Nguyen */ 333425351652SVuong Nguyen if (!iosvc->ack_ok) { 333525351652SVuong Nguyen (void) pthread_mutex_lock( 333625351652SVuong Nguyen &iosvc->msg_q_lock); 333725351652SVuong Nguyen /* 333825351652SVuong Nguyen * put the msg back to the head of Q. 333925351652SVuong Nguyen * If the Q is full at this point, 334025351652SVuong Nguyen * drop the msg at the tail, enq this 334125351652SVuong Nguyen * msg to the head. 334225351652SVuong Nguyen */ 334325351652SVuong Nguyen etm_msg_enq_head(fmd_hdl, iosvc, 334425351652SVuong Nguyen &msg_ele); 334525351652SVuong Nguyen (void) pthread_mutex_unlock( 334625351652SVuong Nguyen &iosvc->msg_q_lock); 334725351652SVuong Nguyen } 334825351652SVuong Nguyen 334925351652SVuong Nguyen /* 335025351652SVuong Nguyen * 335125351652SVuong Nguyen * grab the lock to check the Q len again 335225351652SVuong Nguyen */ 335325351652SVuong Nguyen (void) pthread_mutex_lock(&iosvc->msg_q_lock); 335425351652SVuong Nguyen if (etm_is_dying || iosvc->thr_is_dying) { 335525351652SVuong Nguyen break; 335625351652SVuong Nguyen } 335725351652SVuong Nguyen } /* while dequeing iosvc msgs to send */ 335825351652SVuong Nguyen 335925351652SVuong Nguyen /* 336025351652SVuong Nguyen * we have the mutex lock for msg_q_lock at this point 336125351652SVuong Nguyen * we are here because 336225351652SVuong Nguyen * 1) q_len == 0: then wait on the cv for Q to be filled 336325351652SVuong Nguyen * 2) etm_is_dying 336425351652SVuong Nguyen */ 336525351652SVuong Nguyen if (!etm_is_dying && !iosvc->thr_is_dying && 336625351652SVuong Nguyen iosvc->msg_q_cur_len == 0) { 336725351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 336825351652SVuong Nguyen "info: waiting on msg_q_cv\n"); 336925351652SVuong Nguyen (void) pthread_cond_wait(&iosvc->msg_q_cv, 337025351652SVuong Nguyen &iosvc->msg_q_lock); 337125351652SVuong Nguyen } 337225351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc->msg_q_lock); 337325351652SVuong Nguyen if (etm_is_dying || iosvc->thr_is_dying) { 337425351652SVuong Nguyen break; 337525351652SVuong Nguyen } 337625351652SVuong Nguyen } else { 337725351652SVuong Nguyen (void) etm_sleep(1); 337825351652SVuong Nguyen } /* wait for the start_sendingQ > 0 */ 337925351652SVuong Nguyen } /* etm_is_dying or thr_is_dying */ 338025351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info; etm send thread exiting \n"); 338125351652SVuong Nguyen } /* etm_send_to_remote_root */ 338225351652SVuong Nguyen 338325351652SVuong Nguyen 338425351652SVuong Nguyen /* 338525351652SVuong Nguyen * receive etm msgs from the remote root ldom by calling ds_recv_msg() 338625351652SVuong Nguyen * if FMA events/ereports, call fmd_xprt_post() to post to fmd 338725351652SVuong Nguyen * send ACK back by calling ds_send_msg() 338825351652SVuong Nguyen */ 338925351652SVuong Nguyen static void 339025351652SVuong Nguyen etm_recv_from_remote_root(void *arg) 339125351652SVuong Nguyen { 339225351652SVuong Nguyen etm_iosvc_t *iosvc = (etm_iosvc_t *)arg; /* iosvc ptr */ 339325351652SVuong Nguyen etm_proto_v1_pp_t *pp; /* protocol preamble */ 339425351652SVuong Nguyen etm_proto_v1_ev_hdr_t *ev_hdrp; /* for FMA_EVENT msg */ 339525351652SVuong Nguyen etm_proto_v1_resp_hdr_t *resp_hdrp; /* for RESPONSE msg */ 339625351652SVuong Nguyen int32_t resp_code = 0; /* default is success */ 339725351652SVuong Nguyen int32_t rc; /* return value */ 339825351652SVuong Nguyen size_t maxlen = MAXLEN; 339925351652SVuong Nguyen /* max msg len */ 340025351652SVuong Nguyen char msgbuf[MAXLEN]; /* recv msg buf */ 340125351652SVuong Nguyen size_t msg_size; /* recv msg size */ 340225351652SVuong Nguyen size_t hdr_sz; /* sizeof *hdrp */ 340325351652SVuong Nguyen size_t evsz; /* sizeof *evp */ 340425351652SVuong Nguyen size_t fma_event_size; /* sizeof FMA event */ 340525351652SVuong Nguyen nvlist_t *evp; /* ptr to the nvlist */ 340625351652SVuong Nguyen char *buf; /* ptr to the nvlist */ 340725351652SVuong Nguyen static uint32_t mem_alloc = 0; /* indicate if alloc mem */ 340825351652SVuong Nguyen char *msg; /* ptr to alloc mem */ 340925351652SVuong Nguyen fmd_hdl_t *fmd_hdl = init_hdl; 341025351652SVuong Nguyen 341125351652SVuong Nguyen 341225351652SVuong Nguyen 341325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 341425351652SVuong Nguyen "info: recv from remote iosvc starting with ldom name %s \n", 341525351652SVuong Nguyen iosvc->ldom_name); 341625351652SVuong Nguyen 341725351652SVuong Nguyen /* 341825351652SVuong Nguyen * loop forever until etm_is_dying or the thread is dying 341925351652SVuong Nguyen */ 342025351652SVuong Nguyen 342125351652SVuong Nguyen msg = msgbuf; 342225351652SVuong Nguyen while (!etm_is_dying && !iosvc->thr_is_dying) { 342325351652SVuong Nguyen if (iosvc->ds_hdl == DS_INVALID_HDL) { 342425351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 342525351652SVuong Nguyen "info: ds_hdl is invalid in recv thr\n"); 342625351652SVuong Nguyen (void) etm_sleep(1); 342725351652SVuong Nguyen continue; 342825351652SVuong Nguyen } 342925351652SVuong Nguyen 343025351652SVuong Nguyen /* 343125351652SVuong Nguyen * for now, there are FMA_EVENT and ACK msg type. 343225351652SVuong Nguyen * use FMA_EVENT buf as the maxlen, hdr+1 fma event. 343325351652SVuong Nguyen * FMA_EVENT is big enough to hold an ACK msg. 343425351652SVuong Nguyen * the actual msg size received is in msg_size. 343525351652SVuong Nguyen */ 343625351652SVuong Nguyen rc = (*etm_ds_recv_msg)(iosvc->ds_hdl, msg, maxlen, &msg_size); 343725351652SVuong Nguyen if (rc == EFBIG) { 343825351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 343925351652SVuong Nguyen "info: ds_recv_msg needs mem the size of %d\n", 344025351652SVuong Nguyen msg_size); 344125351652SVuong Nguyen msg = fmd_hdl_zalloc(fmd_hdl, msg_size, FMD_SLEEP); 344225351652SVuong Nguyen mem_alloc = 1; 344325351652SVuong Nguyen } else if (rc == 0) { 344425351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 344525351652SVuong Nguyen "info: ds_recv_msg received a msg ok\n"); 344625351652SVuong Nguyen /* 344725351652SVuong Nguyen * check the magic # in msg.hdr 344825351652SVuong Nguyen */ 344925351652SVuong Nguyen pp = (etm_proto_v1_pp_t *)((ptrdiff_t)msg); 345025351652SVuong Nguyen if (pp->pp_magic_num != ETM_PROTO_MAGIC_NUM) { 345125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 345225351652SVuong Nguyen "info: bad ds recv on magic\n"); 345325351652SVuong Nguyen continue; 345425351652SVuong Nguyen } 345525351652SVuong Nguyen 345625351652SVuong Nguyen /* 345725351652SVuong Nguyen * check the msg type against msg_size to be sure 345825351652SVuong Nguyen * that received msg is not a truncated msg 345925351652SVuong Nguyen */ 346025351652SVuong Nguyen if (pp->pp_msg_type == ETM_MSG_TYPE_FMA_EVENT) { 346125351652SVuong Nguyen 346225351652SVuong Nguyen ev_hdrp = (etm_proto_v1_ev_hdr_t *) 346325351652SVuong Nguyen ((ptrdiff_t)msg); 346425351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: ds received " 346525351652SVuong Nguyen "FMA EVENT xid=%d msg_size=%d\n", 346625351652SVuong Nguyen ev_hdrp->ev_pp.pp_xid, msg_size); 346725351652SVuong Nguyen hdr_sz = sizeof (*ev_hdrp) + 346825351652SVuong Nguyen 1*(sizeof (ev_hdrp->ev_lens[0])); 346925351652SVuong Nguyen fma_event_size = hdr_sz + ev_hdrp->ev_lens[0]; 347025351652SVuong Nguyen if (fma_event_size != msg_size) { 347125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: wrong " 347225351652SVuong Nguyen "ev msg size received\n"); 347325351652SVuong Nguyen continue; 347425351652SVuong Nguyen /* 347525351652SVuong Nguyen * Simply do nothing. The send side 347625351652SVuong Nguyen * will timedcond_wait waiting on the 347725351652SVuong Nguyen * resp msg will timeout and 347825351652SVuong Nguyen * re-send the same msg. 347925351652SVuong Nguyen */ 348025351652SVuong Nguyen } 348125351652SVuong Nguyen if (etm_debug_lvl >= 3) { 348225351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info: recv msg" 348325351652SVuong Nguyen " size %d hdrsz %d evp size %d\n", 348425351652SVuong Nguyen msg_size, hdr_sz, 348525351652SVuong Nguyen ev_hdrp->ev_lens[0]); 348625351652SVuong Nguyen } 348725351652SVuong Nguyen 348825351652SVuong Nguyen if (ev_hdrp->ev_pp.pp_xid != 348925351652SVuong Nguyen iosvc->xid_posted_ev) { 349025351652SVuong Nguyen /* 349125351652SVuong Nguyen * different from last xid posted to 349225351652SVuong Nguyen * fmd, post to fmd now. 349325351652SVuong Nguyen */ 349425351652SVuong Nguyen buf = msg + hdr_sz; 349525351652SVuong Nguyen rc = nvlist_unpack(buf, 349625351652SVuong Nguyen ev_hdrp->ev_lens[0], &evp, 0); 349725351652SVuong Nguyen rc = nvlist_size(evp, &evsz, 349825351652SVuong Nguyen NV_ENCODE_XDR); 349925351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 350025351652SVuong Nguyen "info: evp size %d before fmd" 350125351652SVuong Nguyen "post\n", evsz); 350225351652SVuong Nguyen 350325351652SVuong Nguyen if ((rc = etm_post_to_fmd(fmd_hdl, 350425351652SVuong Nguyen iosvc->fmd_xprt, evp)) >= 0) { 350525351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 350625351652SVuong Nguyen "info: xid posted to fmd %d" 350725351652SVuong Nguyen "\n", 350825351652SVuong Nguyen ev_hdrp->ev_pp.pp_xid); 350925351652SVuong Nguyen iosvc->xid_posted_ev = 351025351652SVuong Nguyen ev_hdrp->ev_pp.pp_xid; 351125351652SVuong Nguyen } 351225351652SVuong Nguyen } 351325351652SVuong Nguyen 351425351652SVuong Nguyen /* 351525351652SVuong Nguyen * ready to send the RESPONSE msg back 351625351652SVuong Nguyen * reuse the msg buffer as the response buffer 351725351652SVuong Nguyen */ 351825351652SVuong Nguyen resp_hdrp = (etm_proto_v1_resp_hdr_t *) 351925351652SVuong Nguyen ((ptrdiff_t)msg); 352025351652SVuong Nguyen resp_hdrp->resp_pp.pp_msg_type = 352125351652SVuong Nguyen ETM_MSG_TYPE_RESPONSE; 352225351652SVuong Nguyen 352325351652SVuong Nguyen resp_hdrp->resp_code = resp_code; 352425351652SVuong Nguyen resp_hdrp->resp_len = sizeof (*resp_hdrp); 352525351652SVuong Nguyen 352625351652SVuong Nguyen /* 352725351652SVuong Nguyen * send the whole response msg in one send 352825351652SVuong Nguyen */ 352925351652SVuong Nguyen if ((*etm_ds_send_msg)(iosvc->ds_hdl, msg, 353025351652SVuong Nguyen sizeof (*resp_hdrp)) != 0) { 353125351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 353225351652SVuong Nguyen "info: send response msg failed\n"); 353325351652SVuong Nguyen } else { 353425351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 353525351652SVuong Nguyen "info: ds send resp msg ok" 353625351652SVuong Nguyen "size %d\n", sizeof (*resp_hdrp)); 353725351652SVuong Nguyen } 353825351652SVuong Nguyen } else if (pp->pp_msg_type == ETM_MSG_TYPE_RESPONSE) { 353925351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 354025351652SVuong Nguyen "info: ds received respond msg xid=%d" 354125351652SVuong Nguyen "msg_size=%d for ldom %s\n", pp->pp_xid, 354225351652SVuong Nguyen msg_size, iosvc->ldom_name); 354325351652SVuong Nguyen if (sizeof (*resp_hdrp) != msg_size) { 354425351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 354525351652SVuong Nguyen "info: wrong resp msg size" 354625351652SVuong Nguyen "received\n"); 354725351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 354825351652SVuong Nguyen "info: resp msg size %d recv resp" 354925351652SVuong Nguyen "msg size %d\n", 355025351652SVuong Nguyen sizeof (*resp_hdrp), msg_size); 355125351652SVuong Nguyen continue; 355225351652SVuong Nguyen } 355325351652SVuong Nguyen /* 355425351652SVuong Nguyen * is the pp.pp_xid == iosvc->cur_send_xid+1, 355525351652SVuong Nguyen * if so, nudge the send routine to send next 355625351652SVuong Nguyen */ 355725351652SVuong Nguyen if (pp->pp_xid != iosvc->cur_send_xid+1) { 355825351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 355925351652SVuong Nguyen "info: ds received resp msg xid=%d " 356025351652SVuong Nguyen "doesn't match cur_send_id=%d\n", 356125351652SVuong Nguyen pp->pp_xid, iosvc->cur_send_xid+1); 356225351652SVuong Nguyen continue; 356325351652SVuong Nguyen } 356425351652SVuong Nguyen (void) pthread_mutex_lock(&iosvc->msg_ack_lock); 356525351652SVuong Nguyen iosvc->ack_ok = 1; 356625351652SVuong Nguyen (void) pthread_cond_signal(&iosvc->msg_ack_cv); 356725351652SVuong Nguyen (void) pthread_mutex_unlock( 356825351652SVuong Nguyen &iosvc->msg_ack_lock); 356925351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 357025351652SVuong Nguyen "info: signaling msg_ack_cv\n"); 357125351652SVuong Nguyen } else { 357225351652SVuong Nguyen /* 357325351652SVuong Nguyen * place holder for future msg types 357425351652SVuong Nguyen */ 357525351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 357625351652SVuong Nguyen "info: ds received unrecognized msg\n"); 357725351652SVuong Nguyen } 357825351652SVuong Nguyen if (mem_alloc) { 357925351652SVuong Nguyen fmd_hdl_free(fmd_hdl, msg, msg_size); 358025351652SVuong Nguyen mem_alloc = 0; 358125351652SVuong Nguyen msg = msgbuf; 358225351652SVuong Nguyen } 358325351652SVuong Nguyen } else { 358425351652SVuong Nguyen if (etm_debug_lvl >= 3) { 358525351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 358625351652SVuong Nguyen "info: ds_recv_msg() failed\n"); 358725351652SVuong Nguyen } 358825351652SVuong Nguyen } /* ds_recv_msg() returns */ 358925351652SVuong Nguyen } /* etm_is_dying */ 359025351652SVuong Nguyen 359125351652SVuong Nguyen /* 359225351652SVuong Nguyen * need to free the mem allocated in msg upon exiting the thread 359325351652SVuong Nguyen */ 359425351652SVuong Nguyen if (mem_alloc) { 359525351652SVuong Nguyen fmd_hdl_free(fmd_hdl, msg, msg_size); 359625351652SVuong Nguyen mem_alloc = 0; 359725351652SVuong Nguyen msg = msgbuf; 359825351652SVuong Nguyen } 359925351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, "info; etm recv thread exiting \n"); 360025351652SVuong Nguyen } /* etm_recv_from_remote_root */ 360125351652SVuong Nguyen 360225351652SVuong Nguyen 360325351652SVuong Nguyen 360425351652SVuong Nguyen /* 360525351652SVuong Nguyen * etm_ds_init 360625351652SVuong Nguyen * initialize DS services function pointers by calling 360725351652SVuong Nguyen * dlopen() followed by dlsym() for each ds func. 360825351652SVuong Nguyen * if any dlopen() or dlsym() call fails, return -ENOENT 360925351652SVuong Nguyen * return >0 for successs, -ENOENT for failure 361025351652SVuong Nguyen */ 361125351652SVuong Nguyen static int 361225351652SVuong Nguyen etm_ds_init(fmd_hdl_t *hdl) 361325351652SVuong Nguyen { 361425351652SVuong Nguyen int rc = 0; 361525351652SVuong Nguyen 361625351652SVuong Nguyen if ((etm_dl_hdl = dlopen(etm_dl_path, etm_dl_mode)) == NULL) { 361725351652SVuong Nguyen fmd_hdl_debug(hdl, "error: failed to dlopen %s\n", etm_dl_path); 361825351652SVuong Nguyen return (-ENOENT); 361925351652SVuong Nguyen } 362025351652SVuong Nguyen 362125351652SVuong Nguyen etm_ds_svc_reg = (int (*)(ds_capability_t *cap, ds_ops_t *ops)) 362225351652SVuong Nguyen dlsym(etm_dl_hdl, "ds_svc_reg"); 362325351652SVuong Nguyen if (etm_ds_svc_reg == NULL) { 362425351652SVuong Nguyen fmd_hdl_debug(hdl, 362525351652SVuong Nguyen "error: failed to dlsym ds_svc_reg() w/ error %s\n", 362625351652SVuong Nguyen dlerror()); 362725351652SVuong Nguyen rc = -ENOENT; 362825351652SVuong Nguyen } 362925351652SVuong Nguyen 363025351652SVuong Nguyen 363125351652SVuong Nguyen etm_ds_clnt_reg = (int (*)(ds_capability_t *cap, ds_ops_t *ops)) 363225351652SVuong Nguyen dlsym(etm_dl_hdl, "ds_clnt_reg"); 363325351652SVuong Nguyen if (etm_ds_clnt_reg == NULL) { 363425351652SVuong Nguyen fmd_hdl_debug(hdl, 363525351652SVuong Nguyen "error: dlsym(ds_clnt_reg) failed w/ errno %d\n", errno); 363625351652SVuong Nguyen rc = -ENOENT; 363725351652SVuong Nguyen } 363825351652SVuong Nguyen 363925351652SVuong Nguyen etm_ds_send_msg = (int (*)(ds_hdl_t hdl, void *buf, size_t buflen)) 364025351652SVuong Nguyen dlsym(etm_dl_hdl, "ds_send_msg"); 364125351652SVuong Nguyen if (etm_ds_send_msg == NULL) { 364225351652SVuong Nguyen fmd_hdl_debug(hdl, "error: dlsym(ds_send_msg) failed\n"); 364325351652SVuong Nguyen rc = -ENOENT; 364425351652SVuong Nguyen } 364525351652SVuong Nguyen 364625351652SVuong Nguyen etm_ds_recv_msg = (int (*)(ds_hdl_t hdl, void *buf, size_t buflen, 364725351652SVuong Nguyen size_t *msglen))dlsym(etm_dl_hdl, "ds_recv_msg"); 364825351652SVuong Nguyen if (etm_ds_recv_msg == NULL) { 364925351652SVuong Nguyen fmd_hdl_debug(hdl, "error: dlsym(ds_recv_msg) failed\n"); 365025351652SVuong Nguyen rc = -ENOENT; 365125351652SVuong Nguyen } 365225351652SVuong Nguyen 365325351652SVuong Nguyen etm_ds_fini = (int (*)(void))dlsym(etm_dl_hdl, "ds_fini"); 365425351652SVuong Nguyen if (etm_ds_fini == NULL) { 365525351652SVuong Nguyen fmd_hdl_debug(hdl, "error: dlsym(ds_fini) failed\n"); 365625351652SVuong Nguyen rc = -ENOENT; 365725351652SVuong Nguyen } 365825351652SVuong Nguyen 365925351652SVuong Nguyen if (rc == -ENOENT) { 366025351652SVuong Nguyen (void) dlclose(etm_dl_hdl); 366125351652SVuong Nguyen } 366225351652SVuong Nguyen return (rc); 366325351652SVuong Nguyen 366425351652SVuong Nguyen } /* etm_ds_init() */ 366525351652SVuong Nguyen 366625351652SVuong Nguyen 366725351652SVuong Nguyen /* 3668733a5356Srb144127 * -------------------------- FMD entry points ------------------------------- 3669733a5356Srb144127 */ 3670733a5356Srb144127 3671733a5356Srb144127 /* 3672733a5356Srb144127 * _fmd_init - initialize the transport for use by ETM and start the 3673733a5356Srb144127 * server daemon to accept new connections to us 3674733a5356Srb144127 * 3675733a5356Srb144127 * FMD will read our *.conf and subscribe us to FMA events 3676733a5356Srb144127 */ 3677733a5356Srb144127 3678733a5356Srb144127 void 3679733a5356Srb144127 _fmd_init(fmd_hdl_t *hdl) 3680733a5356Srb144127 { 3681e2ff4ac6Srb144127 struct timeval tmv; /* timeval */ 3682733a5356Srb144127 ssize_t n; /* gen use */ 36834b476ed5Sdarudy const struct facility *fp; /* syslog facility matching */ 36844b476ed5Sdarudy char *facname; /* syslog facility property */ 368525351652SVuong Nguyen uint32_t type_mask; /* type of the local host */ 368625351652SVuong Nguyen int rc; /* funcs return code */ 368725351652SVuong Nguyen 3688733a5356Srb144127 3689733a5356Srb144127 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) { 3690733a5356Srb144127 return; /* invalid data in configuration file */ 3691733a5356Srb144127 } 3692733a5356Srb144127 3693733a5356Srb144127 fmd_hdl_debug(hdl, "info: module initializing\n"); 3694733a5356Srb144127 369531e37bb4Svn83148 init_hdl = hdl; 369625351652SVuong Nguyen etm_lhp = ldom_init(etm_init_alloc, etm_init_free); 369731e37bb4Svn83148 369831e37bb4Svn83148 /* 369925351652SVuong Nguyen * decide the ldom type, do initialization accordingly 370031e37bb4Svn83148 */ 370125351652SVuong Nguyen if ((rc = ldom_get_type(etm_lhp, &type_mask)) != 0) { 370225351652SVuong Nguyen fmd_hdl_debug(hdl, "error: can't decide ldom type\n"); 370331e37bb4Svn83148 fmd_hdl_debug(hdl, "info: module unregistering\n"); 370425351652SVuong Nguyen ldom_fini(etm_lhp); 370531e37bb4Svn83148 fmd_hdl_unregister(hdl); 370631e37bb4Svn83148 return; 370725351652SVuong Nguyen } 370825351652SVuong Nguyen 370925351652SVuong Nguyen if ((type_mask & LDOM_TYPE_LEGACY) || (type_mask & LDOM_TYPE_CONTROL)) { 371025351652SVuong Nguyen if (type_mask & LDOM_TYPE_LEGACY) { 371125351652SVuong Nguyen /* 371225351652SVuong Nguyen * running on a legacy sun4v domain, 371325351652SVuong Nguyen * act as the the old sun4v 371425351652SVuong Nguyen */ 371525351652SVuong Nguyen etm_ldom_type = LDOM_TYPE_LEGACY; 371625351652SVuong Nguyen fmd_hdl_debug(hdl, "info: running as the old sun4v\n"); 371725351652SVuong Nguyen ldom_fini(etm_lhp); 371825351652SVuong Nguyen } else if (type_mask & LDOM_TYPE_CONTROL) { 371925351652SVuong Nguyen etm_ldom_type = LDOM_TYPE_CONTROL; 372025351652SVuong Nguyen fmd_hdl_debug(hdl, "info: running as control domain\n"); 372125351652SVuong Nguyen 372225351652SVuong Nguyen /* 372325351652SVuong Nguyen * looking for libds.so.1. 372425351652SVuong Nguyen * If not found, don't do DS registration. As a result, 372525351652SVuong Nguyen * there will be no DS callbacks or other DS services. 372625351652SVuong Nguyen */ 372725351652SVuong Nguyen if (etm_ds_init(hdl) >= 0) { 372825351652SVuong Nguyen etm_filter_init(hdl); 372925351652SVuong Nguyen etm_ckpt_init(hdl); 373025351652SVuong Nguyen 373125351652SVuong Nguyen flags = FMD_XPRT_RDWR | FMD_XPRT_ACCEPT; 373225351652SVuong Nguyen 373325351652SVuong Nguyen /* 373425351652SVuong Nguyen * ds client registration 373525351652SVuong Nguyen */ 373625351652SVuong Nguyen if ((rc = (*etm_ds_clnt_reg)(&iosvc_caps, 373725351652SVuong Nguyen &iosvc_ops))) { 373825351652SVuong Nguyen fmd_hdl_debug(hdl, 373925351652SVuong Nguyen "error: ds_clnt_reg(): errno %d\n", rc); 374025351652SVuong Nguyen } 374131e37bb4Svn83148 } else { 374225351652SVuong Nguyen fmd_hdl_debug(hdl, "error: dlopen() libds " 374325351652SVuong Nguyen "failed, continue without the DS services"); 374425351652SVuong Nguyen } 374525351652SVuong Nguyen 374625351652SVuong Nguyen /* 374725351652SVuong Nguyen * register for ldom status events 374825351652SVuong Nguyen */ 374925351652SVuong Nguyen if ((rc = ldom_register_event(etm_lhp, 375025351652SVuong Nguyen ldom_event_handler, hdl))) { 375125351652SVuong Nguyen fmd_hdl_debug(hdl, 375225351652SVuong Nguyen "error: ldom_register_event():" 375325351652SVuong Nguyen " errno %d\n", rc); 375425351652SVuong Nguyen } 375525351652SVuong Nguyen 375625351652SVuong Nguyen /* 375725351652SVuong Nguyen * create the thread for handling both the ldom status 375825351652SVuong Nguyen * change and service events 375925351652SVuong Nguyen */ 376025351652SVuong Nguyen etm_async_e_tid = fmd_thr_create(hdl, 376125351652SVuong Nguyen etm_async_event_handler, hdl); 376231e37bb4Svn83148 } 376331e37bb4Svn83148 3764733a5356Srb144127 /* setup statistics and properties from FMD */ 3765733a5356Srb144127 3766733a5356Srb144127 (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, 376725351652SVuong Nguyen sizeof (etm_stats) / sizeof (fmd_stat_t), 376825351652SVuong Nguyen (fmd_stat_t *)&etm_stats); 3769733a5356Srb144127 377025351652SVuong Nguyen etm_fma_resp_wait_time = fmd_prop_get_int32(hdl, 377125351652SVuong Nguyen ETM_PROP_NM_FMA_RESP_WAIT_TIME); 3772733a5356Srb144127 etm_debug_lvl = fmd_prop_get_int32(hdl, ETM_PROP_NM_DEBUG_LVL); 3773733a5356Srb144127 etm_debug_max_ev_cnt = fmd_prop_get_int32(hdl, 3774733a5356Srb144127 ETM_PROP_NM_DEBUG_MAX_EV_CNT); 3775733a5356Srb144127 fmd_hdl_debug(hdl, "info: etm_debug_lvl %d " 377625351652SVuong Nguyen "etm_debug_max_ev_cnt %d\n", etm_debug_lvl, 377725351652SVuong Nguyen etm_debug_max_ev_cnt); 3778b8677b72Srb144127 3779b8677b72Srb144127 etm_resp_q_max_len = fmd_prop_get_int32(hdl, 3780b8677b72Srb144127 ETM_PROP_NM_MAX_RESP_Q_LEN); 378125351652SVuong Nguyen etm_stats.etm_resp_q_max_len.fmds_value.ui64 = 378225351652SVuong Nguyen etm_resp_q_max_len; 37832ca9f232Srb144127 etm_bad_acc_to_sec = fmd_prop_get_int32(hdl, 37842ca9f232Srb144127 ETM_PROP_NM_BAD_ACC_TO_SEC); 3785733a5356Srb144127 378625351652SVuong Nguyen /* 378725351652SVuong Nguyen * obtain an FMD transport handle so we can post 378825351652SVuong Nguyen * FMA events later 378925351652SVuong Nguyen */ 379000ab1250Srb144127 379100ab1250Srb144127 etm_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); 379200ab1250Srb144127 379325351652SVuong Nguyen /* 379425351652SVuong Nguyen * encourage protocol transaction id to be unique per module 379525351652SVuong Nguyen * load 379625351652SVuong Nguyen */ 3797e2ff4ac6Srb144127 3798e2ff4ac6Srb144127 (void) gettimeofday(&tmv, NULL); 3799e2ff4ac6Srb144127 etm_xid_cur = (uint32_t)((tmv.tv_sec << 10) | 3800e2ff4ac6Srb144127 ((unsigned long)tmv.tv_usec >> 10)); 3801e2ff4ac6Srb144127 3802b8677b72Srb144127 /* init the ETM transport */ 3803733a5356Srb144127 3804733a5356Srb144127 if ((n = etm_xport_init(hdl)) != 0) { 380525351652SVuong Nguyen fmd_hdl_error(hdl, "error: bad xport init errno %d\n", 380625351652SVuong Nguyen (-n)); 3807733a5356Srb144127 fmd_hdl_unregister(hdl); 3808733a5356Srb144127 return; 3809733a5356Srb144127 } 3810733a5356Srb144127 38114b476ed5Sdarudy /* 38124b476ed5Sdarudy * Cache any properties we use every time we receive an alert. 38134b476ed5Sdarudy */ 38144b476ed5Sdarudy syslog_file = fmd_prop_get_int32(hdl, ETM_PROP_NM_SYSLOGD); 38154b476ed5Sdarudy syslog_cons = fmd_prop_get_int32(hdl, ETM_PROP_NM_CONSOLE); 38164b476ed5Sdarudy 38174b476ed5Sdarudy if (syslog_file && (syslog_logfd = open("/dev/conslog", 38184b476ed5Sdarudy O_WRONLY | O_NOCTTY)) == -1) { 381925351652SVuong Nguyen fmd_hdl_error(hdl, 382025351652SVuong Nguyen "error: failed to open /dev/conslog"); 38214b476ed5Sdarudy syslog_file = 0; 38224b476ed5Sdarudy } 38234b476ed5Sdarudy 38244b476ed5Sdarudy if (syslog_cons && (syslog_msgfd = open("/dev/sysmsg", 38254b476ed5Sdarudy O_WRONLY | O_NOCTTY)) == -1) { 38264b476ed5Sdarudy fmd_hdl_error(hdl, "error: failed to open /dev/sysmsg"); 38274b476ed5Sdarudy syslog_cons = 0; 38284b476ed5Sdarudy } 38294b476ed5Sdarudy 38304b476ed5Sdarudy if (syslog_file) { 38314b476ed5Sdarudy /* 383225351652SVuong Nguyen * Look up the value of the "facility" property and 383325351652SVuong Nguyen * use it to determine * what syslog LOG_* facility 383425351652SVuong Nguyen * value we use to fill in our log_ctl_t. 38354b476ed5Sdarudy */ 383625351652SVuong Nguyen facname = fmd_prop_get_string(hdl, 383725351652SVuong Nguyen ETM_PROP_NM_FACILITY); 38384b476ed5Sdarudy 38394b476ed5Sdarudy for (fp = syslog_facs; fp->fac_name != NULL; fp++) { 38404b476ed5Sdarudy if (strcmp(fp->fac_name, facname) == 0) 38414b476ed5Sdarudy break; 38424b476ed5Sdarudy } 38434b476ed5Sdarudy 38444b476ed5Sdarudy if (fp->fac_name == NULL) { 38454b476ed5Sdarudy fmd_hdl_error(hdl, "error: invalid 'facility'" 38464b476ed5Sdarudy " setting: %s\n", facname); 38474b476ed5Sdarudy syslog_file = 0; 38484b476ed5Sdarudy } else { 38494b476ed5Sdarudy syslog_facility = fp->fac_value; 38504b476ed5Sdarudy syslog_ctl.flags = SL_CONSOLE | SL_LOGONLY; 38514b476ed5Sdarudy } 38524b476ed5Sdarudy 38534b476ed5Sdarudy fmd_prop_free_string(hdl, facname); 38544b476ed5Sdarudy } 38554b476ed5Sdarudy 3856b8677b72Srb144127 /* 385725351652SVuong Nguyen * start the message responder and the connection acceptance 385825351652SVuong Nguyen * server; request protocol version be negotiated after waiting 385925351652SVuong Nguyen * a second for the receiver to be ready to start handshaking 3860b8677b72Srb144127 */ 3861b8677b72Srb144127 3862b8677b72Srb144127 etm_resp_tid = fmd_thr_create(hdl, etm_responder, hdl); 3863733a5356Srb144127 etm_svr_tid = fmd_thr_create(hdl, etm_server, hdl); 386431e37bb4Svn83148 386531e37bb4Svn83148 (void) etm_sleep(ETM_SLEEP_QUIK); 3866733a5356Srb144127 etm_req_ver_negot(hdl); 3867733a5356Srb144127 386825351652SVuong Nguyen } else if (type_mask & LDOM_TYPE_ROOT) { 386925351652SVuong Nguyen etm_ldom_type = LDOM_TYPE_ROOT; 387025351652SVuong Nguyen fmd_hdl_debug(hdl, "info: running as root domain\n"); 387125351652SVuong Nguyen 387225351652SVuong Nguyen /* 387325351652SVuong Nguyen * looking for libds.so.1. 387425351652SVuong Nguyen * If not found, don't do DS registration. As a result, 387525351652SVuong Nguyen * there will be no DS callbacks or other DS services. 387625351652SVuong Nguyen */ 387725351652SVuong Nguyen if (etm_ds_init(hdl) < 0) { 387825351652SVuong Nguyen fmd_hdl_debug(hdl, 387925351652SVuong Nguyen "error: dlopen() libds failed, " 388025351652SVuong Nguyen "module unregistering\n"); 388125351652SVuong Nguyen ldom_fini(etm_lhp); 388225351652SVuong Nguyen fmd_hdl_unregister(hdl); 388325351652SVuong Nguyen return; 388425351652SVuong Nguyen } 388525351652SVuong Nguyen 388625351652SVuong Nguyen /* 388725351652SVuong Nguyen * DS service registration 388825351652SVuong Nguyen */ 388925351652SVuong Nguyen if ((rc = (*etm_ds_svc_reg)(&iosvc_caps, &iosvc_ops))) { 389025351652SVuong Nguyen fmd_hdl_debug(hdl, "error: ds_svc_reg(): errno %d\n", 389125351652SVuong Nguyen rc); 389225351652SVuong Nguyen } 389325351652SVuong Nguyen 389425351652SVuong Nguyen /* 389525351652SVuong Nguyen * this thread is created for ds_reg_cb/ds_unreg_cb 389625351652SVuong Nguyen */ 389725351652SVuong Nguyen etm_async_e_tid = fmd_thr_create(hdl, 389825351652SVuong Nguyen etm_async_event_handler, hdl); 389925351652SVuong Nguyen 390025351652SVuong Nguyen flags = FMD_XPRT_RDWR; 390125351652SVuong Nguyen } else if ((type_mask & LDOM_TYPE_IO) || (type_mask == 0)) { 390225351652SVuong Nguyen /* 390325351652SVuong Nguyen * Do not load this module if it is 390425351652SVuong Nguyen * . runing on a non-root ldom 390525351652SVuong Nguyen * . the domain owns no io devices 390625351652SVuong Nguyen */ 390725351652SVuong Nguyen fmd_hdl_debug(hdl, 390825351652SVuong Nguyen "info: non-root ldom, module unregistering\n"); 390925351652SVuong Nguyen ldom_fini(etm_lhp); 391025351652SVuong Nguyen fmd_hdl_unregister(hdl); 391125351652SVuong Nguyen return; 391225351652SVuong Nguyen } else { 391325351652SVuong Nguyen /* 391425351652SVuong Nguyen * place holder, all other cases. unload etm for now 391525351652SVuong Nguyen */ 391625351652SVuong Nguyen fmd_hdl_debug(hdl, 391725351652SVuong Nguyen "info: other ldom type, module unregistering\n"); 391825351652SVuong Nguyen ldom_fini(etm_lhp); 391925351652SVuong Nguyen fmd_hdl_unregister(hdl); 392025351652SVuong Nguyen return; 392125351652SVuong Nguyen } 392225351652SVuong Nguyen 3923733a5356Srb144127 fmd_hdl_debug(hdl, "info: module initialized ok\n"); 3924733a5356Srb144127 3925733a5356Srb144127 } /* _fmd_init() */ 3926733a5356Srb144127 3927733a5356Srb144127 /* 3928733a5356Srb144127 * etm_recv - receive an FMA event from FMD and transport it 3929733a5356Srb144127 * to the remote endpoint 3930733a5356Srb144127 */ 3931733a5356Srb144127 3932733a5356Srb144127 /*ARGSUSED*/ 3933733a5356Srb144127 void 3934733a5356Srb144127 etm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *evp, const char *class) 3935733a5356Srb144127 { 3936733a5356Srb144127 etm_xport_addr_t *addrv; /* vector of transport addresses */ 3937733a5356Srb144127 etm_xport_conn_t conn; /* connection handle */ 3938733a5356Srb144127 etm_proto_v1_ev_hdr_t *hdrp; /* for FMA_EVENT msg */ 3939733a5356Srb144127 ssize_t i, n; /* gen use */ 3940733a5356Srb144127 size_t sz; /* header size */ 3941733a5356Srb144127 size_t buflen; /* size of packed FMA event */ 3942733a5356Srb144127 uint8_t *buf; /* tmp buffer for packed FMA event */ 3943733a5356Srb144127 394425351652SVuong Nguyen /* 394525351652SVuong Nguyen * if this is running on a Root Domain, ignore the events, 394625351652SVuong Nguyen * return right away 394725351652SVuong Nguyen */ 394825351652SVuong Nguyen if (etm_ldom_type == LDOM_TYPE_ROOT) 394925351652SVuong Nguyen return; 395025351652SVuong Nguyen 3951733a5356Srb144127 buflen = 0; 3952b8677b72Srb144127 if ((n = nvlist_size(evp, &buflen, NV_ENCODE_XDR)) != 0) { 3953b8677b72Srb144127 fmd_hdl_error(hdl, "error: FMA event dropped: " 3954b8677b72Srb144127 "event size errno %d class %s\n", n, class); 3955b8677b72Srb144127 etm_stats.etm_os_nvlist_size_fail.fmds_value.ui64++; 3956b8677b72Srb144127 etm_stats.etm_wr_drop_fmaevent.fmds_value.ui64++; 3957b8677b72Srb144127 return; 3958b8677b72Srb144127 } 3959733a5356Srb144127 3960733a5356Srb144127 fmd_hdl_debug(hdl, "info: rcvd event %p from FMD\n", evp); 3961733a5356Srb144127 fmd_hdl_debug(hdl, "info: cnt %llu class %s\n", 3962733a5356Srb144127 etm_stats.etm_rd_fmd_fmaevent.fmds_value.ui64, class); 3963733a5356Srb144127 3964b8677b72Srb144127 etm_stats.etm_rd_fmd_bytes.fmds_value.ui64 += buflen; 3965b8677b72Srb144127 etm_stats.etm_rd_fmd_fmaevent.fmds_value.ui64++; 3966b8677b72Srb144127 3967733a5356Srb144127 /* 3968733a5356Srb144127 * if the debug limit has been set, avoid excessive traffic, 3969733a5356Srb144127 * for example, an infinite cycle using loopback nodes 3970733a5356Srb144127 */ 3971733a5356Srb144127 3972733a5356Srb144127 if ((etm_debug_max_ev_cnt >= 0) && 3973733a5356Srb144127 (etm_stats.etm_rd_fmd_fmaevent.fmds_value.ui64 > 3974733a5356Srb144127 etm_debug_max_ev_cnt)) { 3975733a5356Srb144127 fmd_hdl_debug(hdl, "warning: FMA event dropped: " 3976733a5356Srb144127 "event %p cnt %llu > debug max %d\n", evp, 3977733a5356Srb144127 etm_stats.etm_rd_fmd_fmaevent.fmds_value.ui64, 3978733a5356Srb144127 etm_debug_max_ev_cnt); 3979733a5356Srb144127 etm_stats.etm_wr_drop_fmaevent.fmds_value.ui64++; 3980733a5356Srb144127 return; 3981733a5356Srb144127 } 3982733a5356Srb144127 3983733a5356Srb144127 /* allocate a buffer for the FMA event and nvlist pack it */ 3984733a5356Srb144127 3985733a5356Srb144127 buf = fmd_hdl_zalloc(hdl, buflen, FMD_SLEEP); 3986733a5356Srb144127 398725351652SVuong Nguyen /* 398825351652SVuong Nguyen * increment the ttl value if the event is from remote (a root domain) 398925351652SVuong Nguyen * uncomment this when enabling fault forwarding from Root domains 399025351652SVuong Nguyen * to Control domain. 399125351652SVuong Nguyen * 399225351652SVuong Nguyen * uint8_t ttl; 399325351652SVuong Nguyen * if (fmd_event_local(hdl, evp) != FMD_EVF_LOCAL) { 399425351652SVuong Nguyen * if (nvlist_lookup_uint8(evp, FMD_EVN_TTL, &ttl) == 0) { 399525351652SVuong Nguyen * (void) nvlist_remove(evp, FMD_EVN_TTL, DATA_TYPE_UINT8); 399625351652SVuong Nguyen * (void) nvlist_add_uint8(evp, FMD_EVN_TTL, ttl + 1); 399725351652SVuong Nguyen * } 399825351652SVuong Nguyen * } 399925351652SVuong Nguyen */ 400025351652SVuong Nguyen 4001733a5356Srb144127 if ((n = nvlist_pack(evp, (char **)&buf, &buflen, 4002733a5356Srb144127 NV_ENCODE_XDR, 0)) != 0) { 4003733a5356Srb144127 fmd_hdl_error(hdl, "error: FMA event dropped: " 4004b8677b72Srb144127 "event pack errno %d class %s\n", n, class); 4005733a5356Srb144127 etm_stats.etm_os_nvlist_pack_fail.fmds_value.ui64++; 4006733a5356Srb144127 etm_stats.etm_wr_drop_fmaevent.fmds_value.ui64++; 4007733a5356Srb144127 fmd_hdl_free(hdl, buf, buflen); 4008733a5356Srb144127 return; 4009733a5356Srb144127 } 4010733a5356Srb144127 4011733a5356Srb144127 /* get vector of dst addrs and send the FMA event to each one */ 4012733a5356Srb144127 4013733a5356Srb144127 if ((addrv = etm_xport_get_ev_addrv(hdl, evp)) == NULL) { 4014733a5356Srb144127 fmd_hdl_error(hdl, "error: FMA event dropped: " 4015733a5356Srb144127 "bad event dst addrs errno %d\n", errno); 4016733a5356Srb144127 etm_stats.etm_xport_get_ev_addrv_fail.fmds_value.ui64++; 4017733a5356Srb144127 etm_stats.etm_wr_drop_fmaevent.fmds_value.ui64++; 4018733a5356Srb144127 fmd_hdl_free(hdl, buf, buflen); 4019733a5356Srb144127 return; 4020733a5356Srb144127 } 4021733a5356Srb144127 4022733a5356Srb144127 for (i = 0; addrv[i] != NULL; i++) { 4023733a5356Srb144127 4024733a5356Srb144127 /* open a new connection to this dst addr */ 4025733a5356Srb144127 4026733a5356Srb144127 if ((n = etm_conn_open(hdl, "FMA event dropped: " 4027b8677b72Srb144127 "bad conn open on new ev", addrv[i], &conn)) < 0) { 4028733a5356Srb144127 etm_stats.etm_wr_drop_fmaevent.fmds_value.ui64++; 4029733a5356Srb144127 continue; 4030733a5356Srb144127 } 4031733a5356Srb144127 40322ae66659Sjrutt (void) pthread_mutex_lock(&etm_write_lock); 40332ae66659Sjrutt 4034733a5356Srb144127 /* write the ETM message header */ 4035733a5356Srb144127 4036733a5356Srb144127 if ((hdrp = etm_hdr_write(hdl, conn, evp, NV_ENCODE_XDR, 4037733a5356Srb144127 &sz)) == NULL) { 40382ae66659Sjrutt (void) pthread_mutex_unlock(&etm_write_lock); 4039733a5356Srb144127 fmd_hdl_error(hdl, "error: FMA event dropped: " 4040733a5356Srb144127 "bad hdr write errno %d\n", errno); 4041733a5356Srb144127 (void) etm_conn_close(hdl, 4042733a5356Srb144127 "bad conn close per bad hdr wr", conn); 4043733a5356Srb144127 etm_stats.etm_wr_drop_fmaevent.fmds_value.ui64++; 4044733a5356Srb144127 continue; 4045733a5356Srb144127 } 4046733a5356Srb144127 4047733a5356Srb144127 fmd_hdl_free(hdl, hdrp, sz); /* header not needed */ 4048733a5356Srb144127 etm_stats.etm_wr_hdr_fmaevent.fmds_value.ui64++; 4049733a5356Srb144127 fmd_hdl_debug(hdl, "info: hdr xport write ok for event %p\n", 4050733a5356Srb144127 evp); 4051733a5356Srb144127 4052733a5356Srb144127 /* write the ETM message body, ie, the packed nvlist */ 4053733a5356Srb144127 4054733a5356Srb144127 if ((n = etm_io_op(hdl, "FMA event dropped: " 4055733a5356Srb144127 "bad io write on event", conn, 4056733a5356Srb144127 buf, buflen, ETM_IO_OP_WR)) < 0) { 40572ae66659Sjrutt (void) pthread_mutex_unlock(&etm_write_lock); 4058733a5356Srb144127 (void) etm_conn_close(hdl, 4059733a5356Srb144127 "bad conn close per bad body wr", conn); 4060733a5356Srb144127 etm_stats.etm_wr_drop_fmaevent.fmds_value.ui64++; 4061733a5356Srb144127 continue; 4062733a5356Srb144127 } 4063733a5356Srb144127 40642ae66659Sjrutt (void) pthread_mutex_unlock(&etm_write_lock); 40652ae66659Sjrutt 4066733a5356Srb144127 etm_stats.etm_wr_body_fmaevent.fmds_value.ui64++; 4067733a5356Srb144127 etm_stats.etm_wr_xport_bytes.fmds_value.ui64 += buflen; 4068733a5356Srb144127 fmd_hdl_debug(hdl, "info: body xport write ok for event %p\n", 4069733a5356Srb144127 evp); 4070733a5356Srb144127 4071733a5356Srb144127 /* close the connection */ 4072733a5356Srb144127 4073733a5356Srb144127 (void) etm_conn_close(hdl, "bad conn close after event send", 4074733a5356Srb144127 conn); 4075733a5356Srb144127 } /* foreach dst addr in the vector */ 4076733a5356Srb144127 4077733a5356Srb144127 etm_xport_free_addrv(hdl, addrv); 4078733a5356Srb144127 fmd_hdl_free(hdl, buf, buflen); 4079733a5356Srb144127 4080733a5356Srb144127 } /* etm_recv() */ 4081733a5356Srb144127 408225351652SVuong Nguyen 408325351652SVuong Nguyen /* 408425351652SVuong Nguyen * etm_send - receive an FMA event from FMD and enQ it in the iosvc.Q. 408525351652SVuong Nguyen * etm_send_to_remote_root() deQ and xprt the FMA events to a 408625351652SVuong Nguyen * remote root domain 408725351652SVuong Nguyen * return FMD_SEND_SUCCESS for success, 408825351652SVuong Nguyen * FMD_SEND_FAILED for error 408925351652SVuong Nguyen */ 409025351652SVuong Nguyen 409125351652SVuong Nguyen /*ARGSUSED*/ 409225351652SVuong Nguyen int 409325351652SVuong Nguyen etm_send(fmd_hdl_t *fmd_hdl, fmd_xprt_t *xp, fmd_event_t *ep, nvlist_t *nvl) 409425351652SVuong Nguyen { 409525351652SVuong Nguyen uint32_t pack_it; /* whether to pack/enq the event */ 409625351652SVuong Nguyen etm_pack_msg_type_t msg_type; 409725351652SVuong Nguyen /* tell etm_pack_ds_msg() what to do */ 409825351652SVuong Nguyen etm_iosvc_t *iosvc; /* ptr to cur iosvc struct */ 409925351652SVuong Nguyen char *class; /* nvlist class name */ 410025351652SVuong Nguyen 410125351652SVuong Nguyen pack_it = 1; 410225351652SVuong Nguyen msg_type = FMD_XPRT_OTHER_MSG; 410325351652SVuong Nguyen 410425351652SVuong Nguyen (void) nvlist_lookup_string(nvl, FM_CLASS, &class); 410525351652SVuong Nguyen if (class == NULL) { 410625351652SVuong Nguyen pack_it = 0; 410725351652SVuong Nguyen } else { 410825351652SVuong Nguyen if (etm_debug_lvl >= 1) { 410925351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 411025351652SVuong Nguyen "info: evp class= %s in etm_send\n", class); 411125351652SVuong Nguyen } 411225351652SVuong Nguyen 411325351652SVuong Nguyen if (etm_ldom_type == LDOM_TYPE_CONTROL) { 411425351652SVuong Nguyen iosvc = 411525351652SVuong Nguyen (etm_iosvc_t *)fmd_xprt_getspecific(fmd_hdl, xp); 411625351652SVuong Nguyen 411725351652SVuong Nguyen /* 411825351652SVuong Nguyen * check the flag FORWARDING_FAULTS_TO_CONTROL to 411925351652SVuong Nguyen * decide if or not to drop fault subscription 412025351652SVuong Nguyen * control msgs 412125351652SVuong Nguyen */ 412225351652SVuong Nguyen if (strcmp(class, "resource.fm.xprt.subscribe") == 0) { 412325351652SVuong Nguyen pack_it = 0; 412425351652SVuong Nguyen /* 412525351652SVuong Nguyen * if (FORWARDING_FAULTS_TO_CONTROL == 1) { 412625351652SVuong Nguyen * (void) nvlist_lookup_string(nvl, 412725351652SVuong Nguyen * FM_RSRC_XPRT_SUBCLASS, &subclass); 412825351652SVuong Nguyen * if (strcmp(subclass, "list.suspect") 412925351652SVuong Nguyen * == 0) { 413025351652SVuong Nguyen * pack_it = 1; 413125351652SVuong Nguyen * msg_action = FMD_XPRT_OTHER_MSG; 413225351652SVuong Nguyen * } 413325351652SVuong Nguyen * if (strcmp(subclass, "list.repaired") 413425351652SVuong Nguyen * == 0) { 413525351652SVuong Nguyen * pack_it = 1; 413625351652SVuong Nguyen * msg_action = FMD_XPRT_OTHER_MSG; 413725351652SVuong Nguyen * } 413825351652SVuong Nguyen * } 413925351652SVuong Nguyen */ 414025351652SVuong Nguyen } 414125351652SVuong Nguyen if (strcmp(class, "resource.fm.xprt.run") == 0) { 414225351652SVuong Nguyen pack_it = 1; 414325351652SVuong Nguyen msg_type = FMD_XPRT_RUN_MSG; 414425351652SVuong Nguyen } 414525351652SVuong Nguyen } else { /* has to be the root domain ldom */ 414625351652SVuong Nguyen iosvc = &io_svc; 414725351652SVuong Nguyen /* 414825351652SVuong Nguyen * drop all ereport and fault subscriptions 414925351652SVuong Nguyen * are we dropping too much here, more than just ereport 415025351652SVuong Nguyen * and fault subscriptions? need to check 415125351652SVuong Nguyen */ 415225351652SVuong Nguyen if (strcmp(class, "resource.fm.xprt.subscribe") == 0) 415325351652SVuong Nguyen pack_it = 0; 415425351652SVuong Nguyen if (strcmp(class, "resource.fm.xprt.run") == 0) { 415525351652SVuong Nguyen pack_it = 1; 415625351652SVuong Nguyen msg_type = FMD_XPRT_RUN_MSG; 415725351652SVuong Nguyen } 415825351652SVuong Nguyen } 415925351652SVuong Nguyen } 416025351652SVuong Nguyen 416125351652SVuong Nguyen if (pack_it) { 416225351652SVuong Nguyen if (etm_debug_lvl >= 1) { 416325351652SVuong Nguyen fmd_hdl_debug(fmd_hdl, 416425351652SVuong Nguyen "info: ldom name returned from xprt get specific=" 416525351652SVuong Nguyen "%s xprt=%lld\n", iosvc->ldom_name, xp); 416625351652SVuong Nguyen } 416725351652SVuong Nguyen /* 416825351652SVuong Nguyen * pack the etm msg for the DS library and enq in io_svc->Q 416925351652SVuong Nguyen * when the hdrp is NULL, the packing func will use the static 417025351652SVuong Nguyen * iosvc_hdr 417125351652SVuong Nguyen */ 417225351652SVuong Nguyen (void) etm_pack_ds_msg(fmd_hdl, iosvc, NULL, 0, nvl, msg_type, 417325351652SVuong Nguyen ETM_CKPT_NOOP); 417425351652SVuong Nguyen } 417525351652SVuong Nguyen 417625351652SVuong Nguyen return (FMD_SEND_SUCCESS); 417725351652SVuong Nguyen 417825351652SVuong Nguyen } /* etm_send() */ 417925351652SVuong Nguyen 418025351652SVuong Nguyen 418125351652SVuong Nguyen 4182733a5356Srb144127 /* 4183733a5356Srb144127 * _fmd_fini - stop the server daemon and teardown the transport 4184733a5356Srb144127 */ 4185733a5356Srb144127 4186733a5356Srb144127 void 4187733a5356Srb144127 _fmd_fini(fmd_hdl_t *hdl) 4188733a5356Srb144127 { 4189733a5356Srb144127 ssize_t n; /* gen use */ 419025351652SVuong Nguyen etm_iosvc_t *iosvc; /* ptr to insvc struct */ 419125351652SVuong Nguyen etm_iosvc_q_ele_t msg_ele; /* iosvc msg ele */ 419225351652SVuong Nguyen uint32_t i; /* for loop var */ 4193733a5356Srb144127 4194b8677b72Srb144127 fmd_hdl_debug(hdl, "info: module finalizing\n"); 4195733a5356Srb144127 4196b8677b72Srb144127 /* kill the connection server and responder ; wait for them to die */ 4197733a5356Srb144127 4198733a5356Srb144127 etm_is_dying = 1; 4199733a5356Srb144127 4200733a5356Srb144127 if (etm_svr_tid != NULL) { 4201733a5356Srb144127 fmd_thr_signal(hdl, etm_svr_tid); 4202733a5356Srb144127 fmd_thr_destroy(hdl, etm_svr_tid); 4203733a5356Srb144127 etm_svr_tid = NULL; 4204733a5356Srb144127 } /* if server thread was successfully created */ 4205733a5356Srb144127 4206b8677b72Srb144127 if (etm_resp_tid != NULL) { 4207b8677b72Srb144127 fmd_thr_signal(hdl, etm_resp_tid); 4208b8677b72Srb144127 fmd_thr_destroy(hdl, etm_resp_tid); 4209b8677b72Srb144127 etm_resp_tid = NULL; 4210b8677b72Srb144127 } /* if responder thread was successfully created */ 4211b8677b72Srb144127 421225351652SVuong Nguyen if (etm_async_e_tid != NULL) { 421325351652SVuong Nguyen fmd_thr_signal(hdl, etm_async_e_tid); 421425351652SVuong Nguyen fmd_thr_destroy(hdl, etm_async_e_tid); 421525351652SVuong Nguyen etm_async_e_tid = NULL; 421625351652SVuong Nguyen } /* if async event handler thread was successfully created */ 4217733a5356Srb144127 421825351652SVuong Nguyen 421925351652SVuong Nguyen if ((etm_ldom_type == LDOM_TYPE_LEGACY) || 422025351652SVuong Nguyen (etm_ldom_type == LDOM_TYPE_CONTROL)) { 422125351652SVuong Nguyen 422225351652SVuong Nguyen /* teardown the transport and cleanup syslogging */ 4223733a5356Srb144127 if ((n = etm_xport_fini(hdl)) != 0) { 422425351652SVuong Nguyen fmd_hdl_error(hdl, "warning: xport fini errno %d\n", 422525351652SVuong Nguyen (-n)); 4226733a5356Srb144127 } 422700ab1250Srb144127 if (etm_fmd_xprt != NULL) { 422800ab1250Srb144127 fmd_xprt_close(hdl, etm_fmd_xprt); 422900ab1250Srb144127 } 4230733a5356Srb144127 42314b476ed5Sdarudy if (syslog_logfd != -1) { 42324b476ed5Sdarudy (void) close(syslog_logfd); 42334b476ed5Sdarudy } 42344b476ed5Sdarudy if (syslog_msgfd != -1) { 42354b476ed5Sdarudy (void) close(syslog_msgfd); 42364b476ed5Sdarudy } 423725351652SVuong Nguyen } 423825351652SVuong Nguyen 423925351652SVuong Nguyen if (etm_ldom_type == LDOM_TYPE_CONTROL) { 424025351652SVuong Nguyen if (ldom_unregister_event(etm_lhp)) 424125351652SVuong Nguyen fmd_hdl_debug(hdl, "ldom_unregister_event() failed\n"); 424225351652SVuong Nguyen 424325351652SVuong Nguyen /* 4244d279c7bfSVuong Nguyen * On control domain side, there may be multiple iosvc struct 4245d279c7bfSVuong Nguyen * in use, one for each bound/active domain. Each struct 4246d279c7bfSVuong Nguyen * manages a queue of fma events destined to the root domain. 4247d279c7bfSVuong Nguyen * Need to go thru every iosvc struct to clean up its resources. 424825351652SVuong Nguyen */ 424925351652SVuong Nguyen for (i = 0; i < NUM_OF_ROOT_DOMAINS; i++) { 425025351652SVuong Nguyen if (iosvc_list[i].ldom_name[0] != '\0') { 425125351652SVuong Nguyen /* 425225351652SVuong Nguyen * found an iosvc struct for a root domain 425325351652SVuong Nguyen */ 425425351652SVuong Nguyen iosvc = &iosvc_list[i]; 425525351652SVuong Nguyen (void) pthread_mutex_lock(&iosvc_list_lock); 4256d279c7bfSVuong Nguyen etm_iosvc_cleanup(hdl, iosvc, B_TRUE, B_FALSE); 425725351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc_list_lock); 425825351652SVuong Nguyen 425925351652SVuong Nguyen } else { 426025351652SVuong Nguyen /* 426125351652SVuong Nguyen * reach the end of existing iosvc structures 426225351652SVuong Nguyen */ 426325351652SVuong Nguyen continue; 426425351652SVuong Nguyen } 426525351652SVuong Nguyen } /* for i<NUM_OF_ROOT_DOMAINS */ 426625351652SVuong Nguyen etm_ckpt_fini(hdl); 426725351652SVuong Nguyen etm_filter_fini(hdl); 426825351652SVuong Nguyen 426925351652SVuong Nguyen ldom_fini(etm_lhp); 427025351652SVuong Nguyen 427125351652SVuong Nguyen } else if (etm_ldom_type == LDOM_TYPE_ROOT) { 4272d279c7bfSVuong Nguyen /* 4273d279c7bfSVuong Nguyen * On root domain side, there is only one iosvc struct in use. 4274d279c7bfSVuong Nguyen */ 427525351652SVuong Nguyen iosvc = &io_svc; 427625351652SVuong Nguyen if (iosvc->send_tid != NULL) { 427725351652SVuong Nguyen fmd_thr_signal(hdl, iosvc->send_tid); 427825351652SVuong Nguyen fmd_thr_destroy(hdl, iosvc->send_tid); 427925351652SVuong Nguyen iosvc->send_tid = NULL; 428025351652SVuong Nguyen } /* if io svc send thread was successfully created */ 428125351652SVuong Nguyen 428225351652SVuong Nguyen if (iosvc->recv_tid != NULL) { 428325351652SVuong Nguyen fmd_thr_signal(hdl, iosvc->recv_tid); 428425351652SVuong Nguyen fmd_thr_destroy(hdl, iosvc->recv_tid); 428525351652SVuong Nguyen iosvc->recv_tid = NULL; 428625351652SVuong Nguyen } /* if io svc receive thread was successfully created */ 428725351652SVuong Nguyen 428825351652SVuong Nguyen (void) pthread_mutex_lock(&iosvc->msg_q_lock); 428925351652SVuong Nguyen while (iosvc->msg_q_cur_len > 0) { 429025351652SVuong Nguyen (void) etm_iosvc_msg_deq(hdl, iosvc, &msg_ele); 429125351652SVuong Nguyen fmd_hdl_free(hdl, msg_ele.msg, msg_ele.msg_size); 429225351652SVuong Nguyen } 429325351652SVuong Nguyen (void) pthread_mutex_unlock(&iosvc->msg_q_lock); 429425351652SVuong Nguyen 429525351652SVuong Nguyen if (iosvc->fmd_xprt != NULL) 429625351652SVuong Nguyen fmd_xprt_close(hdl, iosvc->fmd_xprt); 429725351652SVuong Nguyen ldom_fini(etm_lhp); 429825351652SVuong Nguyen } 429925351652SVuong Nguyen if (etm_ds_fini) { 430025351652SVuong Nguyen (*etm_ds_fini)(); 430125351652SVuong Nguyen (void) dlclose(etm_dl_hdl); 430225351652SVuong Nguyen } 43034b476ed5Sdarudy 4304733a5356Srb144127 fmd_hdl_debug(hdl, "info: module finalized ok\n"); 4305733a5356Srb144127 4306733a5356Srb144127 } /* _fmd_fini() */ 4307