1*7513SDarren.Reed@Sun.COM /* 2*7513SDarren.Reed@Sun.COM * CDDL HEADER START 3*7513SDarren.Reed@Sun.COM * 4*7513SDarren.Reed@Sun.COM * The contents of this file are subject to the terms of the 5*7513SDarren.Reed@Sun.COM * Common Development and Distribution License (the "License"). 6*7513SDarren.Reed@Sun.COM * You may not use this file except in compliance with the License. 7*7513SDarren.Reed@Sun.COM * 8*7513SDarren.Reed@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7513SDarren.Reed@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*7513SDarren.Reed@Sun.COM * See the License for the specific language governing permissions 11*7513SDarren.Reed@Sun.COM * and limitations under the License. 12*7513SDarren.Reed@Sun.COM * 13*7513SDarren.Reed@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*7513SDarren.Reed@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7513SDarren.Reed@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*7513SDarren.Reed@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*7513SDarren.Reed@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*7513SDarren.Reed@Sun.COM * 19*7513SDarren.Reed@Sun.COM * CDDL HEADER END 20*7513SDarren.Reed@Sun.COM */ 21*7513SDarren.Reed@Sun.COM /* 22*7513SDarren.Reed@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*7513SDarren.Reed@Sun.COM * Use is subject to license terms. 24*7513SDarren.Reed@Sun.COM */ 25*7513SDarren.Reed@Sun.COM 26*7513SDarren.Reed@Sun.COM #include <sys/param.h> 27*7513SDarren.Reed@Sun.COM #include <sys/atomic.h> 28*7513SDarren.Reed@Sun.COM #include <sys/kmem.h> 29*7513SDarren.Reed@Sun.COM #include <sys/rwlock.h> 30*7513SDarren.Reed@Sun.COM #include <sys/errno.h> 31*7513SDarren.Reed@Sun.COM #include <sys/queue.h> 32*7513SDarren.Reed@Sun.COM #include <sys/sunddi.h> 33*7513SDarren.Reed@Sun.COM #include <inet/common.h> 34*7513SDarren.Reed@Sun.COM #include <inet/led.h> 35*7513SDarren.Reed@Sun.COM #include <inet/ip.h> 36*7513SDarren.Reed@Sun.COM #include <sys/neti.h> 37*7513SDarren.Reed@Sun.COM #include <sys/zone.h> 38*7513SDarren.Reed@Sun.COM #include <sys/sdt.h> 39*7513SDarren.Reed@Sun.COM 40*7513SDarren.Reed@Sun.COM 41*7513SDarren.Reed@Sun.COM typedef boolean_t napplyfn_t(kmutex_t *, neti_stack_t *, void *); 42*7513SDarren.Reed@Sun.COM 43*7513SDarren.Reed@Sun.COM static void *neti_stack_init(netstackid_t stackid, netstack_t *ns); 44*7513SDarren.Reed@Sun.COM static void neti_stack_fini(netstackid_t stackid, void *arg); 45*7513SDarren.Reed@Sun.COM static net_instance_int_t *net_instance_int_create(net_instance_t *nin, 46*7513SDarren.Reed@Sun.COM net_instance_int_t *parent); 47*7513SDarren.Reed@Sun.COM static void neti_stack_shutdown(netstackid_t stackid, void *arg); 48*7513SDarren.Reed@Sun.COM static void net_instance_int_free(net_instance_int_t *nini); 49*7513SDarren.Reed@Sun.COM 50*7513SDarren.Reed@Sun.COM static boolean_t neti_stack_apply_create(kmutex_t *, neti_stack_t *, void *); 51*7513SDarren.Reed@Sun.COM static boolean_t neti_stack_apply_destroy(kmutex_t *, neti_stack_t *, void *); 52*7513SDarren.Reed@Sun.COM static boolean_t neti_stack_apply_shutdown(kmutex_t *, neti_stack_t *, void *); 53*7513SDarren.Reed@Sun.COM static void neti_apply_all_instances(neti_stack_t *, napplyfn_t *); 54*7513SDarren.Reed@Sun.COM static void neti_apply_all_stacks(void *, napplyfn_t *); 55*7513SDarren.Reed@Sun.COM static boolean_t wait_for_nini_inprogress(neti_stack_t *, kmutex_t *, 56*7513SDarren.Reed@Sun.COM net_instance_int_t *, uint32_t); 57*7513SDarren.Reed@Sun.COM 58*7513SDarren.Reed@Sun.COM static nini_head_t neti_instance_list; 59*7513SDarren.Reed@Sun.COM static neti_stack_head_t neti_stack_list; 60*7513SDarren.Reed@Sun.COM static kmutex_t neti_stack_lock; 61*7513SDarren.Reed@Sun.COM 62*7513SDarren.Reed@Sun.COM void 63*7513SDarren.Reed@Sun.COM neti_init() 64*7513SDarren.Reed@Sun.COM { 65*7513SDarren.Reed@Sun.COM mutex_init(&neti_stack_lock, NULL, MUTEX_DRIVER, NULL); 66*7513SDarren.Reed@Sun.COM 67*7513SDarren.Reed@Sun.COM LIST_INIT(&neti_instance_list); 68*7513SDarren.Reed@Sun.COM LIST_INIT(&neti_stack_list); 69*7513SDarren.Reed@Sun.COM /* 70*7513SDarren.Reed@Sun.COM * We want to be informed each time a netstack is created or 71*7513SDarren.Reed@Sun.COM * destroyed in the kernel. 72*7513SDarren.Reed@Sun.COM */ 73*7513SDarren.Reed@Sun.COM netstack_register(NS_NETI, neti_stack_init, neti_stack_shutdown, 74*7513SDarren.Reed@Sun.COM neti_stack_fini); 75*7513SDarren.Reed@Sun.COM } 76*7513SDarren.Reed@Sun.COM 77*7513SDarren.Reed@Sun.COM void 78*7513SDarren.Reed@Sun.COM neti_fini() 79*7513SDarren.Reed@Sun.COM { 80*7513SDarren.Reed@Sun.COM ASSERT(LIST_EMPTY(&neti_instance_list)); 81*7513SDarren.Reed@Sun.COM ASSERT(LIST_EMPTY(&neti_stack_list)); 82*7513SDarren.Reed@Sun.COM 83*7513SDarren.Reed@Sun.COM netstack_unregister(NS_NETI); 84*7513SDarren.Reed@Sun.COM 85*7513SDarren.Reed@Sun.COM mutex_destroy(&neti_stack_lock); 86*7513SDarren.Reed@Sun.COM } 87*7513SDarren.Reed@Sun.COM 88*7513SDarren.Reed@Sun.COM /* 89*7513SDarren.Reed@Sun.COM * Initialize the neti stack instance. Because this is called out of the 90*7513SDarren.Reed@Sun.COM * netstack framework, it is not possible for it to be called twice with 91*7513SDarren.Reed@Sun.COM * the same values for (stackid,ns). The same also applies to the other 92*7513SDarren.Reed@Sun.COM * two functions used with netstack_register: neti_stack_shutdown and 93*7513SDarren.Reed@Sun.COM * neti_stack_fini. 94*7513SDarren.Reed@Sun.COM */ 95*7513SDarren.Reed@Sun.COM static void * 96*7513SDarren.Reed@Sun.COM neti_stack_init(netstackid_t stackid, netstack_t *ns) 97*7513SDarren.Reed@Sun.COM { 98*7513SDarren.Reed@Sun.COM net_instance_int_t *dup; 99*7513SDarren.Reed@Sun.COM net_instance_int_t *n; 100*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 101*7513SDarren.Reed@Sun.COM 102*7513SDarren.Reed@Sun.COM nts = kmem_zalloc(sizeof (*nts), KM_SLEEP); 103*7513SDarren.Reed@Sun.COM LIST_INIT(&nts->nts_instances); 104*7513SDarren.Reed@Sun.COM nts->nts_id = (netid_t)stackid; 105*7513SDarren.Reed@Sun.COM nts->nts_stackid = stackid; 106*7513SDarren.Reed@Sun.COM nts->nts_netstack = ns; 107*7513SDarren.Reed@Sun.COM nts->nts_zoneid = netstackid_to_zoneid(stackid); 108*7513SDarren.Reed@Sun.COM nts->nts_flags = NSF_ZONE_CREATE; 109*7513SDarren.Reed@Sun.COM cv_init(&nts->nts_cv, NULL, CV_DRIVER, NULL); 110*7513SDarren.Reed@Sun.COM mutex_init(&nts->nts_lock, NULL, MUTEX_DRIVER, NULL); 111*7513SDarren.Reed@Sun.COM 112*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 113*7513SDarren.Reed@Sun.COM LIST_INSERT_HEAD(&neti_stack_list, nts, nts_next); 114*7513SDarren.Reed@Sun.COM 115*7513SDarren.Reed@Sun.COM LIST_FOREACH(n, &neti_instance_list, nini_next) { 116*7513SDarren.Reed@Sun.COM /* 117*7513SDarren.Reed@Sun.COM * This function returns with the NSS_CREATE_NEEDED flag 118*7513SDarren.Reed@Sun.COM * set in "dup", so it is adequately prepared for the 119*7513SDarren.Reed@Sun.COM * upcoming apply. 120*7513SDarren.Reed@Sun.COM */ 121*7513SDarren.Reed@Sun.COM dup = net_instance_int_create(n->nini_instance, n); 122*7513SDarren.Reed@Sun.COM 123*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 124*7513SDarren.Reed@Sun.COM LIST_INSERT_HEAD(&nts->nts_instances, dup, nini_next); 125*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 126*7513SDarren.Reed@Sun.COM } 127*7513SDarren.Reed@Sun.COM 128*7513SDarren.Reed@Sun.COM neti_apply_all_instances(nts, neti_stack_apply_create); 129*7513SDarren.Reed@Sun.COM 130*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 131*7513SDarren.Reed@Sun.COM nts->nts_flags &= ~NSF_ZONE_CREATE; 132*7513SDarren.Reed@Sun.COM cv_signal(&nts->nts_cv); 133*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 134*7513SDarren.Reed@Sun.COM 135*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 136*7513SDarren.Reed@Sun.COM 137*7513SDarren.Reed@Sun.COM return (nts); 138*7513SDarren.Reed@Sun.COM } 139*7513SDarren.Reed@Sun.COM 140*7513SDarren.Reed@Sun.COM /* 141*7513SDarren.Reed@Sun.COM * Run the shutdown for all of the hooks. 142*7513SDarren.Reed@Sun.COM */ 143*7513SDarren.Reed@Sun.COM /*ARGSUSED*/ 144*7513SDarren.Reed@Sun.COM static void 145*7513SDarren.Reed@Sun.COM neti_stack_shutdown(netstackid_t stackid, void *arg) 146*7513SDarren.Reed@Sun.COM { 147*7513SDarren.Reed@Sun.COM neti_stack_t *nts = arg; 148*7513SDarren.Reed@Sun.COM net_instance_int_t *n; 149*7513SDarren.Reed@Sun.COM struct net_data *nd; 150*7513SDarren.Reed@Sun.COM 151*7513SDarren.Reed@Sun.COM ASSERT(nts != NULL); 152*7513SDarren.Reed@Sun.COM 153*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 154*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 155*7513SDarren.Reed@Sun.COM /* 156*7513SDarren.Reed@Sun.COM * Walk through all of the protocol stacks and mark them as shutting 157*7513SDarren.Reed@Sun.COM * down. 158*7513SDarren.Reed@Sun.COM */ 159*7513SDarren.Reed@Sun.COM LIST_FOREACH(nd, &nts->nts_netd_head, netd_list) { 160*7513SDarren.Reed@Sun.COM nd->netd_condemned = 1; 161*7513SDarren.Reed@Sun.COM } 162*7513SDarren.Reed@Sun.COM 163*7513SDarren.Reed@Sun.COM /* 164*7513SDarren.Reed@Sun.COM * Now proceed to see which callbacks are waiting to hear about the 165*7513SDarren.Reed@Sun.COM * impending shutdown... 166*7513SDarren.Reed@Sun.COM */ 167*7513SDarren.Reed@Sun.COM LIST_FOREACH(n, &nts->nts_instances, nini_next) { 168*7513SDarren.Reed@Sun.COM if (n->nini_instance->nin_shutdown == NULL) { 169*7513SDarren.Reed@Sun.COM /* 170*7513SDarren.Reed@Sun.COM * If there is no shutdown function registered, 171*7513SDarren.Reed@Sun.COM * fake that we have completed it. 172*7513SDarren.Reed@Sun.COM */ 173*7513SDarren.Reed@Sun.COM n->nini_flags |= NSS_SHUTDOWN_COMPLETED; 174*7513SDarren.Reed@Sun.COM continue; 175*7513SDarren.Reed@Sun.COM } 176*7513SDarren.Reed@Sun.COM 177*7513SDarren.Reed@Sun.COM /* 178*7513SDarren.Reed@Sun.COM * We need to ensure that we don't try and shutdown something 179*7513SDarren.Reed@Sun.COM * that is already in the process of being shutdown or 180*7513SDarren.Reed@Sun.COM * destroyed. If it is still being created, that's ok, the 181*7513SDarren.Reed@Sun.COM * shtudown flag is added to the mix of things to do. 182*7513SDarren.Reed@Sun.COM */ 183*7513SDarren.Reed@Sun.COM if ((n->nini_flags & (NSS_DESTROY_ALL|NSS_SHUTDOWN_ALL)) == 0) 184*7513SDarren.Reed@Sun.COM n->nini_flags |= NSS_SHUTDOWN_NEEDED; 185*7513SDarren.Reed@Sun.COM } 186*7513SDarren.Reed@Sun.COM nts->nts_flags |= NSF_ZONE_SHUTDOWN; 187*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 188*7513SDarren.Reed@Sun.COM 189*7513SDarren.Reed@Sun.COM neti_apply_all_instances(nts, neti_stack_apply_shutdown); 190*7513SDarren.Reed@Sun.COM 191*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 192*7513SDarren.Reed@Sun.COM 193*7513SDarren.Reed@Sun.COM nts->nts_netstack = NULL; 194*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 195*7513SDarren.Reed@Sun.COM 196*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 197*7513SDarren.Reed@Sun.COM ASSERT(nts != NULL); 198*7513SDarren.Reed@Sun.COM } 199*7513SDarren.Reed@Sun.COM 200*7513SDarren.Reed@Sun.COM /* 201*7513SDarren.Reed@Sun.COM * Free the neti stack instance. 202*7513SDarren.Reed@Sun.COM * This function relies on the netstack framework only calling the _destroy 203*7513SDarren.Reed@Sun.COM * callback once for each stackid. The netstack framework also provides us 204*7513SDarren.Reed@Sun.COM * with assurance that nobody else will be doing any work (_create, _shutdown) 205*7513SDarren.Reed@Sun.COM * on it, so there is no need to set and use flags to guard against 206*7513SDarren.Reed@Sun.COM * simultaneous execution (ie. no need to set NSF_CLOSING.) 207*7513SDarren.Reed@Sun.COM * What is required, however, is to make sure that we don't corrupt the 208*7513SDarren.Reed@Sun.COM * list of neti_stack_t's for other code that walks it. 209*7513SDarren.Reed@Sun.COM */ 210*7513SDarren.Reed@Sun.COM /*ARGSUSED*/ 211*7513SDarren.Reed@Sun.COM static void 212*7513SDarren.Reed@Sun.COM neti_stack_fini(netstackid_t stackid, void *arg) 213*7513SDarren.Reed@Sun.COM { 214*7513SDarren.Reed@Sun.COM neti_stack_t *nts = arg; 215*7513SDarren.Reed@Sun.COM net_instance_int_t *n; 216*7513SDarren.Reed@Sun.COM struct net_data *nd; 217*7513SDarren.Reed@Sun.COM 218*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 219*7513SDarren.Reed@Sun.COM LIST_REMOVE(nts, nts_next); 220*7513SDarren.Reed@Sun.COM 221*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 222*7513SDarren.Reed@Sun.COM nts->nts_flags |= NSF_ZONE_DESTROY; 223*7513SDarren.Reed@Sun.COM /* 224*7513SDarren.Reed@Sun.COM * Walk through all of the protocol stacks and mark them as being 225*7513SDarren.Reed@Sun.COM * destroyed. 226*7513SDarren.Reed@Sun.COM */ 227*7513SDarren.Reed@Sun.COM LIST_FOREACH(nd, &nts->nts_netd_head, netd_list) { 228*7513SDarren.Reed@Sun.COM nd->netd_condemned = 2; 229*7513SDarren.Reed@Sun.COM } 230*7513SDarren.Reed@Sun.COM 231*7513SDarren.Reed@Sun.COM LIST_FOREACH(n, &nts->nts_instances, nini_next) { 232*7513SDarren.Reed@Sun.COM ASSERT((n->nini_flags & NSS_SHUTDOWN_ALL) != 0); 233*7513SDarren.Reed@Sun.COM if (n->nini_instance->nin_shutdown == NULL) 234*7513SDarren.Reed@Sun.COM continue; 235*7513SDarren.Reed@Sun.COM if ((n->nini_flags & NSS_DESTROY_ALL) == 0) 236*7513SDarren.Reed@Sun.COM n->nini_flags |= NSS_DESTROY_NEEDED; 237*7513SDarren.Reed@Sun.COM } 238*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 239*7513SDarren.Reed@Sun.COM 240*7513SDarren.Reed@Sun.COM neti_apply_all_instances(nts, neti_stack_apply_destroy); 241*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 242*7513SDarren.Reed@Sun.COM 243*7513SDarren.Reed@Sun.COM while (!LIST_EMPTY(&nts->nts_instances)) { 244*7513SDarren.Reed@Sun.COM n = LIST_FIRST(&nts->nts_instances); 245*7513SDarren.Reed@Sun.COM LIST_REMOVE(n, nini_next); 246*7513SDarren.Reed@Sun.COM 247*7513SDarren.Reed@Sun.COM net_instance_int_free(n); 248*7513SDarren.Reed@Sun.COM } 249*7513SDarren.Reed@Sun.COM 250*7513SDarren.Reed@Sun.COM ASSERT(LIST_EMPTY(&nts->nts_netd_head)); 251*7513SDarren.Reed@Sun.COM 252*7513SDarren.Reed@Sun.COM mutex_destroy(&nts->nts_lock); 253*7513SDarren.Reed@Sun.COM cv_destroy(&nts->nts_cv); 254*7513SDarren.Reed@Sun.COM 255*7513SDarren.Reed@Sun.COM kmem_free(nts, sizeof (*nts)); 256*7513SDarren.Reed@Sun.COM } 257*7513SDarren.Reed@Sun.COM 258*7513SDarren.Reed@Sun.COM static net_instance_int_t * 259*7513SDarren.Reed@Sun.COM net_instance_int_create(net_instance_t *nin, net_instance_int_t *parent) 260*7513SDarren.Reed@Sun.COM { 261*7513SDarren.Reed@Sun.COM net_instance_int_t *nini; 262*7513SDarren.Reed@Sun.COM 263*7513SDarren.Reed@Sun.COM nini = kmem_zalloc(sizeof (net_instance_int_t), KM_SLEEP); 264*7513SDarren.Reed@Sun.COM nini->nini_instance = nin; 265*7513SDarren.Reed@Sun.COM nini->nini_parent = parent; 266*7513SDarren.Reed@Sun.COM if (parent != NULL) { 267*7513SDarren.Reed@Sun.COM /* 268*7513SDarren.Reed@Sun.COM * If the parent pointer is non-NULL then we take that as 269*7513SDarren.Reed@Sun.COM * an indication that the net_instance_int_t is being 270*7513SDarren.Reed@Sun.COM * created for an active instance and there will expect 271*7513SDarren.Reed@Sun.COM * the create function to be called. In contrast, if 272*7513SDarren.Reed@Sun.COM * parent is NULL then this code assumes the object is 273*7513SDarren.Reed@Sun.COM * being prepared for insertion onto the master list of 274*7513SDarren.Reed@Sun.COM * callbacks to be called when an instance is created, etc. 275*7513SDarren.Reed@Sun.COM */ 276*7513SDarren.Reed@Sun.COM parent->nini_ref++; 277*7513SDarren.Reed@Sun.COM nini->nini_flags |= NSS_CREATE_NEEDED; 278*7513SDarren.Reed@Sun.COM } 279*7513SDarren.Reed@Sun.COM 280*7513SDarren.Reed@Sun.COM cv_init(&nini->nini_cv, NULL, CV_DRIVER, NULL); 281*7513SDarren.Reed@Sun.COM 282*7513SDarren.Reed@Sun.COM return (nini); 283*7513SDarren.Reed@Sun.COM } 284*7513SDarren.Reed@Sun.COM 285*7513SDarren.Reed@Sun.COM static void 286*7513SDarren.Reed@Sun.COM net_instance_int_free(net_instance_int_t *nini) 287*7513SDarren.Reed@Sun.COM { 288*7513SDarren.Reed@Sun.COM 289*7513SDarren.Reed@Sun.COM cv_destroy(&nini->nini_cv); 290*7513SDarren.Reed@Sun.COM 291*7513SDarren.Reed@Sun.COM if (nini->nini_parent != NULL) 292*7513SDarren.Reed@Sun.COM nini->nini_parent->nini_ref--; 293*7513SDarren.Reed@Sun.COM 294*7513SDarren.Reed@Sun.COM ASSERT(nini->nini_ref == 0); 295*7513SDarren.Reed@Sun.COM kmem_free(nini, sizeof (*nini)); 296*7513SDarren.Reed@Sun.COM } 297*7513SDarren.Reed@Sun.COM 298*7513SDarren.Reed@Sun.COM net_instance_t * 299*7513SDarren.Reed@Sun.COM net_instance_alloc(const int version) 300*7513SDarren.Reed@Sun.COM { 301*7513SDarren.Reed@Sun.COM net_instance_t *nin; 302*7513SDarren.Reed@Sun.COM 303*7513SDarren.Reed@Sun.COM if (version != NETINFO_VERSION) 304*7513SDarren.Reed@Sun.COM return (NULL); 305*7513SDarren.Reed@Sun.COM 306*7513SDarren.Reed@Sun.COM nin = kmem_zalloc(sizeof (net_instance_t), KM_SLEEP); 307*7513SDarren.Reed@Sun.COM nin->nin_version = version; 308*7513SDarren.Reed@Sun.COM 309*7513SDarren.Reed@Sun.COM return (nin); 310*7513SDarren.Reed@Sun.COM } 311*7513SDarren.Reed@Sun.COM 312*7513SDarren.Reed@Sun.COM void 313*7513SDarren.Reed@Sun.COM net_instance_free(net_instance_t *nin) 314*7513SDarren.Reed@Sun.COM { 315*7513SDarren.Reed@Sun.COM kmem_free(nin, sizeof (*nin)); 316*7513SDarren.Reed@Sun.COM } 317*7513SDarren.Reed@Sun.COM 318*7513SDarren.Reed@Sun.COM int 319*7513SDarren.Reed@Sun.COM net_instance_register(net_instance_t *nin) 320*7513SDarren.Reed@Sun.COM { 321*7513SDarren.Reed@Sun.COM net_instance_int_t *parent; 322*7513SDarren.Reed@Sun.COM net_instance_int_t *tmp; 323*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 324*7513SDarren.Reed@Sun.COM 325*7513SDarren.Reed@Sun.COM ASSERT(nin->nin_name != NULL); 326*7513SDarren.Reed@Sun.COM 327*7513SDarren.Reed@Sun.COM if (nin->nin_create == NULL || nin->nin_destroy == NULL) 328*7513SDarren.Reed@Sun.COM return (DDI_FAILURE); 329*7513SDarren.Reed@Sun.COM 330*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 331*7513SDarren.Reed@Sun.COM /* 332*7513SDarren.Reed@Sun.COM * Search for duplicate, either on the global list or on any 333*7513SDarren.Reed@Sun.COM * of the known instances. 334*7513SDarren.Reed@Sun.COM */ 335*7513SDarren.Reed@Sun.COM LIST_FOREACH(tmp, &neti_instance_list, nini_next) { 336*7513SDarren.Reed@Sun.COM if (strcmp(nin->nin_name, tmp->nini_instance->nin_name) == 0) { 337*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 338*7513SDarren.Reed@Sun.COM return (DDI_FAILURE); 339*7513SDarren.Reed@Sun.COM } 340*7513SDarren.Reed@Sun.COM } 341*7513SDarren.Reed@Sun.COM 342*7513SDarren.Reed@Sun.COM /* 343*7513SDarren.Reed@Sun.COM * Now insert and activate. 344*7513SDarren.Reed@Sun.COM */ 345*7513SDarren.Reed@Sun.COM parent = net_instance_int_create(nin, NULL); 346*7513SDarren.Reed@Sun.COM ASSERT(parent != NULL); 347*7513SDarren.Reed@Sun.COM LIST_INSERT_HEAD(&neti_instance_list, parent, nini_next); 348*7513SDarren.Reed@Sun.COM 349*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 350*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 351*7513SDarren.Reed@Sun.COM /* 352*7513SDarren.Reed@Sun.COM * If shutdown of the zone has begun then do not add a new 353*7513SDarren.Reed@Sun.COM * instance of the object being registered. 354*7513SDarren.Reed@Sun.COM */ 355*7513SDarren.Reed@Sun.COM if ((nts->nts_flags & NSF_ZONE_SHUTDOWN) || 356*7513SDarren.Reed@Sun.COM (nts->nts_netstack == NULL)) { 357*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 358*7513SDarren.Reed@Sun.COM continue; 359*7513SDarren.Reed@Sun.COM } 360*7513SDarren.Reed@Sun.COM /* 361*7513SDarren.Reed@Sun.COM * This function returns with the NSS_CREATE_NEEDED flag 362*7513SDarren.Reed@Sun.COM * set in "dup", so it is adequately prepared for the 363*7513SDarren.Reed@Sun.COM * upcoming apply. 364*7513SDarren.Reed@Sun.COM */ 365*7513SDarren.Reed@Sun.COM tmp = net_instance_int_create(nin, parent); 366*7513SDarren.Reed@Sun.COM ASSERT(tmp != NULL); 367*7513SDarren.Reed@Sun.COM LIST_INSERT_HEAD(&nts->nts_instances, tmp, nini_next); 368*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 369*7513SDarren.Reed@Sun.COM 370*7513SDarren.Reed@Sun.COM } 371*7513SDarren.Reed@Sun.COM 372*7513SDarren.Reed@Sun.COM neti_apply_all_stacks(parent, neti_stack_apply_create); 373*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 374*7513SDarren.Reed@Sun.COM 375*7513SDarren.Reed@Sun.COM return (DDI_SUCCESS); 376*7513SDarren.Reed@Sun.COM } 377*7513SDarren.Reed@Sun.COM 378*7513SDarren.Reed@Sun.COM /* 379*7513SDarren.Reed@Sun.COM * While net_instance_register() isn't likely to be racing against itself, 380*7513SDarren.Reed@Sun.COM * net_instance_unregister() can be entered from various directions that 381*7513SDarren.Reed@Sun.COM * can compete: shutdown of a zone, unloading of a module (and it calling 382*7513SDarren.Reed@Sun.COM * _unregister() as part of that) and the module doing an _unregister() 383*7513SDarren.Reed@Sun.COM * anyway. 384*7513SDarren.Reed@Sun.COM */ 385*7513SDarren.Reed@Sun.COM int 386*7513SDarren.Reed@Sun.COM net_instance_unregister(net_instance_t *nin) 387*7513SDarren.Reed@Sun.COM { 388*7513SDarren.Reed@Sun.COM net_instance_int_t *parent; 389*7513SDarren.Reed@Sun.COM net_instance_int_t *tmp; 390*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 391*7513SDarren.Reed@Sun.COM 392*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 393*7513SDarren.Reed@Sun.COM 394*7513SDarren.Reed@Sun.COM LIST_FOREACH(tmp, &neti_instance_list, nini_next) { 395*7513SDarren.Reed@Sun.COM if (strcmp(tmp->nini_instance->nin_name, nin->nin_name) == 0) { 396*7513SDarren.Reed@Sun.COM LIST_REMOVE(tmp, nini_next); 397*7513SDarren.Reed@Sun.COM break; 398*7513SDarren.Reed@Sun.COM } 399*7513SDarren.Reed@Sun.COM } 400*7513SDarren.Reed@Sun.COM 401*7513SDarren.Reed@Sun.COM if (tmp == NULL) { 402*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 403*7513SDarren.Reed@Sun.COM return (DDI_FAILURE); 404*7513SDarren.Reed@Sun.COM } 405*7513SDarren.Reed@Sun.COM parent = tmp; 406*7513SDarren.Reed@Sun.COM 407*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 408*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 409*7513SDarren.Reed@Sun.COM LIST_FOREACH(tmp, &nts->nts_instances, nini_next) { 410*7513SDarren.Reed@Sun.COM if (tmp->nini_parent != parent) 411*7513SDarren.Reed@Sun.COM continue; 412*7513SDarren.Reed@Sun.COM /* 413*7513SDarren.Reed@Sun.COM * Netstack difference: 414*7513SDarren.Reed@Sun.COM * In netstack.c, there is a check for 415*7513SDarren.Reed@Sun.COM * NSS_CREATE_COMPLETED before setting the other 416*7513SDarren.Reed@Sun.COM * _NEEDED flags. If we consider that a list 417*7513SDarren.Reed@Sun.COM * member must always have at least the _CREATE_NEEDED 418*7513SDarren.Reed@Sun.COM * flag set and that wait_for_nini_inprogress will 419*7513SDarren.Reed@Sun.COM * also wait for that flag to be cleared in both of 420*7513SDarren.Reed@Sun.COM * the shutdown and destroy apply functions. 421*7513SDarren.Reed@Sun.COM * 422*7513SDarren.Reed@Sun.COM * It is possible to optimize out the case where 423*7513SDarren.Reed@Sun.COM * all three _NEEDED flags are set to being able 424*7513SDarren.Reed@Sun.COM * to pretend everything has been done and just 425*7513SDarren.Reed@Sun.COM * set all three _COMPLETE flags. This makes a 426*7513SDarren.Reed@Sun.COM * special case that we then need to consider in 427*7513SDarren.Reed@Sun.COM * other locations, so for the sake of simplicity, 428*7513SDarren.Reed@Sun.COM * we leave it as it is. 429*7513SDarren.Reed@Sun.COM */ 430*7513SDarren.Reed@Sun.COM if ((tmp->nini_flags & NSS_SHUTDOWN_ALL) == 0) 431*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_SHUTDOWN_NEEDED; 432*7513SDarren.Reed@Sun.COM if ((tmp->nini_flags & NSS_DESTROY_ALL) == 0) 433*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_DESTROY_NEEDED; 434*7513SDarren.Reed@Sun.COM } 435*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 436*7513SDarren.Reed@Sun.COM } 437*7513SDarren.Reed@Sun.COM 438*7513SDarren.Reed@Sun.COM /* 439*7513SDarren.Reed@Sun.COM * Each of these functions ensures that the requisite _COMPLETED 440*7513SDarren.Reed@Sun.COM * flag is present before calling the apply function. So we are 441*7513SDarren.Reed@Sun.COM * guaranteed to have NSS_CREATE_COMPLETED|NSS_SHUTDOWN_COMPLETED 442*7513SDarren.Reed@Sun.COM * both set after the first call here and when the second completes, 443*7513SDarren.Reed@Sun.COM * NSS_DESTROY_COMPLETED is also set. 444*7513SDarren.Reed@Sun.COM */ 445*7513SDarren.Reed@Sun.COM neti_apply_all_stacks(parent, neti_stack_apply_shutdown); 446*7513SDarren.Reed@Sun.COM neti_apply_all_stacks(parent, neti_stack_apply_destroy); 447*7513SDarren.Reed@Sun.COM 448*7513SDarren.Reed@Sun.COM /* 449*7513SDarren.Reed@Sun.COM * Remove the instance callback information from each stack. 450*7513SDarren.Reed@Sun.COM */ 451*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 452*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 453*7513SDarren.Reed@Sun.COM LIST_FOREACH(tmp, &nts->nts_instances, nini_next) { 454*7513SDarren.Reed@Sun.COM if ((tmp->nini_parent == parent) && 455*7513SDarren.Reed@Sun.COM (tmp->nini_flags & NSS_SHUTDOWN_COMPLETED) && 456*7513SDarren.Reed@Sun.COM (tmp->nini_flags & NSS_DESTROY_COMPLETED)) { 457*7513SDarren.Reed@Sun.COM /* 458*7513SDarren.Reed@Sun.COM * There should only be one entry that has a 459*7513SDarren.Reed@Sun.COM * matching nini_parent so there is no need to 460*7513SDarren.Reed@Sun.COM * worry about continuing a loop where we are 461*7513SDarren.Reed@Sun.COM * free'ing the structure holding the 'next' 462*7513SDarren.Reed@Sun.COM * pointer. 463*7513SDarren.Reed@Sun.COM */ 464*7513SDarren.Reed@Sun.COM LIST_REMOVE(tmp, nini_next); 465*7513SDarren.Reed@Sun.COM net_instance_int_free(tmp); 466*7513SDarren.Reed@Sun.COM break; 467*7513SDarren.Reed@Sun.COM } 468*7513SDarren.Reed@Sun.COM } 469*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 470*7513SDarren.Reed@Sun.COM } 471*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 472*7513SDarren.Reed@Sun.COM 473*7513SDarren.Reed@Sun.COM net_instance_int_free(parent); 474*7513SDarren.Reed@Sun.COM 475*7513SDarren.Reed@Sun.COM return (DDI_SUCCESS); 476*7513SDarren.Reed@Sun.COM } 477*7513SDarren.Reed@Sun.COM 478*7513SDarren.Reed@Sun.COM static void 479*7513SDarren.Reed@Sun.COM neti_apply_all_instances(neti_stack_t *nts, napplyfn_t *applyfn) 480*7513SDarren.Reed@Sun.COM { 481*7513SDarren.Reed@Sun.COM net_instance_int_t *n; 482*7513SDarren.Reed@Sun.COM 483*7513SDarren.Reed@Sun.COM ASSERT(mutex_owned(&neti_stack_lock)); 484*7513SDarren.Reed@Sun.COM 485*7513SDarren.Reed@Sun.COM n = LIST_FIRST(&nts->nts_instances); 486*7513SDarren.Reed@Sun.COM while (n != NULL) { 487*7513SDarren.Reed@Sun.COM if ((applyfn)(&neti_stack_lock, nts, n->nini_parent)) { 488*7513SDarren.Reed@Sun.COM /* Lock dropped - restart at head */ 489*7513SDarren.Reed@Sun.COM n = LIST_FIRST(&nts->nts_instances); 490*7513SDarren.Reed@Sun.COM } else { 491*7513SDarren.Reed@Sun.COM n = LIST_NEXT(n, nini_next); 492*7513SDarren.Reed@Sun.COM } 493*7513SDarren.Reed@Sun.COM } 494*7513SDarren.Reed@Sun.COM } 495*7513SDarren.Reed@Sun.COM 496*7513SDarren.Reed@Sun.COM static void 497*7513SDarren.Reed@Sun.COM neti_apply_all_stacks(void *parent, napplyfn_t *applyfn) 498*7513SDarren.Reed@Sun.COM { 499*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 500*7513SDarren.Reed@Sun.COM 501*7513SDarren.Reed@Sun.COM ASSERT(mutex_owned(&neti_stack_lock)); 502*7513SDarren.Reed@Sun.COM 503*7513SDarren.Reed@Sun.COM nts = LIST_FIRST(&neti_stack_list); 504*7513SDarren.Reed@Sun.COM while (nts != NULL) { 505*7513SDarren.Reed@Sun.COM /* 506*7513SDarren.Reed@Sun.COM * This function differs, in that it doesn't have a call to 507*7513SDarren.Reed@Sun.COM * a "wait_creator" call, from the zsd/netstack code. The 508*7513SDarren.Reed@Sun.COM * waiting is pushed into the apply functions which cause 509*7513SDarren.Reed@Sun.COM * the waiting to be done in wait_for_nini_progress with 510*7513SDarren.Reed@Sun.COM * the passing in of cmask. 511*7513SDarren.Reed@Sun.COM */ 512*7513SDarren.Reed@Sun.COM if ((applyfn)(&neti_stack_lock, nts, parent)) { 513*7513SDarren.Reed@Sun.COM /* Lock dropped - restart at head */ 514*7513SDarren.Reed@Sun.COM nts = LIST_FIRST(&neti_stack_list); 515*7513SDarren.Reed@Sun.COM } else { 516*7513SDarren.Reed@Sun.COM nts = LIST_NEXT(nts, nts_next); 517*7513SDarren.Reed@Sun.COM } 518*7513SDarren.Reed@Sun.COM } 519*7513SDarren.Reed@Sun.COM } 520*7513SDarren.Reed@Sun.COM 521*7513SDarren.Reed@Sun.COM static boolean_t 522*7513SDarren.Reed@Sun.COM neti_stack_apply_create(kmutex_t *lockp, neti_stack_t *nts, void *parent) 523*7513SDarren.Reed@Sun.COM { 524*7513SDarren.Reed@Sun.COM void *result; 525*7513SDarren.Reed@Sun.COM boolean_t dropped = B_FALSE; 526*7513SDarren.Reed@Sun.COM net_instance_int_t *tmp; 527*7513SDarren.Reed@Sun.COM net_instance_t *nin; 528*7513SDarren.Reed@Sun.COM 529*7513SDarren.Reed@Sun.COM ASSERT(parent != NULL); 530*7513SDarren.Reed@Sun.COM ASSERT(lockp != NULL); 531*7513SDarren.Reed@Sun.COM ASSERT(mutex_owned(lockp)); 532*7513SDarren.Reed@Sun.COM 533*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 534*7513SDarren.Reed@Sun.COM 535*7513SDarren.Reed@Sun.COM LIST_FOREACH(tmp, &nts->nts_instances, nini_next) { 536*7513SDarren.Reed@Sun.COM if (tmp->nini_parent == parent) 537*7513SDarren.Reed@Sun.COM break; 538*7513SDarren.Reed@Sun.COM } 539*7513SDarren.Reed@Sun.COM if (tmp == NULL) { 540*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 541*7513SDarren.Reed@Sun.COM return (dropped); 542*7513SDarren.Reed@Sun.COM } 543*7513SDarren.Reed@Sun.COM 544*7513SDarren.Reed@Sun.COM if (wait_for_nini_inprogress(nts, lockp, tmp, 0)) 545*7513SDarren.Reed@Sun.COM dropped = B_TRUE; 546*7513SDarren.Reed@Sun.COM 547*7513SDarren.Reed@Sun.COM if (tmp->nini_flags & NSS_CREATE_NEEDED) { 548*7513SDarren.Reed@Sun.COM nin = tmp->nini_instance; 549*7513SDarren.Reed@Sun.COM tmp->nini_flags &= ~NSS_CREATE_NEEDED; 550*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_CREATE_INPROGRESS; 551*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__create__inprogress, 552*7513SDarren.Reed@Sun.COM neti_stack_t *, nts, net_instance_int_t *, tmp); 553*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 554*7513SDarren.Reed@Sun.COM mutex_exit(lockp); 555*7513SDarren.Reed@Sun.COM dropped = B_TRUE; 556*7513SDarren.Reed@Sun.COM 557*7513SDarren.Reed@Sun.COM ASSERT(tmp->nini_created == NULL); 558*7513SDarren.Reed@Sun.COM ASSERT(nin->nin_create != NULL); 559*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__create__start, 560*7513SDarren.Reed@Sun.COM netstackid_t, nts->nts_id, 561*7513SDarren.Reed@Sun.COM neti_stack_t *, nts); 562*7513SDarren.Reed@Sun.COM result = (nin->nin_create)(nts->nts_id); 563*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__create__end, 564*7513SDarren.Reed@Sun.COM void *, result, neti_stack_t *, nts); 565*7513SDarren.Reed@Sun.COM 566*7513SDarren.Reed@Sun.COM ASSERT(result != NULL); 567*7513SDarren.Reed@Sun.COM mutex_enter(lockp); 568*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 569*7513SDarren.Reed@Sun.COM tmp->nini_created = result; 570*7513SDarren.Reed@Sun.COM tmp->nini_flags &= ~NSS_CREATE_INPROGRESS; 571*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_CREATE_COMPLETED; 572*7513SDarren.Reed@Sun.COM cv_broadcast(&tmp->nini_cv); 573*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__create__completed, 574*7513SDarren.Reed@Sun.COM neti_stack_t *, nts, net_instance_int_t *, tmp); 575*7513SDarren.Reed@Sun.COM } 576*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 577*7513SDarren.Reed@Sun.COM return (dropped); 578*7513SDarren.Reed@Sun.COM } 579*7513SDarren.Reed@Sun.COM 580*7513SDarren.Reed@Sun.COM 581*7513SDarren.Reed@Sun.COM static boolean_t 582*7513SDarren.Reed@Sun.COM neti_stack_apply_shutdown(kmutex_t *lockp, neti_stack_t *nts, void *parent) 583*7513SDarren.Reed@Sun.COM { 584*7513SDarren.Reed@Sun.COM boolean_t dropped = B_FALSE; 585*7513SDarren.Reed@Sun.COM net_instance_int_t *tmp; 586*7513SDarren.Reed@Sun.COM net_instance_t *nin; 587*7513SDarren.Reed@Sun.COM 588*7513SDarren.Reed@Sun.COM ASSERT(parent != NULL); 589*7513SDarren.Reed@Sun.COM ASSERT(lockp != NULL); 590*7513SDarren.Reed@Sun.COM ASSERT(mutex_owned(lockp)); 591*7513SDarren.Reed@Sun.COM 592*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 593*7513SDarren.Reed@Sun.COM 594*7513SDarren.Reed@Sun.COM LIST_FOREACH(tmp, &nts->nts_instances, nini_next) { 595*7513SDarren.Reed@Sun.COM if (tmp->nini_parent == parent) 596*7513SDarren.Reed@Sun.COM break; 597*7513SDarren.Reed@Sun.COM } 598*7513SDarren.Reed@Sun.COM if (tmp == NULL) { 599*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 600*7513SDarren.Reed@Sun.COM return (dropped); 601*7513SDarren.Reed@Sun.COM } 602*7513SDarren.Reed@Sun.COM 603*7513SDarren.Reed@Sun.COM if (wait_for_nini_inprogress(nts, lockp, tmp, NSS_CREATE_NEEDED)) 604*7513SDarren.Reed@Sun.COM dropped = B_TRUE; 605*7513SDarren.Reed@Sun.COM 606*7513SDarren.Reed@Sun.COM nin = tmp->nini_instance; 607*7513SDarren.Reed@Sun.COM if (nin->nin_shutdown == NULL) { 608*7513SDarren.Reed@Sun.COM /* 609*7513SDarren.Reed@Sun.COM * If there is no shutdown function, fake having completed it. 610*7513SDarren.Reed@Sun.COM */ 611*7513SDarren.Reed@Sun.COM if (tmp->nini_flags & NSS_SHUTDOWN_NEEDED) { 612*7513SDarren.Reed@Sun.COM tmp->nini_flags &= ~NSS_SHUTDOWN_NEEDED; 613*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_SHUTDOWN_COMPLETED; 614*7513SDarren.Reed@Sun.COM } 615*7513SDarren.Reed@Sun.COM 616*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 617*7513SDarren.Reed@Sun.COM return (dropped); 618*7513SDarren.Reed@Sun.COM } 619*7513SDarren.Reed@Sun.COM 620*7513SDarren.Reed@Sun.COM if (tmp->nini_flags & NSS_SHUTDOWN_NEEDED) { 621*7513SDarren.Reed@Sun.COM ASSERT((tmp->nini_flags & NSS_CREATE_COMPLETED) != 0); 622*7513SDarren.Reed@Sun.COM tmp->nini_flags &= ~NSS_SHUTDOWN_NEEDED; 623*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_SHUTDOWN_INPROGRESS; 624*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__shutdown__inprogress, 625*7513SDarren.Reed@Sun.COM neti_stack_t *, nts, net_instance_int_t *, tmp); 626*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 627*7513SDarren.Reed@Sun.COM mutex_exit(lockp); 628*7513SDarren.Reed@Sun.COM dropped = B_TRUE; 629*7513SDarren.Reed@Sun.COM 630*7513SDarren.Reed@Sun.COM ASSERT(nin->nin_shutdown != NULL); 631*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__shutdown__start, 632*7513SDarren.Reed@Sun.COM netstackid_t, nts->nts_id, 633*7513SDarren.Reed@Sun.COM neti_stack_t *, nts); 634*7513SDarren.Reed@Sun.COM (nin->nin_shutdown)(nts->nts_id, tmp->nini_created); 635*7513SDarren.Reed@Sun.COM DTRACE_PROBE1(neti__stack__shutdown__end, 636*7513SDarren.Reed@Sun.COM neti_stack_t *, nts); 637*7513SDarren.Reed@Sun.COM 638*7513SDarren.Reed@Sun.COM mutex_enter(lockp); 639*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 640*7513SDarren.Reed@Sun.COM tmp->nini_flags &= ~NSS_SHUTDOWN_INPROGRESS; 641*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_SHUTDOWN_COMPLETED; 642*7513SDarren.Reed@Sun.COM cv_broadcast(&tmp->nini_cv); 643*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__shutdown__completed, 644*7513SDarren.Reed@Sun.COM neti_stack_t *, nts, net_instance_int_t *, tmp); 645*7513SDarren.Reed@Sun.COM } 646*7513SDarren.Reed@Sun.COM ASSERT((tmp->nini_flags & NSS_SHUTDOWN_COMPLETED) != 0); 647*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 648*7513SDarren.Reed@Sun.COM return (dropped); 649*7513SDarren.Reed@Sun.COM } 650*7513SDarren.Reed@Sun.COM 651*7513SDarren.Reed@Sun.COM static boolean_t 652*7513SDarren.Reed@Sun.COM neti_stack_apply_destroy(kmutex_t *lockp, neti_stack_t *nts, void *parent) 653*7513SDarren.Reed@Sun.COM { 654*7513SDarren.Reed@Sun.COM boolean_t dropped = B_FALSE; 655*7513SDarren.Reed@Sun.COM net_instance_int_t *tmp; 656*7513SDarren.Reed@Sun.COM net_instance_t *nin; 657*7513SDarren.Reed@Sun.COM 658*7513SDarren.Reed@Sun.COM ASSERT(parent != NULL); 659*7513SDarren.Reed@Sun.COM ASSERT(lockp != NULL); 660*7513SDarren.Reed@Sun.COM ASSERT(mutex_owned(lockp)); 661*7513SDarren.Reed@Sun.COM 662*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 663*7513SDarren.Reed@Sun.COM 664*7513SDarren.Reed@Sun.COM LIST_FOREACH(tmp, &nts->nts_instances, nini_next) { 665*7513SDarren.Reed@Sun.COM if (tmp->nini_parent == parent) 666*7513SDarren.Reed@Sun.COM break; 667*7513SDarren.Reed@Sun.COM } 668*7513SDarren.Reed@Sun.COM if (tmp == NULL) { 669*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 670*7513SDarren.Reed@Sun.COM return (dropped); 671*7513SDarren.Reed@Sun.COM } 672*7513SDarren.Reed@Sun.COM 673*7513SDarren.Reed@Sun.COM /* 674*7513SDarren.Reed@Sun.COM * We pause here so that when we continue we know that we're the 675*7513SDarren.Reed@Sun.COM * only one doing anything active with this node. 676*7513SDarren.Reed@Sun.COM */ 677*7513SDarren.Reed@Sun.COM if (wait_for_nini_inprogress(nts, lockp, tmp, 678*7513SDarren.Reed@Sun.COM NSS_CREATE_NEEDED|NSS_SHUTDOWN_NEEDED)) 679*7513SDarren.Reed@Sun.COM dropped = B_TRUE; 680*7513SDarren.Reed@Sun.COM 681*7513SDarren.Reed@Sun.COM if (tmp->nini_flags & NSS_DESTROY_NEEDED) { 682*7513SDarren.Reed@Sun.COM ASSERT((tmp->nini_flags & NSS_SHUTDOWN_COMPLETED) != 0); 683*7513SDarren.Reed@Sun.COM nin = tmp->nini_instance; 684*7513SDarren.Reed@Sun.COM tmp->nini_flags &= ~NSS_DESTROY_NEEDED; 685*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_DESTROY_INPROGRESS; 686*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__destroy__inprogress, 687*7513SDarren.Reed@Sun.COM neti_stack_t *, nts, net_instance_int_t *, tmp); 688*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 689*7513SDarren.Reed@Sun.COM mutex_exit(lockp); 690*7513SDarren.Reed@Sun.COM dropped = B_TRUE; 691*7513SDarren.Reed@Sun.COM 692*7513SDarren.Reed@Sun.COM ASSERT(nin->nin_destroy != NULL); 693*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__destroy__start, 694*7513SDarren.Reed@Sun.COM netstackid_t, nts->nts_id, 695*7513SDarren.Reed@Sun.COM neti_stack_t *, nts); 696*7513SDarren.Reed@Sun.COM (nin->nin_destroy)(nts->nts_id, tmp->nini_created); 697*7513SDarren.Reed@Sun.COM DTRACE_PROBE1(neti__stack__destroy__end, 698*7513SDarren.Reed@Sun.COM neti_stack_t *, nts); 699*7513SDarren.Reed@Sun.COM 700*7513SDarren.Reed@Sun.COM mutex_enter(lockp); 701*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 702*7513SDarren.Reed@Sun.COM tmp->nini_flags &= ~NSS_DESTROY_INPROGRESS; 703*7513SDarren.Reed@Sun.COM tmp->nini_flags |= NSS_DESTROY_COMPLETED; 704*7513SDarren.Reed@Sun.COM cv_broadcast(&tmp->nini_cv); 705*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(neti__stack__destroy__completed, 706*7513SDarren.Reed@Sun.COM neti_stack_t *, nts, net_instance_int_t *, tmp); 707*7513SDarren.Reed@Sun.COM } 708*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 709*7513SDarren.Reed@Sun.COM return (dropped); 710*7513SDarren.Reed@Sun.COM } 711*7513SDarren.Reed@Sun.COM 712*7513SDarren.Reed@Sun.COM static boolean_t 713*7513SDarren.Reed@Sun.COM wait_for_nini_inprogress(neti_stack_t *nts, kmutex_t *lockp, 714*7513SDarren.Reed@Sun.COM net_instance_int_t *nini, uint32_t cmask) 715*7513SDarren.Reed@Sun.COM { 716*7513SDarren.Reed@Sun.COM boolean_t dropped = B_FALSE; 717*7513SDarren.Reed@Sun.COM 718*7513SDarren.Reed@Sun.COM ASSERT(lockp != NULL); 719*7513SDarren.Reed@Sun.COM ASSERT(mutex_owned(lockp)); 720*7513SDarren.Reed@Sun.COM 721*7513SDarren.Reed@Sun.COM while (nini->nini_flags & (NSS_ALL_INPROGRESS|cmask)) { 722*7513SDarren.Reed@Sun.COM DTRACE_PROBE2(netstack__wait__nms__inprogress, 723*7513SDarren.Reed@Sun.COM neti_stack_t *, nts, net_instance_int_t *, nini); 724*7513SDarren.Reed@Sun.COM dropped = B_TRUE; 725*7513SDarren.Reed@Sun.COM mutex_exit(lockp); 726*7513SDarren.Reed@Sun.COM 727*7513SDarren.Reed@Sun.COM cv_wait(&nini->nini_cv, &nts->nts_lock); 728*7513SDarren.Reed@Sun.COM 729*7513SDarren.Reed@Sun.COM /* First drop netstack_lock to preserve order */ 730*7513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 731*7513SDarren.Reed@Sun.COM mutex_enter(lockp); 732*7513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 733*7513SDarren.Reed@Sun.COM } 734*7513SDarren.Reed@Sun.COM return (dropped); 735*7513SDarren.Reed@Sun.COM } 736*7513SDarren.Reed@Sun.COM 737*7513SDarren.Reed@Sun.COM /* ======================================================================= */ 738*7513SDarren.Reed@Sun.COM 739*7513SDarren.Reed@Sun.COM netid_t 740*7513SDarren.Reed@Sun.COM net_zoneidtonetid(zoneid_t zoneid) 741*7513SDarren.Reed@Sun.COM { 742*7513SDarren.Reed@Sun.COM 743*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 744*7513SDarren.Reed@Sun.COM 745*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 746*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 747*7513SDarren.Reed@Sun.COM if (nts->nts_zoneid == zoneid) { 748*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 749*7513SDarren.Reed@Sun.COM return (nts->nts_id); 750*7513SDarren.Reed@Sun.COM } 751*7513SDarren.Reed@Sun.COM } 752*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 753*7513SDarren.Reed@Sun.COM 754*7513SDarren.Reed@Sun.COM return (-1); 755*7513SDarren.Reed@Sun.COM } 756*7513SDarren.Reed@Sun.COM 757*7513SDarren.Reed@Sun.COM zoneid_t 758*7513SDarren.Reed@Sun.COM net_getzoneidbynetid(netid_t netid) 759*7513SDarren.Reed@Sun.COM { 760*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 761*7513SDarren.Reed@Sun.COM 762*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 763*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 764*7513SDarren.Reed@Sun.COM if (nts->nts_id == netid) { 765*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 766*7513SDarren.Reed@Sun.COM return (nts->nts_zoneid); 767*7513SDarren.Reed@Sun.COM } 768*7513SDarren.Reed@Sun.COM } 769*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 770*7513SDarren.Reed@Sun.COM 771*7513SDarren.Reed@Sun.COM return (-1); 772*7513SDarren.Reed@Sun.COM } 773*7513SDarren.Reed@Sun.COM 774*7513SDarren.Reed@Sun.COM netstackid_t 775*7513SDarren.Reed@Sun.COM net_getnetstackidbynetid(netid_t netid) 776*7513SDarren.Reed@Sun.COM { 777*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 778*7513SDarren.Reed@Sun.COM 779*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 780*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 781*7513SDarren.Reed@Sun.COM if (nts->nts_id == netid) { 782*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 783*7513SDarren.Reed@Sun.COM return (nts->nts_stackid); 784*7513SDarren.Reed@Sun.COM } 785*7513SDarren.Reed@Sun.COM } 786*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 787*7513SDarren.Reed@Sun.COM 788*7513SDarren.Reed@Sun.COM return (-1); 789*7513SDarren.Reed@Sun.COM } 790*7513SDarren.Reed@Sun.COM 791*7513SDarren.Reed@Sun.COM netid_t 792*7513SDarren.Reed@Sun.COM net_getnetidbynetstackid(netstackid_t netstackid) 793*7513SDarren.Reed@Sun.COM { 794*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 795*7513SDarren.Reed@Sun.COM 796*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 797*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 798*7513SDarren.Reed@Sun.COM if (nts->nts_stackid == netstackid) { 799*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 800*7513SDarren.Reed@Sun.COM return (nts->nts_id); 801*7513SDarren.Reed@Sun.COM } 802*7513SDarren.Reed@Sun.COM } 803*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 804*7513SDarren.Reed@Sun.COM 805*7513SDarren.Reed@Sun.COM return (-1); 806*7513SDarren.Reed@Sun.COM } 807*7513SDarren.Reed@Sun.COM 808*7513SDarren.Reed@Sun.COM neti_stack_t * 809*7513SDarren.Reed@Sun.COM net_getnetistackbyid(netid_t netid) 810*7513SDarren.Reed@Sun.COM { 811*7513SDarren.Reed@Sun.COM neti_stack_t *nts; 812*7513SDarren.Reed@Sun.COM 813*7513SDarren.Reed@Sun.COM mutex_enter(&neti_stack_lock); 814*7513SDarren.Reed@Sun.COM LIST_FOREACH(nts, &neti_stack_list, nts_next) { 815*7513SDarren.Reed@Sun.COM if (nts->nts_id == netid) { 816*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 817*7513SDarren.Reed@Sun.COM return (nts); 818*7513SDarren.Reed@Sun.COM } 819*7513SDarren.Reed@Sun.COM } 820*7513SDarren.Reed@Sun.COM mutex_exit(&neti_stack_lock); 821*7513SDarren.Reed@Sun.COM 822*7513SDarren.Reed@Sun.COM return (NULL); 823*7513SDarren.Reed@Sun.COM } 824*7513SDarren.Reed@Sun.COM 825*7513SDarren.Reed@Sun.COM int 826*7513SDarren.Reed@Sun.COM net_instance_notify_register(netid_t netid, hook_notify_fn_t callback, 827*7513SDarren.Reed@Sun.COM void *arg) 828*7513SDarren.Reed@Sun.COM { 829*7513SDarren.Reed@Sun.COM 830*7513SDarren.Reed@Sun.COM return (hook_stack_notify_register(net_getnetstackidbynetid(netid), 831*7513SDarren.Reed@Sun.COM callback, arg)); 832*7513SDarren.Reed@Sun.COM } 833*7513SDarren.Reed@Sun.COM 834*7513SDarren.Reed@Sun.COM int 835*7513SDarren.Reed@Sun.COM net_instance_notify_unregister(netid_t netid, hook_notify_fn_t callback) 836*7513SDarren.Reed@Sun.COM { 837*7513SDarren.Reed@Sun.COM 838*7513SDarren.Reed@Sun.COM return (hook_stack_notify_unregister(net_getnetstackidbynetid(netid), 839*7513SDarren.Reed@Sun.COM callback)); 840*7513SDarren.Reed@Sun.COM } 841