13938Sjbeck /*
23938Sjbeck * CDDL HEADER START
33938Sjbeck *
43938Sjbeck * The contents of this file are subject to the terms of the
53938Sjbeck * Common Development and Distribution License (the "License").
63938Sjbeck * You may not use this file except in compliance with the License.
73938Sjbeck *
83938Sjbeck * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93938Sjbeck * or http://www.opensolaris.org/os/licensing.
103938Sjbeck * See the License for the specific language governing permissions
113938Sjbeck * and limitations under the License.
123938Sjbeck *
133938Sjbeck * When distributing Covered Code, include this CDDL HEADER in each
143938Sjbeck * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153938Sjbeck * If applicable, add the following below this CDDL HEADER, with the
163938Sjbeck * fields enclosed by brackets "[]" replaced with your own identifying
173938Sjbeck * information: Portions Copyright [yyyy] [name of copyright owner]
183938Sjbeck *
193938Sjbeck * CDDL HEADER END
203938Sjbeck */
213938Sjbeck
223938Sjbeck /*
23*12576SAnurag.Maskey@Oracle.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
243938Sjbeck */
253938Sjbeck
2611767SAnurag.Maskey@Sun.COM #include <atomic.h>
273938Sjbeck #include <errno.h>
2811767SAnurag.Maskey@Sun.COM #include <execinfo.h>
2911767SAnurag.Maskey@Sun.COM #include <libuutil.h>
303938Sjbeck #include <pthread.h>
3111767SAnurag.Maskey@Sun.COM #include <signal.h>
323938Sjbeck #include <stdlib.h>
333938Sjbeck #include <string.h>
3411767SAnurag.Maskey@Sun.COM #include <strings.h>
353938Sjbeck #include <syslog.h>
3611767SAnurag.Maskey@Sun.COM #include <sys/time.h>
373938Sjbeck #include <unistd.h>
383938Sjbeck
3911767SAnurag.Maskey@Sun.COM #include "conditions.h"
4011767SAnurag.Maskey@Sun.COM #include "events.h"
4111767SAnurag.Maskey@Sun.COM #include "objects.h"
4211767SAnurag.Maskey@Sun.COM #include "util.h"
433938Sjbeck
4411767SAnurag.Maskey@Sun.COM /*
4511767SAnurag.Maskey@Sun.COM * events.c - contains routines which create/destroy event sources,
4611767SAnurag.Maskey@Sun.COM * handle the event queue and process events from that queue.
4711767SAnurag.Maskey@Sun.COM */
483938Sjbeck
4911767SAnurag.Maskey@Sun.COM /* Add new event sources here. */
5011767SAnurag.Maskey@Sun.COM struct nwamd_event_source {
5111767SAnurag.Maskey@Sun.COM char *name;
5211767SAnurag.Maskey@Sun.COM void (*events_init)(void);
5311767SAnurag.Maskey@Sun.COM void (*events_fini)(void);
5411767SAnurag.Maskey@Sun.COM } event_sources[] = {
5511767SAnurag.Maskey@Sun.COM { "routing_events",
5611767SAnurag.Maskey@Sun.COM nwamd_routing_events_init, nwamd_routing_events_fini },
5711767SAnurag.Maskey@Sun.COM { "sysevent_events",
5811767SAnurag.Maskey@Sun.COM nwamd_sysevent_events_init, nwamd_sysevent_events_fini },
593938Sjbeck };
603938Sjbeck
6111767SAnurag.Maskey@Sun.COM /* Counter for event ids */
6211767SAnurag.Maskey@Sun.COM static uint64_t event_id_counter = 0;
633938Sjbeck
6411767SAnurag.Maskey@Sun.COM static uu_list_pool_t *event_pool = NULL;
6511767SAnurag.Maskey@Sun.COM static uu_list_t *event_queue = NULL;
6611767SAnurag.Maskey@Sun.COM static pthread_mutex_t event_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
6711767SAnurag.Maskey@Sun.COM static pthread_cond_t event_queue_cond = PTHREAD_COND_INITIALIZER;
687645Sjames.d.carlson@sun.com
6911767SAnurag.Maskey@Sun.COM static int nwamd_event_compare(const void *, const void *, void *);
703938Sjbeck
7111767SAnurag.Maskey@Sun.COM static const char *
nwamd_event_name(int event_type)7211767SAnurag.Maskey@Sun.COM nwamd_event_name(int event_type)
733938Sjbeck {
7411767SAnurag.Maskey@Sun.COM if (event_type <= NWAM_EVENT_MAX)
7511767SAnurag.Maskey@Sun.COM return (nwam_event_type_to_string(event_type));
763938Sjbeck
7711767SAnurag.Maskey@Sun.COM switch (event_type) {
7811767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_OBJECT_INIT:
7911767SAnurag.Maskey@Sun.COM return ("OBJECT_INIT");
8011767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_OBJECT_FINI:
8111767SAnurag.Maskey@Sun.COM return ("OBJECT_FINI");
8211767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS:
8311767SAnurag.Maskey@Sun.COM return ("TIMED_CHECK_CONDITIONS");
8411767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS:
8511767SAnurag.Maskey@Sun.COM return ("TRIGGERED_CHECK_CONDITIONS");
8611767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_NCU_CHECK:
8711767SAnurag.Maskey@Sun.COM return ("NCU_CHECK");
8811767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_TIMER:
897645Sjames.d.carlson@sun.com return ("TIMER");
9011767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_UPGRADE:
9111767SAnurag.Maskey@Sun.COM return ("UPGRADE");
9211767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_PERIODIC_SCAN:
9311767SAnurag.Maskey@Sun.COM return ("PERIODIC_SCAN");
9411767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_QUEUE_QUIET:
9511767SAnurag.Maskey@Sun.COM return ("QUEUE_QUIET");
963938Sjbeck default:
9711767SAnurag.Maskey@Sun.COM return ("N/A");
983938Sjbeck }
993938Sjbeck }
1003938Sjbeck
10111767SAnurag.Maskey@Sun.COM void
nwamd_event_sources_init(void)10211767SAnurag.Maskey@Sun.COM nwamd_event_sources_init(void)
1033938Sjbeck {
10411767SAnurag.Maskey@Sun.COM int i;
1053938Sjbeck
10611767SAnurag.Maskey@Sun.COM /*
10711767SAnurag.Maskey@Sun.COM * Now we can safely initialize event sources.
10811767SAnurag.Maskey@Sun.COM */
10911767SAnurag.Maskey@Sun.COM for (i = 0;
11011767SAnurag.Maskey@Sun.COM i < sizeof (event_sources) / sizeof (struct nwamd_event_source);
11111767SAnurag.Maskey@Sun.COM i++) {
11211767SAnurag.Maskey@Sun.COM if (event_sources[i].events_init != NULL)
11311767SAnurag.Maskey@Sun.COM event_sources[i].events_init();
1143938Sjbeck }
1153938Sjbeck }
1163938Sjbeck
11711767SAnurag.Maskey@Sun.COM void
nwamd_event_sources_fini(void)11811767SAnurag.Maskey@Sun.COM nwamd_event_sources_fini(void)
1197645Sjames.d.carlson@sun.com {
12011767SAnurag.Maskey@Sun.COM int i;
1217645Sjames.d.carlson@sun.com
12211767SAnurag.Maskey@Sun.COM for (i = 0;
12311767SAnurag.Maskey@Sun.COM i < sizeof (event_sources) / sizeof (struct nwamd_event_source);
12411767SAnurag.Maskey@Sun.COM i++) {
12511767SAnurag.Maskey@Sun.COM if (event_sources[i].events_init != NULL)
12611767SAnurag.Maskey@Sun.COM event_sources[i].events_fini();
1277645Sjames.d.carlson@sun.com }
1287645Sjames.d.carlson@sun.com }
1297645Sjames.d.carlson@sun.com
1307645Sjames.d.carlson@sun.com /*
13111767SAnurag.Maskey@Sun.COM * Comparison function for events, passed in as callback to
13211767SAnurag.Maskey@Sun.COM * uu_list_pool_create(). Compare by time, so that timer
13311767SAnurag.Maskey@Sun.COM * event queue can be sorted by nearest time to present.
1347645Sjames.d.carlson@sun.com */
1353938Sjbeck /* ARGSUSED */
13611767SAnurag.Maskey@Sun.COM static int
nwamd_event_compare(const void * l_arg,const void * r_arg,void * private)13711767SAnurag.Maskey@Sun.COM nwamd_event_compare(const void *l_arg, const void *r_arg, void *private)
1383938Sjbeck {
13911767SAnurag.Maskey@Sun.COM nwamd_event_t l = (nwamd_event_t)l_arg;
14011767SAnurag.Maskey@Sun.COM nwamd_event_t r = (nwamd_event_t)r_arg;
14111767SAnurag.Maskey@Sun.COM int rv;
14211767SAnurag.Maskey@Sun.COM
14311767SAnurag.Maskey@Sun.COM rv = l->event_time.tv_sec - r->event_time.tv_sec;
14411767SAnurag.Maskey@Sun.COM if (rv == 0)
14511767SAnurag.Maskey@Sun.COM rv = l->event_time.tv_nsec - r->event_time.tv_nsec;
14611767SAnurag.Maskey@Sun.COM
14711767SAnurag.Maskey@Sun.COM return (rv);
14811767SAnurag.Maskey@Sun.COM }
1493938Sjbeck
15011767SAnurag.Maskey@Sun.COM void
nwamd_event_queue_init(void)15111767SAnurag.Maskey@Sun.COM nwamd_event_queue_init(void)
15211767SAnurag.Maskey@Sun.COM {
15311767SAnurag.Maskey@Sun.COM event_pool = uu_list_pool_create("event_queue_pool",
15411767SAnurag.Maskey@Sun.COM sizeof (struct nwamd_event),
15511767SAnurag.Maskey@Sun.COM offsetof(struct nwamd_event, event_node),
15611767SAnurag.Maskey@Sun.COM nwamd_event_compare, UU_LIST_POOL_DEBUG);
15711767SAnurag.Maskey@Sun.COM if (event_pool == NULL)
15811767SAnurag.Maskey@Sun.COM pfail("uu_list_pool_create failed with error %d", uu_error());
15911767SAnurag.Maskey@Sun.COM event_queue = uu_list_create(event_pool, NULL, UU_LIST_SORTED);
16011767SAnurag.Maskey@Sun.COM if (event_queue == NULL)
16111767SAnurag.Maskey@Sun.COM pfail("uu_list_create failed with error %d", uu_error());
16211767SAnurag.Maskey@Sun.COM }
16311767SAnurag.Maskey@Sun.COM
16411767SAnurag.Maskey@Sun.COM void
nwamd_event_queue_fini(void)16511767SAnurag.Maskey@Sun.COM nwamd_event_queue_fini(void)
16611767SAnurag.Maskey@Sun.COM {
16711767SAnurag.Maskey@Sun.COM void *cookie = NULL;
16811767SAnurag.Maskey@Sun.COM nwamd_event_t event;
16911767SAnurag.Maskey@Sun.COM
17011767SAnurag.Maskey@Sun.COM while ((event = uu_list_teardown(event_queue, &cookie)) != NULL)
17111767SAnurag.Maskey@Sun.COM nwamd_event_fini(event);
17211767SAnurag.Maskey@Sun.COM uu_list_destroy(event_queue);
17311767SAnurag.Maskey@Sun.COM if (event_pool != NULL)
17411767SAnurag.Maskey@Sun.COM uu_list_pool_destroy(event_pool);
17511767SAnurag.Maskey@Sun.COM }
17611767SAnurag.Maskey@Sun.COM
17711767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init(int32_t type,nwam_object_type_t object_type,size_t size,const char * object_name)17811767SAnurag.Maskey@Sun.COM nwamd_event_init(int32_t type, nwam_object_type_t object_type,
17911767SAnurag.Maskey@Sun.COM size_t size, const char *object_name)
18011767SAnurag.Maskey@Sun.COM {
18111767SAnurag.Maskey@Sun.COM nwamd_event_t event;
18211767SAnurag.Maskey@Sun.COM
18311767SAnurag.Maskey@Sun.COM event = calloc(1, sizeof (struct nwamd_event));
18411767SAnurag.Maskey@Sun.COM if (event == NULL) {
18511767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_event_init: could not create %s event for "
18611767SAnurag.Maskey@Sun.COM "object %s", nwamd_event_name(type),
18711767SAnurag.Maskey@Sun.COM object_name != NULL ? object_name : "<no object>");
18811767SAnurag.Maskey@Sun.COM return (NULL);
1893938Sjbeck }
1903938Sjbeck
19111767SAnurag.Maskey@Sun.COM /* Is this an externally-visible event? */
19211767SAnurag.Maskey@Sun.COM if (type <= NWAM_EVENT_MAX) {
19311767SAnurag.Maskey@Sun.COM event->event_send = B_TRUE;
19411767SAnurag.Maskey@Sun.COM event->event_msg = calloc(1, sizeof (struct nwam_event) + size);
19511767SAnurag.Maskey@Sun.COM if (event->event_msg == NULL) {
19611767SAnurag.Maskey@Sun.COM nlog(LOG_ERR,
19711767SAnurag.Maskey@Sun.COM "nwamd_event_init: could not create %s event",
19811767SAnurag.Maskey@Sun.COM nwamd_event_name(type));
19911767SAnurag.Maskey@Sun.COM free(event);
20011767SAnurag.Maskey@Sun.COM return (NULL);
2013938Sjbeck }
20211767SAnurag.Maskey@Sun.COM event->event_msg->nwe_type = type;
20311767SAnurag.Maskey@Sun.COM event->event_msg->nwe_size = sizeof (struct nwam_event) + size;
20411767SAnurag.Maskey@Sun.COM } else {
20511767SAnurag.Maskey@Sun.COM event->event_send = B_FALSE;
20611767SAnurag.Maskey@Sun.COM event->event_msg = NULL;
20711767SAnurag.Maskey@Sun.COM }
2087645Sjames.d.carlson@sun.com
20911767SAnurag.Maskey@Sun.COM event->event_type = type;
2107645Sjames.d.carlson@sun.com
21111767SAnurag.Maskey@Sun.COM if (object_name != NULL) {
21211767SAnurag.Maskey@Sun.COM (void) strlcpy(event->event_object, object_name,
21311767SAnurag.Maskey@Sun.COM NWAM_MAX_NAME_LEN);
21411767SAnurag.Maskey@Sun.COM event->event_object_type = object_type;
21511767SAnurag.Maskey@Sun.COM } else {
21611767SAnurag.Maskey@Sun.COM event->event_object[0] = '\0';
21711767SAnurag.Maskey@Sun.COM }
2187645Sjames.d.carlson@sun.com
21911767SAnurag.Maskey@Sun.COM /* Set event id */
22011767SAnurag.Maskey@Sun.COM event->event_id = atomic_add_64_nv(&event_id_counter, 1);
22111767SAnurag.Maskey@Sun.COM (void) clock_gettime(CLOCK_REALTIME, &event->event_time);
2223938Sjbeck
22311767SAnurag.Maskey@Sun.COM return (event);
2243938Sjbeck }
2253938Sjbeck
22611767SAnurag.Maskey@Sun.COM void
nwamd_event_do_not_send(nwamd_event_t event)22711767SAnurag.Maskey@Sun.COM nwamd_event_do_not_send(nwamd_event_t event)
2283938Sjbeck {
22911767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "nwamd_event_do_not_send: cancelling delivery of "
23011767SAnurag.Maskey@Sun.COM "event %s for object %s", nwamd_event_name(event->event_type),
23111767SAnurag.Maskey@Sun.COM event->event_object[0] != '\0' ?
23211767SAnurag.Maskey@Sun.COM event->event_object : "<no object>");
23311767SAnurag.Maskey@Sun.COM event->event_send = B_FALSE;
2343938Sjbeck }
2353938Sjbeck
23611767SAnurag.Maskey@Sun.COM void
nwamd_event_fini(nwamd_event_t event)23711767SAnurag.Maskey@Sun.COM nwamd_event_fini(nwamd_event_t event)
2383938Sjbeck {
23911767SAnurag.Maskey@Sun.COM if (event != NULL) {
24011767SAnurag.Maskey@Sun.COM free(event->event_msg);
24111767SAnurag.Maskey@Sun.COM free(event);
2423938Sjbeck }
2433938Sjbeck }
2443938Sjbeck
24511767SAnurag.Maskey@Sun.COM 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)24611767SAnurag.Maskey@Sun.COM nwamd_event_init_object_action(nwam_object_type_t object_type,
24711767SAnurag.Maskey@Sun.COM const char *object_name, const char *parent_name,
24811767SAnurag.Maskey@Sun.COM nwam_action_t object_action)
24911767SAnurag.Maskey@Sun.COM {
25011767SAnurag.Maskey@Sun.COM nwamd_event_t event;
25111767SAnurag.Maskey@Sun.COM
25211767SAnurag.Maskey@Sun.COM event = nwamd_event_init(NWAM_EVENT_TYPE_OBJECT_ACTION,
25311767SAnurag.Maskey@Sun.COM object_type, 0, object_name);
25411767SAnurag.Maskey@Sun.COM if (event == NULL)
25511767SAnurag.Maskey@Sun.COM return (NULL);
25611767SAnurag.Maskey@Sun.COM
25711767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_object_action.nwe_action = object_action;
25811767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_object_action.nwe_object_type =
25911767SAnurag.Maskey@Sun.COM object_type;
26011767SAnurag.Maskey@Sun.COM (void) strlcpy(event->event_msg->nwe_data.nwe_object_action.nwe_name,
26111767SAnurag.Maskey@Sun.COM object_name,
26211767SAnurag.Maskey@Sun.COM sizeof (event->event_msg->nwe_data.nwe_object_action.nwe_name));
26311767SAnurag.Maskey@Sun.COM if (parent_name == NULL) {
26411767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_object_action.nwe_parent[0] =
26511767SAnurag.Maskey@Sun.COM '\0';
26611767SAnurag.Maskey@Sun.COM return (event);
26711767SAnurag.Maskey@Sun.COM }
26811767SAnurag.Maskey@Sun.COM (void) strlcpy
26911767SAnurag.Maskey@Sun.COM (event->event_msg->nwe_data.nwe_object_action.nwe_parent,
27011767SAnurag.Maskey@Sun.COM parent_name,
27111767SAnurag.Maskey@Sun.COM sizeof (event->event_msg->nwe_data.nwe_object_action.nwe_parent));
27211767SAnurag.Maskey@Sun.COM return (event);
27311767SAnurag.Maskey@Sun.COM }
27411767SAnurag.Maskey@Sun.COM
27511767SAnurag.Maskey@Sun.COM 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)27611767SAnurag.Maskey@Sun.COM nwamd_event_init_object_state(nwam_object_type_t object_type,
27711767SAnurag.Maskey@Sun.COM const char *object_name, nwam_state_t state, nwam_aux_state_t aux_state)
27811767SAnurag.Maskey@Sun.COM {
27911767SAnurag.Maskey@Sun.COM nwamd_event_t event;
28011767SAnurag.Maskey@Sun.COM
28111767SAnurag.Maskey@Sun.COM event = nwamd_event_init(NWAM_EVENT_TYPE_OBJECT_STATE,
28211767SAnurag.Maskey@Sun.COM object_type, 0, object_name);
28311767SAnurag.Maskey@Sun.COM if (event == NULL)
28411767SAnurag.Maskey@Sun.COM return (NULL);
28511767SAnurag.Maskey@Sun.COM
28611767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_object_state.nwe_state = state;
28711767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_object_state.nwe_aux_state = aux_state;
28811767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_object_state.nwe_object_type =
28911767SAnurag.Maskey@Sun.COM object_type;
29011767SAnurag.Maskey@Sun.COM (void) strlcpy(event->event_msg->nwe_data.nwe_object_state.nwe_name,
29111767SAnurag.Maskey@Sun.COM object_name,
29211767SAnurag.Maskey@Sun.COM sizeof (event->event_msg->nwe_data.nwe_object_state.nwe_name));
29311767SAnurag.Maskey@Sun.COM
29411767SAnurag.Maskey@Sun.COM return (event);
29511767SAnurag.Maskey@Sun.COM }
29611767SAnurag.Maskey@Sun.COM
29711767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_priority_group_change(int64_t priority)29811767SAnurag.Maskey@Sun.COM nwamd_event_init_priority_group_change(int64_t priority)
2993938Sjbeck {
30011767SAnurag.Maskey@Sun.COM nwamd_event_t event;
30111767SAnurag.Maskey@Sun.COM
30211767SAnurag.Maskey@Sun.COM event = nwamd_event_init(NWAM_EVENT_TYPE_PRIORITY_GROUP,
30311767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL);
30411767SAnurag.Maskey@Sun.COM if (event == NULL)
30511767SAnurag.Maskey@Sun.COM return (NULL);
30611767SAnurag.Maskey@Sun.COM
30711767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_priority_group_info.nwe_priority =
30811767SAnurag.Maskey@Sun.COM priority;
30911767SAnurag.Maskey@Sun.COM
31011767SAnurag.Maskey@Sun.COM return (event);
31111767SAnurag.Maskey@Sun.COM }
31211767SAnurag.Maskey@Sun.COM
31311767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_link_action(const char * name,nwam_action_t link_action)31411767SAnurag.Maskey@Sun.COM nwamd_event_init_link_action(const char *name, nwam_action_t link_action)
31511767SAnurag.Maskey@Sun.COM {
31611767SAnurag.Maskey@Sun.COM nwamd_event_t event;
31711767SAnurag.Maskey@Sun.COM nwam_error_t err;
31811767SAnurag.Maskey@Sun.COM char *object_name;
3193938Sjbeck
32011767SAnurag.Maskey@Sun.COM if ((err = nwam_ncu_name_to_typed_name(name, NWAM_NCU_TYPE_LINK,
32111767SAnurag.Maskey@Sun.COM &object_name)) != NWAM_SUCCESS) {
32211767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_event_init_link_action: "
32311767SAnurag.Maskey@Sun.COM "nwam_ncu_name_to_typed_name: %s",
32411767SAnurag.Maskey@Sun.COM nwam_strerror(err));
32511767SAnurag.Maskey@Sun.COM return (NULL);
32611767SAnurag.Maskey@Sun.COM }
32711767SAnurag.Maskey@Sun.COM event = nwamd_event_init(NWAM_EVENT_TYPE_LINK_ACTION,
32811767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_NCU, 0, object_name);
32911767SAnurag.Maskey@Sun.COM free(object_name);
33011767SAnurag.Maskey@Sun.COM if (event == NULL)
33111767SAnurag.Maskey@Sun.COM return (NULL);
33211767SAnurag.Maskey@Sun.COM
33311767SAnurag.Maskey@Sun.COM (void) strlcpy(event->event_msg->nwe_data.nwe_link_action.nwe_name,
33411767SAnurag.Maskey@Sun.COM name,
33511767SAnurag.Maskey@Sun.COM sizeof (event->event_msg->nwe_data.nwe_link_action.nwe_name));
33611767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_link_action.nwe_action = link_action;
33711767SAnurag.Maskey@Sun.COM
33811767SAnurag.Maskey@Sun.COM return (event);
33911767SAnurag.Maskey@Sun.COM }
34011767SAnurag.Maskey@Sun.COM
34111767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_link_state(const char * name,boolean_t up)34211767SAnurag.Maskey@Sun.COM nwamd_event_init_link_state(const char *name, boolean_t up)
34311767SAnurag.Maskey@Sun.COM {
34411767SAnurag.Maskey@Sun.COM nwamd_event_t event;
34511767SAnurag.Maskey@Sun.COM nwam_error_t err;
34611767SAnurag.Maskey@Sun.COM char *object_name;
34711767SAnurag.Maskey@Sun.COM
34811767SAnurag.Maskey@Sun.COM if ((err = nwam_ncu_name_to_typed_name(name, NWAM_NCU_TYPE_LINK,
34911767SAnurag.Maskey@Sun.COM &object_name)) != NWAM_SUCCESS) {
35011767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_event_init_link_state: "
35111767SAnurag.Maskey@Sun.COM "nwam_ncu_name_to_typed_name: %s",
35211767SAnurag.Maskey@Sun.COM nwam_strerror(err));
35311767SAnurag.Maskey@Sun.COM return (NULL);
35411767SAnurag.Maskey@Sun.COM }
35511767SAnurag.Maskey@Sun.COM
35611767SAnurag.Maskey@Sun.COM event = nwamd_event_init(NWAM_EVENT_TYPE_LINK_STATE,
35711767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_NCU, 0, object_name);
35811767SAnurag.Maskey@Sun.COM free(object_name);
35911767SAnurag.Maskey@Sun.COM if (event == NULL)
3603938Sjbeck return (NULL);
3613938Sjbeck
36211767SAnurag.Maskey@Sun.COM (void) strlcpy(event->event_msg->nwe_data.nwe_link_state.nwe_name, name,
36311767SAnurag.Maskey@Sun.COM sizeof (event->event_msg->nwe_data.nwe_link_state.nwe_name));
36411767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_link_state.nwe_link_up = up;
36511767SAnurag.Maskey@Sun.COM
36611767SAnurag.Maskey@Sun.COM return (event);
36711767SAnurag.Maskey@Sun.COM }
36811767SAnurag.Maskey@Sun.COM
36911767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_if_state(const char * linkname,uint32_t flags,uint32_t addr_added,struct sockaddr * addr,struct sockaddr * netmask)37011767SAnurag.Maskey@Sun.COM nwamd_event_init_if_state(const char *linkname, uint32_t flags,
371*12576SAnurag.Maskey@Oracle.COM uint32_t addr_added, struct sockaddr *addr, struct sockaddr *netmask)
37211767SAnurag.Maskey@Sun.COM {
37311767SAnurag.Maskey@Sun.COM nwamd_event_t event;
37411767SAnurag.Maskey@Sun.COM nwam_error_t err;
37511767SAnurag.Maskey@Sun.COM char *object_name;
37611767SAnurag.Maskey@Sun.COM
37711767SAnurag.Maskey@Sun.COM /* linkname does not contain the lifnum */
37811767SAnurag.Maskey@Sun.COM if ((err = nwam_ncu_name_to_typed_name(linkname,
37911767SAnurag.Maskey@Sun.COM NWAM_NCU_TYPE_INTERFACE, &object_name)) != NWAM_SUCCESS) {
38011767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_event_init_if_state: "
38111767SAnurag.Maskey@Sun.COM "nwam_ncu_name_to_typed_name: %s",
38211767SAnurag.Maskey@Sun.COM nwam_strerror(err));
38311767SAnurag.Maskey@Sun.COM return (NULL);
3843938Sjbeck }
38511767SAnurag.Maskey@Sun.COM
38611767SAnurag.Maskey@Sun.COM event = nwamd_event_init(NWAM_EVENT_TYPE_IF_STATE,
38711767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_NCU, 0, object_name);
38811767SAnurag.Maskey@Sun.COM free(object_name);
38911767SAnurag.Maskey@Sun.COM if (event == NULL)
39011767SAnurag.Maskey@Sun.COM return (NULL);
39111767SAnurag.Maskey@Sun.COM
39211767SAnurag.Maskey@Sun.COM (void) strlcpy(event->event_msg->nwe_data.nwe_if_state.nwe_name,
39311767SAnurag.Maskey@Sun.COM linkname,
39411767SAnurag.Maskey@Sun.COM sizeof (event->event_msg->nwe_data.nwe_if_state.nwe_name));
39511767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_if_state.nwe_flags = flags;
39611767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_if_state.nwe_addr_added = addr_added;
39711767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_if_state.nwe_addr_valid = (addr != NULL);
39811767SAnurag.Maskey@Sun.COM
39911767SAnurag.Maskey@Sun.COM if (addr != NULL) {
40011767SAnurag.Maskey@Sun.COM bcopy(addr, &(event->event_msg->nwe_data.nwe_if_state.nwe_addr),
40111767SAnurag.Maskey@Sun.COM addr->sa_family == AF_INET ? sizeof (struct sockaddr_in) :
40211767SAnurag.Maskey@Sun.COM sizeof (struct sockaddr_in6));
40311767SAnurag.Maskey@Sun.COM }
404*12576SAnurag.Maskey@Oracle.COM if (netmask != NULL) {
405*12576SAnurag.Maskey@Oracle.COM bcopy(netmask,
406*12576SAnurag.Maskey@Oracle.COM &(event->event_msg->nwe_data.nwe_if_state.nwe_netmask),
407*12576SAnurag.Maskey@Oracle.COM netmask->sa_family == AF_INET ?
408*12576SAnurag.Maskey@Oracle.COM sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6));
409*12576SAnurag.Maskey@Oracle.COM }
41011767SAnurag.Maskey@Sun.COM
41111767SAnurag.Maskey@Sun.COM return (event);
4123938Sjbeck }
4133938Sjbeck
41411767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_wlan(const char * name,int32_t type,boolean_t connected,nwam_wlan_t * wlans,uint_t num_wlans)41511767SAnurag.Maskey@Sun.COM nwamd_event_init_wlan(const char *name, int32_t type, boolean_t connected,
41611767SAnurag.Maskey@Sun.COM nwam_wlan_t *wlans, uint_t num_wlans)
41711767SAnurag.Maskey@Sun.COM {
41811767SAnurag.Maskey@Sun.COM size_t size = 0;
41911767SAnurag.Maskey@Sun.COM char *object_name;
42011767SAnurag.Maskey@Sun.COM nwamd_event_t event;
42111767SAnurag.Maskey@Sun.COM nwam_error_t err;
42211767SAnurag.Maskey@Sun.COM
42311767SAnurag.Maskey@Sun.COM switch (type) {
42411767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_WLAN_SCAN_REPORT:
42511767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_WLAN_NEED_CHOICE:
42611767SAnurag.Maskey@Sun.COM size = sizeof (nwam_wlan_t) * (num_wlans - 1);
42711767SAnurag.Maskey@Sun.COM break;
42811767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_WLAN_NEED_KEY:
42911767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT:
43011767SAnurag.Maskey@Sun.COM break;
43111767SAnurag.Maskey@Sun.COM default:
43211767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_event_init_wlan: unexpected "
43311767SAnurag.Maskey@Sun.COM "event type %s (%d)", nwamd_event_name(type), type);
43411767SAnurag.Maskey@Sun.COM return (NULL);
43511767SAnurag.Maskey@Sun.COM }
43611767SAnurag.Maskey@Sun.COM if ((err = nwam_ncu_name_to_typed_name(name, NWAM_NCU_TYPE_LINK,
43711767SAnurag.Maskey@Sun.COM &object_name)) != NWAM_SUCCESS) {
43811767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_event_init_wlan: "
43911767SAnurag.Maskey@Sun.COM "nwam_ncu_name_to_typed_name: %s",
44011767SAnurag.Maskey@Sun.COM nwam_strerror(err));
44111767SAnurag.Maskey@Sun.COM return (NULL);
44211767SAnurag.Maskey@Sun.COM }
44311767SAnurag.Maskey@Sun.COM
44411767SAnurag.Maskey@Sun.COM event = nwamd_event_init(type, NWAM_OBJECT_TYPE_NCU, size, object_name);
44511767SAnurag.Maskey@Sun.COM free(object_name);
44611767SAnurag.Maskey@Sun.COM if (event == NULL)
44711767SAnurag.Maskey@Sun.COM return (NULL);
44811767SAnurag.Maskey@Sun.COM
44911767SAnurag.Maskey@Sun.COM (void) strlcpy(event->event_msg->nwe_data.nwe_wlan_info.nwe_name, name,
45011767SAnurag.Maskey@Sun.COM sizeof (event->event_msg->nwe_data.nwe_wlan_info.nwe_name));
45111767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_wlan_info.nwe_connected = connected;
45211767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.nwe_wlan_info.nwe_num_wlans = num_wlans;
45311767SAnurag.Maskey@Sun.COM
45411767SAnurag.Maskey@Sun.COM /* copy the wlans */
45511767SAnurag.Maskey@Sun.COM (void) memcpy(event->event_msg->nwe_data.nwe_wlan_info.nwe_wlans, wlans,
45611767SAnurag.Maskey@Sun.COM num_wlans * sizeof (nwam_wlan_t));
45711767SAnurag.Maskey@Sun.COM
45811767SAnurag.Maskey@Sun.COM return (event);
45911767SAnurag.Maskey@Sun.COM }
46011767SAnurag.Maskey@Sun.COM
46111767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_ncu_check(void)46211767SAnurag.Maskey@Sun.COM nwamd_event_init_ncu_check(void)
4633938Sjbeck {
46411767SAnurag.Maskey@Sun.COM return (nwamd_event_init(NWAM_EVENT_TYPE_NCU_CHECK,
46511767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_NCP, 0, NULL));
46611767SAnurag.Maskey@Sun.COM }
46711767SAnurag.Maskey@Sun.COM
46811767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_init(void)46911767SAnurag.Maskey@Sun.COM nwamd_event_init_init(void)
47011767SAnurag.Maskey@Sun.COM {
47111767SAnurag.Maskey@Sun.COM return (nwamd_event_init(NWAM_EVENT_TYPE_INIT,
47211767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL));
47311767SAnurag.Maskey@Sun.COM }
47411767SAnurag.Maskey@Sun.COM
47511767SAnurag.Maskey@Sun.COM nwamd_event_t
nwamd_event_init_shutdown(void)47611767SAnurag.Maskey@Sun.COM nwamd_event_init_shutdown(void)
47711767SAnurag.Maskey@Sun.COM {
47811767SAnurag.Maskey@Sun.COM return (nwamd_event_init(NWAM_EVENT_TYPE_SHUTDOWN,
47911767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL));
48011767SAnurag.Maskey@Sun.COM }
48111767SAnurag.Maskey@Sun.COM
48211767SAnurag.Maskey@Sun.COM /*
48311767SAnurag.Maskey@Sun.COM * Add event to the event list.
48411767SAnurag.Maskey@Sun.COM */
48511767SAnurag.Maskey@Sun.COM void
nwamd_event_enqueue(nwamd_event_t event)48611767SAnurag.Maskey@Sun.COM nwamd_event_enqueue(nwamd_event_t event)
48711767SAnurag.Maskey@Sun.COM {
48811767SAnurag.Maskey@Sun.COM nwamd_event_enqueue_timed(event, 0);
48911767SAnurag.Maskey@Sun.COM }
49011767SAnurag.Maskey@Sun.COM
49111767SAnurag.Maskey@Sun.COM /*
49211767SAnurag.Maskey@Sun.COM * Schedule an event to be added to the event list for future processing.
49311767SAnurag.Maskey@Sun.COM * The event will be scheduled in delta_seconds seconds mod schedule delay and
49411767SAnurag.Maskey@Sun.COM * time resolution.
49511767SAnurag.Maskey@Sun.COM */
49611767SAnurag.Maskey@Sun.COM void
nwamd_event_enqueue_timed(nwamd_event_t event,int delta_seconds)49711767SAnurag.Maskey@Sun.COM nwamd_event_enqueue_timed(nwamd_event_t event, int delta_seconds)
49811767SAnurag.Maskey@Sun.COM {
49911767SAnurag.Maskey@Sun.COM uu_list_index_t idx;
50011767SAnurag.Maskey@Sun.COM
50111767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "enqueueing event %lld %d (%s) for object %s in %ds",
50211767SAnurag.Maskey@Sun.COM event->event_id, event->event_type,
50311767SAnurag.Maskey@Sun.COM nwamd_event_name(event->event_type),
50411767SAnurag.Maskey@Sun.COM event->event_object[0] != 0 ? event->event_object : "none",
50511767SAnurag.Maskey@Sun.COM delta_seconds);
50611767SAnurag.Maskey@Sun.COM
50711767SAnurag.Maskey@Sun.COM (void) clock_gettime(CLOCK_REALTIME, &event->event_time);
50811767SAnurag.Maskey@Sun.COM event->event_time.tv_sec += delta_seconds;
50911767SAnurag.Maskey@Sun.COM
51011767SAnurag.Maskey@Sun.COM uu_list_node_init(event, &event->event_node, event_pool);
51111767SAnurag.Maskey@Sun.COM
51211767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&event_queue_mutex);
5133938Sjbeck
5143938Sjbeck /*
51511767SAnurag.Maskey@Sun.COM * Find appropriate location to insert the event based on time.
5163938Sjbeck */
51711767SAnurag.Maskey@Sun.COM (void) uu_list_find(event_queue, event, NULL, &idx);
51811767SAnurag.Maskey@Sun.COM (void) uu_list_insert(event_queue, event, idx);
51911767SAnurag.Maskey@Sun.COM
52011767SAnurag.Maskey@Sun.COM (void) pthread_cond_signal(&event_queue_cond);
52111767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&event_queue_mutex);
52211767SAnurag.Maskey@Sun.COM }
52311767SAnurag.Maskey@Sun.COM
52411767SAnurag.Maskey@Sun.COM /*
52511767SAnurag.Maskey@Sun.COM * Is the specified event enqueued on the event (or pending event queue)
52611767SAnurag.Maskey@Sun.COM * for execution in when seconds? An object may be specified also.
52711767SAnurag.Maskey@Sun.COM */
52811767SAnurag.Maskey@Sun.COM boolean_t
nwamd_event_enqueued(int32_t event_type,nwam_object_type_t object_type,const char * object)52911767SAnurag.Maskey@Sun.COM nwamd_event_enqueued(int32_t event_type, nwam_object_type_t object_type,
53011767SAnurag.Maskey@Sun.COM const char *object)
53111767SAnurag.Maskey@Sun.COM {
53211767SAnurag.Maskey@Sun.COM nwamd_event_t event;
5333938Sjbeck
53411767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&event_queue_mutex);
53511767SAnurag.Maskey@Sun.COM for (event = uu_list_first(event_queue);
53611767SAnurag.Maskey@Sun.COM event != NULL;
53711767SAnurag.Maskey@Sun.COM event = uu_list_next(event_queue, event)) {
53811767SAnurag.Maskey@Sun.COM if (event->event_type != event_type)
53911767SAnurag.Maskey@Sun.COM continue;
54011767SAnurag.Maskey@Sun.COM if (object_type != NWAM_OBJECT_TYPE_UNKNOWN &&
54111767SAnurag.Maskey@Sun.COM event->event_object_type != object_type)
54211767SAnurag.Maskey@Sun.COM continue;
54311767SAnurag.Maskey@Sun.COM if (object != NULL && strcmp(object, event->event_object) != 0)
54411767SAnurag.Maskey@Sun.COM continue;
54511767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&event_queue_mutex);
54611767SAnurag.Maskey@Sun.COM return (B_TRUE);
5473938Sjbeck }
54811767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&event_queue_mutex);
54911767SAnurag.Maskey@Sun.COM
55011767SAnurag.Maskey@Sun.COM return (B_FALSE);
55111767SAnurag.Maskey@Sun.COM }
55211767SAnurag.Maskey@Sun.COM
55311767SAnurag.Maskey@Sun.COM /*
55411767SAnurag.Maskey@Sun.COM * Is the time in the past.
55511767SAnurag.Maskey@Sun.COM */
55611767SAnurag.Maskey@Sun.COM static boolean_t
in_past(struct timespec t)55711767SAnurag.Maskey@Sun.COM in_past(struct timespec t)
55811767SAnurag.Maskey@Sun.COM {
55911767SAnurag.Maskey@Sun.COM struct timespec now;
56011767SAnurag.Maskey@Sun.COM
56111767SAnurag.Maskey@Sun.COM (void) clock_gettime(CLOCK_REALTIME, &now);
56211767SAnurag.Maskey@Sun.COM if (t.tv_sec < now.tv_sec)
56311767SAnurag.Maskey@Sun.COM return (B_TRUE);
56411767SAnurag.Maskey@Sun.COM if (t.tv_sec > now.tv_sec)
56511767SAnurag.Maskey@Sun.COM return (B_FALSE);
56611767SAnurag.Maskey@Sun.COM if (t.tv_nsec < now.tv_nsec)
56711767SAnurag.Maskey@Sun.COM return (B_TRUE);
56811767SAnurag.Maskey@Sun.COM return (B_FALSE);
56911767SAnurag.Maskey@Sun.COM }
5703938Sjbeck
57111767SAnurag.Maskey@Sun.COM /*
57211767SAnurag.Maskey@Sun.COM * Remove event at head of event list for processing. This takes a number of
57311767SAnurag.Maskey@Sun.COM * nanoseconds to wait. If the number is 0 then it blocks. If there is
57411767SAnurag.Maskey@Sun.COM * nothing on the queue then it returns an event which says that the queue
57511767SAnurag.Maskey@Sun.COM * is quiet.
57611767SAnurag.Maskey@Sun.COM */
57711767SAnurag.Maskey@Sun.COM static nwamd_event_t
nwamd_event_dequeue(long nsec)57811767SAnurag.Maskey@Sun.COM nwamd_event_dequeue(long nsec)
57911767SAnurag.Maskey@Sun.COM {
58011767SAnurag.Maskey@Sun.COM nwamd_event_t event;
58111767SAnurag.Maskey@Sun.COM
58211767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&event_queue_mutex);
58311767SAnurag.Maskey@Sun.COM event = uu_list_first(event_queue);
58411767SAnurag.Maskey@Sun.COM if (event == NULL && nsec == 0) {
58511767SAnurag.Maskey@Sun.COM do {
58611767SAnurag.Maskey@Sun.COM (void) pthread_cond_wait(&event_queue_cond,
58711767SAnurag.Maskey@Sun.COM &event_queue_mutex);
58811767SAnurag.Maskey@Sun.COM } while ((event = uu_list_first(event_queue)) == NULL);
58911767SAnurag.Maskey@Sun.COM } else {
59011767SAnurag.Maskey@Sun.COM struct timespec waitcap;
59111767SAnurag.Maskey@Sun.COM
59211767SAnurag.Maskey@Sun.COM if (nsec != 0) {
59311767SAnurag.Maskey@Sun.COM (void) clock_gettime(CLOCK_REALTIME, &waitcap);
59411767SAnurag.Maskey@Sun.COM waitcap.tv_nsec += nsec;
59511767SAnurag.Maskey@Sun.COM waitcap.tv_sec += NSEC_TO_SEC(waitcap.tv_nsec);
59611767SAnurag.Maskey@Sun.COM waitcap.tv_nsec = NSEC_TO_FRACNSEC(waitcap.tv_nsec);
5978264Sjames.d.carlson@sun.com }
59811767SAnurag.Maskey@Sun.COM
59911767SAnurag.Maskey@Sun.COM /*
60011767SAnurag.Maskey@Sun.COM * Keep going as long as the first event hasn't matured and
60111767SAnurag.Maskey@Sun.COM * we havn't passed our maximum wait time.
60211767SAnurag.Maskey@Sun.COM */
60311767SAnurag.Maskey@Sun.COM while ((event == NULL || !in_past(event->event_time)) &&
60411767SAnurag.Maskey@Sun.COM (nsec == 0 || !in_past(waitcap))) {
60511767SAnurag.Maskey@Sun.COM struct timespec eventwait;
60611767SAnurag.Maskey@Sun.COM
60711767SAnurag.Maskey@Sun.COM /*
60811767SAnurag.Maskey@Sun.COM * Three cases:
60911767SAnurag.Maskey@Sun.COM * no maximum waittime - just use the event
61011767SAnurag.Maskey@Sun.COM * both an event and cap - take the least one
61111767SAnurag.Maskey@Sun.COM * just a maximum waittime - use it
61211767SAnurag.Maskey@Sun.COM */
61311767SAnurag.Maskey@Sun.COM if (nsec == 0) {
61411767SAnurag.Maskey@Sun.COM eventwait = event->event_time;
61511767SAnurag.Maskey@Sun.COM } else if (event != NULL) {
61611767SAnurag.Maskey@Sun.COM uint64_t diff;
61711767SAnurag.Maskey@Sun.COM diff = SEC_TO_NSEC(event->event_time.tv_sec -
61811767SAnurag.Maskey@Sun.COM waitcap.tv_sec) +
61911767SAnurag.Maskey@Sun.COM event->event_time.tv_nsec - waitcap.tv_nsec;
62011767SAnurag.Maskey@Sun.COM
62111767SAnurag.Maskey@Sun.COM if (diff > 0)
62211767SAnurag.Maskey@Sun.COM eventwait = waitcap;
62311767SAnurag.Maskey@Sun.COM else
62411767SAnurag.Maskey@Sun.COM eventwait = event->event_time;
62511767SAnurag.Maskey@Sun.COM } else {
62611767SAnurag.Maskey@Sun.COM /*
62711767SAnurag.Maskey@Sun.COM * Note that if the event is NULL then nsec is
62811767SAnurag.Maskey@Sun.COM * nonzero and waitcap is valid.
62911767SAnurag.Maskey@Sun.COM */
63011767SAnurag.Maskey@Sun.COM eventwait = waitcap;
63111767SAnurag.Maskey@Sun.COM }
63211767SAnurag.Maskey@Sun.COM
63311767SAnurag.Maskey@Sun.COM (void) pthread_cond_timedwait(&event_queue_cond,
63411767SAnurag.Maskey@Sun.COM &event_queue_mutex, &eventwait);
63511767SAnurag.Maskey@Sun.COM event = uu_list_first(event_queue);
63611767SAnurag.Maskey@Sun.COM }
6373938Sjbeck }
6383938Sjbeck
6397645Sjames.d.carlson@sun.com /*
64011767SAnurag.Maskey@Sun.COM * At this point we've met the guard contition of the while loop.
64111767SAnurag.Maskey@Sun.COM * The event at the top of the queue might be mature in which case
64211767SAnurag.Maskey@Sun.COM * we use it. Otherwise we hit our cap and we need to enqueue a
64311767SAnurag.Maskey@Sun.COM * quiesced queue event.
6447645Sjames.d.carlson@sun.com */
64511767SAnurag.Maskey@Sun.COM if (event != NULL && in_past(event->event_time)) {
64611767SAnurag.Maskey@Sun.COM uu_list_remove(event_queue, event);
64711767SAnurag.Maskey@Sun.COM uu_list_node_fini(event, &event->event_node, event_pool);
64811767SAnurag.Maskey@Sun.COM } else {
64911767SAnurag.Maskey@Sun.COM event = nwamd_event_init(NWAM_EVENT_TYPE_QUEUE_QUIET,
65011767SAnurag.Maskey@Sun.COM NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL);
65111767SAnurag.Maskey@Sun.COM }
65211767SAnurag.Maskey@Sun.COM
65311767SAnurag.Maskey@Sun.COM if (event != NULL)
65411767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG,
65511767SAnurag.Maskey@Sun.COM "dequeueing event %lld of type %d (%s) for object %s",
65611767SAnurag.Maskey@Sun.COM event->event_id, event->event_type,
65711767SAnurag.Maskey@Sun.COM nwamd_event_name(event->event_type),
65811767SAnurag.Maskey@Sun.COM event->event_object[0] != 0 ? event->event_object :
65911767SAnurag.Maskey@Sun.COM "none");
66011767SAnurag.Maskey@Sun.COM
66111767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&event_queue_mutex);
66211767SAnurag.Maskey@Sun.COM
66311767SAnurag.Maskey@Sun.COM return (event);
66411767SAnurag.Maskey@Sun.COM }
66511767SAnurag.Maskey@Sun.COM
66611767SAnurag.Maskey@Sun.COM void
nwamd_event_send(nwam_event_t event_msg)66711767SAnurag.Maskey@Sun.COM nwamd_event_send(nwam_event_t event_msg)
66811767SAnurag.Maskey@Sun.COM {
66911767SAnurag.Maskey@Sun.COM nwam_error_t err;
67011767SAnurag.Maskey@Sun.COM
67111767SAnurag.Maskey@Sun.COM if (shutting_down && event_msg->nwe_type != NWAM_EVENT_TYPE_SHUTDOWN) {
67211767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "nwamd_event_send: tossing event as nwamd "
67311767SAnurag.Maskey@Sun.COM "is shutting down");
67411767SAnurag.Maskey@Sun.COM return;
67511767SAnurag.Maskey@Sun.COM }
67611767SAnurag.Maskey@Sun.COM
67711767SAnurag.Maskey@Sun.COM err = nwam_event_send(event_msg);
67811767SAnurag.Maskey@Sun.COM
67911767SAnurag.Maskey@Sun.COM if (err != NWAM_SUCCESS) {
68011767SAnurag.Maskey@Sun.COM nlog(LOG_ERR, "nwamd_event_send: nwam_event_send: %s",
68111767SAnurag.Maskey@Sun.COM nwam_strerror(err));
68211767SAnurag.Maskey@Sun.COM }
68311767SAnurag.Maskey@Sun.COM }
68411767SAnurag.Maskey@Sun.COM
68511767SAnurag.Maskey@Sun.COM /*
68611767SAnurag.Maskey@Sun.COM * Run state machine for object. Method is run if
68711767SAnurag.Maskey@Sun.COM * - event method is non-null
68811767SAnurag.Maskey@Sun.COM * - event method is valid for current object state (determined by
68911767SAnurag.Maskey@Sun.COM * ORing the current state against the set of valid states for the method).
69011767SAnurag.Maskey@Sun.COM *
69111767SAnurag.Maskey@Sun.COM * If these criteria are met, the method is run.
69211767SAnurag.Maskey@Sun.COM */
69311767SAnurag.Maskey@Sun.COM static void
nwamd_event_run_method(nwamd_event_t event)69411767SAnurag.Maskey@Sun.COM nwamd_event_run_method(nwamd_event_t event)
69511767SAnurag.Maskey@Sun.COM {
69611767SAnurag.Maskey@Sun.COM nwamd_event_method_t *event_methods;
69711767SAnurag.Maskey@Sun.COM int i;
69811767SAnurag.Maskey@Sun.COM
69911767SAnurag.Maskey@Sun.COM event_methods = nwamd_object_event_methods(event->event_object_type);
70011767SAnurag.Maskey@Sun.COM
70111767SAnurag.Maskey@Sun.COM /* If we're shutting down, only fini events are accepted for objects */
70211767SAnurag.Maskey@Sun.COM if (shutting_down && event->event_type != NWAM_EVENT_TYPE_OBJECT_FINI) {
70311767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "nwamd_event_run_method: tossing non-fini "
70411767SAnurag.Maskey@Sun.COM "event %s for object %s",
70511767SAnurag.Maskey@Sun.COM nwamd_event_name(event->event_type), event->event_object);
70611767SAnurag.Maskey@Sun.COM return;
70711767SAnurag.Maskey@Sun.COM }
70811767SAnurag.Maskey@Sun.COM
70911767SAnurag.Maskey@Sun.COM for (i = 0;
71011767SAnurag.Maskey@Sun.COM event_methods[i].event_type != NWAM_EVENT_TYPE_NOOP;
71111767SAnurag.Maskey@Sun.COM i++) {
71211767SAnurag.Maskey@Sun.COM if (event_methods[i].event_type ==
71311767SAnurag.Maskey@Sun.COM event->event_type &&
71411767SAnurag.Maskey@Sun.COM event_methods[i].event_method != NULL) {
71511767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG,
71611767SAnurag.Maskey@Sun.COM "(%p) %s: running method for event %s",
71711767SAnurag.Maskey@Sun.COM (void *)event, event->event_object,
71811767SAnurag.Maskey@Sun.COM nwamd_event_name(event->event_type));
71911767SAnurag.Maskey@Sun.COM /* run method */
72011767SAnurag.Maskey@Sun.COM event_methods[i].event_method(event);
72111767SAnurag.Maskey@Sun.COM return;
72211767SAnurag.Maskey@Sun.COM }
72311767SAnurag.Maskey@Sun.COM }
72411767SAnurag.Maskey@Sun.COM nlog(LOG_DEBUG, "(%p) %s: no matching method for event %d (%s)",
72511767SAnurag.Maskey@Sun.COM (void *)event, event->event_object, event->event_type,
72611767SAnurag.Maskey@Sun.COM nwamd_event_name(event->event_type));
72711767SAnurag.Maskey@Sun.COM }
72811767SAnurag.Maskey@Sun.COM
72911767SAnurag.Maskey@Sun.COM /*
73011767SAnurag.Maskey@Sun.COM * Called when we are checking to see what should be activated. First activate
73111767SAnurag.Maskey@Sun.COM * all of the manual NCUs. Then see if we can find a valid priority group.
73211767SAnurag.Maskey@Sun.COM * If we can, activate it. Otherwise try all the priority groups starting
73311767SAnurag.Maskey@Sun.COM * with the lowest one that makes sense.
73411767SAnurag.Maskey@Sun.COM */
73511767SAnurag.Maskey@Sun.COM static void
nwamd_activate_ncus(void)73611767SAnurag.Maskey@Sun.COM nwamd_activate_ncus(void) {
73711767SAnurag.Maskey@Sun.COM int64_t prio = INVALID_PRIORITY_GROUP;
73811767SAnurag.Maskey@Sun.COM boolean_t selected;
7397645Sjames.d.carlson@sun.com
74011767SAnurag.Maskey@Sun.COM nwamd_ncp_activate_manual_ncus();
74111767SAnurag.Maskey@Sun.COM selected = nwamd_ncp_check_priority_group(&prio);
74211767SAnurag.Maskey@Sun.COM if (selected) {
74311767SAnurag.Maskey@Sun.COM /*
74411767SAnurag.Maskey@Sun.COM * Activate chosen priority group and stop anything going on in
74511767SAnurag.Maskey@Sun.COM * lesser priority groups.
74611767SAnurag.Maskey@Sun.COM */
74711767SAnurag.Maskey@Sun.COM nwamd_ncp_activate_priority_group(prio);
74811767SAnurag.Maskey@Sun.COM nwamd_ncp_deactivate_priority_group_all(prio + 1);
74911767SAnurag.Maskey@Sun.COM } else {
75011767SAnurag.Maskey@Sun.COM /*
75111767SAnurag.Maskey@Sun.COM * Nothing unique could be started so try them all. Once one
75211767SAnurag.Maskey@Sun.COM * of them gets into a reasonable state then we will prune
75311767SAnurag.Maskey@Sun.COM * everything below it (see first part of this conditional).
75411767SAnurag.Maskey@Sun.COM */
75511767SAnurag.Maskey@Sun.COM int64_t oldprio = INVALID_PRIORITY_GROUP;
75611767SAnurag.Maskey@Sun.COM while (nwamd_ncp_find_next_priority_group(++oldprio, &prio)) {
75711767SAnurag.Maskey@Sun.COM nwamd_ncp_activate_priority_group(prio);
75811767SAnurag.Maskey@Sun.COM oldprio = prio;
75911767SAnurag.Maskey@Sun.COM }
76011767SAnurag.Maskey@Sun.COM }
76111767SAnurag.Maskey@Sun.COM }
76211767SAnurag.Maskey@Sun.COM
76311767SAnurag.Maskey@Sun.COM /*
76411767SAnurag.Maskey@Sun.COM * Event handler thread
76511767SAnurag.Maskey@Sun.COM *
76611767SAnurag.Maskey@Sun.COM * The complexity in this code comes about from wanting to delay the decision
76711767SAnurag.Maskey@Sun.COM * making process until after bursts of events. Keep roughly polling (waiting
76811767SAnurag.Maskey@Sun.COM * for .1s) until we see the queue quiet event and then block.
76911767SAnurag.Maskey@Sun.COM */
77011767SAnurag.Maskey@Sun.COM void
nwamd_event_handler(void)77111767SAnurag.Maskey@Sun.COM nwamd_event_handler(void)
77211767SAnurag.Maskey@Sun.COM {
77311767SAnurag.Maskey@Sun.COM boolean_t got_shutdown_event = B_FALSE;
77411767SAnurag.Maskey@Sun.COM boolean_t check_conditions = B_FALSE;
77511767SAnurag.Maskey@Sun.COM boolean_t ncu_check = B_FALSE;
77611767SAnurag.Maskey@Sun.COM int queue_quiet_time = 0;
77711767SAnurag.Maskey@Sun.COM nwamd_event_t event;
77811767SAnurag.Maskey@Sun.COM
77911767SAnurag.Maskey@Sun.COM /*
78011767SAnurag.Maskey@Sun.COM * Dequeue events and process them. In most cases, events have
78111767SAnurag.Maskey@Sun.COM * an assocated object type, and we use this to retrieve
78211767SAnurag.Maskey@Sun.COM * the function that will process the event.
78311767SAnurag.Maskey@Sun.COM */
78411767SAnurag.Maskey@Sun.COM while (!got_shutdown_event) {
78511767SAnurag.Maskey@Sun.COM event = nwamd_event_dequeue(queue_quiet_time);
78611767SAnurag.Maskey@Sun.COM /* keep pulling events as long as they are close together */
78711767SAnurag.Maskey@Sun.COM queue_quiet_time = SEC_TO_NSEC(1)/10;
7883938Sjbeck
78911767SAnurag.Maskey@Sun.COM /*
79011767SAnurag.Maskey@Sun.COM * This is an event with no associated object.
79111767SAnurag.Maskey@Sun.COM */
79211767SAnurag.Maskey@Sun.COM if (event->event_object[0] == '\0') {
79311767SAnurag.Maskey@Sun.COM switch (event->event_type) {
79411767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_NOOP:
79511767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_INIT:
79611767SAnurag.Maskey@Sun.COM /*
79711767SAnurag.Maskey@Sun.COM * The only action for an INIT event
79811767SAnurag.Maskey@Sun.COM * is to relay it to event listeners,
79911767SAnurag.Maskey@Sun.COM * which is done below.
80011767SAnurag.Maskey@Sun.COM */
80111767SAnurag.Maskey@Sun.COM break;
80211767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_PRIORITY_GROUP:
80311767SAnurag.Maskey@Sun.COM (void) pthread_mutex_lock(&active_ncp_mutex);
80411767SAnurag.Maskey@Sun.COM current_ncu_priority_group =
80511767SAnurag.Maskey@Sun.COM event->event_msg->nwe_data.
80611767SAnurag.Maskey@Sun.COM nwe_priority_group_info.nwe_priority;
80711767SAnurag.Maskey@Sun.COM (void) pthread_mutex_unlock(&active_ncp_mutex);
80811767SAnurag.Maskey@Sun.COM break;
80911767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS:
81011767SAnurag.Maskey@Sun.COM if (!shutting_down) {
81111767SAnurag.Maskey@Sun.COM nwamd_set_timed_check_all_conditions();
81211767SAnurag.Maskey@Sun.COM check_conditions = B_TRUE;
81311767SAnurag.Maskey@Sun.COM }
81411767SAnurag.Maskey@Sun.COM break;
81511767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS:
81611767SAnurag.Maskey@Sun.COM if (!shutting_down)
81711767SAnurag.Maskey@Sun.COM check_conditions = B_TRUE;
81811767SAnurag.Maskey@Sun.COM break;
81911767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_NCU_CHECK:
82011767SAnurag.Maskey@Sun.COM if (!shutting_down)
82111767SAnurag.Maskey@Sun.COM ncu_check = B_TRUE;
82211767SAnurag.Maskey@Sun.COM break;
82311767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_UPGRADE:
82411767SAnurag.Maskey@Sun.COM if (!shutting_down) {
82511767SAnurag.Maskey@Sun.COM /*
82611767SAnurag.Maskey@Sun.COM * Upgrade events have no associated
82711767SAnurag.Maskey@Sun.COM * object.
82811767SAnurag.Maskey@Sun.COM */
82911767SAnurag.Maskey@Sun.COM nwamd_event_run_method(event);
83011767SAnurag.Maskey@Sun.COM }
83111767SAnurag.Maskey@Sun.COM break;
83211767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_SHUTDOWN:
83311767SAnurag.Maskey@Sun.COM got_shutdown_event = B_TRUE;
83411767SAnurag.Maskey@Sun.COM break;
83511767SAnurag.Maskey@Sun.COM
83611767SAnurag.Maskey@Sun.COM /*
83711767SAnurag.Maskey@Sun.COM * We want to delay processing of condition and ncu
83811767SAnurag.Maskey@Sun.COM * checking until after short bursts of events. So we
83911767SAnurag.Maskey@Sun.COM * keep track of times we've scheduled checking and
84011767SAnurag.Maskey@Sun.COM * wait for the queue to quiesce.
84111767SAnurag.Maskey@Sun.COM */
84211767SAnurag.Maskey@Sun.COM case NWAM_EVENT_TYPE_QUEUE_QUIET:
84311767SAnurag.Maskey@Sun.COM queue_quiet_time = 0; /* now we can block */
84411767SAnurag.Maskey@Sun.COM if (!shutting_down && check_conditions) {
84511767SAnurag.Maskey@Sun.COM nwamd_check_all_conditions();
84611767SAnurag.Maskey@Sun.COM check_conditions = B_FALSE;
84711767SAnurag.Maskey@Sun.COM }
84811767SAnurag.Maskey@Sun.COM
84911767SAnurag.Maskey@Sun.COM if (!shutting_down && ncu_check) {
85011767SAnurag.Maskey@Sun.COM nwamd_activate_ncus();
85111767SAnurag.Maskey@Sun.COM ncu_check = B_FALSE;
85211767SAnurag.Maskey@Sun.COM }
85311767SAnurag.Maskey@Sun.COM break;
85411767SAnurag.Maskey@Sun.COM
85511767SAnurag.Maskey@Sun.COM default:
85611767SAnurag.Maskey@Sun.COM nlog(LOG_ERR,
85711767SAnurag.Maskey@Sun.COM "event %d (%s)had no object associated "
85811767SAnurag.Maskey@Sun.COM "with it", event->event_type,
85911767SAnurag.Maskey@Sun.COM nwamd_event_name(event->event_type));
86011767SAnurag.Maskey@Sun.COM break;
86111767SAnurag.Maskey@Sun.COM }
86211767SAnurag.Maskey@Sun.COM } else {
86311767SAnurag.Maskey@Sun.COM /*
86411767SAnurag.Maskey@Sun.COM * Event has an associated object - run event method
86511767SAnurag.Maskey@Sun.COM * for that object type (if any).
86611767SAnurag.Maskey@Sun.COM */
86711767SAnurag.Maskey@Sun.COM nwamd_event_run_method(event);
86811767SAnurag.Maskey@Sun.COM }
86911767SAnurag.Maskey@Sun.COM /*
87011767SAnurag.Maskey@Sun.COM * Send associated message to listeners if event type is
87111767SAnurag.Maskey@Sun.COM * externally visible.
87211767SAnurag.Maskey@Sun.COM */
87311767SAnurag.Maskey@Sun.COM if (event->event_send)
87411767SAnurag.Maskey@Sun.COM nwamd_event_send(event->event_msg);
87511767SAnurag.Maskey@Sun.COM
87611767SAnurag.Maskey@Sun.COM nwamd_event_fini(event);
87711767SAnurag.Maskey@Sun.COM }
87811767SAnurag.Maskey@Sun.COM /* If we get here, we got a shutdown event. */
87911767SAnurag.Maskey@Sun.COM nwamd_event_queue_fini();
88011767SAnurag.Maskey@Sun.COM nwamd_object_lists_fini();
8813938Sjbeck }
882