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 }, 59d71dbb73Sjbeck }; 60d71dbb73Sjbeck 616ba597c5SAnurag S. Maskey /* Counter for event ids */ 626ba597c5SAnurag S. Maskey static uint64_t event_id_counter = 0; 636ba597c5SAnurag S. Maskey 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; 686ba597c5SAnurag S. Maskey 696ba597c5SAnurag S. Maskey static int nwamd_event_compare(const void *, const void *, void *); 706ba597c5SAnurag S. Maskey 716ba597c5SAnurag S. Maskey static const char * 726ba597c5SAnurag S. Maskey nwamd_event_name(int event_type) 736ba597c5SAnurag S. Maskey { 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 } 1006ba597c5SAnurag S. Maskey 101d71dbb73Sjbeck 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 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(); 127b00044a2SJames Carlson } 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 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 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 1656ba597c5SAnurag S. Maskey nwamd_event_queue_fini(void) 166d71dbb73Sjbeck { 1676ba597c5SAnurag S. Maskey void *cookie = NULL; 1686ba597c5SAnurag S. Maskey nwamd_event_t event; 169d71dbb73Sjbeck 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 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; 182b00044a2SJames Carlson 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); 201b00044a2SJames Carlson } 2026ba597c5SAnurag S. Maskey event->event_msg->nwe_type = type; 2036ba597c5SAnurag S. Maskey event->event_msg->nwe_size = sizeof (struct nwam_event) + size; 204b00044a2SJames Carlson } else { 2056ba597c5SAnurag S. Maskey event->event_send = B_FALSE; 2066ba597c5SAnurag S. Maskey event->event_msg = NULL; 207b00044a2SJames Carlson } 208b00044a2SJames Carlson 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; 2156ba597c5SAnurag S. Maskey } else { 2166ba597c5SAnurag S. Maskey event->event_object[0] = '\0'; 2176ba597c5SAnurag S. Maskey } 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); 2246ba597c5SAnurag S. Maskey } 2256ba597c5SAnurag S. Maskey 2266ba597c5SAnurag S. Maskey void 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 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 } 243b00044a2SJames Carlson } 244b00044a2SJames Carlson 2456ba597c5SAnurag S. Maskey nwamd_event_t 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) 249d71dbb73Sjbeck { 2506ba597c5SAnurag S. Maskey nwamd_event_t event; 251d71dbb73Sjbeck 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); 2676ba597c5SAnurag S. Maskey } 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); 273d71dbb73Sjbeck } 274d71dbb73Sjbeck 2756ba597c5SAnurag S. Maskey nwamd_event_t 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) 2786ba597c5SAnurag S. Maskey { 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); 285d71dbb73Sjbeck 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); 295d71dbb73Sjbeck } 296d71dbb73Sjbeck 2976ba597c5SAnurag S. Maskey nwamd_event_t 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); 311d71dbb73Sjbeck } 312d71dbb73Sjbeck 3136ba597c5SAnurag S. Maskey nwamd_event_t 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); 3266ba597c5SAnurag S. Maskey } 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); 3326ba597c5SAnurag S. Maskey 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; 3376ba597c5SAnurag S. Maskey 3386ba597c5SAnurag S. Maskey return (event); 339d71dbb73Sjbeck } 340d71dbb73Sjbeck 3416ba597c5SAnurag S. Maskey nwamd_event_t 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; 347d71dbb73Sjbeck 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)); 353d71dbb73Sjbeck return (NULL); 354d71dbb73Sjbeck } 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) 360d71dbb73Sjbeck 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; 3656ba597c5SAnurag S. Maskey 3666ba597c5SAnurag S. Maskey return (event); 367d71dbb73Sjbeck } 368d71dbb73Sjbeck 3696ba597c5SAnurag S. Maskey nwamd_event_t 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 } 3856ba597c5SAnurag S. Maskey 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); 3916ba597c5SAnurag S. Maskey 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 } 4106ba597c5SAnurag S. Maskey 4116ba597c5SAnurag S. Maskey return (event); 4126ba597c5SAnurag S. Maskey } 4136ba597c5SAnurag S. Maskey 4146ba597c5SAnurag S. Maskey nwamd_event_t 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; 4226ba597c5SAnurag S. Maskey 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 } 4436ba597c5SAnurag S. Maskey 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); 4486ba597c5SAnurag S. Maskey 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; 4536ba597c5SAnurag S. Maskey 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)); 4576ba597c5SAnurag S. Maskey 4586ba597c5SAnurag S. Maskey return (event); 4596ba597c5SAnurag S. Maskey } 4606ba597c5SAnurag S. Maskey 4616ba597c5SAnurag S. Maskey nwamd_event_t 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 } 4676ba597c5SAnurag S. Maskey 4686ba597c5SAnurag S. Maskey nwamd_event_t 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 } 4746ba597c5SAnurag S. Maskey 4756ba597c5SAnurag S. Maskey nwamd_event_t 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 } 4816ba597c5SAnurag S. Maskey 4826ba597c5SAnurag S. Maskey /* 4836ba597c5SAnurag S. Maskey * Add event to the event list. 4846ba597c5SAnurag S. Maskey */ 4856ba597c5SAnurag S. Maskey void 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 } 4906ba597c5SAnurag S. Maskey 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 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; 5006ba597c5SAnurag S. Maskey 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); 5066ba597c5SAnurag S. Maskey 5076ba597c5SAnurag S. Maskey (void) clock_gettime(CLOCK_REALTIME, &event->event_time); 5086ba597c5SAnurag S. Maskey event->event_time.tv_sec += delta_seconds; 5096ba597c5SAnurag S. Maskey 5106ba597c5SAnurag S. Maskey uu_list_node_init(event, &event->event_node, event_pool); 5116ba597c5SAnurag S. Maskey 5126ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&event_queue_mutex); 5136ba597c5SAnurag S. Maskey 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); 5196ba597c5SAnurag S. Maskey 5206ba597c5SAnurag S. Maskey (void) pthread_cond_signal(&event_queue_cond); 5216ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&event_queue_mutex); 5226ba597c5SAnurag S. Maskey } 5236ba597c5SAnurag S. Maskey 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 */ 528d71dbb73Sjbeck boolean_t 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; 533d71dbb73Sjbeck 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); 546d71dbb73Sjbeck return (B_TRUE); 547d71dbb73Sjbeck } 5486ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&event_queue_mutex); 5496ba597c5SAnurag S. Maskey 5506ba597c5SAnurag S. Maskey return (B_FALSE); 5516ba597c5SAnurag S. Maskey } 5526ba597c5SAnurag S. Maskey 5536ba597c5SAnurag S. Maskey /* 5546ba597c5SAnurag S. Maskey * Is the time in the past. 5556ba597c5SAnurag S. Maskey */ 5566ba597c5SAnurag S. Maskey static boolean_t 5576ba597c5SAnurag S. Maskey in_past(struct timespec t) 5586ba597c5SAnurag S. Maskey { 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); 5696ba597c5SAnurag S. Maskey } 5706ba597c5SAnurag S. Maskey 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 5786ba597c5SAnurag S. Maskey nwamd_event_dequeue(long nsec) 5796ba597c5SAnurag S. Maskey { 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; 5916ba597c5SAnurag S. Maskey 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 } 6376ba597c5SAnurag S. Maskey } 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); 6646ba597c5SAnurag S. Maskey } 6656ba597c5SAnurag S. Maskey 6666ba597c5SAnurag S. Maskey void 6676ba597c5SAnurag S. Maskey nwamd_event_send(nwam_event_t event_msg) 6686ba597c5SAnurag S. Maskey { 6696ba597c5SAnurag S. Maskey nwam_error_t err; 6706ba597c5SAnurag S. Maskey 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); 6786ba597c5SAnurag S. Maskey 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)); 6826ba597c5SAnurag S. Maskey } 6836ba597c5SAnurag S. Maskey } 6846ba597c5SAnurag S. Maskey 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 6946ba597c5SAnurag S. Maskey nwamd_event_run_method(nwamd_event_t event) 6956ba597c5SAnurag S. Maskey { 6966ba597c5SAnurag S. Maskey nwamd_event_method_t *event_methods; 6976ba597c5SAnurag S. Maskey int i; 6986ba597c5SAnurag S. Maskey 6996ba597c5SAnurag S. Maskey event_methods = nwamd_object_event_methods(event->event_object_type); 7006ba597c5SAnurag S. Maskey 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; 7076ba597c5SAnurag S. Maskey } 7086ba597c5SAnurag S. Maskey 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; 7226ba597c5SAnurag S. Maskey } 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 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); 7496ba597c5SAnurag S. Maskey } 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 } 7606ba597c5SAnurag S. Maskey } 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 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; 7786ba597c5SAnurag S. Maskey 7796ba597c5SAnurag S. Maskey /* 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. 7836ba597c5SAnurag S. Maskey */ 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; 8356ba597c5SAnurag S. Maskey 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; 8546ba597c5SAnurag S. Maskey 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(); 8816ba597c5SAnurag S. Maskey } 882