1d71dbb73Sjbeck /*
2d71dbb73Sjbeck  * CDDL HEADER START
3d71dbb73Sjbeck  *
4d71dbb73Sjbeck  * The contents of this file are subject to the terms of the
5d71dbb73Sjbeck  * Common Development and Distribution License (the "License").
6d71dbb73Sjbeck  * You may not use this file except in compliance with the License.
7d71dbb73Sjbeck  *
8d71dbb73Sjbeck  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d71dbb73Sjbeck  * or http://www.opensolaris.org/os/licensing.
10d71dbb73Sjbeck  * See the License for the specific language governing permissions
11d71dbb73Sjbeck  * and limitations under the License.
12d71dbb73Sjbeck  *
13d71dbb73Sjbeck  * When distributing Covered Code, include this CDDL HEADER in each
14d71dbb73Sjbeck  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d71dbb73Sjbeck  * If applicable, add the following below this CDDL HEADER, with the
16d71dbb73Sjbeck  * fields enclosed by brackets "[]" replaced with your own identifying
17d71dbb73Sjbeck  * information: Portions Copyright [yyyy] [name of copyright owner]
18d71dbb73Sjbeck  *
19d71dbb73Sjbeck  * CDDL HEADER END
20d71dbb73Sjbeck  */
21d71dbb73Sjbeck 
22d71dbb73Sjbeck /*
23*f6da83d4SAnurag S. Maskey  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24d71dbb73Sjbeck  */
25d71dbb73Sjbeck 
266ba597c5SAnurag S. Maskey #include <atomic.h>
27d71dbb73Sjbeck #include <errno.h>
286ba597c5SAnurag S. Maskey #include <execinfo.h>
296ba597c5SAnurag S. Maskey #include <libuutil.h>
30d71dbb73Sjbeck #include <pthread.h>
316ba597c5SAnurag S. Maskey #include <signal.h>
32d71dbb73Sjbeck #include <stdlib.h>
33d71dbb73Sjbeck #include <string.h>
346ba597c5SAnurag S. Maskey #include <strings.h>
35d71dbb73Sjbeck #include <syslog.h>
366ba597c5SAnurag S. Maskey #include <sys/time.h>
37d71dbb73Sjbeck #include <unistd.h>
38d71dbb73Sjbeck 
396ba597c5SAnurag S. Maskey #include "conditions.h"
406ba597c5SAnurag S. Maskey #include "events.h"
416ba597c5SAnurag S. Maskey #include "objects.h"
426ba597c5SAnurag S. Maskey #include "util.h"
43d71dbb73Sjbeck 
446ba597c5SAnurag S. Maskey /*
456ba597c5SAnurag S. Maskey  * events.c - contains routines which create/destroy event sources,
466ba597c5SAnurag S. Maskey  * handle the event queue and process events from that queue.
476ba597c5SAnurag S. Maskey  */
48d71dbb73Sjbeck 
496ba597c5SAnurag S. Maskey /* Add new event sources here. */
506ba597c5SAnurag S. Maskey struct nwamd_event_source {
516ba597c5SAnurag S. Maskey 	char *name;
526ba597c5SAnurag S. Maskey 	void (*events_init)(void);
536ba597c5SAnurag S. Maskey 	void (*events_fini)(void);
546ba597c5SAnurag S. Maskey } event_sources[] = {
556ba597c5SAnurag S. Maskey 	{ "routing_events",
566ba597c5SAnurag S. Maskey 	nwamd_routing_events_init, nwamd_routing_events_fini },
576ba597c5SAnurag S. Maskey 	{ "sysevent_events",
586ba597c5SAnurag S. Maskey 	nwamd_sysevent_events_init, nwamd_sysevent_events_fini },
596ba597c5SAnurag S. Maskey };
60d71dbb73Sjbeck 
616ba597c5SAnurag S. Maskey /* Counter for event ids */
626ba597c5SAnurag S. Maskey static uint64_t event_id_counter = 0;
63b00044a2SJames Carlson 
646ba597c5SAnurag S. Maskey static uu_list_pool_t *event_pool = NULL;
656ba597c5SAnurag S. Maskey static uu_list_t *event_queue = NULL;
666ba597c5SAnurag S. Maskey static pthread_mutex_t event_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
676ba597c5SAnurag S. Maskey static pthread_cond_t event_queue_cond = PTHREAD_COND_INITIALIZER;
68d71dbb73Sjbeck 
696ba597c5SAnurag S. Maskey static int nwamd_event_compare(const void *, const void *, void *);
706ba597c5SAnurag S. Maskey 
716ba597c5SAnurag S. Maskey static const char *
nwamd_event_name(int event_type)726ba597c5SAnurag S. Maskey nwamd_event_name(int event_type)
73d71dbb73Sjbeck {
746ba597c5SAnurag S. Maskey 	if (event_type <= NWAM_EVENT_MAX)
756ba597c5SAnurag S. Maskey 		return (nwam_event_type_to_string(event_type));
766ba597c5SAnurag S. Maskey 
776ba597c5SAnurag S. Maskey 	switch (event_type) {
786ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_OBJECT_INIT:
796ba597c5SAnurag S. Maskey 		return ("OBJECT_INIT");
806ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_OBJECT_FINI:
816ba597c5SAnurag S. Maskey 		return ("OBJECT_FINI");
826ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS:
836ba597c5SAnurag S. Maskey 		return ("TIMED_CHECK_CONDITIONS");
846ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS:
856ba597c5SAnurag S. Maskey 		return ("TRIGGERED_CHECK_CONDITIONS");
866ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_NCU_CHECK:
876ba597c5SAnurag S. Maskey 		return ("NCU_CHECK");
886ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_TIMER:
896ba597c5SAnurag S. Maskey 		return ("TIMER");
906ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_UPGRADE:
916ba597c5SAnurag S. Maskey 		return ("UPGRADE");
926ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_PERIODIC_SCAN:
936ba597c5SAnurag S. Maskey 		return ("PERIODIC_SCAN");
946ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_QUEUE_QUIET:
956ba597c5SAnurag S. Maskey 		return ("QUEUE_QUIET");
966ba597c5SAnurag S. Maskey 	default:
976ba597c5SAnurag S. Maskey 		return ("N/A");
986ba597c5SAnurag S. Maskey 	}
996ba597c5SAnurag S. Maskey }
100d71dbb73Sjbeck 
101d71dbb73Sjbeck void
nwamd_event_sources_init(void)1026ba597c5SAnurag S. Maskey nwamd_event_sources_init(void)
103d71dbb73Sjbeck {
1046ba597c5SAnurag S. Maskey 	int i;
1056ba597c5SAnurag S. Maskey 
1066ba597c5SAnurag S. Maskey 	/*
1076ba597c5SAnurag S. Maskey 	 * Now we can safely initialize event sources.
1086ba597c5SAnurag S. Maskey 	 */
1096ba597c5SAnurag S. Maskey 	for (i = 0;
1106ba597c5SAnurag S. Maskey 	    i < sizeof (event_sources) / sizeof (struct nwamd_event_source);
1116ba597c5SAnurag S. Maskey 	    i++) {
1126ba597c5SAnurag S. Maskey 		if (event_sources[i].events_init != NULL)
1136ba597c5SAnurag S. Maskey 			event_sources[i].events_init();
1146ba597c5SAnurag S. Maskey 	}
115d71dbb73Sjbeck }
116d71dbb73Sjbeck 
1176ba597c5SAnurag S. Maskey void
nwamd_event_sources_fini(void)1186ba597c5SAnurag S. Maskey nwamd_event_sources_fini(void)
119d71dbb73Sjbeck {
1206ba597c5SAnurag S. Maskey 	int i;
121b00044a2SJames Carlson 
1226ba597c5SAnurag S. Maskey 	for (i = 0;
1236ba597c5SAnurag S. Maskey 	    i < sizeof (event_sources) / sizeof (struct nwamd_event_source);
1246ba597c5SAnurag S. Maskey 	    i++) {
1256ba597c5SAnurag S. Maskey 		if (event_sources[i].events_init != NULL)
1266ba597c5SAnurag S. Maskey 			event_sources[i].events_fini();
127d71dbb73Sjbeck 	}
128d71dbb73Sjbeck }
129d71dbb73Sjbeck 
130d71dbb73Sjbeck /*
1316ba597c5SAnurag S. Maskey  * Comparison function for events, passed in as callback to
1326ba597c5SAnurag S. Maskey  * uu_list_pool_create(). Compare by time, so that timer
1336ba597c5SAnurag S. Maskey  * event queue can be sorted by nearest time to present.
134d71dbb73Sjbeck  */
1356ba597c5SAnurag S. Maskey /* ARGSUSED */
1366ba597c5SAnurag S. Maskey static int
nwamd_event_compare(const void * l_arg,const void * r_arg,void * private)1376ba597c5SAnurag S. Maskey nwamd_event_compare(const void *l_arg, const void *r_arg, void *private)
138d71dbb73Sjbeck {
1396ba597c5SAnurag S. Maskey 	nwamd_event_t l = (nwamd_event_t)l_arg;
1406ba597c5SAnurag S. Maskey 	nwamd_event_t r = (nwamd_event_t)r_arg;
1416ba597c5SAnurag S. Maskey 	int rv;
142d71dbb73Sjbeck 
1436ba597c5SAnurag S. Maskey 	rv = l->event_time.tv_sec - r->event_time.tv_sec;
1446ba597c5SAnurag S. Maskey 	if (rv == 0)
1456ba597c5SAnurag S. Maskey 		rv = l->event_time.tv_nsec - r->event_time.tv_nsec;
146d71dbb73Sjbeck 
147d71dbb73Sjbeck 	return (rv);
148d71dbb73Sjbeck }
149d71dbb73Sjbeck 
1506ba597c5SAnurag S. Maskey void
nwamd_event_queue_init(void)1516ba597c5SAnurag S. Maskey nwamd_event_queue_init(void)
152d71dbb73Sjbeck {
1536ba597c5SAnurag S. Maskey 	event_pool = uu_list_pool_create("event_queue_pool",
1546ba597c5SAnurag S. Maskey 	    sizeof (struct nwamd_event),
1556ba597c5SAnurag S. Maskey 	    offsetof(struct nwamd_event, event_node),
1566ba597c5SAnurag S. Maskey 	    nwamd_event_compare, UU_LIST_POOL_DEBUG);
1576ba597c5SAnurag S. Maskey 	if (event_pool == NULL)
1586ba597c5SAnurag S. Maskey 		pfail("uu_list_pool_create failed with error %d", uu_error());
1596ba597c5SAnurag S. Maskey 	event_queue = uu_list_create(event_pool, NULL, UU_LIST_SORTED);
1606ba597c5SAnurag S. Maskey 	if (event_queue == NULL)
1616ba597c5SAnurag S. Maskey 		pfail("uu_list_create failed with error %d", uu_error());
162d71dbb73Sjbeck }
163d71dbb73Sjbeck 
1646ba597c5SAnurag S. Maskey void
nwamd_event_queue_fini(void)1656ba597c5SAnurag S. Maskey nwamd_event_queue_fini(void)
166d71dbb73Sjbeck {
1676ba597c5SAnurag S. Maskey 	void *cookie = NULL;
1686ba597c5SAnurag S. Maskey 	nwamd_event_t event;
1696ba597c5SAnurag S. Maskey 
1706ba597c5SAnurag S. Maskey 	while ((event = uu_list_teardown(event_queue, &cookie)) != NULL)
1716ba597c5SAnurag S. Maskey 		nwamd_event_fini(event);
1726ba597c5SAnurag S. Maskey 	uu_list_destroy(event_queue);
1736ba597c5SAnurag S. Maskey 	if (event_pool != NULL)
1746ba597c5SAnurag S. Maskey 		uu_list_pool_destroy(event_pool);
175d71dbb73Sjbeck }
176d71dbb73Sjbeck 
1776ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init(int32_t type,nwam_object_type_t object_type,size_t size,const char * object_name)1786ba597c5SAnurag S. Maskey nwamd_event_init(int32_t type, nwam_object_type_t object_type,
1796ba597c5SAnurag S. Maskey     size_t size, const char *object_name)
180b00044a2SJames Carlson {
1816ba597c5SAnurag S. Maskey 	nwamd_event_t event;
1826ba597c5SAnurag S. Maskey 
1836ba597c5SAnurag S. Maskey 	event = calloc(1, sizeof (struct nwamd_event));
1846ba597c5SAnurag S. Maskey 	if (event == NULL) {
1856ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_event_init: could not create %s event for "
1866ba597c5SAnurag S. Maskey 		    "object %s", nwamd_event_name(type),
1876ba597c5SAnurag S. Maskey 		    object_name != NULL ? object_name : "<no object>");
1886ba597c5SAnurag S. Maskey 		return (NULL);
189b00044a2SJames Carlson 	}
190b00044a2SJames Carlson 
1916ba597c5SAnurag S. Maskey 	/* Is this an externally-visible event? */
1926ba597c5SAnurag S. Maskey 	if (type <= NWAM_EVENT_MAX) {
1936ba597c5SAnurag S. Maskey 		event->event_send = B_TRUE;
1946ba597c5SAnurag S. Maskey 		event->event_msg = calloc(1, sizeof (struct nwam_event) + size);
1956ba597c5SAnurag S. Maskey 		if (event->event_msg == NULL) {
1966ba597c5SAnurag S. Maskey 			nlog(LOG_ERR,
1976ba597c5SAnurag S. Maskey 			    "nwamd_event_init: could not create %s event",
1986ba597c5SAnurag S. Maskey 			    nwamd_event_name(type));
1996ba597c5SAnurag S. Maskey 			free(event);
2006ba597c5SAnurag S. Maskey 			return (NULL);
2016ba597c5SAnurag S. Maskey 		}
2026ba597c5SAnurag S. Maskey 		event->event_msg->nwe_type = type;
2036ba597c5SAnurag S. Maskey 		event->event_msg->nwe_size = sizeof (struct nwam_event) + size;
2046ba597c5SAnurag S. Maskey 	} else {
2056ba597c5SAnurag S. Maskey 		event->event_send = B_FALSE;
2066ba597c5SAnurag S. Maskey 		event->event_msg = NULL;
207b00044a2SJames Carlson 	}
2086ba597c5SAnurag S. Maskey 
2096ba597c5SAnurag S. Maskey 	event->event_type = type;
2106ba597c5SAnurag S. Maskey 
2116ba597c5SAnurag S. Maskey 	if (object_name != NULL) {
2126ba597c5SAnurag S. Maskey 		(void) strlcpy(event->event_object, object_name,
2136ba597c5SAnurag S. Maskey 		    NWAM_MAX_NAME_LEN);
2146ba597c5SAnurag S. Maskey 		event->event_object_type = object_type;
215b00044a2SJames Carlson 	} else {
2166ba597c5SAnurag S. Maskey 		event->event_object[0] = '\0';
217b00044a2SJames Carlson 	}
2186ba597c5SAnurag S. Maskey 
2196ba597c5SAnurag S. Maskey 	/* Set event id */
2206ba597c5SAnurag S. Maskey 	event->event_id = atomic_add_64_nv(&event_id_counter, 1);
2216ba597c5SAnurag S. Maskey 	(void) clock_gettime(CLOCK_REALTIME, &event->event_time);
2226ba597c5SAnurag S. Maskey 
2236ba597c5SAnurag S. Maskey 	return (event);
224b00044a2SJames Carlson }
225b00044a2SJames Carlson 
2266ba597c5SAnurag S. Maskey void
nwamd_event_do_not_send(nwamd_event_t event)2276ba597c5SAnurag S. Maskey nwamd_event_do_not_send(nwamd_event_t event)
228b00044a2SJames Carlson {
2296ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_event_do_not_send: cancelling delivery of "
2306ba597c5SAnurag S. Maskey 	    "event %s for object %s", nwamd_event_name(event->event_type),
2316ba597c5SAnurag S. Maskey 	    event->event_object[0] != '\0' ?
2326ba597c5SAnurag S. Maskey 	    event->event_object : "<no object>");
2336ba597c5SAnurag S. Maskey 	event->event_send = B_FALSE;
234b00044a2SJames Carlson }
235b00044a2SJames Carlson 
2366ba597c5SAnurag S. Maskey void
nwamd_event_fini(nwamd_event_t event)2376ba597c5SAnurag S. Maskey nwamd_event_fini(nwamd_event_t event)
238b00044a2SJames Carlson {
2396ba597c5SAnurag S. Maskey 	if (event != NULL) {
2406ba597c5SAnurag S. Maskey 		free(event->event_msg);
2416ba597c5SAnurag S. Maskey 		free(event);
242b00044a2SJames Carlson 	}
2436ba597c5SAnurag S. Maskey }
2446ba597c5SAnurag S. Maskey 
2456ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_object_action(nwam_object_type_t object_type,const char * object_name,const char * parent_name,nwam_action_t object_action)2466ba597c5SAnurag S. Maskey nwamd_event_init_object_action(nwam_object_type_t object_type,
2476ba597c5SAnurag S. Maskey     const char *object_name, const char *parent_name,
2486ba597c5SAnurag S. Maskey     nwam_action_t object_action)
2496ba597c5SAnurag S. Maskey {
2506ba597c5SAnurag S. Maskey 	nwamd_event_t event;
2516ba597c5SAnurag S. Maskey 
2526ba597c5SAnurag S. Maskey 	event = nwamd_event_init(NWAM_EVENT_TYPE_OBJECT_ACTION,
2536ba597c5SAnurag S. Maskey 	    object_type, 0, object_name);
2546ba597c5SAnurag S. Maskey 	if (event == NULL)
2556ba597c5SAnurag S. Maskey 		return (NULL);
2566ba597c5SAnurag S. Maskey 
2576ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_object_action.nwe_action = object_action;
2586ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_object_action.nwe_object_type =
2596ba597c5SAnurag S. Maskey 	    object_type;
2606ba597c5SAnurag S. Maskey 	(void) strlcpy(event->event_msg->nwe_data.nwe_object_action.nwe_name,
2616ba597c5SAnurag S. Maskey 	    object_name,
2626ba597c5SAnurag S. Maskey 	    sizeof (event->event_msg->nwe_data.nwe_object_action.nwe_name));
2636ba597c5SAnurag S. Maskey 	if (parent_name == NULL) {
2646ba597c5SAnurag S. Maskey 		event->event_msg->nwe_data.nwe_object_action.nwe_parent[0] =
2656ba597c5SAnurag S. Maskey 		    '\0';
2666ba597c5SAnurag S. Maskey 		return (event);
267b00044a2SJames Carlson 	}
2686ba597c5SAnurag S. Maskey 	(void) strlcpy
2696ba597c5SAnurag S. Maskey 	    (event->event_msg->nwe_data.nwe_object_action.nwe_parent,
2706ba597c5SAnurag S. Maskey 	    parent_name,
2716ba597c5SAnurag S. Maskey 	    sizeof (event->event_msg->nwe_data.nwe_object_action.nwe_parent));
2726ba597c5SAnurag S. Maskey 	return (event);
273b00044a2SJames Carlson }
274b00044a2SJames Carlson 
2756ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_object_state(nwam_object_type_t object_type,const char * object_name,nwam_state_t state,nwam_aux_state_t aux_state)2766ba597c5SAnurag S. Maskey nwamd_event_init_object_state(nwam_object_type_t object_type,
2776ba597c5SAnurag S. Maskey     const char *object_name, nwam_state_t state, nwam_aux_state_t aux_state)
278d71dbb73Sjbeck {
2796ba597c5SAnurag S. Maskey 	nwamd_event_t event;
280d71dbb73Sjbeck 
2816ba597c5SAnurag S. Maskey 	event = nwamd_event_init(NWAM_EVENT_TYPE_OBJECT_STATE,
2826ba597c5SAnurag S. Maskey 	    object_type, 0, object_name);
2836ba597c5SAnurag S. Maskey 	if (event == NULL)
2846ba597c5SAnurag S. Maskey 		return (NULL);
2856ba597c5SAnurag S. Maskey 
2866ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_object_state.nwe_state = state;
2876ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_object_state.nwe_aux_state = aux_state;
2886ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_object_state.nwe_object_type =
2896ba597c5SAnurag S. Maskey 	    object_type;
2906ba597c5SAnurag S. Maskey 	(void) strlcpy(event->event_msg->nwe_data.nwe_object_state.nwe_name,
2916ba597c5SAnurag S. Maskey 	    object_name,
2926ba597c5SAnurag S. Maskey 	    sizeof (event->event_msg->nwe_data.nwe_object_state.nwe_name));
2936ba597c5SAnurag S. Maskey 
2946ba597c5SAnurag S. Maskey 	return (event);
2956ba597c5SAnurag S. Maskey }
2966ba597c5SAnurag S. Maskey 
2976ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_priority_group_change(int64_t priority)2986ba597c5SAnurag S. Maskey nwamd_event_init_priority_group_change(int64_t priority)
2996ba597c5SAnurag S. Maskey {
3006ba597c5SAnurag S. Maskey 	nwamd_event_t event;
3016ba597c5SAnurag S. Maskey 
3026ba597c5SAnurag S. Maskey 	event = nwamd_event_init(NWAM_EVENT_TYPE_PRIORITY_GROUP,
3036ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL);
3046ba597c5SAnurag S. Maskey 	if (event == NULL)
3056ba597c5SAnurag S. Maskey 		return (NULL);
3066ba597c5SAnurag S. Maskey 
3076ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_priority_group_info.nwe_priority =
3086ba597c5SAnurag S. Maskey 	    priority;
3096ba597c5SAnurag S. Maskey 
3106ba597c5SAnurag S. Maskey 	return (event);
3116ba597c5SAnurag S. Maskey }
3126ba597c5SAnurag S. Maskey 
3136ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_link_action(const char * name,nwam_action_t link_action)3146ba597c5SAnurag S. Maskey nwamd_event_init_link_action(const char *name, nwam_action_t link_action)
3156ba597c5SAnurag S. Maskey {
3166ba597c5SAnurag S. Maskey 	nwamd_event_t event;
3176ba597c5SAnurag S. Maskey 	nwam_error_t err;
3186ba597c5SAnurag S. Maskey 	char *object_name;
3196ba597c5SAnurag S. Maskey 
3206ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_name_to_typed_name(name, NWAM_NCU_TYPE_LINK,
3216ba597c5SAnurag S. Maskey 	    &object_name)) != NWAM_SUCCESS) {
3226ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_event_init_link_action: "
3236ba597c5SAnurag S. Maskey 		    "nwam_ncu_name_to_typed_name: %s",
3246ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
3256ba597c5SAnurag S. Maskey 		return (NULL);
326d71dbb73Sjbeck 	}
3276ba597c5SAnurag S. Maskey 	event = nwamd_event_init(NWAM_EVENT_TYPE_LINK_ACTION,
3286ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_NCU, 0, object_name);
3296ba597c5SAnurag S. Maskey 	free(object_name);
3306ba597c5SAnurag S. Maskey 	if (event == NULL)
3316ba597c5SAnurag S. Maskey 		return (NULL);
332d71dbb73Sjbeck 
3336ba597c5SAnurag S. Maskey 	(void) strlcpy(event->event_msg->nwe_data.nwe_link_action.nwe_name,
3346ba597c5SAnurag S. Maskey 	    name,
3356ba597c5SAnurag S. Maskey 	    sizeof (event->event_msg->nwe_data.nwe_link_action.nwe_name));
3366ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_link_action.nwe_action = link_action;
337d71dbb73Sjbeck 
3386ba597c5SAnurag S. Maskey 	return (event);
3396ba597c5SAnurag S. Maskey }
340d71dbb73Sjbeck 
3416ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_link_state(const char * name,boolean_t up)3426ba597c5SAnurag S. Maskey nwamd_event_init_link_state(const char *name, boolean_t up)
3436ba597c5SAnurag S. Maskey {
3446ba597c5SAnurag S. Maskey 	nwamd_event_t event;
3456ba597c5SAnurag S. Maskey 	nwam_error_t err;
3466ba597c5SAnurag S. Maskey 	char *object_name;
3476ba597c5SAnurag S. Maskey 
3486ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_name_to_typed_name(name, NWAM_NCU_TYPE_LINK,
3496ba597c5SAnurag S. Maskey 	    &object_name)) != NWAM_SUCCESS) {
3506ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_event_init_link_state: "
3516ba597c5SAnurag S. Maskey 		    "nwam_ncu_name_to_typed_name: %s",
3526ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
3536ba597c5SAnurag S. Maskey 		return (NULL);
3546ba597c5SAnurag S. Maskey 	}
355d71dbb73Sjbeck 
3566ba597c5SAnurag S. Maskey 	event = nwamd_event_init(NWAM_EVENT_TYPE_LINK_STATE,
3576ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_NCU, 0, object_name);
3586ba597c5SAnurag S. Maskey 	free(object_name);
3596ba597c5SAnurag S. Maskey 	if (event == NULL)
3606ba597c5SAnurag S. Maskey 		return (NULL);
361d71dbb73Sjbeck 
3626ba597c5SAnurag S. Maskey 	(void) strlcpy(event->event_msg->nwe_data.nwe_link_state.nwe_name, name,
3636ba597c5SAnurag S. Maskey 	    sizeof (event->event_msg->nwe_data.nwe_link_state.nwe_name));
3646ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_link_state.nwe_link_up = up;
365d71dbb73Sjbeck 
3666ba597c5SAnurag S. Maskey 	return (event);
3676ba597c5SAnurag S. Maskey }
368d71dbb73Sjbeck 
3696ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_if_state(const char * linkname,uint32_t flags,uint32_t addr_added,struct sockaddr * addr,struct sockaddr * netmask)3706ba597c5SAnurag S. Maskey nwamd_event_init_if_state(const char *linkname, uint32_t flags,
371*f6da83d4SAnurag S. Maskey     uint32_t addr_added, struct sockaddr *addr, struct sockaddr *netmask)
3726ba597c5SAnurag S. Maskey {
3736ba597c5SAnurag S. Maskey 	nwamd_event_t event;
3746ba597c5SAnurag S. Maskey 	nwam_error_t err;
3756ba597c5SAnurag S. Maskey 	char *object_name;
3766ba597c5SAnurag S. Maskey 
3776ba597c5SAnurag S. Maskey 	/* linkname does not contain the lifnum */
3786ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_name_to_typed_name(linkname,
3796ba597c5SAnurag S. Maskey 	    NWAM_NCU_TYPE_INTERFACE, &object_name)) != NWAM_SUCCESS) {
3806ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_event_init_if_state: "
3816ba597c5SAnurag S. Maskey 		    "nwam_ncu_name_to_typed_name: %s",
3826ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
3836ba597c5SAnurag S. Maskey 		return (NULL);
3846ba597c5SAnurag S. Maskey 	}
385b00044a2SJames Carlson 
3866ba597c5SAnurag S. Maskey 	event = nwamd_event_init(NWAM_EVENT_TYPE_IF_STATE,
3876ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_NCU, 0, object_name);
3886ba597c5SAnurag S. Maskey 	free(object_name);
3896ba597c5SAnurag S. Maskey 	if (event == NULL)
3906ba597c5SAnurag S. Maskey 		return (NULL);
391b00044a2SJames Carlson 
3926ba597c5SAnurag S. Maskey 	(void) strlcpy(event->event_msg->nwe_data.nwe_if_state.nwe_name,
3936ba597c5SAnurag S. Maskey 	    linkname,
3946ba597c5SAnurag S. Maskey 	    sizeof (event->event_msg->nwe_data.nwe_if_state.nwe_name));
3956ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_if_state.nwe_flags = flags;
3966ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_if_state.nwe_addr_added = addr_added;
3976ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_if_state.nwe_addr_valid = (addr != NULL);
3986ba597c5SAnurag S. Maskey 
3996ba597c5SAnurag S. Maskey 	if (addr != NULL) {
4006ba597c5SAnurag S. Maskey 		bcopy(addr, &(event->event_msg->nwe_data.nwe_if_state.nwe_addr),
4016ba597c5SAnurag S. Maskey 		    addr->sa_family == AF_INET ? sizeof (struct sockaddr_in) :
4026ba597c5SAnurag S. Maskey 		    sizeof (struct sockaddr_in6));
4036ba597c5SAnurag S. Maskey 	}
404*f6da83d4SAnurag S. Maskey 	if (netmask != NULL) {
405*f6da83d4SAnurag S. Maskey 		bcopy(netmask,
406*f6da83d4SAnurag S. Maskey 		    &(event->event_msg->nwe_data.nwe_if_state.nwe_netmask),
407*f6da83d4SAnurag S. Maskey 		    netmask->sa_family == AF_INET ?
408*f6da83d4SAnurag S. Maskey 		    sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6));
409*f6da83d4SAnurag S. Maskey 	}
410b00044a2SJames Carlson 
4116ba597c5SAnurag S. Maskey 	return (event);
4126ba597c5SAnurag S. Maskey }
413b00044a2SJames Carlson 
4146ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_wlan(const char * name,int32_t type,boolean_t connected,nwam_wlan_t * wlans,uint_t num_wlans)4156ba597c5SAnurag S. Maskey nwamd_event_init_wlan(const char *name, int32_t type, boolean_t connected,
4166ba597c5SAnurag S. Maskey     nwam_wlan_t *wlans, uint_t num_wlans)
4176ba597c5SAnurag S. Maskey {
4186ba597c5SAnurag S. Maskey 	size_t size = 0;
4196ba597c5SAnurag S. Maskey 	char *object_name;
4206ba597c5SAnurag S. Maskey 	nwamd_event_t event;
4216ba597c5SAnurag S. Maskey 	nwam_error_t err;
422b00044a2SJames Carlson 
4236ba597c5SAnurag S. Maskey 	switch (type) {
4246ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_SCAN_REPORT:
4256ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_NEED_CHOICE:
4266ba597c5SAnurag S. Maskey 		size = sizeof (nwam_wlan_t) * (num_wlans - 1);
4276ba597c5SAnurag S. Maskey 		break;
4286ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_NEED_KEY:
4296ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT:
4306ba597c5SAnurag S. Maskey 		break;
4316ba597c5SAnurag S. Maskey 	default:
4326ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_event_init_wlan: unexpected "
4336ba597c5SAnurag S. Maskey 		    "event type %s (%d)", nwamd_event_name(type), type);
4346ba597c5SAnurag S. Maskey 		return (NULL);
4356ba597c5SAnurag S. Maskey 	}
4366ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_name_to_typed_name(name, NWAM_NCU_TYPE_LINK,
4376ba597c5SAnurag S. Maskey 	    &object_name)) != NWAM_SUCCESS) {
4386ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_event_init_wlan: "
4396ba597c5SAnurag S. Maskey 		    "nwam_ncu_name_to_typed_name: %s",
4406ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
4416ba597c5SAnurag S. Maskey 		return (NULL);
4426ba597c5SAnurag S. Maskey 	}
443b00044a2SJames Carlson 
4446ba597c5SAnurag S. Maskey 	event = nwamd_event_init(type, NWAM_OBJECT_TYPE_NCU, size, object_name);
4456ba597c5SAnurag S. Maskey 	free(object_name);
4466ba597c5SAnurag S. Maskey 	if (event == NULL)
4476ba597c5SAnurag S. Maskey 		return (NULL);
448b00044a2SJames Carlson 
4496ba597c5SAnurag S. Maskey 	(void) strlcpy(event->event_msg->nwe_data.nwe_wlan_info.nwe_name, name,
4506ba597c5SAnurag S. Maskey 	    sizeof (event->event_msg->nwe_data.nwe_wlan_info.nwe_name));
4516ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_wlan_info.nwe_connected = connected;
4526ba597c5SAnurag S. Maskey 	event->event_msg->nwe_data.nwe_wlan_info.nwe_num_wlans = num_wlans;
453b00044a2SJames Carlson 
4546ba597c5SAnurag S. Maskey 	/* copy the wlans */
4556ba597c5SAnurag S. Maskey 	(void) memcpy(event->event_msg->nwe_data.nwe_wlan_info.nwe_wlans, wlans,
4566ba597c5SAnurag S. Maskey 	    num_wlans * sizeof (nwam_wlan_t));
457d71dbb73Sjbeck 
4586ba597c5SAnurag S. Maskey 	return (event);
4596ba597c5SAnurag S. Maskey }
460d71dbb73Sjbeck 
4616ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_ncu_check(void)4626ba597c5SAnurag S. Maskey nwamd_event_init_ncu_check(void)
4636ba597c5SAnurag S. Maskey {
4646ba597c5SAnurag S. Maskey 	return (nwamd_event_init(NWAM_EVENT_TYPE_NCU_CHECK,
4656ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_NCP, 0, NULL));
4666ba597c5SAnurag S. Maskey }
467b00044a2SJames Carlson 
4686ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_init(void)4696ba597c5SAnurag S. Maskey nwamd_event_init_init(void)
4706ba597c5SAnurag S. Maskey {
4716ba597c5SAnurag S. Maskey 	return (nwamd_event_init(NWAM_EVENT_TYPE_INIT,
4726ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL));
4736ba597c5SAnurag S. Maskey }
474d71dbb73Sjbeck 
4756ba597c5SAnurag S. Maskey nwamd_event_t
nwamd_event_init_shutdown(void)4766ba597c5SAnurag S. Maskey nwamd_event_init_shutdown(void)
4776ba597c5SAnurag S. Maskey {
4786ba597c5SAnurag S. Maskey 	return (nwamd_event_init(NWAM_EVENT_TYPE_SHUTDOWN,
4796ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL));
4806ba597c5SAnurag S. Maskey }
481b00044a2SJames Carlson 
4826ba597c5SAnurag S. Maskey /*
4836ba597c5SAnurag S. Maskey  * Add event to the event list.
4846ba597c5SAnurag S. Maskey  */
4856ba597c5SAnurag S. Maskey void
nwamd_event_enqueue(nwamd_event_t event)4866ba597c5SAnurag S. Maskey nwamd_event_enqueue(nwamd_event_t event)
4876ba597c5SAnurag S. Maskey {
4886ba597c5SAnurag S. Maskey 	nwamd_event_enqueue_timed(event, 0);
4896ba597c5SAnurag S. Maskey }
490d71dbb73Sjbeck 
4916ba597c5SAnurag S. Maskey /*
4926ba597c5SAnurag S. Maskey  * Schedule an event to be added to the event list for future processing.
4936ba597c5SAnurag S. Maskey  * The event will be scheduled in delta_seconds seconds mod schedule delay and
4946ba597c5SAnurag S. Maskey  * time resolution.
4956ba597c5SAnurag S. Maskey  */
4966ba597c5SAnurag S. Maskey void
nwamd_event_enqueue_timed(nwamd_event_t event,int delta_seconds)4976ba597c5SAnurag S. Maskey nwamd_event_enqueue_timed(nwamd_event_t event, int delta_seconds)
4986ba597c5SAnurag S. Maskey {
4996ba597c5SAnurag S. Maskey 	uu_list_index_t idx;
500d71dbb73Sjbeck 
5016ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "enqueueing event %lld %d (%s) for object %s in %ds",
5026ba597c5SAnurag S. Maskey 	    event->event_id, event->event_type,
5036ba597c5SAnurag S. Maskey 	    nwamd_event_name(event->event_type),
5046ba597c5SAnurag S. Maskey 	    event->event_object[0] != 0 ?  event->event_object : "none",
5056ba597c5SAnurag S. Maskey 	    delta_seconds);
506d71dbb73Sjbeck 
5076ba597c5SAnurag S. Maskey 	(void) clock_gettime(CLOCK_REALTIME, &event->event_time);
5086ba597c5SAnurag S. Maskey 	event->event_time.tv_sec += delta_seconds;
509b00044a2SJames Carlson 
5106ba597c5SAnurag S. Maskey 	uu_list_node_init(event, &event->event_node, event_pool);
511b00044a2SJames Carlson 
5126ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&event_queue_mutex);
513d71dbb73Sjbeck 
5146ba597c5SAnurag S. Maskey 	/*
5156ba597c5SAnurag S. Maskey 	 * Find appropriate location to insert the event based on time.
5166ba597c5SAnurag S. Maskey 	 */
5176ba597c5SAnurag S. Maskey 	(void) uu_list_find(event_queue, event, NULL, &idx);
5186ba597c5SAnurag S. Maskey 	(void) uu_list_insert(event_queue, event, idx);
519b00044a2SJames Carlson 
5206ba597c5SAnurag S. Maskey 	(void) pthread_cond_signal(&event_queue_cond);
5216ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&event_queue_mutex);
522d71dbb73Sjbeck }
523d71dbb73Sjbeck 
5246ba597c5SAnurag S. Maskey /*
5256ba597c5SAnurag S. Maskey  * Is the specified event enqueued on the event (or pending event queue)
5266ba597c5SAnurag S. Maskey  * for execution in when seconds? An object may be specified also.
5276ba597c5SAnurag S. Maskey  */
5286ba597c5SAnurag S. Maskey boolean_t
nwamd_event_enqueued(int32_t event_type,nwam_object_type_t object_type,const char * object)5296ba597c5SAnurag S. Maskey nwamd_event_enqueued(int32_t event_type, nwam_object_type_t object_type,
5306ba597c5SAnurag S. Maskey     const char *object)
531d71dbb73Sjbeck {
5326ba597c5SAnurag S. Maskey 	nwamd_event_t event;
5336ba597c5SAnurag S. Maskey 
5346ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&event_queue_mutex);
5356ba597c5SAnurag S. Maskey 	for (event = uu_list_first(event_queue);
5366ba597c5SAnurag S. Maskey 	    event != NULL;
5376ba597c5SAnurag S. Maskey 	    event = uu_list_next(event_queue, event)) {
5386ba597c5SAnurag S. Maskey 		if (event->event_type != event_type)
5396ba597c5SAnurag S. Maskey 			continue;
5406ba597c5SAnurag S. Maskey 		if (object_type != NWAM_OBJECT_TYPE_UNKNOWN &&
5416ba597c5SAnurag S. Maskey 		    event->event_object_type != object_type)
5426ba597c5SAnurag S. Maskey 			continue;
5436ba597c5SAnurag S. Maskey 		if (object != NULL && strcmp(object, event->event_object) != 0)
5446ba597c5SAnurag S. Maskey 			continue;
5456ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&event_queue_mutex);
5466ba597c5SAnurag S. Maskey 		return (B_TRUE);
547d71dbb73Sjbeck 	}
5486ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&event_queue_mutex);
5496ba597c5SAnurag S. Maskey 
5506ba597c5SAnurag S. Maskey 	return (B_FALSE);
551d71dbb73Sjbeck }
552d71dbb73Sjbeck 
5536ba597c5SAnurag S. Maskey /*
5546ba597c5SAnurag S. Maskey  * Is the time in the past.
5556ba597c5SAnurag S. Maskey  */
5566ba597c5SAnurag S. Maskey static boolean_t
in_past(struct timespec t)5576ba597c5SAnurag S. Maskey in_past(struct timespec t)
558d71dbb73Sjbeck {
5596ba597c5SAnurag S. Maskey 	struct timespec now;
5606ba597c5SAnurag S. Maskey 
5616ba597c5SAnurag S. Maskey 	(void) clock_gettime(CLOCK_REALTIME, &now);
5626ba597c5SAnurag S. Maskey 	if (t.tv_sec < now.tv_sec)
5636ba597c5SAnurag S. Maskey 		return (B_TRUE);
5646ba597c5SAnurag S. Maskey 	if (t.tv_sec > now.tv_sec)
5656ba597c5SAnurag S. Maskey 		return (B_FALSE);
5666ba597c5SAnurag S. Maskey 	if (t.tv_nsec < now.tv_nsec)
5676ba597c5SAnurag S. Maskey 		return (B_TRUE);
5686ba597c5SAnurag S. Maskey 	return (B_FALSE);
569d71dbb73Sjbeck }
570d71dbb73Sjbeck 
5716ba597c5SAnurag S. Maskey /*
5726ba597c5SAnurag S. Maskey  * Remove event at head of event list for processing.  This takes a number of
5736ba597c5SAnurag S. Maskey  * nanoseconds to wait.  If the number is 0 then it blocks.  If there is
5746ba597c5SAnurag S. Maskey  * nothing on the queue then it returns an event which says that the queue
5756ba597c5SAnurag S. Maskey  * is quiet.
5766ba597c5SAnurag S. Maskey  */
5776ba597c5SAnurag S. Maskey static nwamd_event_t
nwamd_event_dequeue(long nsec)5786ba597c5SAnurag S. Maskey nwamd_event_dequeue(long nsec)
579d71dbb73Sjbeck {
5806ba597c5SAnurag S. Maskey 	nwamd_event_t event;
5816ba597c5SAnurag S. Maskey 
5826ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&event_queue_mutex);
5836ba597c5SAnurag S. Maskey 	event = uu_list_first(event_queue);
5846ba597c5SAnurag S. Maskey 	if (event == NULL && nsec == 0) {
5856ba597c5SAnurag S. Maskey 		do {
5866ba597c5SAnurag S. Maskey 			(void) pthread_cond_wait(&event_queue_cond,
5876ba597c5SAnurag S. Maskey 			    &event_queue_mutex);
5886ba597c5SAnurag S. Maskey 		} while ((event = uu_list_first(event_queue)) == NULL);
5896ba597c5SAnurag S. Maskey 	} else {
5906ba597c5SAnurag S. Maskey 		struct timespec waitcap;
591d71dbb73Sjbeck 
5926ba597c5SAnurag S. Maskey 		if (nsec != 0) {
5936ba597c5SAnurag S. Maskey 			(void) clock_gettime(CLOCK_REALTIME, &waitcap);
5946ba597c5SAnurag S. Maskey 			waitcap.tv_nsec += nsec;
5956ba597c5SAnurag S. Maskey 			waitcap.tv_sec += NSEC_TO_SEC(waitcap.tv_nsec);
5966ba597c5SAnurag S. Maskey 			waitcap.tv_nsec = NSEC_TO_FRACNSEC(waitcap.tv_nsec);
5976ba597c5SAnurag S. Maskey 		}
5986ba597c5SAnurag S. Maskey 
5996ba597c5SAnurag S. Maskey 		/*
6006ba597c5SAnurag S. Maskey 		 * Keep going as long as the first event hasn't matured and
6016ba597c5SAnurag S. Maskey 		 * we havn't passed our maximum wait time.
6026ba597c5SAnurag S. Maskey 		 */
6036ba597c5SAnurag S. Maskey 		while ((event == NULL || !in_past(event->event_time)) &&
6046ba597c5SAnurag S. Maskey 		    (nsec == 0 || !in_past(waitcap)))  {
6056ba597c5SAnurag S. Maskey 			struct timespec eventwait;
6066ba597c5SAnurag S. Maskey 
6076ba597c5SAnurag S. Maskey 			/*
6086ba597c5SAnurag S. Maskey 			 * Three cases:
6096ba597c5SAnurag S. Maskey 			 *	no maximum waittime - just use the event
6106ba597c5SAnurag S. Maskey 			 *	both an event and cap - take the least one
6116ba597c5SAnurag S. Maskey 			 *	just a maximum waittime - use it
6126ba597c5SAnurag S. Maskey 			 */
6136ba597c5SAnurag S. Maskey 			if (nsec == 0) {
6146ba597c5SAnurag S. Maskey 				eventwait = event->event_time;
6156ba597c5SAnurag S. Maskey 			} else if (event != NULL) {
6166ba597c5SAnurag S. Maskey 				uint64_t diff;
6176ba597c5SAnurag S. Maskey 				diff = SEC_TO_NSEC(event->event_time.tv_sec -
6186ba597c5SAnurag S. Maskey 				    waitcap.tv_sec) +
6196ba597c5SAnurag S. Maskey 				    event->event_time.tv_nsec - waitcap.tv_nsec;
6206ba597c5SAnurag S. Maskey 
6216ba597c5SAnurag S. Maskey 				if (diff > 0)
6226ba597c5SAnurag S. Maskey 					eventwait = waitcap;
6236ba597c5SAnurag S. Maskey 				else
6246ba597c5SAnurag S. Maskey 					eventwait = event->event_time;
6256ba597c5SAnurag S. Maskey 			} else {
6266ba597c5SAnurag S. Maskey 				/*
6276ba597c5SAnurag S. Maskey 				 * Note that if the event is NULL then nsec is
6286ba597c5SAnurag S. Maskey 				 * nonzero and waitcap is valid.
6296ba597c5SAnurag S. Maskey 				 */
6306ba597c5SAnurag S. Maskey 				eventwait = waitcap;
6316ba597c5SAnurag S. Maskey 			}
6326ba597c5SAnurag S. Maskey 
6336ba597c5SAnurag S. Maskey 			(void) pthread_cond_timedwait(&event_queue_cond,
6346ba597c5SAnurag S. Maskey 			    &event_queue_mutex, &eventwait);
6356ba597c5SAnurag S. Maskey 			event = uu_list_first(event_queue);
6366ba597c5SAnurag S. Maskey 		}
637d71dbb73Sjbeck 	}
6386ba597c5SAnurag S. Maskey 
6396ba597c5SAnurag S. Maskey 	/*
6406ba597c5SAnurag S. Maskey 	 * At this point we've met the guard contition of the while loop.
6416ba597c5SAnurag S. Maskey 	 * The event at the top of the queue might be mature in which case
6426ba597c5SAnurag S. Maskey 	 * we use it.  Otherwise we hit our cap and we need to enqueue a
6436ba597c5SAnurag S. Maskey 	 * quiesced queue event.
6446ba597c5SAnurag S. Maskey 	 */
6456ba597c5SAnurag S. Maskey 	if (event != NULL && in_past(event->event_time)) {
6466ba597c5SAnurag S. Maskey 		uu_list_remove(event_queue, event);
6476ba597c5SAnurag S. Maskey 		uu_list_node_fini(event, &event->event_node, event_pool);
6486ba597c5SAnurag S. Maskey 	} else {
6496ba597c5SAnurag S. Maskey 		event = nwamd_event_init(NWAM_EVENT_TYPE_QUEUE_QUIET,
6506ba597c5SAnurag S. Maskey 		    NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL);
6516ba597c5SAnurag S. Maskey 	}
6526ba597c5SAnurag S. Maskey 
6536ba597c5SAnurag S. Maskey 	if (event != NULL)
6546ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG,
6556ba597c5SAnurag S. Maskey 		    "dequeueing event %lld of type %d (%s) for object %s",
6566ba597c5SAnurag S. Maskey 		    event->event_id, event->event_type,
6576ba597c5SAnurag S. Maskey 		    nwamd_event_name(event->event_type),
6586ba597c5SAnurag S. Maskey 		    event->event_object[0] != 0 ?  event->event_object :
6596ba597c5SAnurag S. Maskey 		    "none");
6606ba597c5SAnurag S. Maskey 
6616ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&event_queue_mutex);
6626ba597c5SAnurag S. Maskey 
6636ba597c5SAnurag S. Maskey 	return (event);
664d71dbb73Sjbeck }
665d71dbb73Sjbeck 
6666ba597c5SAnurag S. Maskey void
nwamd_event_send(nwam_event_t event_msg)6676ba597c5SAnurag S. Maskey nwamd_event_send(nwam_event_t event_msg)
668d71dbb73Sjbeck {
6696ba597c5SAnurag S. Maskey 	nwam_error_t err;
670d71dbb73Sjbeck 
6716ba597c5SAnurag S. Maskey 	if (shutting_down && event_msg->nwe_type != NWAM_EVENT_TYPE_SHUTDOWN) {
6726ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_event_send: tossing event as nwamd "
6736ba597c5SAnurag S. Maskey 		    "is shutting down");
6746ba597c5SAnurag S. Maskey 		return;
6756ba597c5SAnurag S. Maskey 	}
6766ba597c5SAnurag S. Maskey 
6776ba597c5SAnurag S. Maskey 	err = nwam_event_send(event_msg);
678d71dbb73Sjbeck 
6796ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
6806ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_event_send: nwam_event_send: %s",
6816ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
682d71dbb73Sjbeck 	}
683d71dbb73Sjbeck }
684d71dbb73Sjbeck 
6856ba597c5SAnurag S. Maskey /*
6866ba597c5SAnurag S. Maskey  * Run state machine for object. Method is run if
6876ba597c5SAnurag S. Maskey  * - event method is non-null
6886ba597c5SAnurag S. Maskey  * - event method is valid for current object state (determined by
6896ba597c5SAnurag S. Maskey  * ORing the current state against the set of valid states for the method).
6906ba597c5SAnurag S. Maskey  *
6916ba597c5SAnurag S. Maskey  * If these criteria are met, the method is run.
6926ba597c5SAnurag S. Maskey  */
6936ba597c5SAnurag S. Maskey static void
nwamd_event_run_method(nwamd_event_t event)6946ba597c5SAnurag S. Maskey nwamd_event_run_method(nwamd_event_t event)
695d71dbb73Sjbeck {
6966ba597c5SAnurag S. Maskey 	nwamd_event_method_t *event_methods;
6976ba597c5SAnurag S. Maskey 	int i;
698d71dbb73Sjbeck 
6996ba597c5SAnurag S. Maskey 	event_methods = nwamd_object_event_methods(event->event_object_type);
700d71dbb73Sjbeck 
7016ba597c5SAnurag S. Maskey 	/* If we're shutting down, only fini events are accepted for objects */
7026ba597c5SAnurag S. Maskey 	if (shutting_down && event->event_type != NWAM_EVENT_TYPE_OBJECT_FINI) {
7036ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_event_run_method: tossing non-fini "
7046ba597c5SAnurag S. Maskey 		    "event %s for object %s",
7056ba597c5SAnurag S. Maskey 		    nwamd_event_name(event->event_type), event->event_object);
7066ba597c5SAnurag S. Maskey 		return;
707d71dbb73Sjbeck 	}
708d71dbb73Sjbeck 
7096ba597c5SAnurag S. Maskey 	for (i = 0;
7106ba597c5SAnurag S. Maskey 	    event_methods[i].event_type != NWAM_EVENT_TYPE_NOOP;
7116ba597c5SAnurag S. Maskey 	    i++) {
7126ba597c5SAnurag S. Maskey 		if (event_methods[i].event_type ==
7136ba597c5SAnurag S. Maskey 		    event->event_type &&
7146ba597c5SAnurag S. Maskey 		    event_methods[i].event_method != NULL) {
7156ba597c5SAnurag S. Maskey 			nlog(LOG_DEBUG,
7166ba597c5SAnurag S. Maskey 			    "(%p) %s: running method for event %s",
7176ba597c5SAnurag S. Maskey 			    (void *)event, event->event_object,
7186ba597c5SAnurag S. Maskey 			    nwamd_event_name(event->event_type));
7196ba597c5SAnurag S. Maskey 			/* run method */
7206ba597c5SAnurag S. Maskey 			event_methods[i].event_method(event);
7216ba597c5SAnurag S. Maskey 			return;
722ab32bdf2SJames Carlson 		}
7236ba597c5SAnurag S. Maskey 	}
7246ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "(%p) %s: no matching method for event %d (%s)",
7256ba597c5SAnurag S. Maskey 	    (void *)event, event->event_object, event->event_type,
7266ba597c5SAnurag S. Maskey 	    nwamd_event_name(event->event_type));
7276ba597c5SAnurag S. Maskey }
7286ba597c5SAnurag S. Maskey 
7296ba597c5SAnurag S. Maskey /*
7306ba597c5SAnurag S. Maskey  * Called when we are checking to see what should be activated.  First activate
7316ba597c5SAnurag S. Maskey  * all of the manual NCUs.  Then see if we can find a valid priority group.
7326ba597c5SAnurag S. Maskey  * If we can, activate it.  Otherwise try all the priority groups starting
7336ba597c5SAnurag S. Maskey  * with the lowest one that makes sense.
7346ba597c5SAnurag S. Maskey  */
7356ba597c5SAnurag S. Maskey static void
nwamd_activate_ncus(void)7366ba597c5SAnurag S. Maskey nwamd_activate_ncus(void) {
7376ba597c5SAnurag S. Maskey 	int64_t prio = INVALID_PRIORITY_GROUP;
7386ba597c5SAnurag S. Maskey 	boolean_t selected;
7396ba597c5SAnurag S. Maskey 
7406ba597c5SAnurag S. Maskey 	nwamd_ncp_activate_manual_ncus();
7416ba597c5SAnurag S. Maskey 	selected = nwamd_ncp_check_priority_group(&prio);
7426ba597c5SAnurag S. Maskey 	if (selected) {
7436ba597c5SAnurag S. Maskey 		/*
7446ba597c5SAnurag S. Maskey 		 * Activate chosen priority group and stop anything going on in
7456ba597c5SAnurag S. Maskey 		 * lesser priority groups.
7466ba597c5SAnurag S. Maskey 		 */
7476ba597c5SAnurag S. Maskey 		nwamd_ncp_activate_priority_group(prio);
7486ba597c5SAnurag S. Maskey 		nwamd_ncp_deactivate_priority_group_all(prio + 1);
749d71dbb73Sjbeck 	} else {
7506ba597c5SAnurag S. Maskey 		/*
7516ba597c5SAnurag S. Maskey 		 * Nothing unique could be started so try them all.  Once one
7526ba597c5SAnurag S. Maskey 		 * of them gets into a reasonable state then we will prune
7536ba597c5SAnurag S. Maskey 		 * everything below it (see first part of this conditional).
7546ba597c5SAnurag S. Maskey 		 */
7556ba597c5SAnurag S. Maskey 		int64_t oldprio = INVALID_PRIORITY_GROUP;
7566ba597c5SAnurag S. Maskey 		while (nwamd_ncp_find_next_priority_group(++oldprio, &prio)) {
7576ba597c5SAnurag S. Maskey 			nwamd_ncp_activate_priority_group(prio);
7586ba597c5SAnurag S. Maskey 			oldprio = prio;
7596ba597c5SAnurag S. Maskey 		}
760d71dbb73Sjbeck 	}
7616ba597c5SAnurag S. Maskey }
7626ba597c5SAnurag S. Maskey 
7636ba597c5SAnurag S. Maskey /*
7646ba597c5SAnurag S. Maskey  * Event handler thread
7656ba597c5SAnurag S. Maskey  *
7666ba597c5SAnurag S. Maskey  * The complexity in this code comes about from wanting to delay the decision
7676ba597c5SAnurag S. Maskey  * making process until after bursts of events.  Keep roughly polling (waiting
7686ba597c5SAnurag S. Maskey  * for .1s) until we see the queue quiet event and then block.
7696ba597c5SAnurag S. Maskey  */
7706ba597c5SAnurag S. Maskey void
nwamd_event_handler(void)7716ba597c5SAnurag S. Maskey nwamd_event_handler(void)
7726ba597c5SAnurag S. Maskey {
7736ba597c5SAnurag S. Maskey 	boolean_t got_shutdown_event = B_FALSE;
7746ba597c5SAnurag S. Maskey 	boolean_t check_conditions = B_FALSE;
7756ba597c5SAnurag S. Maskey 	boolean_t ncu_check = B_FALSE;
7766ba597c5SAnurag S. Maskey 	int queue_quiet_time = 0;
7776ba597c5SAnurag S. Maskey 	nwamd_event_t event;
778d71dbb73Sjbeck 
779b00044a2SJames Carlson 	/*
7806ba597c5SAnurag S. Maskey 	 * Dequeue events and process them.  In most cases, events have
7816ba597c5SAnurag S. Maskey 	 * an assocated object type, and we use this to retrieve
7826ba597c5SAnurag S. Maskey 	 * the function that will process the event.
783b00044a2SJames Carlson 	 */
7846ba597c5SAnurag S. Maskey 	while (!got_shutdown_event) {
7856ba597c5SAnurag S. Maskey 		event = nwamd_event_dequeue(queue_quiet_time);
7866ba597c5SAnurag S. Maskey 		/* keep pulling events as long as they are close together */
7876ba597c5SAnurag S. Maskey 		queue_quiet_time = SEC_TO_NSEC(1)/10;
7886ba597c5SAnurag S. Maskey 
7896ba597c5SAnurag S. Maskey 		/*
7906ba597c5SAnurag S. Maskey 		 * This is an event with no associated object.
7916ba597c5SAnurag S. Maskey 		 */
7926ba597c5SAnurag S. Maskey 		if (event->event_object[0] == '\0') {
7936ba597c5SAnurag S. Maskey 			switch (event->event_type) {
7946ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_NOOP:
7956ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_INIT:
7966ba597c5SAnurag S. Maskey 				/*
7976ba597c5SAnurag S. Maskey 				 * The only action for an INIT event
7986ba597c5SAnurag S. Maskey 				 * is to relay it to event listeners,
7996ba597c5SAnurag S. Maskey 				 * which is done below.
8006ba597c5SAnurag S. Maskey 				 */
8016ba597c5SAnurag S. Maskey 				break;
8026ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_PRIORITY_GROUP:
8036ba597c5SAnurag S. Maskey 				(void) pthread_mutex_lock(&active_ncp_mutex);
8046ba597c5SAnurag S. Maskey 				current_ncu_priority_group =
8056ba597c5SAnurag S. Maskey 				    event->event_msg->nwe_data.
8066ba597c5SAnurag S. Maskey 				    nwe_priority_group_info.nwe_priority;
8076ba597c5SAnurag S. Maskey 				(void) pthread_mutex_unlock(&active_ncp_mutex);
8086ba597c5SAnurag S. Maskey 				break;
8096ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS:
8106ba597c5SAnurag S. Maskey 				if (!shutting_down) {
8116ba597c5SAnurag S. Maskey 					nwamd_set_timed_check_all_conditions();
8126ba597c5SAnurag S. Maskey 					check_conditions = B_TRUE;
8136ba597c5SAnurag S. Maskey 				}
8146ba597c5SAnurag S. Maskey 				break;
8156ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS:
8166ba597c5SAnurag S. Maskey 				if (!shutting_down)
8176ba597c5SAnurag S. Maskey 					check_conditions = B_TRUE;
8186ba597c5SAnurag S. Maskey 				break;
8196ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_NCU_CHECK:
8206ba597c5SAnurag S. Maskey 				if (!shutting_down)
8216ba597c5SAnurag S. Maskey 					ncu_check = B_TRUE;
8226ba597c5SAnurag S. Maskey 				break;
8236ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_UPGRADE:
8246ba597c5SAnurag S. Maskey 				if (!shutting_down) {
8256ba597c5SAnurag S. Maskey 					/*
8266ba597c5SAnurag S. Maskey 					 * Upgrade events have no associated
8276ba597c5SAnurag S. Maskey 					 * object.
8286ba597c5SAnurag S. Maskey 					 */
8296ba597c5SAnurag S. Maskey 					nwamd_event_run_method(event);
8306ba597c5SAnurag S. Maskey 				}
8316ba597c5SAnurag S. Maskey 				break;
8326ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_SHUTDOWN:
8336ba597c5SAnurag S. Maskey 				got_shutdown_event = B_TRUE;
8346ba597c5SAnurag S. Maskey 				break;
835b00044a2SJames Carlson 
8366ba597c5SAnurag S. Maskey 			/*
8376ba597c5SAnurag S. Maskey 			 * We want to delay processing of condition and ncu
8386ba597c5SAnurag S. Maskey 			 * checking until after short bursts of events.  So we
8396ba597c5SAnurag S. Maskey 			 * keep track of times we've scheduled checking and
8406ba597c5SAnurag S. Maskey 			 * wait for the queue to quiesce.
8416ba597c5SAnurag S. Maskey 			 */
8426ba597c5SAnurag S. Maskey 			case NWAM_EVENT_TYPE_QUEUE_QUIET:
8436ba597c5SAnurag S. Maskey 				queue_quiet_time = 0; /* now we can block */
8446ba597c5SAnurag S. Maskey 				if (!shutting_down && check_conditions) {
8456ba597c5SAnurag S. Maskey 					nwamd_check_all_conditions();
8466ba597c5SAnurag S. Maskey 					check_conditions = B_FALSE;
8476ba597c5SAnurag S. Maskey 				}
8486ba597c5SAnurag S. Maskey 
8496ba597c5SAnurag S. Maskey 				if (!shutting_down && ncu_check) {
8506ba597c5SAnurag S. Maskey 					nwamd_activate_ncus();
8516ba597c5SAnurag S. Maskey 					ncu_check = B_FALSE;
8526ba597c5SAnurag S. Maskey 				}
8536ba597c5SAnurag S. Maskey 				break;
854d71dbb73Sjbeck 
8556ba597c5SAnurag S. Maskey 			default:
8566ba597c5SAnurag S. Maskey 				nlog(LOG_ERR,
8576ba597c5SAnurag S. Maskey 				    "event %d (%s)had no object associated "
8586ba597c5SAnurag S. Maskey 				    "with it", event->event_type,
8596ba597c5SAnurag S. Maskey 				    nwamd_event_name(event->event_type));
8606ba597c5SAnurag S. Maskey 				break;
8616ba597c5SAnurag S. Maskey 			}
8626ba597c5SAnurag S. Maskey 		} else {
8636ba597c5SAnurag S. Maskey 			/*
8646ba597c5SAnurag S. Maskey 			 * Event has an associated object - run event method
8656ba597c5SAnurag S. Maskey 			 * for that object type (if any).
8666ba597c5SAnurag S. Maskey 			 */
8676ba597c5SAnurag S. Maskey 			nwamd_event_run_method(event);
8686ba597c5SAnurag S. Maskey 		}
8696ba597c5SAnurag S. Maskey 		/*
8706ba597c5SAnurag S. Maskey 		 * Send associated message to listeners if event type is
8716ba597c5SAnurag S. Maskey 		 * externally visible.
8726ba597c5SAnurag S. Maskey 		 */
8736ba597c5SAnurag S. Maskey 		if (event->event_send)
8746ba597c5SAnurag S. Maskey 			nwamd_event_send(event->event_msg);
8756ba597c5SAnurag S. Maskey 
8766ba597c5SAnurag S. Maskey 		nwamd_event_fini(event);
8776ba597c5SAnurag S. Maskey 	}
8786ba597c5SAnurag S. Maskey 	/* If we get here, we got a shutdown event. */
8796ba597c5SAnurag S. Maskey 	nwamd_event_queue_fini();
8806ba597c5SAnurag S. Maskey 	nwamd_object_lists_fini();
881d71dbb73Sjbeck }
882