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 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 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 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 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 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 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 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 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 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 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 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 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 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