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