xref: /illumos-gate/usr/src/cmd/cmd-inet/lib/nwamd/ncp.c (revision f6da83d4)
16ba597c5SAnurag S. Maskey /*
26ba597c5SAnurag S. Maskey  * CDDL HEADER START
36ba597c5SAnurag S. Maskey  *
46ba597c5SAnurag S. Maskey  * The contents of this file are subject to the terms of the
56ba597c5SAnurag S. Maskey  * Common Development and Distribution License (the "License").
66ba597c5SAnurag S. Maskey  * You may not use this file except in compliance with the License.
76ba597c5SAnurag S. Maskey  *
86ba597c5SAnurag S. Maskey  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96ba597c5SAnurag S. Maskey  * or http://www.opensolaris.org/os/licensing.
106ba597c5SAnurag S. Maskey  * See the License for the specific language governing permissions
116ba597c5SAnurag S. Maskey  * and limitations under the License.
126ba597c5SAnurag S. Maskey  *
136ba597c5SAnurag S. Maskey  * When distributing Covered Code, include this CDDL HEADER in each
146ba597c5SAnurag S. Maskey  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156ba597c5SAnurag S. Maskey  * If applicable, add the following below this CDDL HEADER, with the
166ba597c5SAnurag S. Maskey  * fields enclosed by brackets "[]" replaced with your own identifying
176ba597c5SAnurag S. Maskey  * information: Portions Copyright [yyyy] [name of copyright owner]
186ba597c5SAnurag S. Maskey  *
196ba597c5SAnurag S. Maskey  * CDDL HEADER END
206ba597c5SAnurag S. Maskey  */
216ba597c5SAnurag S. Maskey 
226ba597c5SAnurag S. Maskey /*
2371ed50cfSAnurag S. Maskey  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
246ba597c5SAnurag S. Maskey  */
256ba597c5SAnurag S. Maskey 
266ba597c5SAnurag S. Maskey #include <arpa/inet.h>
276ba597c5SAnurag S. Maskey #include <assert.h>
286ba597c5SAnurag S. Maskey #include <libdllink.h>
296ba597c5SAnurag S. Maskey #include <libdlstat.h>
306ba597c5SAnurag S. Maskey #include <libnwam.h>
316ba597c5SAnurag S. Maskey #include <libscf.h>
326ba597c5SAnurag S. Maskey #include <netinet/in.h>
336ba597c5SAnurag S. Maskey #include <stdlib.h>
346ba597c5SAnurag S. Maskey #include <sys/socket.h>
356ba597c5SAnurag S. Maskey #include <sys/time.h>
366ba597c5SAnurag S. Maskey #include <sys/types.h>
376ba597c5SAnurag S. Maskey #include <values.h>
386ba597c5SAnurag S. Maskey 
396ba597c5SAnurag S. Maskey #include "conditions.h"
406ba597c5SAnurag S. Maskey #include "events.h"
416ba597c5SAnurag S. Maskey #include "objects.h"
426ba597c5SAnurag S. Maskey #include "ncp.h"
436ba597c5SAnurag S. Maskey #include "ncu.h"
446ba597c5SAnurag S. Maskey #include "util.h"
456ba597c5SAnurag S. Maskey 
466ba597c5SAnurag S. Maskey /*
476ba597c5SAnurag S. Maskey  * ncp.c - handles NCP actions.
486ba597c5SAnurag S. Maskey  */
496ba597c5SAnurag S. Maskey 
506ba597c5SAnurag S. Maskey char active_ncp[NWAM_MAX_NAME_LEN];
516ba597c5SAnurag S. Maskey nwam_ncp_handle_t active_ncph = NULL;
526ba597c5SAnurag S. Maskey int64_t current_ncu_priority_group = INVALID_PRIORITY_GROUP;
536ba597c5SAnurag S. Maskey /*
546ba597c5SAnurag S. Maskey  * active_ncp_mutex protects active_ncp, active_ncph and
556ba597c5SAnurag S. Maskey  * current_ncu_priority_group.
566ba597c5SAnurag S. Maskey  */
576ba597c5SAnurag S. Maskey pthread_mutex_t active_ncp_mutex = PTHREAD_MUTEX_INITIALIZER;
586ba597c5SAnurag S. Maskey 
596ba597c5SAnurag S. Maskey /*
606ba597c5SAnurag S. Maskey  * The variable ncu_wait_time specifies how long to wait to obtain a
616ba597c5SAnurag S. Maskey  * DHCP lease before giving up on that NCU and moving on to the next/lower
626ba597c5SAnurag S. Maskey  * priority-group.
636ba597c5SAnurag S. Maskey  */
646ba597c5SAnurag S. Maskey uint64_t ncu_wait_time = NCU_WAIT_TIME_DEFAULT;
656ba597c5SAnurag S. Maskey 
666ba597c5SAnurag S. Maskey /*
676ba597c5SAnurag S. Maskey  * Specifies if this is the first time the NCP has been enabled. True
686ba597c5SAnurag S. Maskey  * on startup so that we can differentiate between when we start up
696ba597c5SAnurag S. Maskey  * with a given NCP versus when we are asked to reenable it.
706ba597c5SAnurag S. Maskey  */
716ba597c5SAnurag S. Maskey boolean_t initial_ncp_enable = B_TRUE;
726ba597c5SAnurag S. Maskey 
736ba597c5SAnurag S. Maskey /*
746ba597c5SAnurag S. Maskey  * nwamd_ncp_handle_enable_event() should be called in the event handling
756ba597c5SAnurag S. Maskey  * loop in response to an _ENABLE event, triggered as a result of an
766ba597c5SAnurag S. Maskey  * nwam_ncp_enable() call from a libnwam consumer.  To enable the new NCP,
776ba597c5SAnurag S. Maskey  * we first call nwamd_fini_ncus() on the old NCP.  This results in enqueueing
786ba597c5SAnurag S. Maskey  * of a set of _FINI events for each NCU.  These events are handled and in
796ba597c5SAnurag S. Maskey  * order to tear down config, (online*, uninitialized) state change events
806ba597c5SAnurag S. Maskey  * are created and consumed directly by the fini event handler (these events
816ba597c5SAnurag S. Maskey  * are not enqueued as this would result in state events for the old NCP
826ba597c5SAnurag S. Maskey  * appearing after the new NCP has been enabled.  After the _FINI events are
836ba597c5SAnurag S. Maskey  * enqueued, we enqueue an NCP _OBJECT_STATE event for the new NCP.  Since
846ba597c5SAnurag S. Maskey  * it is enqueued after the _FINI events, we are guaranteed no events for the
856ba597c5SAnurag S. Maskey  * old NCP will appear after the new NCP is activated.
866ba597c5SAnurag S. Maskey  */
876ba597c5SAnurag S. Maskey void
nwamd_ncp_handle_enable_event(nwamd_event_t event)886ba597c5SAnurag S. Maskey nwamd_ncp_handle_enable_event(nwamd_event_t event)
896ba597c5SAnurag S. Maskey {
906ba597c5SAnurag S. Maskey 	char *new_ncp = event->event_object;
916ba597c5SAnurag S. Maskey 	nwam_ncp_handle_t new_ncph;
926ba597c5SAnurag S. Maskey 	nwam_error_t err;
936ba597c5SAnurag S. Maskey 
946ba597c5SAnurag S. Maskey 	if (new_ncp[0] == '\0')
956ba597c5SAnurag S. Maskey 		return;
966ba597c5SAnurag S. Maskey 
976ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
986ba597c5SAnurag S. Maskey 	if (strcmp(active_ncp, new_ncp) == 0 && !initial_ncp_enable) {
996ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncp_handle_enable_event: "
1006ba597c5SAnurag S. Maskey 		    "%s is already active", new_ncp);
1016ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&active_ncp_mutex);
1026ba597c5SAnurag S. Maskey 		return;
1036ba597c5SAnurag S. Maskey 	}
1046ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
1056ba597c5SAnurag S. Maskey 
1066ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncp_handle_enable_event: activating NCP %s",
1076ba597c5SAnurag S. Maskey 	    new_ncp);
1086ba597c5SAnurag S. Maskey 
1096ba597c5SAnurag S. Maskey 	/*
1106ba597c5SAnurag S. Maskey 	 * To activate new NCP, run nwamd_fini_ncus(), reset the active
1116ba597c5SAnurag S. Maskey 	 * priority-group, set the active_ncp property and refresh the
1126ba597c5SAnurag S. Maskey 	 * daemon.  The refresh action will trigger a re-read of the NCUs
1136ba597c5SAnurag S. Maskey 	 * for the activated NCP.
1146ba597c5SAnurag S. Maskey 	 */
1156ba597c5SAnurag S. Maskey 
1166ba597c5SAnurag S. Maskey 	nwamd_fini_ncus();
1176ba597c5SAnurag S. Maskey 
11871ed50cfSAnurag S. Maskey 	if ((err = nwam_ncp_read(new_ncp, 0, &new_ncph))
11971ed50cfSAnurag S. Maskey 	    == NWAM_ENTITY_NOT_FOUND) {
1206ba597c5SAnurag S. Maskey 		err = nwam_ncp_create(new_ncp, 0, &new_ncph);
1216ba597c5SAnurag S. Maskey 	}
1226ba597c5SAnurag S. Maskey 
1236ba597c5SAnurag S. Maskey 	if (err == NWAM_SUCCESS) {
12471ed50cfSAnurag S. Maskey 		nwam_ncp_free(new_ncph);
1256ba597c5SAnurag S. Maskey 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCP, new_ncp,
1266ba597c5SAnurag S. Maskey 		    NWAM_STATE_ONLINE, NWAM_AUX_STATE_ACTIVE);
12771ed50cfSAnurag S. Maskey 	} else if (initial_ncp_enable) {
12871ed50cfSAnurag S. Maskey 		/*
12971ed50cfSAnurag S. Maskey 		 * We weren't able to enable the NCP when nwamd starts up,
13071ed50cfSAnurag S. Maskey 		 * retry in a few seconds.
13171ed50cfSAnurag S. Maskey 		 */
13271ed50cfSAnurag S. Maskey 		nwamd_event_t retry_event = nwamd_event_init_object_action
13371ed50cfSAnurag S. Maskey 		    (NWAM_OBJECT_TYPE_NCP, new_ncp, NULL, NWAM_ACTION_ENABLE);
13471ed50cfSAnurag S. Maskey 		if (retry_event == NULL) {
13571ed50cfSAnurag S. Maskey 			nlog(LOG_ERR, "nwamd_ncp_handle_enable_event: "
13671ed50cfSAnurag S. Maskey 			    "could not create retry event to enable %s NCP",
13771ed50cfSAnurag S. Maskey 			    new_ncp);
13871ed50cfSAnurag S. Maskey 			return;
13971ed50cfSAnurag S. Maskey 		}
14071ed50cfSAnurag S. Maskey 
14171ed50cfSAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncp_handle_enable_event: "
14271ed50cfSAnurag S. Maskey 		    "failed to enable %s NCP, retrying in %d seconds",
14371ed50cfSAnurag S. Maskey 		    new_ncp, NWAMD_READONLY_RETRY_INTERVAL);
14471ed50cfSAnurag S. Maskey 		nwamd_event_enqueue_timed(retry_event,
14571ed50cfSAnurag S. Maskey 		    NWAMD_READONLY_RETRY_INTERVAL);
1466ba597c5SAnurag S. Maskey 	} else {
1476ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncp_handle_enable_event: error %s",
1486ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
1496ba597c5SAnurag S. Maskey 		return;
1506ba597c5SAnurag S. Maskey 	}
1516ba597c5SAnurag S. Maskey }
1526ba597c5SAnurag S. Maskey 
1536ba597c5SAnurag S. Maskey void
nwamd_ncp_handle_action_event(nwamd_event_t event)1546ba597c5SAnurag S. Maskey nwamd_ncp_handle_action_event(nwamd_event_t event)
1556ba597c5SAnurag S. Maskey {
1566ba597c5SAnurag S. Maskey 	switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) {
1576ba597c5SAnurag S. Maskey 	case NWAM_ACTION_ENABLE:
1586ba597c5SAnurag S. Maskey 		nwamd_ncp_handle_enable_event(event);
1596ba597c5SAnurag S. Maskey 		break;
1606ba597c5SAnurag S. Maskey 	case NWAM_ACTION_ADD:
1616ba597c5SAnurag S. Maskey 	case NWAM_ACTION_DESTROY:
1626ba597c5SAnurag S. Maskey 		/* nothing to do */
1636ba597c5SAnurag S. Maskey 		break;
1646ba597c5SAnurag S. Maskey 	default:
1656ba597c5SAnurag S. Maskey 		nlog(LOG_INFO, "nwam_ncp_handle_action_event: "
1666ba597c5SAnurag S. Maskey 		    "unexpected action");
1676ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
1686ba597c5SAnurag S. Maskey 		break;
1696ba597c5SAnurag S. Maskey 	}
1706ba597c5SAnurag S. Maskey }
1716ba597c5SAnurag S. Maskey 
1726ba597c5SAnurag S. Maskey /*
1736ba597c5SAnurag S. Maskey  * The only state events we create are (online, active) events which are
1746ba597c5SAnurag S. Maskey  * generated as part of an NCP enable action (see above).
1756ba597c5SAnurag S. Maskey  */
1766ba597c5SAnurag S. Maskey void
nwamd_ncp_handle_state_event(nwamd_event_t event)1776ba597c5SAnurag S. Maskey nwamd_ncp_handle_state_event(nwamd_event_t event)
1786ba597c5SAnurag S. Maskey {
1796ba597c5SAnurag S. Maskey 	char *new_ncp = event->event_object;
1806ba597c5SAnurag S. Maskey 	nwam_ncp_handle_t new_ncph, old_ncph;
1816ba597c5SAnurag S. Maskey 	nwam_error_t err;
1826ba597c5SAnurag S. Maskey 
1836ba597c5SAnurag S. Maskey 	/* The NCP to be activated should always exist. */
1846ba597c5SAnurag S. Maskey 	if ((err = nwam_ncp_read(new_ncp, 0, &new_ncph)) != NWAM_SUCCESS) {
1856ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncp_handle_state_event: "
1866ba597c5SAnurag S. Maskey 		    "cannot read NCP %s: : %s", new_ncp, nwam_strerror(err));
1876ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
1886ba597c5SAnurag S. Maskey 		return;
1896ba597c5SAnurag S. Maskey 	}
1906ba597c5SAnurag S. Maskey 
1916ba597c5SAnurag S. Maskey 	/*
1926ba597c5SAnurag S. Maskey 	 * To activate new NCP, reset the active priority-group, set the
1936ba597c5SAnurag S. Maskey 	 * active_ncp property and refresh the daemon.  The refresh action will
1946ba597c5SAnurag S. Maskey 	 * trigger a re-read of the NCUs for the activated NCP.
1956ba597c5SAnurag S. Maskey 	 */
1966ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
1976ba597c5SAnurag S. Maskey 	old_ncph = active_ncph;
1986ba597c5SAnurag S. Maskey 	active_ncph = new_ncph;
1996ba597c5SAnurag S. Maskey 	nwam_ncp_free(old_ncph);
2006ba597c5SAnurag S. Maskey 	current_ncu_priority_group = INVALID_PRIORITY_GROUP;
2016ba597c5SAnurag S. Maskey 	(void) strlcpy(active_ncp, event->event_object,
2026ba597c5SAnurag S. Maskey 	    sizeof (active_ncp));
2036ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
2046ba597c5SAnurag S. Maskey 	(void) nwamd_set_string_property(OUR_FMRI, OUR_PG,
2056ba597c5SAnurag S. Maskey 	    OUR_ACTIVE_NCP_PROP_NAME, new_ncp);
2066ba597c5SAnurag S. Maskey 	(void) smf_refresh_instance(OUR_FMRI);
2076ba597c5SAnurag S. Maskey 	initial_ncp_enable = B_FALSE;
2086ba597c5SAnurag S. Maskey }
2096ba597c5SAnurag S. Maskey 
2106ba597c5SAnurag S. Maskey int
nwamd_ncp_action(const char * ncp,nwam_action_t action)2116ba597c5SAnurag S. Maskey nwamd_ncp_action(const char *ncp, nwam_action_t action)
2126ba597c5SAnurag S. Maskey {
2136ba597c5SAnurag S. Maskey 	nwamd_event_t event = nwamd_event_init_object_action
2146ba597c5SAnurag S. Maskey 	    (NWAM_OBJECT_TYPE_NCP, ncp, NULL, action);
2156ba597c5SAnurag S. Maskey 	if (event == NULL)
2166ba597c5SAnurag S. Maskey 		return (1);
2176ba597c5SAnurag S. Maskey 	nwamd_event_enqueue(event);
2186ba597c5SAnurag S. Maskey 	return (0);
2196ba597c5SAnurag S. Maskey }
2206ba597c5SAnurag S. Maskey 
2216ba597c5SAnurag S. Maskey /*
2226ba597c5SAnurag S. Maskey  * Below this point are routines handling NCU prioritization
2236ba597c5SAnurag S. Maskey  * policy for the active NCP.
2246ba597c5SAnurag S. Maskey  */
2256ba597c5SAnurag S. Maskey 
2266ba597c5SAnurag S. Maskey struct priority_group_cbarg {
2276ba597c5SAnurag S. Maskey 	uint64_t minpriority;
2286ba597c5SAnurag S. Maskey 	uint64_t currpriority;
2296ba597c5SAnurag S. Maskey 	boolean_t found;
2306ba597c5SAnurag S. Maskey };
2316ba597c5SAnurag S. Maskey 
2326ba597c5SAnurag S. Maskey /* Callback used to find next pg in NCP that is >= start_pg */
2336ba597c5SAnurag S. Maskey static int
find_next_priority_group_cb(nwamd_object_t object,void * data)2346ba597c5SAnurag S. Maskey find_next_priority_group_cb(nwamd_object_t object, void *data)
2356ba597c5SAnurag S. Maskey {
2366ba597c5SAnurag S. Maskey 	struct priority_group_cbarg *cbarg = data;
2376ba597c5SAnurag S. Maskey 	uint64_t priority;
2386ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu = object->nwamd_object_data;
2396ba597c5SAnurag S. Maskey 
240*f6da83d4SAnurag S. Maskey 	if (ncu->ncu_link.nwamd_link_activation_mode !=
2416ba597c5SAnurag S. Maskey 	    NWAM_ACTIVATION_MODE_PRIORITIZED)
2426ba597c5SAnurag S. Maskey 		return (0);
2436ba597c5SAnurag S. Maskey 
244*f6da83d4SAnurag S. Maskey 	priority = ncu->ncu_link.nwamd_link_priority_group;
2456ba597c5SAnurag S. Maskey 
2466ba597c5SAnurag S. Maskey 	if (priority >= cbarg->minpriority && priority < cbarg->currpriority) {
2476ba597c5SAnurag S. Maskey 		cbarg->found = B_TRUE;
2486ba597c5SAnurag S. Maskey 		cbarg->currpriority = priority;
2496ba597c5SAnurag S. Maskey 	}
2506ba597c5SAnurag S. Maskey 	return (0);
2516ba597c5SAnurag S. Maskey }
2526ba597c5SAnurag S. Maskey 
2536ba597c5SAnurag S. Maskey /* Set current_pg to next pg in NCP that is >= start_pg */
2546ba597c5SAnurag S. Maskey boolean_t
nwamd_ncp_find_next_priority_group(int64_t minpriority,int64_t * nextpriorityp)2556ba597c5SAnurag S. Maskey nwamd_ncp_find_next_priority_group(int64_t minpriority,
2566ba597c5SAnurag S. Maskey     int64_t *nextpriorityp)
2576ba597c5SAnurag S. Maskey {
2586ba597c5SAnurag S. Maskey 	struct priority_group_cbarg cbarg;
2596ba597c5SAnurag S. Maskey 
2606ba597c5SAnurag S. Maskey 	cbarg.minpriority = minpriority;
2616ba597c5SAnurag S. Maskey 	cbarg.currpriority = MAXINT;
2626ba597c5SAnurag S. Maskey 	cbarg.found = B_FALSE;
2636ba597c5SAnurag S. Maskey 
2646ba597c5SAnurag S. Maskey 	(void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU,
2656ba597c5SAnurag S. Maskey 	    find_next_priority_group_cb, &cbarg);
2666ba597c5SAnurag S. Maskey 
2676ba597c5SAnurag S. Maskey 	if (cbarg.found) {
2686ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncp_find_next_priority_group: "
2696ba597c5SAnurag S. Maskey 		    "next priority group >= %lld is %lld",
2706ba597c5SAnurag S. Maskey 		    minpriority, cbarg.currpriority);
2716ba597c5SAnurag S. Maskey 		*nextpriorityp = cbarg.currpriority;
2726ba597c5SAnurag S. Maskey 		return (B_TRUE);
2736ba597c5SAnurag S. Maskey 	} else {
2746ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncp_find_next_priority_group: "
2756ba597c5SAnurag S. Maskey 		    "no priority groups >= %lld exist", minpriority);
2766ba597c5SAnurag S. Maskey 		return (B_FALSE);
2776ba597c5SAnurag S. Maskey 	}
2786ba597c5SAnurag S. Maskey }
2796ba597c5SAnurag S. Maskey 
2806ba597c5SAnurag S. Maskey /*
2816ba597c5SAnurag S. Maskey  * Struct for walking NCUs in the selected priority group.  We count
2826ba597c5SAnurag S. Maskey  * how many of the exclusive, all and shared NCUs are online, and
2836ba597c5SAnurag S. Maskey  * if activate_or_deactivate is true, we either activate or deactivate
2846ba597c5SAnurag S. Maskey  * (depending on the value of activate) offline/online NCUs.
2856ba597c5SAnurag S. Maskey  */
2866ba597c5SAnurag S. Maskey struct nwamd_ncu_check_walk_arg {
2876ba597c5SAnurag S. Maskey 	boolean_t manual;	/* enable manual NCUs only */
2886ba597c5SAnurag S. Maskey 	int64_t priority_group; /* interested priority-group for this walk */
2896ba597c5SAnurag S. Maskey 	uint64_t exclusive_ncus;
2906ba597c5SAnurag S. Maskey 	uint64_t exclusive_online_ncus;
2916ba597c5SAnurag S. Maskey 	uint64_t shared_ncus;
2926ba597c5SAnurag S. Maskey 	uint64_t shared_online_ncus;
2936ba597c5SAnurag S. Maskey 	uint64_t all_ncus;
2946ba597c5SAnurag S. Maskey 	uint64_t all_online_ncus;
2956ba597c5SAnurag S. Maskey 	boolean_t activate_or_deactivate;
2966ba597c5SAnurag S. Maskey 	boolean_t activate;
2976ba597c5SAnurag S. Maskey };
2986ba597c5SAnurag S. Maskey 
2996ba597c5SAnurag S. Maskey /*
3006ba597c5SAnurag S. Maskey  * This function serves a number of purposes:
3016ba597c5SAnurag S. Maskey  * - it supports activation/deactivation of manual NCUs in the current NCP
3026ba597c5SAnurag S. Maskey  * (when wa->manual is true, wa->activate determines if we activate or
3036ba597c5SAnurag S. Maskey  * deactivate the current NCU)
3046ba597c5SAnurag S. Maskey  * - it supports checking/activation of a particular priority group in
3056ba597c5SAnurag S. Maskey  * the active NCP. This works as follows:
3066ba597c5SAnurag S. Maskey  *
3076ba597c5SAnurag S. Maskey  * Count up numbers of exclusive, shared and all NCUs, and how many of each
3086ba597c5SAnurag S. Maskey  * are online.  If an NCU is waiting for IP address to be assigned, it is
3096ba597c5SAnurag S. Maskey  * also considered online.  If activate_or_deactivate is true, we also
3106ba597c5SAnurag S. Maskey  * either activate (if activate is true) or deactivate prioritized NCUs
3116ba597c5SAnurag S. Maskey  * that are offline or online.
3126ba597c5SAnurag S. Maskey  */
3136ba597c5SAnurag S. Maskey static int
nwamd_ncu_check_or_activate(nwamd_object_t object,void * data)3146ba597c5SAnurag S. Maskey nwamd_ncu_check_or_activate(nwamd_object_t object, void *data)
3156ba597c5SAnurag S. Maskey {
3166ba597c5SAnurag S. Maskey 	struct nwamd_ncu_check_walk_arg *wa = data;
3176ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu;
3186ba597c5SAnurag S. Maskey 	uint64_t priority_group, priority_mode;
3196ba597c5SAnurag S. Maskey 	nwamd_object_t if_obj;
3206ba597c5SAnurag S. Maskey 	nwam_state_t state, if_state;
3216ba597c5SAnurag S. Maskey 	nwam_aux_state_t aux_state, if_aux_state;
3226ba597c5SAnurag S. Maskey 	char *name;
3236ba597c5SAnurag S. Maskey 
3246ba597c5SAnurag S. Maskey 	state = object->nwamd_object_state;
3256ba597c5SAnurag S. Maskey 	aux_state = object->nwamd_object_aux_state;
3266ba597c5SAnurag S. Maskey 	name = object->nwamd_object_name;
3276ba597c5SAnurag S. Maskey 	ncu = object->nwamd_object_data;
3286ba597c5SAnurag S. Maskey 
3296ba597c5SAnurag S. Maskey 	/* skip NCUs in UNINITIALIZED state */
3306ba597c5SAnurag S. Maskey 	if (state == NWAM_STATE_UNINITIALIZED) {
3316ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
3326ba597c5SAnurag S. Maskey 		    "skipping uninitialized ncu %s", name);
3336ba597c5SAnurag S. Maskey 		return (0);
3346ba597c5SAnurag S. Maskey 	}
3356ba597c5SAnurag S. Maskey 	if (!wa->manual && wa->priority_group == INVALID_PRIORITY_GROUP)
3366ba597c5SAnurag S. Maskey 		return (0);
3376ba597c5SAnurag S. Maskey 
3386ba597c5SAnurag S. Maskey 	if (ncu->ncu_type != NWAM_NCU_TYPE_LINK) {
3396ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
3406ba597c5SAnurag S. Maskey 		    "skipping interface NCU %s", name);
3416ba597c5SAnurag S. Maskey 		return (0);
3426ba597c5SAnurag S. Maskey 	}
343*f6da83d4SAnurag S. Maskey 	if (!wa->manual && ncu->ncu_link.nwamd_link_activation_mode !=
3446ba597c5SAnurag S. Maskey 	    NWAM_ACTIVATION_MODE_PRIORITIZED) {
3456ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
3466ba597c5SAnurag S. Maskey 		    "skipping non-prioritized NCU %s", name);
3476ba597c5SAnurag S. Maskey 		return (0);
3486ba597c5SAnurag S. Maskey 	}
349*f6da83d4SAnurag S. Maskey 	if (wa->manual && ncu->ncu_link.nwamd_link_activation_mode !=
3506ba597c5SAnurag S. Maskey 	    NWAM_ACTIVATION_MODE_MANUAL) {
3516ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
3526ba597c5SAnurag S. Maskey 		    "skipping non-manual NCU %s", name);
3536ba597c5SAnurag S. Maskey 		return (0);
3546ba597c5SAnurag S. Maskey 	}
3556ba597c5SAnurag S. Maskey 
356*f6da83d4SAnurag S. Maskey 	priority_group = ncu->ncu_link.nwamd_link_priority_group;
357*f6da83d4SAnurag S. Maskey 	priority_mode = ncu->ncu_link.nwamd_link_priority_mode;
3586ba597c5SAnurag S. Maskey 	/* Only work with NCUs in the requested priority-group */
3596ba597c5SAnurag S. Maskey 	if (!wa->manual && priority_group != wa->priority_group) {
3606ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
3616ba597c5SAnurag S. Maskey 		    "skipping NCU %s in different priority-group", name);
3626ba597c5SAnurag S. Maskey 		return (0);
3636ba597c5SAnurag S. Maskey 	}
3646ba597c5SAnurag S. Maskey 	/* Get the state of the corresponding interface NCU */
3656ba597c5SAnurag S. Maskey 	if ((if_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_INTERFACE,
3666ba597c5SAnurag S. Maskey 	    ncu->ncu_name)) == NULL) {
3676ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_check_or_activate: "
3686ba597c5SAnurag S. Maskey 		    "interface NCU of %s not found, skipping", name);
3696ba597c5SAnurag S. Maskey 		return (0);
3706ba597c5SAnurag S. Maskey 	}
3716ba597c5SAnurag S. Maskey 	if_state = if_obj->nwamd_object_state;
3726ba597c5SAnurag S. Maskey 	if_aux_state = if_obj->nwamd_object_aux_state;
3736ba597c5SAnurag S. Maskey 	nwamd_object_release(if_obj);
3746ba597c5SAnurag S. Maskey 
3756ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: %s ncu %s",
3766ba597c5SAnurag S. Maskey 	    wa->activate_or_deactivate ?
3776ba597c5SAnurag S. Maskey 	    (wa->activate ? "activating" : "deactivating") :
3786ba597c5SAnurag S. Maskey 	    "checking", name);
3796ba597c5SAnurag S. Maskey 
3806ba597c5SAnurag S. Maskey 	if (wa->manual) {
3816ba597c5SAnurag S. Maskey 		if (wa->activate_or_deactivate && wa->activate) {
3826ba597c5SAnurag S. Maskey 			if (state == NWAM_STATE_OFFLINE && ncu->ncu_enabled) {
3836ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
3846ba597c5SAnurag S. Maskey 				    "moving NCU %s to offline* from offline",
3856ba597c5SAnurag S. Maskey 				    name);
3866ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
3876ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_OFFLINE_TO_ONLINE,
3886ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_INITIALIZED);
3896ba597c5SAnurag S. Maskey 			}
3906ba597c5SAnurag S. Maskey 			if (state != NWAM_STATE_DISABLED &&
3916ba597c5SAnurag S. Maskey 			    !ncu->ncu_enabled) {
3926ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
3936ba597c5SAnurag S. Maskey 				    "moving NCU %s to online* (disabling)",
3946ba597c5SAnurag S. Maskey 				    name);
3956ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
3966ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_ONLINE_TO_OFFLINE,
3976ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_MANUAL_DISABLE);
3986ba597c5SAnurag S. Maskey 			}
3996ba597c5SAnurag S. Maskey 		}
4006ba597c5SAnurag S. Maskey 		return (0);
4016ba597c5SAnurag S. Maskey 	}
4026ba597c5SAnurag S. Maskey 	switch (priority_mode) {
4036ba597c5SAnurag S. Maskey 	case NWAM_PRIORITY_MODE_EXCLUSIVE:
4046ba597c5SAnurag S. Maskey 		wa->exclusive_ncus++;
4056ba597c5SAnurag S. Maskey 		if (state == NWAM_STATE_ONLINE &&
4066ba597c5SAnurag S. Maskey 		    (if_state == NWAM_STATE_ONLINE ||
4076ba597c5SAnurag S. Maskey 		    if_aux_state == NWAM_AUX_STATE_IF_WAITING_FOR_ADDR))
4086ba597c5SAnurag S. Maskey 			wa->exclusive_online_ncus++;
4096ba597c5SAnurag S. Maskey 
4106ba597c5SAnurag S. Maskey 		/*
4116ba597c5SAnurag S. Maskey 		 * For exclusive NCUs, we activate offline NCUs as long
4126ba597c5SAnurag S. Maskey 		 * as no other exclusive NCUs are active.
4136ba597c5SAnurag S. Maskey 		 */
4146ba597c5SAnurag S. Maskey 		if (wa->activate_or_deactivate && wa->activate) {
4156ba597c5SAnurag S. Maskey 			if (state == NWAM_STATE_OFFLINE &&
4166ba597c5SAnurag S. Maskey 			    wa->exclusive_online_ncus == 0) {
4176ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
4186ba597c5SAnurag S. Maskey 				    "moving NCU %s to offline* from offline",
4196ba597c5SAnurag S. Maskey 				    name);
4206ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4216ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_OFFLINE_TO_ONLINE,
4226ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_INITIALIZED);
4236ba597c5SAnurag S. Maskey 			}
4246ba597c5SAnurag S. Maskey 		}
4256ba597c5SAnurag S. Maskey 		if (wa->activate_or_deactivate && !wa->activate) {
4266ba597c5SAnurag S. Maskey 			if (aux_state != NWAM_AUX_STATE_CONDITIONS_NOT_MET) {
4276ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
4286ba597c5SAnurag S. Maskey 				    "deactivating NCU %s", name);
4296ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4306ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_ONLINE_TO_OFFLINE,
4316ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_CONDITIONS_NOT_MET);
4326ba597c5SAnurag S. Maskey 			}
4336ba597c5SAnurag S. Maskey 		}
4346ba597c5SAnurag S. Maskey 		/*
4356ba597c5SAnurag S. Maskey 		 * If we are activating or checking the priority group and
4366ba597c5SAnurag S. Maskey 		 * too many exclusive NCUs are online, take this NCU down.
4376ba597c5SAnurag S. Maskey 		 */
4386ba597c5SAnurag S. Maskey 		if ((wa->activate_or_deactivate && wa->activate) ||
4396ba597c5SAnurag S. Maskey 		    !wa->activate_or_deactivate) {
4406ba597c5SAnurag S. Maskey 			if (state == NWAM_STATE_ONLINE &&
4416ba597c5SAnurag S. Maskey 			    if_state == NWAM_STATE_ONLINE &&
4426ba597c5SAnurag S. Maskey 			    wa->exclusive_online_ncus > 1) {
4436ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
4446ba597c5SAnurag S. Maskey 				    "moving NCU %s to online* since another "
4456ba597c5SAnurag S. Maskey 				    "NCU is already active",
4466ba597c5SAnurag S. Maskey 				    name);
4476ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4486ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_ONLINE_TO_OFFLINE,
4496ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_CONDITIONS_NOT_MET);
4506ba597c5SAnurag S. Maskey 			}
4516ba597c5SAnurag S. Maskey 		}
4526ba597c5SAnurag S. Maskey 		break;
4536ba597c5SAnurag S. Maskey 	case NWAM_PRIORITY_MODE_SHARED:
4546ba597c5SAnurag S. Maskey 		wa->shared_ncus++;
4556ba597c5SAnurag S. Maskey 		if (state == NWAM_STATE_ONLINE &&
4566ba597c5SAnurag S. Maskey 		    (if_state == NWAM_STATE_ONLINE ||
4576ba597c5SAnurag S. Maskey 		    if_aux_state == NWAM_AUX_STATE_IF_WAITING_FOR_ADDR))
4586ba597c5SAnurag S. Maskey 			wa->shared_online_ncus++;
4596ba597c5SAnurag S. Maskey 
4606ba597c5SAnurag S. Maskey 		if (wa->activate_or_deactivate && wa->activate) {
4616ba597c5SAnurag S. Maskey 			if (state == NWAM_STATE_OFFLINE) {
4626ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
4636ba597c5SAnurag S. Maskey 				    "activating NCU %s", name);
4646ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4656ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_OFFLINE_TO_ONLINE,
4666ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_INITIALIZED);
4676ba597c5SAnurag S. Maskey 			}
4686ba597c5SAnurag S. Maskey 		}
4696ba597c5SAnurag S. Maskey 		if (wa->activate_or_deactivate && !wa->activate) {
4706ba597c5SAnurag S. Maskey 			if (aux_state != NWAM_AUX_STATE_CONDITIONS_NOT_MET) {
4716ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
4726ba597c5SAnurag S. Maskey 				    "deactivating NCU %s", name);
4736ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4746ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_ONLINE_TO_OFFLINE,
4756ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_CONDITIONS_NOT_MET);
4766ba597c5SAnurag S. Maskey 			}
4776ba597c5SAnurag S. Maskey 		}
4786ba597c5SAnurag S. Maskey 		break;
4796ba597c5SAnurag S. Maskey 	case NWAM_PRIORITY_MODE_ALL:
4806ba597c5SAnurag S. Maskey 		wa->all_ncus++;
4816ba597c5SAnurag S. Maskey 		if (state == NWAM_STATE_ONLINE &&
4826ba597c5SAnurag S. Maskey 		    (if_state == NWAM_STATE_ONLINE ||
4836ba597c5SAnurag S. Maskey 		    if_aux_state == NWAM_AUX_STATE_IF_WAITING_FOR_ADDR))
4846ba597c5SAnurag S. Maskey 			wa->all_online_ncus++;
4856ba597c5SAnurag S. Maskey 
4866ba597c5SAnurag S. Maskey 		/*
4876ba597c5SAnurag S. Maskey 		 * For "all" NCUs, activate/deactivate all offline/online
4886ba597c5SAnurag S. Maskey 		 * NCUs.
4896ba597c5SAnurag S. Maskey 		 */
4906ba597c5SAnurag S. Maskey 		if (wa->activate_or_deactivate && wa->activate) {
4916ba597c5SAnurag S. Maskey 			if (state == NWAM_STATE_OFFLINE) {
4926ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
4936ba597c5SAnurag S. Maskey 				    "activating NCU %s", name);
4946ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4956ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_OFFLINE_TO_ONLINE,
4966ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_INITIALIZED);
4976ba597c5SAnurag S. Maskey 			}
4986ba597c5SAnurag S. Maskey 		}
4996ba597c5SAnurag S. Maskey 		if (wa->activate_or_deactivate && !wa->activate) {
5006ba597c5SAnurag S. Maskey 			if (aux_state != NWAM_AUX_STATE_CONDITIONS_NOT_MET) {
5016ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
5026ba597c5SAnurag S. Maskey 				    "deactivating NCU %s", name);
5036ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
5046ba597c5SAnurag S. Maskey 				    name, NWAM_STATE_ONLINE_TO_OFFLINE,
5056ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_CONDITIONS_NOT_MET);
5066ba597c5SAnurag S. Maskey 			}
5076ba597c5SAnurag S. Maskey 		}
5086ba597c5SAnurag S. Maskey 
5096ba597c5SAnurag S. Maskey 		break;
5106ba597c5SAnurag S. Maskey 	default:
5116ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_check_or_activate: "
5126ba597c5SAnurag S. Maskey 		    "invalid priority-mode");
5136ba597c5SAnurag S. Maskey 		break;
5146ba597c5SAnurag S. Maskey 	}
5156ba597c5SAnurag S. Maskey 
5166ba597c5SAnurag S. Maskey 	return (0);
5176ba597c5SAnurag S. Maskey }
5186ba597c5SAnurag S. Maskey 
5196ba597c5SAnurag S. Maskey void
nwamd_ncp_activate_priority_group(int64_t priority)5206ba597c5SAnurag S. Maskey nwamd_ncp_activate_priority_group(int64_t priority)
5216ba597c5SAnurag S. Maskey {
5226ba597c5SAnurag S. Maskey 	struct nwamd_ncu_check_walk_arg wa;
5236ba597c5SAnurag S. Maskey 	nwamd_event_t check_event, priority_event;
5246ba597c5SAnurag S. Maskey 
5256ba597c5SAnurag S. Maskey 	if (priority == INVALID_PRIORITY_GROUP)
5266ba597c5SAnurag S. Maskey 		return;
5276ba597c5SAnurag S. Maskey 
5286ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
5296ba597c5SAnurag S. Maskey 	if (priority == current_ncu_priority_group) {
5306ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&active_ncp_mutex);
5316ba597c5SAnurag S. Maskey 		return;
5326ba597c5SAnurag S. Maskey 	}
5336ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
5346ba597c5SAnurag S. Maskey 
5356ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncp_activate_priority_group: "
5366ba597c5SAnurag S. Maskey 	    "activating priority group %lld", priority);
5376ba597c5SAnurag S. Maskey 
5386ba597c5SAnurag S. Maskey 	wa.manual = B_FALSE;
5396ba597c5SAnurag S. Maskey 	wa.priority_group = priority;
5406ba597c5SAnurag S. Maskey 	wa.exclusive_ncus = 0;
5416ba597c5SAnurag S. Maskey 	wa.exclusive_online_ncus = 0;
5426ba597c5SAnurag S. Maskey 	wa.shared_ncus = 0;
5436ba597c5SAnurag S. Maskey 	wa.shared_online_ncus = 0;
5446ba597c5SAnurag S. Maskey 	wa.all_ncus = 0;
5456ba597c5SAnurag S. Maskey 	wa.all_online_ncus = 0;
5466ba597c5SAnurag S. Maskey 	wa.activate_or_deactivate = B_TRUE;
5476ba597c5SAnurag S. Maskey 	wa.activate = B_TRUE;
5486ba597c5SAnurag S. Maskey 
5496ba597c5SAnurag S. Maskey 	if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU,
5506ba597c5SAnurag S. Maskey 	    nwamd_ncu_check_or_activate, &wa) != 0) {
5516ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncp_activate_priority_group: "
5526ba597c5SAnurag S. Maskey 		    "nwamd_walk_objects() failed");
5536ba597c5SAnurag S. Maskey 		return;
5546ba597c5SAnurag S. Maskey 	}
5556ba597c5SAnurag S. Maskey 
5566ba597c5SAnurag S. Maskey 	/*
5576ba597c5SAnurag S. Maskey 	 * Enqueue event to update current_ncu_priority_group and send to
5586ba597c5SAnurag S. Maskey 	 * any event listeners.
5596ba597c5SAnurag S. Maskey 	 */
5606ba597c5SAnurag S. Maskey 	priority_event = nwamd_event_init_priority_group_change(priority);
5616ba597c5SAnurag S. Maskey 	if (priority_event == NULL)
5626ba597c5SAnurag S. Maskey 		return;
5636ba597c5SAnurag S. Maskey 	nwamd_event_enqueue(priority_event);
5646ba597c5SAnurag S. Maskey 
5656ba597c5SAnurag S. Maskey 	/*
5666ba597c5SAnurag S. Maskey 	 * Now we've activated a new priority group, enqueue an event
5676ba597c5SAnurag S. Maskey 	 * to check up on the state of this priority group.
5686ba597c5SAnurag S. Maskey 	 */
5696ba597c5SAnurag S. Maskey 	check_event = nwamd_event_init_ncu_check();
5706ba597c5SAnurag S. Maskey 	if (check_event == NULL)
5716ba597c5SAnurag S. Maskey 		return;
5726ba597c5SAnurag S. Maskey 	nwamd_event_enqueue_timed(check_event, ncu_wait_time);
5736ba597c5SAnurag S. Maskey }
5746ba597c5SAnurag S. Maskey 
5756ba597c5SAnurag S. Maskey void
nwamd_ncp_deactivate_priority_group(int64_t priority)5766ba597c5SAnurag S. Maskey nwamd_ncp_deactivate_priority_group(int64_t priority)
5776ba597c5SAnurag S. Maskey {
5786ba597c5SAnurag S. Maskey 	struct nwamd_ncu_check_walk_arg wa;
5796ba597c5SAnurag S. Maskey 
5806ba597c5SAnurag S. Maskey 	if (priority == INVALID_PRIORITY_GROUP)
5816ba597c5SAnurag S. Maskey 		return;
5826ba597c5SAnurag S. Maskey 
5836ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncp_deactivate_priority_group: "
5846ba597c5SAnurag S. Maskey 	    "deactivating priority group %lld", priority);
5856ba597c5SAnurag S. Maskey 
5866ba597c5SAnurag S. Maskey 	wa.manual = B_FALSE;
5876ba597c5SAnurag S. Maskey 	wa.priority_group = priority;
5886ba597c5SAnurag S. Maskey 	wa.exclusive_ncus = 0;
5896ba597c5SAnurag S. Maskey 	wa.exclusive_online_ncus = 0;
5906ba597c5SAnurag S. Maskey 	wa.shared_ncus = 0;
5916ba597c5SAnurag S. Maskey 	wa.shared_online_ncus = 0;
5926ba597c5SAnurag S. Maskey 	wa.all_ncus = 0;
5936ba597c5SAnurag S. Maskey 	wa.all_online_ncus = 0;
5946ba597c5SAnurag S. Maskey 	wa.activate_or_deactivate = B_TRUE;
5956ba597c5SAnurag S. Maskey 	wa.activate = B_FALSE;
5966ba597c5SAnurag S. Maskey 
5976ba597c5SAnurag S. Maskey 	if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU,
5986ba597c5SAnurag S. Maskey 	    nwamd_ncu_check_or_activate, &wa) != 0) {
5996ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncp_deactivate_priority_group: "
6006ba597c5SAnurag S. Maskey 		    "nwamd_walk_objects() failed");
6016ba597c5SAnurag S. Maskey 		return;
6026ba597c5SAnurag S. Maskey 	}
6036ba597c5SAnurag S. Maskey }
6046ba597c5SAnurag S. Maskey 
6056ba597c5SAnurag S. Maskey /*
6066ba597c5SAnurag S. Maskey  * This function deactivates all priority groups at level 'priority' and lower
6076ba597c5SAnurag S. Maskey  * (which is, numerically, all priorities >= priority).
6086ba597c5SAnurag S. Maskey  */
6096ba597c5SAnurag S. Maskey void
nwamd_ncp_deactivate_priority_group_all(int64_t priority)6106ba597c5SAnurag S. Maskey nwamd_ncp_deactivate_priority_group_all(int64_t priority)
6116ba597c5SAnurag S. Maskey {
6126ba597c5SAnurag S. Maskey 	if (priority == INVALID_PRIORITY_GROUP)
6136ba597c5SAnurag S. Maskey 		return;
6146ba597c5SAnurag S. Maskey 
6156ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncp_deactivate_priority_group_all: "
6166ba597c5SAnurag S. Maskey 	    "deactivating priority group less than or equal to %lld", priority);
6176ba597c5SAnurag S. Maskey 
6186ba597c5SAnurag S. Maskey 	do {
6196ba597c5SAnurag S. Maskey 		nwamd_ncp_deactivate_priority_group(priority);
6206ba597c5SAnurag S. Maskey 	} while (nwamd_ncp_find_next_priority_group(priority + 1, &priority));
6216ba597c5SAnurag S. Maskey }
6226ba597c5SAnurag S. Maskey 
6236ba597c5SAnurag S. Maskey /*
6246ba597c5SAnurag S. Maskey  * Returns 'true' if it found the highest priority group no higher then what
6256ba597c5SAnurag S. Maskey  * is passed that should be activated and sets *priority to that.
6266ba597c5SAnurag S. Maskey  */
6276ba597c5SAnurag S. Maskey boolean_t
nwamd_ncp_check_priority_group(int64_t * priority)6286ba597c5SAnurag S. Maskey nwamd_ncp_check_priority_group(int64_t *priority)
6296ba597c5SAnurag S. Maskey {
6306ba597c5SAnurag S. Maskey 	struct nwamd_ncu_check_walk_arg wa;
6316ba597c5SAnurag S. Maskey 	boolean_t conditions_met = B_FALSE;
6326ba597c5SAnurag S. Maskey 
6336ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncp_check_priority_group: "
6346ba597c5SAnurag S. Maskey 	    "checking priority group %lld", *priority);
6356ba597c5SAnurag S. Maskey 
6366ba597c5SAnurag S. Maskey 	if (*priority == INVALID_PRIORITY_GROUP) {
6376ba597c5SAnurag S. Maskey 		if (!nwamd_ncp_find_next_priority_group(0, priority))
6386ba597c5SAnurag S. Maskey 			return (B_FALSE);
6396ba597c5SAnurag S. Maskey 	}
6406ba597c5SAnurag S. Maskey 
6416ba597c5SAnurag S. Maskey 	while (!conditions_met) {
6426ba597c5SAnurag S. Maskey 		(void) memset(&wa, 0, sizeof (wa));
6436ba597c5SAnurag S. Maskey 		wa.manual = B_FALSE;
6446ba597c5SAnurag S. Maskey 		wa.priority_group = *priority;
6456ba597c5SAnurag S. Maskey 		wa.activate_or_deactivate = B_FALSE;
6466ba597c5SAnurag S. Maskey 
6476ba597c5SAnurag S. Maskey 		if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU,
6486ba597c5SAnurag S. Maskey 		    nwamd_ncu_check_or_activate, &wa) != 0) {
6496ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "nwamd_ncp_check_priority_group: "
6506ba597c5SAnurag S. Maskey 			    "nwamd_walk_objects() failed");
6516ba597c5SAnurag S. Maskey 			return (B_FALSE);
6526ba597c5SAnurag S. Maskey 		}
6536ba597c5SAnurag S. Maskey 
6546ba597c5SAnurag S. Maskey 		/*
6556ba597c5SAnurag S. Maskey 		 * Are activation conditons satisifed? In other words:
6566ba597c5SAnurag S. Maskey 		 * - exactly one of the exclusive NCUs is online
6576ba597c5SAnurag S. Maskey 		 * - 1 or more shared NCUs are online
6586ba597c5SAnurag S. Maskey 		 * - all of the all NCUs are online.
6596ba597c5SAnurag S. Maskey 		 * If any of these is untrue, conditions are not satisfied.
6606ba597c5SAnurag S. Maskey 		 */
6616ba597c5SAnurag S. Maskey 		conditions_met = B_TRUE;
6626ba597c5SAnurag S. Maskey 		if (wa.exclusive_ncus > 0 && wa.exclusive_online_ncus != 1)
6636ba597c5SAnurag S. Maskey 			conditions_met = B_FALSE;
6646ba597c5SAnurag S. Maskey 		if (wa.shared_ncus > 0 && wa.shared_online_ncus == 0)
6656ba597c5SAnurag S. Maskey 			conditions_met = B_FALSE;
6666ba597c5SAnurag S. Maskey 		if (wa.all_ncus > 0 && wa.all_ncus != wa.all_online_ncus)
6676ba597c5SAnurag S. Maskey 			conditions_met = B_FALSE;
6686ba597c5SAnurag S. Maskey 		if (wa.exclusive_online_ncus == 0 &&
6696ba597c5SAnurag S. Maskey 		    wa.shared_online_ncus == 0 && wa.all_online_ncus == 0)
6706ba597c5SAnurag S. Maskey 			conditions_met = B_FALSE;
6716ba597c5SAnurag S. Maskey 
6726ba597c5SAnurag S. Maskey 		if (conditions_met) {
6736ba597c5SAnurag S. Maskey 			return (B_TRUE);
6746ba597c5SAnurag S. Maskey 		} else {
6756ba597c5SAnurag S. Maskey 			/*
6766ba597c5SAnurag S. Maskey 			 * If there is a next pg, activate it. If not, do
6776ba597c5SAnurag S. Maskey 			 * nothing - we're stuck here unless an event occurs
6786ba597c5SAnurag S. Maskey 			 * for our or a higher pg.
6796ba597c5SAnurag S. Maskey 			 */
6806ba597c5SAnurag S. Maskey 			if (!nwamd_ncp_find_next_priority_group
6816ba597c5SAnurag S. Maskey 			    (wa.priority_group + 1, priority)) {
6826ba597c5SAnurag S. Maskey 				nlog(LOG_DEBUG, "ran out of prio groups");
6836ba597c5SAnurag S. Maskey 				return (B_FALSE);
6846ba597c5SAnurag S. Maskey 			}
6856ba597c5SAnurag S. Maskey 		}
6866ba597c5SAnurag S. Maskey 	}
6876ba597c5SAnurag S. Maskey 	return (B_FALSE);
6886ba597c5SAnurag S. Maskey }
6896ba597c5SAnurag S. Maskey 
6906ba597c5SAnurag S. Maskey void
nwamd_ncp_activate_manual_ncus(void)6916ba597c5SAnurag S. Maskey nwamd_ncp_activate_manual_ncus(void)
6926ba597c5SAnurag S. Maskey {
6936ba597c5SAnurag S. Maskey 	struct nwamd_ncu_check_walk_arg wa;
6946ba597c5SAnurag S. Maskey 
6956ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncp_activate_manual_ncus: activating NCUs");
6966ba597c5SAnurag S. Maskey 
6976ba597c5SAnurag S. Maskey 	wa.manual = B_TRUE;
6986ba597c5SAnurag S. Maskey 	wa.activate_or_deactivate = B_TRUE;
6996ba597c5SAnurag S. Maskey 	wa.activate = B_TRUE;
7006ba597c5SAnurag S. Maskey 
7016ba597c5SAnurag S. Maskey 	if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU,
7026ba597c5SAnurag S. Maskey 	    nwamd_ncu_check_or_activate, &wa) != 0) {
7036ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncp_activate_manual_ncus: "
7046ba597c5SAnurag S. Maskey 		    "nwamd_walk_objects() failed");
7056ba597c5SAnurag S. Maskey 		return;
7066ba597c5SAnurag S. Maskey 	}
7076ba597c5SAnurag S. Maskey }
7086ba597c5SAnurag S. Maskey 
7096ba597c5SAnurag S. Maskey void
nwamd_create_ncu_check_event(uint64_t when)7106ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(uint64_t when)
7116ba597c5SAnurag S. Maskey {
7126ba597c5SAnurag S. Maskey 	nwamd_event_t check_event = nwamd_event_init_ncu_check();
7136ba597c5SAnurag S. Maskey 	if (check_event != NULL)
7146ba597c5SAnurag S. Maskey 		nwamd_event_enqueue_timed(check_event, when);
7156ba597c5SAnurag S. Maskey }
716