1*6ba597c5SAnurag S. Maskey /* 2*6ba597c5SAnurag S. Maskey * CDDL HEADER START 3*6ba597c5SAnurag S. Maskey * 4*6ba597c5SAnurag S. Maskey * The contents of this file are subject to the terms of the 5*6ba597c5SAnurag S. Maskey * Common Development and Distribution License (the "License"). 6*6ba597c5SAnurag S. Maskey * You may not use this file except in compliance with the License. 7*6ba597c5SAnurag S. Maskey * 8*6ba597c5SAnurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6ba597c5SAnurag S. Maskey * or http://www.opensolaris.org/os/licensing. 10*6ba597c5SAnurag S. Maskey * See the License for the specific language governing permissions 11*6ba597c5SAnurag S. Maskey * and limitations under the License. 12*6ba597c5SAnurag S. Maskey * 13*6ba597c5SAnurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each 14*6ba597c5SAnurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6ba597c5SAnurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the 16*6ba597c5SAnurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying 17*6ba597c5SAnurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner] 18*6ba597c5SAnurag S. Maskey * 19*6ba597c5SAnurag S. Maskey * CDDL HEADER END 20*6ba597c5SAnurag S. Maskey */ 21*6ba597c5SAnurag S. Maskey 22*6ba597c5SAnurag S. Maskey /* 23*6ba597c5SAnurag S. Maskey * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24*6ba597c5SAnurag S. Maskey * Use is subject to license terms. 25*6ba597c5SAnurag S. Maskey */ 26*6ba597c5SAnurag S. Maskey 27*6ba597c5SAnurag S. Maskey #include <arpa/inet.h> 28*6ba597c5SAnurag S. Maskey #include <assert.h> 29*6ba597c5SAnurag S. Maskey #include <libdllink.h> 30*6ba597c5SAnurag S. Maskey #include <libdlstat.h> 31*6ba597c5SAnurag S. Maskey #include <libnwam.h> 32*6ba597c5SAnurag S. Maskey #include <libscf.h> 33*6ba597c5SAnurag S. Maskey #include <netinet/in.h> 34*6ba597c5SAnurag S. Maskey #include <stdlib.h> 35*6ba597c5SAnurag S. Maskey #include <sys/socket.h> 36*6ba597c5SAnurag S. Maskey #include <sys/time.h> 37*6ba597c5SAnurag S. Maskey #include <sys/types.h> 38*6ba597c5SAnurag S. Maskey #include <values.h> 39*6ba597c5SAnurag S. Maskey 40*6ba597c5SAnurag S. Maskey #include "conditions.h" 41*6ba597c5SAnurag S. Maskey #include "events.h" 42*6ba597c5SAnurag S. Maskey #include "objects.h" 43*6ba597c5SAnurag S. Maskey #include "ncp.h" 44*6ba597c5SAnurag S. Maskey #include "ncu.h" 45*6ba597c5SAnurag S. Maskey #include "util.h" 46*6ba597c5SAnurag S. Maskey 47*6ba597c5SAnurag S. Maskey /* 48*6ba597c5SAnurag S. Maskey * ncp.c - handles NCP actions. 49*6ba597c5SAnurag S. Maskey */ 50*6ba597c5SAnurag S. Maskey 51*6ba597c5SAnurag S. Maskey char active_ncp[NWAM_MAX_NAME_LEN]; 52*6ba597c5SAnurag S. Maskey nwam_ncp_handle_t active_ncph = NULL; 53*6ba597c5SAnurag S. Maskey int64_t current_ncu_priority_group = INVALID_PRIORITY_GROUP; 54*6ba597c5SAnurag S. Maskey /* 55*6ba597c5SAnurag S. Maskey * active_ncp_mutex protects active_ncp, active_ncph and 56*6ba597c5SAnurag S. Maskey * current_ncu_priority_group. 57*6ba597c5SAnurag S. Maskey */ 58*6ba597c5SAnurag S. Maskey pthread_mutex_t active_ncp_mutex = PTHREAD_MUTEX_INITIALIZER; 59*6ba597c5SAnurag S. Maskey 60*6ba597c5SAnurag S. Maskey /* 61*6ba597c5SAnurag S. Maskey * The variable ncu_wait_time specifies how long to wait to obtain a 62*6ba597c5SAnurag S. Maskey * DHCP lease before giving up on that NCU and moving on to the next/lower 63*6ba597c5SAnurag S. Maskey * priority-group. 64*6ba597c5SAnurag S. Maskey */ 65*6ba597c5SAnurag S. Maskey uint64_t ncu_wait_time = NCU_WAIT_TIME_DEFAULT; 66*6ba597c5SAnurag S. Maskey 67*6ba597c5SAnurag S. Maskey /* 68*6ba597c5SAnurag S. Maskey * Specifies if this is the first time the NCP has been enabled. True 69*6ba597c5SAnurag S. Maskey * on startup so that we can differentiate between when we start up 70*6ba597c5SAnurag S. Maskey * with a given NCP versus when we are asked to reenable it. 71*6ba597c5SAnurag S. Maskey */ 72*6ba597c5SAnurag S. Maskey boolean_t initial_ncp_enable = B_TRUE; 73*6ba597c5SAnurag S. Maskey 74*6ba597c5SAnurag S. Maskey /* 75*6ba597c5SAnurag S. Maskey * nwamd_ncp_handle_enable_event() should be called in the event handling 76*6ba597c5SAnurag S. Maskey * loop in response to an _ENABLE event, triggered as a result of an 77*6ba597c5SAnurag S. Maskey * nwam_ncp_enable() call from a libnwam consumer. To enable the new NCP, 78*6ba597c5SAnurag S. Maskey * we first call nwamd_fini_ncus() on the old NCP. This results in enqueueing 79*6ba597c5SAnurag S. Maskey * of a set of _FINI events for each NCU. These events are handled and in 80*6ba597c5SAnurag S. Maskey * order to tear down config, (online*, uninitialized) state change events 81*6ba597c5SAnurag S. Maskey * are created and consumed directly by the fini event handler (these events 82*6ba597c5SAnurag S. Maskey * are not enqueued as this would result in state events for the old NCP 83*6ba597c5SAnurag S. Maskey * appearing after the new NCP has been enabled. After the _FINI events are 84*6ba597c5SAnurag S. Maskey * enqueued, we enqueue an NCP _OBJECT_STATE event for the new NCP. Since 85*6ba597c5SAnurag S. Maskey * it is enqueued after the _FINI events, we are guaranteed no events for the 86*6ba597c5SAnurag S. Maskey * old NCP will appear after the new NCP is activated. 87*6ba597c5SAnurag S. Maskey */ 88*6ba597c5SAnurag S. Maskey void 89*6ba597c5SAnurag S. Maskey nwamd_ncp_handle_enable_event(nwamd_event_t event) 90*6ba597c5SAnurag S. Maskey { 91*6ba597c5SAnurag S. Maskey char *new_ncp = event->event_object; 92*6ba597c5SAnurag S. Maskey nwam_ncp_handle_t new_ncph; 93*6ba597c5SAnurag S. Maskey nwam_error_t err; 94*6ba597c5SAnurag S. Maskey 95*6ba597c5SAnurag S. Maskey if (new_ncp[0] == '\0') 96*6ba597c5SAnurag S. Maskey return; 97*6ba597c5SAnurag S. Maskey 98*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 99*6ba597c5SAnurag S. Maskey if (strcmp(active_ncp, new_ncp) == 0 && !initial_ncp_enable) { 100*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_handle_enable_event: " 101*6ba597c5SAnurag S. Maskey "%s is already active", new_ncp); 102*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 103*6ba597c5SAnurag S. Maskey return; 104*6ba597c5SAnurag S. Maskey } 105*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 106*6ba597c5SAnurag S. Maskey 107*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_handle_enable_event: activating NCP %s", 108*6ba597c5SAnurag S. Maskey new_ncp); 109*6ba597c5SAnurag S. Maskey 110*6ba597c5SAnurag S. Maskey /* 111*6ba597c5SAnurag S. Maskey * To activate new NCP, run nwamd_fini_ncus(), reset the active 112*6ba597c5SAnurag S. Maskey * priority-group, set the active_ncp property and refresh the 113*6ba597c5SAnurag S. Maskey * daemon. The refresh action will trigger a re-read of the NCUs 114*6ba597c5SAnurag S. Maskey * for the activated NCP. 115*6ba597c5SAnurag S. Maskey */ 116*6ba597c5SAnurag S. Maskey 117*6ba597c5SAnurag S. Maskey nwamd_fini_ncus(); 118*6ba597c5SAnurag S. Maskey 119*6ba597c5SAnurag S. Maskey err = nwam_ncp_read(new_ncp, 0, &new_ncph); 120*6ba597c5SAnurag S. Maskey switch (err) { 121*6ba597c5SAnurag S. Maskey case NWAM_ENTITY_NOT_FOUND: 122*6ba597c5SAnurag S. Maskey err = nwam_ncp_create(new_ncp, 0, &new_ncph); 123*6ba597c5SAnurag S. Maskey break; 124*6ba597c5SAnurag S. Maskey case NWAM_SUCCESS: 125*6ba597c5SAnurag S. Maskey break; 126*6ba597c5SAnurag S. Maskey default: 127*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncp_handle_enable_event: error %s", 128*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 129*6ba597c5SAnurag S. Maskey return; 130*6ba597c5SAnurag S. Maskey } 131*6ba597c5SAnurag S. Maskey nwam_ncp_free(new_ncph); 132*6ba597c5SAnurag S. Maskey 133*6ba597c5SAnurag S. Maskey if (err == NWAM_SUCCESS) { 134*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCP, new_ncp, 135*6ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE, NWAM_AUX_STATE_ACTIVE); 136*6ba597c5SAnurag S. Maskey } else { 137*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncp_handle_enable_event: error %s", 138*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 139*6ba597c5SAnurag S. Maskey return; 140*6ba597c5SAnurag S. Maskey } 141*6ba597c5SAnurag S. Maskey } 142*6ba597c5SAnurag S. Maskey 143*6ba597c5SAnurag S. Maskey void 144*6ba597c5SAnurag S. Maskey nwamd_ncp_handle_action_event(nwamd_event_t event) 145*6ba597c5SAnurag S. Maskey { 146*6ba597c5SAnurag S. Maskey switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) { 147*6ba597c5SAnurag S. Maskey case NWAM_ACTION_ENABLE: 148*6ba597c5SAnurag S. Maskey nwamd_ncp_handle_enable_event(event); 149*6ba597c5SAnurag S. Maskey break; 150*6ba597c5SAnurag S. Maskey case NWAM_ACTION_ADD: 151*6ba597c5SAnurag S. Maskey case NWAM_ACTION_DESTROY: 152*6ba597c5SAnurag S. Maskey /* nothing to do */ 153*6ba597c5SAnurag S. Maskey break; 154*6ba597c5SAnurag S. Maskey default: 155*6ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwam_ncp_handle_action_event: " 156*6ba597c5SAnurag S. Maskey "unexpected action"); 157*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 158*6ba597c5SAnurag S. Maskey break; 159*6ba597c5SAnurag S. Maskey } 160*6ba597c5SAnurag S. Maskey } 161*6ba597c5SAnurag S. Maskey 162*6ba597c5SAnurag S. Maskey /* 163*6ba597c5SAnurag S. Maskey * The only state events we create are (online, active) events which are 164*6ba597c5SAnurag S. Maskey * generated as part of an NCP enable action (see above). 165*6ba597c5SAnurag S. Maskey */ 166*6ba597c5SAnurag S. Maskey void 167*6ba597c5SAnurag S. Maskey nwamd_ncp_handle_state_event(nwamd_event_t event) 168*6ba597c5SAnurag S. Maskey { 169*6ba597c5SAnurag S. Maskey char *new_ncp = event->event_object; 170*6ba597c5SAnurag S. Maskey nwam_ncp_handle_t new_ncph, old_ncph; 171*6ba597c5SAnurag S. Maskey nwam_error_t err; 172*6ba597c5SAnurag S. Maskey 173*6ba597c5SAnurag S. Maskey /* The NCP to be activated should always exist. */ 174*6ba597c5SAnurag S. Maskey if ((err = nwam_ncp_read(new_ncp, 0, &new_ncph)) != NWAM_SUCCESS) { 175*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncp_handle_state_event: " 176*6ba597c5SAnurag S. Maskey "cannot read NCP %s: : %s", new_ncp, nwam_strerror(err)); 177*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 178*6ba597c5SAnurag S. Maskey return; 179*6ba597c5SAnurag S. Maskey } 180*6ba597c5SAnurag S. Maskey 181*6ba597c5SAnurag S. Maskey /* 182*6ba597c5SAnurag S. Maskey * To activate new NCP, reset the active priority-group, set the 183*6ba597c5SAnurag S. Maskey * active_ncp property and refresh the daemon. The refresh action will 184*6ba597c5SAnurag S. Maskey * trigger a re-read of the NCUs for the activated NCP. 185*6ba597c5SAnurag S. Maskey */ 186*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 187*6ba597c5SAnurag S. Maskey old_ncph = active_ncph; 188*6ba597c5SAnurag S. Maskey active_ncph = new_ncph; 189*6ba597c5SAnurag S. Maskey nwam_ncp_free(old_ncph); 190*6ba597c5SAnurag S. Maskey current_ncu_priority_group = INVALID_PRIORITY_GROUP; 191*6ba597c5SAnurag S. Maskey (void) strlcpy(active_ncp, event->event_object, 192*6ba597c5SAnurag S. Maskey sizeof (active_ncp)); 193*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 194*6ba597c5SAnurag S. Maskey (void) nwamd_set_string_property(OUR_FMRI, OUR_PG, 195*6ba597c5SAnurag S. Maskey OUR_ACTIVE_NCP_PROP_NAME, new_ncp); 196*6ba597c5SAnurag S. Maskey (void) smf_refresh_instance(OUR_FMRI); 197*6ba597c5SAnurag S. Maskey initial_ncp_enable = B_FALSE; 198*6ba597c5SAnurag S. Maskey } 199*6ba597c5SAnurag S. Maskey 200*6ba597c5SAnurag S. Maskey int 201*6ba597c5SAnurag S. Maskey nwamd_ncp_action(const char *ncp, nwam_action_t action) 202*6ba597c5SAnurag S. Maskey { 203*6ba597c5SAnurag S. Maskey nwamd_event_t event = nwamd_event_init_object_action 204*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCP, ncp, NULL, action); 205*6ba597c5SAnurag S. Maskey if (event == NULL) 206*6ba597c5SAnurag S. Maskey return (1); 207*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 208*6ba597c5SAnurag S. Maskey return (0); 209*6ba597c5SAnurag S. Maskey } 210*6ba597c5SAnurag S. Maskey 211*6ba597c5SAnurag S. Maskey /* 212*6ba597c5SAnurag S. Maskey * Below this point are routines handling NCU prioritization 213*6ba597c5SAnurag S. Maskey * policy for the active NCP. 214*6ba597c5SAnurag S. Maskey */ 215*6ba597c5SAnurag S. Maskey 216*6ba597c5SAnurag S. Maskey struct priority_group_cbarg { 217*6ba597c5SAnurag S. Maskey uint64_t minpriority; 218*6ba597c5SAnurag S. Maskey uint64_t currpriority; 219*6ba597c5SAnurag S. Maskey boolean_t found; 220*6ba597c5SAnurag S. Maskey }; 221*6ba597c5SAnurag S. Maskey 222*6ba597c5SAnurag S. Maskey /* Callback used to find next pg in NCP that is >= start_pg */ 223*6ba597c5SAnurag S. Maskey static int 224*6ba597c5SAnurag S. Maskey find_next_priority_group_cb(nwamd_object_t object, void *data) 225*6ba597c5SAnurag S. Maskey { 226*6ba597c5SAnurag S. Maskey struct priority_group_cbarg *cbarg = data; 227*6ba597c5SAnurag S. Maskey uint64_t priority; 228*6ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu = object->nwamd_object_data; 229*6ba597c5SAnurag S. Maskey 230*6ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_link.nwamd_link_activation_mode != 231*6ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED) 232*6ba597c5SAnurag S. Maskey return (0); 233*6ba597c5SAnurag S. Maskey 234*6ba597c5SAnurag S. Maskey priority = ncu->ncu_node.u_link.nwamd_link_priority_group; 235*6ba597c5SAnurag S. Maskey 236*6ba597c5SAnurag S. Maskey if (priority >= cbarg->minpriority && priority < cbarg->currpriority) { 237*6ba597c5SAnurag S. Maskey cbarg->found = B_TRUE; 238*6ba597c5SAnurag S. Maskey cbarg->currpriority = priority; 239*6ba597c5SAnurag S. Maskey } 240*6ba597c5SAnurag S. Maskey return (0); 241*6ba597c5SAnurag S. Maskey } 242*6ba597c5SAnurag S. Maskey 243*6ba597c5SAnurag S. Maskey 244*6ba597c5SAnurag S. Maskey /* Set current_pg to next pg in NCP that is >= start_pg */ 245*6ba597c5SAnurag S. Maskey boolean_t 246*6ba597c5SAnurag S. Maskey nwamd_ncp_find_next_priority_group(int64_t minpriority, 247*6ba597c5SAnurag S. Maskey int64_t *nextpriorityp) 248*6ba597c5SAnurag S. Maskey { 249*6ba597c5SAnurag S. Maskey struct priority_group_cbarg cbarg; 250*6ba597c5SAnurag S. Maskey 251*6ba597c5SAnurag S. Maskey cbarg.minpriority = minpriority; 252*6ba597c5SAnurag S. Maskey cbarg.currpriority = MAXINT; 253*6ba597c5SAnurag S. Maskey cbarg.found = B_FALSE; 254*6ba597c5SAnurag S. Maskey 255*6ba597c5SAnurag S. Maskey (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, 256*6ba597c5SAnurag S. Maskey find_next_priority_group_cb, &cbarg); 257*6ba597c5SAnurag S. Maskey 258*6ba597c5SAnurag S. Maskey if (cbarg.found) { 259*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_find_next_priority_group: " 260*6ba597c5SAnurag S. Maskey "next priority group >= %lld is %lld", 261*6ba597c5SAnurag S. Maskey minpriority, cbarg.currpriority); 262*6ba597c5SAnurag S. Maskey *nextpriorityp = cbarg.currpriority; 263*6ba597c5SAnurag S. Maskey return (B_TRUE); 264*6ba597c5SAnurag S. Maskey } else { 265*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_find_next_priority_group: " 266*6ba597c5SAnurag S. Maskey "no priority groups >= %lld exist", minpriority); 267*6ba597c5SAnurag S. Maskey return (B_FALSE); 268*6ba597c5SAnurag S. Maskey } 269*6ba597c5SAnurag S. Maskey } 270*6ba597c5SAnurag S. Maskey 271*6ba597c5SAnurag S. Maskey /* 272*6ba597c5SAnurag S. Maskey * Struct for walking NCUs in the selected priority group. We count 273*6ba597c5SAnurag S. Maskey * how many of the exclusive, all and shared NCUs are online, and 274*6ba597c5SAnurag S. Maskey * if activate_or_deactivate is true, we either activate or deactivate 275*6ba597c5SAnurag S. Maskey * (depending on the value of activate) offline/online NCUs. 276*6ba597c5SAnurag S. Maskey */ 277*6ba597c5SAnurag S. Maskey struct nwamd_ncu_check_walk_arg { 278*6ba597c5SAnurag S. Maskey boolean_t manual; /* enable manual NCUs only */ 279*6ba597c5SAnurag S. Maskey int64_t priority_group; /* interested priority-group for this walk */ 280*6ba597c5SAnurag S. Maskey uint64_t exclusive_ncus; 281*6ba597c5SAnurag S. Maskey uint64_t exclusive_online_ncus; 282*6ba597c5SAnurag S. Maskey uint64_t shared_ncus; 283*6ba597c5SAnurag S. Maskey uint64_t shared_online_ncus; 284*6ba597c5SAnurag S. Maskey uint64_t all_ncus; 285*6ba597c5SAnurag S. Maskey uint64_t all_online_ncus; 286*6ba597c5SAnurag S. Maskey boolean_t activate_or_deactivate; 287*6ba597c5SAnurag S. Maskey boolean_t activate; 288*6ba597c5SAnurag S. Maskey }; 289*6ba597c5SAnurag S. Maskey 290*6ba597c5SAnurag S. Maskey /* 291*6ba597c5SAnurag S. Maskey * This function serves a number of purposes: 292*6ba597c5SAnurag S. Maskey * - it supports activation/deactivation of manual NCUs in the current NCP 293*6ba597c5SAnurag S. Maskey * (when wa->manual is true, wa->activate determines if we activate or 294*6ba597c5SAnurag S. Maskey * deactivate the current NCU) 295*6ba597c5SAnurag S. Maskey * - it supports checking/activation of a particular priority group in 296*6ba597c5SAnurag S. Maskey * the active NCP. This works as follows: 297*6ba597c5SAnurag S. Maskey * 298*6ba597c5SAnurag S. Maskey * Count up numbers of exclusive, shared and all NCUs, and how many of each 299*6ba597c5SAnurag S. Maskey * are online. If an NCU is waiting for IP address to be assigned, it is 300*6ba597c5SAnurag S. Maskey * also considered online. If activate_or_deactivate is true, we also 301*6ba597c5SAnurag S. Maskey * either activate (if activate is true) or deactivate prioritized NCUs 302*6ba597c5SAnurag S. Maskey * that are offline or online. 303*6ba597c5SAnurag S. Maskey */ 304*6ba597c5SAnurag S. Maskey static int 305*6ba597c5SAnurag S. Maskey nwamd_ncu_check_or_activate(nwamd_object_t object, void *data) 306*6ba597c5SAnurag S. Maskey { 307*6ba597c5SAnurag S. Maskey struct nwamd_ncu_check_walk_arg *wa = data; 308*6ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu; 309*6ba597c5SAnurag S. Maskey uint64_t priority_group, priority_mode; 310*6ba597c5SAnurag S. Maskey nwamd_object_t if_obj; 311*6ba597c5SAnurag S. Maskey nwam_state_t state, if_state; 312*6ba597c5SAnurag S. Maskey nwam_aux_state_t aux_state, if_aux_state; 313*6ba597c5SAnurag S. Maskey char *name; 314*6ba597c5SAnurag S. Maskey 315*6ba597c5SAnurag S. Maskey state = object->nwamd_object_state; 316*6ba597c5SAnurag S. Maskey aux_state = object->nwamd_object_aux_state; 317*6ba597c5SAnurag S. Maskey name = object->nwamd_object_name; 318*6ba597c5SAnurag S. Maskey ncu = object->nwamd_object_data; 319*6ba597c5SAnurag S. Maskey 320*6ba597c5SAnurag S. Maskey /* skip NCUs in UNINITIALIZED state */ 321*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_UNINITIALIZED) { 322*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 323*6ba597c5SAnurag S. Maskey "skipping uninitialized ncu %s", name); 324*6ba597c5SAnurag S. Maskey return (0); 325*6ba597c5SAnurag S. Maskey } 326*6ba597c5SAnurag S. Maskey if (!wa->manual && wa->priority_group == INVALID_PRIORITY_GROUP) 327*6ba597c5SAnurag S. Maskey return (0); 328*6ba597c5SAnurag S. Maskey 329*6ba597c5SAnurag S. Maskey if (ncu->ncu_type != NWAM_NCU_TYPE_LINK) { 330*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 331*6ba597c5SAnurag S. Maskey "skipping interface NCU %s", name); 332*6ba597c5SAnurag S. Maskey return (0); 333*6ba597c5SAnurag S. Maskey } 334*6ba597c5SAnurag S. Maskey if (!wa->manual && ncu->ncu_node.u_link.nwamd_link_activation_mode != 335*6ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED) { 336*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 337*6ba597c5SAnurag S. Maskey "skipping non-prioritized NCU %s", name); 338*6ba597c5SAnurag S. Maskey return (0); 339*6ba597c5SAnurag S. Maskey } 340*6ba597c5SAnurag S. Maskey if (wa->manual && ncu->ncu_node.u_link.nwamd_link_activation_mode != 341*6ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_MANUAL) { 342*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 343*6ba597c5SAnurag S. Maskey "skipping non-manual NCU %s", name); 344*6ba597c5SAnurag S. Maskey return (0); 345*6ba597c5SAnurag S. Maskey } 346*6ba597c5SAnurag S. Maskey 347*6ba597c5SAnurag S. Maskey priority_group = ncu->ncu_node.u_link.nwamd_link_priority_group; 348*6ba597c5SAnurag S. Maskey priority_mode = ncu->ncu_node.u_link.nwamd_link_priority_mode; 349*6ba597c5SAnurag S. Maskey /* Only work with NCUs in the requested priority-group */ 350*6ba597c5SAnurag S. Maskey if (!wa->manual && priority_group != wa->priority_group) { 351*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 352*6ba597c5SAnurag S. Maskey "skipping NCU %s in different priority-group", name); 353*6ba597c5SAnurag S. Maskey return (0); 354*6ba597c5SAnurag S. Maskey } 355*6ba597c5SAnurag S. Maskey /* Get the state of the corresponding interface NCU */ 356*6ba597c5SAnurag S. Maskey if ((if_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_INTERFACE, 357*6ba597c5SAnurag S. Maskey ncu->ncu_name)) == NULL) { 358*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_check_or_activate: " 359*6ba597c5SAnurag S. Maskey "interface NCU of %s not found, skipping", name); 360*6ba597c5SAnurag S. Maskey return (0); 361*6ba597c5SAnurag S. Maskey } 362*6ba597c5SAnurag S. Maskey if_state = if_obj->nwamd_object_state; 363*6ba597c5SAnurag S. Maskey if_aux_state = if_obj->nwamd_object_aux_state; 364*6ba597c5SAnurag S. Maskey nwamd_object_release(if_obj); 365*6ba597c5SAnurag S. Maskey 366*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: %s ncu %s", 367*6ba597c5SAnurag S. Maskey wa->activate_or_deactivate ? 368*6ba597c5SAnurag S. Maskey (wa->activate ? "activating" : "deactivating") : 369*6ba597c5SAnurag S. Maskey "checking", name); 370*6ba597c5SAnurag S. Maskey 371*6ba597c5SAnurag S. Maskey if (wa->manual) { 372*6ba597c5SAnurag S. Maskey if (wa->activate_or_deactivate && wa->activate) { 373*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_OFFLINE && ncu->ncu_enabled) { 374*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 375*6ba597c5SAnurag S. Maskey "moving NCU %s to offline* from offline", 376*6ba597c5SAnurag S. Maskey name); 377*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 378*6ba597c5SAnurag S. Maskey name, NWAM_STATE_OFFLINE_TO_ONLINE, 379*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 380*6ba597c5SAnurag S. Maskey } 381*6ba597c5SAnurag S. Maskey if (state != NWAM_STATE_DISABLED && 382*6ba597c5SAnurag S. Maskey !ncu->ncu_enabled) { 383*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 384*6ba597c5SAnurag S. Maskey "moving NCU %s to online* (disabling)", 385*6ba597c5SAnurag S. Maskey name); 386*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 387*6ba597c5SAnurag S. Maskey name, NWAM_STATE_ONLINE_TO_OFFLINE, 388*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 389*6ba597c5SAnurag S. Maskey } 390*6ba597c5SAnurag S. Maskey } 391*6ba597c5SAnurag S. Maskey return (0); 392*6ba597c5SAnurag S. Maskey } 393*6ba597c5SAnurag S. Maskey switch (priority_mode) { 394*6ba597c5SAnurag S. Maskey case NWAM_PRIORITY_MODE_EXCLUSIVE: 395*6ba597c5SAnurag S. Maskey wa->exclusive_ncus++; 396*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_ONLINE && 397*6ba597c5SAnurag S. Maskey (if_state == NWAM_STATE_ONLINE || 398*6ba597c5SAnurag S. Maskey if_aux_state == NWAM_AUX_STATE_IF_WAITING_FOR_ADDR)) 399*6ba597c5SAnurag S. Maskey wa->exclusive_online_ncus++; 400*6ba597c5SAnurag S. Maskey 401*6ba597c5SAnurag S. Maskey /* 402*6ba597c5SAnurag S. Maskey * For exclusive NCUs, we activate offline NCUs as long 403*6ba597c5SAnurag S. Maskey * as no other exclusive NCUs are active. 404*6ba597c5SAnurag S. Maskey */ 405*6ba597c5SAnurag S. Maskey if (wa->activate_or_deactivate && wa->activate) { 406*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_OFFLINE && 407*6ba597c5SAnurag S. Maskey wa->exclusive_online_ncus == 0) { 408*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 409*6ba597c5SAnurag S. Maskey "moving NCU %s to offline* from offline", 410*6ba597c5SAnurag S. Maskey name); 411*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 412*6ba597c5SAnurag S. Maskey name, NWAM_STATE_OFFLINE_TO_ONLINE, 413*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 414*6ba597c5SAnurag S. Maskey } 415*6ba597c5SAnurag S. Maskey } 416*6ba597c5SAnurag S. Maskey if (wa->activate_or_deactivate && !wa->activate) { 417*6ba597c5SAnurag S. Maskey if (aux_state != NWAM_AUX_STATE_CONDITIONS_NOT_MET) { 418*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 419*6ba597c5SAnurag S. Maskey "deactivating NCU %s", name); 420*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 421*6ba597c5SAnurag S. Maskey name, NWAM_STATE_ONLINE_TO_OFFLINE, 422*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 423*6ba597c5SAnurag S. Maskey } 424*6ba597c5SAnurag S. Maskey } 425*6ba597c5SAnurag S. Maskey /* 426*6ba597c5SAnurag S. Maskey * If we are activating or checking the priority group and 427*6ba597c5SAnurag S. Maskey * too many exclusive NCUs are online, take this NCU down. 428*6ba597c5SAnurag S. Maskey */ 429*6ba597c5SAnurag S. Maskey if ((wa->activate_or_deactivate && wa->activate) || 430*6ba597c5SAnurag S. Maskey !wa->activate_or_deactivate) { 431*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_ONLINE && 432*6ba597c5SAnurag S. Maskey if_state == NWAM_STATE_ONLINE && 433*6ba597c5SAnurag S. Maskey wa->exclusive_online_ncus > 1) { 434*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 435*6ba597c5SAnurag S. Maskey "moving NCU %s to online* since another " 436*6ba597c5SAnurag S. Maskey "NCU is already active", 437*6ba597c5SAnurag S. Maskey name); 438*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 439*6ba597c5SAnurag S. Maskey name, NWAM_STATE_ONLINE_TO_OFFLINE, 440*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 441*6ba597c5SAnurag S. Maskey } 442*6ba597c5SAnurag S. Maskey } 443*6ba597c5SAnurag S. Maskey break; 444*6ba597c5SAnurag S. Maskey case NWAM_PRIORITY_MODE_SHARED: 445*6ba597c5SAnurag S. Maskey wa->shared_ncus++; 446*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_ONLINE && 447*6ba597c5SAnurag S. Maskey (if_state == NWAM_STATE_ONLINE || 448*6ba597c5SAnurag S. Maskey if_aux_state == NWAM_AUX_STATE_IF_WAITING_FOR_ADDR)) 449*6ba597c5SAnurag S. Maskey wa->shared_online_ncus++; 450*6ba597c5SAnurag S. Maskey 451*6ba597c5SAnurag S. Maskey if (wa->activate_or_deactivate && wa->activate) { 452*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_OFFLINE) { 453*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 454*6ba597c5SAnurag S. Maskey "activating NCU %s", name); 455*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 456*6ba597c5SAnurag S. Maskey name, NWAM_STATE_OFFLINE_TO_ONLINE, 457*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 458*6ba597c5SAnurag S. Maskey } 459*6ba597c5SAnurag S. Maskey } 460*6ba597c5SAnurag S. Maskey if (wa->activate_or_deactivate && !wa->activate) { 461*6ba597c5SAnurag S. Maskey if (aux_state != NWAM_AUX_STATE_CONDITIONS_NOT_MET) { 462*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 463*6ba597c5SAnurag S. Maskey "deactivating NCU %s", name); 464*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 465*6ba597c5SAnurag S. Maskey name, NWAM_STATE_ONLINE_TO_OFFLINE, 466*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 467*6ba597c5SAnurag S. Maskey } 468*6ba597c5SAnurag S. Maskey } 469*6ba597c5SAnurag S. Maskey break; 470*6ba597c5SAnurag S. Maskey case NWAM_PRIORITY_MODE_ALL: 471*6ba597c5SAnurag S. Maskey wa->all_ncus++; 472*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_ONLINE && 473*6ba597c5SAnurag S. Maskey (if_state == NWAM_STATE_ONLINE || 474*6ba597c5SAnurag S. Maskey if_aux_state == NWAM_AUX_STATE_IF_WAITING_FOR_ADDR)) 475*6ba597c5SAnurag S. Maskey wa->all_online_ncus++; 476*6ba597c5SAnurag S. Maskey 477*6ba597c5SAnurag S. Maskey /* 478*6ba597c5SAnurag S. Maskey * For "all" NCUs, activate/deactivate all offline/online 479*6ba597c5SAnurag S. Maskey * NCUs. 480*6ba597c5SAnurag S. Maskey */ 481*6ba597c5SAnurag S. Maskey if (wa->activate_or_deactivate && wa->activate) { 482*6ba597c5SAnurag S. Maskey if (state == NWAM_STATE_OFFLINE) { 483*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 484*6ba597c5SAnurag S. Maskey "activating NCU %s", name); 485*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 486*6ba597c5SAnurag S. Maskey name, NWAM_STATE_OFFLINE_TO_ONLINE, 487*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 488*6ba597c5SAnurag S. Maskey } 489*6ba597c5SAnurag S. Maskey } 490*6ba597c5SAnurag S. Maskey if (wa->activate_or_deactivate && !wa->activate) { 491*6ba597c5SAnurag S. Maskey if (aux_state != NWAM_AUX_STATE_CONDITIONS_NOT_MET) { 492*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " 493*6ba597c5SAnurag S. Maskey "deactivating NCU %s", name); 494*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 495*6ba597c5SAnurag S. Maskey name, NWAM_STATE_ONLINE_TO_OFFLINE, 496*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 497*6ba597c5SAnurag S. Maskey } 498*6ba597c5SAnurag S. Maskey } 499*6ba597c5SAnurag S. Maskey 500*6ba597c5SAnurag S. Maskey break; 501*6ba597c5SAnurag S. Maskey default: 502*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_check_or_activate: " 503*6ba597c5SAnurag S. Maskey "invalid priority-mode"); 504*6ba597c5SAnurag S. Maskey break; 505*6ba597c5SAnurag S. Maskey } 506*6ba597c5SAnurag S. Maskey 507*6ba597c5SAnurag S. Maskey return (0); 508*6ba597c5SAnurag S. Maskey } 509*6ba597c5SAnurag S. Maskey 510*6ba597c5SAnurag S. Maskey void 511*6ba597c5SAnurag S. Maskey nwamd_ncp_activate_priority_group(int64_t priority) 512*6ba597c5SAnurag S. Maskey { 513*6ba597c5SAnurag S. Maskey struct nwamd_ncu_check_walk_arg wa; 514*6ba597c5SAnurag S. Maskey nwamd_event_t check_event, priority_event; 515*6ba597c5SAnurag S. Maskey 516*6ba597c5SAnurag S. Maskey if (priority == INVALID_PRIORITY_GROUP) 517*6ba597c5SAnurag S. Maskey return; 518*6ba597c5SAnurag S. Maskey 519*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 520*6ba597c5SAnurag S. Maskey if (priority == current_ncu_priority_group) { 521*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 522*6ba597c5SAnurag S. Maskey return; 523*6ba597c5SAnurag S. Maskey } 524*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 525*6ba597c5SAnurag S. Maskey 526*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_activate_priority_group: " 527*6ba597c5SAnurag S. Maskey "activating priority group %lld", priority); 528*6ba597c5SAnurag S. Maskey 529*6ba597c5SAnurag S. Maskey wa.manual = B_FALSE; 530*6ba597c5SAnurag S. Maskey wa.priority_group = priority; 531*6ba597c5SAnurag S. Maskey wa.exclusive_ncus = 0; 532*6ba597c5SAnurag S. Maskey wa.exclusive_online_ncus = 0; 533*6ba597c5SAnurag S. Maskey wa.shared_ncus = 0; 534*6ba597c5SAnurag S. Maskey wa.shared_online_ncus = 0; 535*6ba597c5SAnurag S. Maskey wa.all_ncus = 0; 536*6ba597c5SAnurag S. Maskey wa.all_online_ncus = 0; 537*6ba597c5SAnurag S. Maskey wa.activate_or_deactivate = B_TRUE; 538*6ba597c5SAnurag S. Maskey wa.activate = B_TRUE; 539*6ba597c5SAnurag S. Maskey 540*6ba597c5SAnurag S. Maskey if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, 541*6ba597c5SAnurag S. Maskey nwamd_ncu_check_or_activate, &wa) != 0) { 542*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncp_activate_priority_group: " 543*6ba597c5SAnurag S. Maskey "nwamd_walk_objects() failed"); 544*6ba597c5SAnurag S. Maskey return; 545*6ba597c5SAnurag S. Maskey } 546*6ba597c5SAnurag S. Maskey 547*6ba597c5SAnurag S. Maskey /* 548*6ba597c5SAnurag S. Maskey * Enqueue event to update current_ncu_priority_group and send to 549*6ba597c5SAnurag S. Maskey * any event listeners. 550*6ba597c5SAnurag S. Maskey */ 551*6ba597c5SAnurag S. Maskey priority_event = nwamd_event_init_priority_group_change(priority); 552*6ba597c5SAnurag S. Maskey if (priority_event == NULL) 553*6ba597c5SAnurag S. Maskey return; 554*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(priority_event); 555*6ba597c5SAnurag S. Maskey 556*6ba597c5SAnurag S. Maskey /* 557*6ba597c5SAnurag S. Maskey * Now we've activated a new priority group, enqueue an event 558*6ba597c5SAnurag S. Maskey * to check up on the state of this priority group. 559*6ba597c5SAnurag S. Maskey */ 560*6ba597c5SAnurag S. Maskey check_event = nwamd_event_init_ncu_check(); 561*6ba597c5SAnurag S. Maskey if (check_event == NULL) 562*6ba597c5SAnurag S. Maskey return; 563*6ba597c5SAnurag S. Maskey nwamd_event_enqueue_timed(check_event, ncu_wait_time); 564*6ba597c5SAnurag S. Maskey } 565*6ba597c5SAnurag S. Maskey 566*6ba597c5SAnurag S. Maskey void 567*6ba597c5SAnurag S. Maskey nwamd_ncp_deactivate_priority_group(int64_t priority) 568*6ba597c5SAnurag S. Maskey { 569*6ba597c5SAnurag S. Maskey struct nwamd_ncu_check_walk_arg wa; 570*6ba597c5SAnurag S. Maskey 571*6ba597c5SAnurag S. Maskey if (priority == INVALID_PRIORITY_GROUP) 572*6ba597c5SAnurag S. Maskey return; 573*6ba597c5SAnurag S. Maskey 574*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_deactivate_priority_group: " 575*6ba597c5SAnurag S. Maskey "deactivating priority group %lld", priority); 576*6ba597c5SAnurag S. Maskey 577*6ba597c5SAnurag S. Maskey wa.manual = B_FALSE; 578*6ba597c5SAnurag S. Maskey wa.priority_group = priority; 579*6ba597c5SAnurag S. Maskey wa.exclusive_ncus = 0; 580*6ba597c5SAnurag S. Maskey wa.exclusive_online_ncus = 0; 581*6ba597c5SAnurag S. Maskey wa.shared_ncus = 0; 582*6ba597c5SAnurag S. Maskey wa.shared_online_ncus = 0; 583*6ba597c5SAnurag S. Maskey wa.all_ncus = 0; 584*6ba597c5SAnurag S. Maskey wa.all_online_ncus = 0; 585*6ba597c5SAnurag S. Maskey wa.activate_or_deactivate = B_TRUE; 586*6ba597c5SAnurag S. Maskey wa.activate = B_FALSE; 587*6ba597c5SAnurag S. Maskey 588*6ba597c5SAnurag S. Maskey if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, 589*6ba597c5SAnurag S. Maskey nwamd_ncu_check_or_activate, &wa) != 0) { 590*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncp_deactivate_priority_group: " 591*6ba597c5SAnurag S. Maskey "nwamd_walk_objects() failed"); 592*6ba597c5SAnurag S. Maskey return; 593*6ba597c5SAnurag S. Maskey } 594*6ba597c5SAnurag S. Maskey } 595*6ba597c5SAnurag S. Maskey 596*6ba597c5SAnurag S. Maskey /* 597*6ba597c5SAnurag S. Maskey * This function deactivates all priority groups at level 'priority' and lower 598*6ba597c5SAnurag S. Maskey * (which is, numerically, all priorities >= priority). 599*6ba597c5SAnurag S. Maskey */ 600*6ba597c5SAnurag S. Maskey void 601*6ba597c5SAnurag S. Maskey nwamd_ncp_deactivate_priority_group_all(int64_t priority) 602*6ba597c5SAnurag S. Maskey { 603*6ba597c5SAnurag S. Maskey if (priority == INVALID_PRIORITY_GROUP) 604*6ba597c5SAnurag S. Maskey return; 605*6ba597c5SAnurag S. Maskey 606*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_deactivate_priority_group_all: " 607*6ba597c5SAnurag S. Maskey "deactivating priority group less than or equal to %lld", priority); 608*6ba597c5SAnurag S. Maskey 609*6ba597c5SAnurag S. Maskey do { 610*6ba597c5SAnurag S. Maskey nwamd_ncp_deactivate_priority_group(priority); 611*6ba597c5SAnurag S. Maskey } while (nwamd_ncp_find_next_priority_group(priority + 1, &priority)); 612*6ba597c5SAnurag S. Maskey } 613*6ba597c5SAnurag S. Maskey 614*6ba597c5SAnurag S. Maskey /* 615*6ba597c5SAnurag S. Maskey * Returns 'true' if it found the highest priority group no higher then what 616*6ba597c5SAnurag S. Maskey * is passed that should be activated and sets *priority to that. 617*6ba597c5SAnurag S. Maskey */ 618*6ba597c5SAnurag S. Maskey boolean_t 619*6ba597c5SAnurag S. Maskey nwamd_ncp_check_priority_group(int64_t *priority) 620*6ba597c5SAnurag S. Maskey { 621*6ba597c5SAnurag S. Maskey struct nwamd_ncu_check_walk_arg wa; 622*6ba597c5SAnurag S. Maskey boolean_t conditions_met = B_FALSE; 623*6ba597c5SAnurag S. Maskey 624*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_check_priority_group: " 625*6ba597c5SAnurag S. Maskey "checking priority group %lld", *priority); 626*6ba597c5SAnurag S. Maskey 627*6ba597c5SAnurag S. Maskey if (*priority == INVALID_PRIORITY_GROUP) { 628*6ba597c5SAnurag S. Maskey if (!nwamd_ncp_find_next_priority_group(0, priority)) 629*6ba597c5SAnurag S. Maskey return (B_FALSE); 630*6ba597c5SAnurag S. Maskey } 631*6ba597c5SAnurag S. Maskey 632*6ba597c5SAnurag S. Maskey while (!conditions_met) { 633*6ba597c5SAnurag S. Maskey (void) memset(&wa, 0, sizeof (wa)); 634*6ba597c5SAnurag S. Maskey wa.manual = B_FALSE; 635*6ba597c5SAnurag S. Maskey wa.priority_group = *priority; 636*6ba597c5SAnurag S. Maskey wa.activate_or_deactivate = B_FALSE; 637*6ba597c5SAnurag S. Maskey 638*6ba597c5SAnurag S. Maskey if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, 639*6ba597c5SAnurag S. Maskey nwamd_ncu_check_or_activate, &wa) != 0) { 640*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncp_check_priority_group: " 641*6ba597c5SAnurag S. Maskey "nwamd_walk_objects() failed"); 642*6ba597c5SAnurag S. Maskey return (B_FALSE); 643*6ba597c5SAnurag S. Maskey } 644*6ba597c5SAnurag S. Maskey 645*6ba597c5SAnurag S. Maskey /* 646*6ba597c5SAnurag S. Maskey * Are activation conditons satisifed? In other words: 647*6ba597c5SAnurag S. Maskey * - exactly one of the exclusive NCUs is online 648*6ba597c5SAnurag S. Maskey * - 1 or more shared NCUs are online 649*6ba597c5SAnurag S. Maskey * - all of the all NCUs are online. 650*6ba597c5SAnurag S. Maskey * If any of these is untrue, conditions are not satisfied. 651*6ba597c5SAnurag S. Maskey */ 652*6ba597c5SAnurag S. Maskey conditions_met = B_TRUE; 653*6ba597c5SAnurag S. Maskey if (wa.exclusive_ncus > 0 && wa.exclusive_online_ncus != 1) 654*6ba597c5SAnurag S. Maskey conditions_met = B_FALSE; 655*6ba597c5SAnurag S. Maskey if (wa.shared_ncus > 0 && wa.shared_online_ncus == 0) 656*6ba597c5SAnurag S. Maskey conditions_met = B_FALSE; 657*6ba597c5SAnurag S. Maskey if (wa.all_ncus > 0 && wa.all_ncus != wa.all_online_ncus) 658*6ba597c5SAnurag S. Maskey conditions_met = B_FALSE; 659*6ba597c5SAnurag S. Maskey if (wa.exclusive_online_ncus == 0 && 660*6ba597c5SAnurag S. Maskey wa.shared_online_ncus == 0 && wa.all_online_ncus == 0) 661*6ba597c5SAnurag S. Maskey conditions_met = B_FALSE; 662*6ba597c5SAnurag S. Maskey 663*6ba597c5SAnurag S. Maskey if (conditions_met) { 664*6ba597c5SAnurag S. Maskey return (B_TRUE); 665*6ba597c5SAnurag S. Maskey } else { 666*6ba597c5SAnurag S. Maskey /* 667*6ba597c5SAnurag S. Maskey * If there is a next pg, activate it. If not, do 668*6ba597c5SAnurag S. Maskey * nothing - we're stuck here unless an event occurs 669*6ba597c5SAnurag S. Maskey * for our or a higher pg. 670*6ba597c5SAnurag S. Maskey */ 671*6ba597c5SAnurag S. Maskey if (!nwamd_ncp_find_next_priority_group 672*6ba597c5SAnurag S. Maskey (wa.priority_group + 1, priority)) { 673*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "ran out of prio groups"); 674*6ba597c5SAnurag S. Maskey return (B_FALSE); 675*6ba597c5SAnurag S. Maskey } 676*6ba597c5SAnurag S. Maskey } 677*6ba597c5SAnurag S. Maskey } 678*6ba597c5SAnurag S. Maskey return (B_FALSE); 679*6ba597c5SAnurag S. Maskey } 680*6ba597c5SAnurag S. Maskey 681*6ba597c5SAnurag S. Maskey void 682*6ba597c5SAnurag S. Maskey nwamd_ncp_activate_manual_ncus(void) 683*6ba597c5SAnurag S. Maskey { 684*6ba597c5SAnurag S. Maskey struct nwamd_ncu_check_walk_arg wa; 685*6ba597c5SAnurag S. Maskey 686*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncp_activate_manual_ncus: activating NCUs"); 687*6ba597c5SAnurag S. Maskey 688*6ba597c5SAnurag S. Maskey wa.manual = B_TRUE; 689*6ba597c5SAnurag S. Maskey wa.activate_or_deactivate = B_TRUE; 690*6ba597c5SAnurag S. Maskey wa.activate = B_TRUE; 691*6ba597c5SAnurag S. Maskey 692*6ba597c5SAnurag S. Maskey if (nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, 693*6ba597c5SAnurag S. Maskey nwamd_ncu_check_or_activate, &wa) != 0) { 694*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncp_activate_manual_ncus: " 695*6ba597c5SAnurag S. Maskey "nwamd_walk_objects() failed"); 696*6ba597c5SAnurag S. Maskey return; 697*6ba597c5SAnurag S. Maskey } 698*6ba597c5SAnurag S. Maskey } 699*6ba597c5SAnurag S. Maskey 700*6ba597c5SAnurag S. Maskey void 701*6ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(uint64_t when) 702*6ba597c5SAnurag S. Maskey { 703*6ba597c5SAnurag S. Maskey nwamd_event_t check_event = nwamd_event_init_ncu_check(); 704*6ba597c5SAnurag S. Maskey if (check_event != NULL) 705*6ba597c5SAnurag S. Maskey nwamd_event_enqueue_timed(check_event, when); 706*6ba597c5SAnurag S. Maskey } 707