17ddc9b1aSDarren Reed /*
27ddc9b1aSDarren Reed * CDDL HEADER START
37ddc9b1aSDarren Reed *
47ddc9b1aSDarren Reed * The contents of this file are subject to the terms of the
57ddc9b1aSDarren Reed * Common Development and Distribution License (the "License").
67ddc9b1aSDarren Reed * You may not use this file except in compliance with the License.
77ddc9b1aSDarren Reed *
87ddc9b1aSDarren Reed * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97ddc9b1aSDarren Reed * or http://www.opensolaris.org/os/licensing.
107ddc9b1aSDarren Reed * See the License for the specific language governing permissions
117ddc9b1aSDarren Reed * and limitations under the License.
127ddc9b1aSDarren Reed *
137ddc9b1aSDarren Reed * When distributing Covered Code, include this CDDL HEADER in each
147ddc9b1aSDarren Reed * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157ddc9b1aSDarren Reed * If applicable, add the following below this CDDL HEADER, with the
167ddc9b1aSDarren Reed * fields enclosed by brackets "[]" replaced with your own identifying
177ddc9b1aSDarren Reed * information: Portions Copyright [yyyy] [name of copyright owner]
187ddc9b1aSDarren Reed *
197ddc9b1aSDarren Reed * CDDL HEADER END
207ddc9b1aSDarren Reed */
217ddc9b1aSDarren Reed /*
227ddc9b1aSDarren Reed * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237ddc9b1aSDarren Reed * Use is subject to license terms.
247ddc9b1aSDarren Reed */
257ddc9b1aSDarren Reed
267ddc9b1aSDarren Reed #include <sys/param.h>
277ddc9b1aSDarren Reed #include <sys/atomic.h>
287ddc9b1aSDarren Reed #include <sys/kmem.h>
297ddc9b1aSDarren Reed #include <sys/rwlock.h>
307ddc9b1aSDarren Reed #include <sys/errno.h>
317ddc9b1aSDarren Reed #include <sys/queue.h>
327ddc9b1aSDarren Reed #include <sys/sunddi.h>
337ddc9b1aSDarren Reed #include <inet/common.h>
347ddc9b1aSDarren Reed #include <inet/led.h>
357ddc9b1aSDarren Reed #include <inet/ip.h>
367ddc9b1aSDarren Reed #include <sys/neti.h>
377ddc9b1aSDarren Reed #include <sys/zone.h>
387ddc9b1aSDarren Reed #include <sys/sdt.h>
397ddc9b1aSDarren Reed
407ddc9b1aSDarren Reed
41*8ad74188SDarren Reed typedef boolean_t napplyfn_t(neti_stack_t *, void *);
427ddc9b1aSDarren Reed
437ddc9b1aSDarren Reed static void *neti_stack_init(netstackid_t stackid, netstack_t *ns);
447ddc9b1aSDarren Reed static void neti_stack_fini(netstackid_t stackid, void *arg);
457ddc9b1aSDarren Reed static net_instance_int_t *net_instance_int_create(net_instance_t *nin,
467ddc9b1aSDarren Reed net_instance_int_t *parent);
477ddc9b1aSDarren Reed static void neti_stack_shutdown(netstackid_t stackid, void *arg);
487ddc9b1aSDarren Reed static void net_instance_int_free(net_instance_int_t *nini);
497ddc9b1aSDarren Reed
50*8ad74188SDarren Reed static boolean_t neti_stack_apply_create(neti_stack_t *, void *);
51*8ad74188SDarren Reed static boolean_t neti_stack_apply_destroy(neti_stack_t *, void *);
52*8ad74188SDarren Reed static boolean_t neti_stack_apply_shutdown(neti_stack_t *, void *);
537ddc9b1aSDarren Reed static void neti_apply_all_instances(neti_stack_t *, napplyfn_t *);
547ddc9b1aSDarren Reed static void neti_apply_all_stacks(void *, napplyfn_t *);
55*8ad74188SDarren Reed static boolean_t wait_for_nini_inprogress(neti_stack_t *,
567ddc9b1aSDarren Reed net_instance_int_t *, uint32_t);
577ddc9b1aSDarren Reed
587ddc9b1aSDarren Reed static nini_head_t neti_instance_list;
597ddc9b1aSDarren Reed static neti_stack_head_t neti_stack_list;
607ddc9b1aSDarren Reed static kmutex_t neti_stack_lock;
617ddc9b1aSDarren Reed
627ddc9b1aSDarren Reed void
neti_init()637ddc9b1aSDarren Reed neti_init()
647ddc9b1aSDarren Reed {
657ddc9b1aSDarren Reed mutex_init(&neti_stack_lock, NULL, MUTEX_DRIVER, NULL);
667ddc9b1aSDarren Reed
677ddc9b1aSDarren Reed LIST_INIT(&neti_instance_list);
687ddc9b1aSDarren Reed LIST_INIT(&neti_stack_list);
697ddc9b1aSDarren Reed /*
707ddc9b1aSDarren Reed * We want to be informed each time a netstack is created or
717ddc9b1aSDarren Reed * destroyed in the kernel.
727ddc9b1aSDarren Reed */
737ddc9b1aSDarren Reed netstack_register(NS_NETI, neti_stack_init, neti_stack_shutdown,
747ddc9b1aSDarren Reed neti_stack_fini);
757ddc9b1aSDarren Reed }
767ddc9b1aSDarren Reed
777ddc9b1aSDarren Reed void
neti_fini()787ddc9b1aSDarren Reed neti_fini()
797ddc9b1aSDarren Reed {
807ddc9b1aSDarren Reed ASSERT(LIST_EMPTY(&neti_instance_list));
817ddc9b1aSDarren Reed ASSERT(LIST_EMPTY(&neti_stack_list));
827ddc9b1aSDarren Reed
837ddc9b1aSDarren Reed netstack_unregister(NS_NETI);
847ddc9b1aSDarren Reed
857ddc9b1aSDarren Reed mutex_destroy(&neti_stack_lock);
867ddc9b1aSDarren Reed }
877ddc9b1aSDarren Reed
887ddc9b1aSDarren Reed /*
897ddc9b1aSDarren Reed * Initialize the neti stack instance. Because this is called out of the
907ddc9b1aSDarren Reed * netstack framework, it is not possible for it to be called twice with
917ddc9b1aSDarren Reed * the same values for (stackid,ns). The same also applies to the other
927ddc9b1aSDarren Reed * two functions used with netstack_register: neti_stack_shutdown and
937ddc9b1aSDarren Reed * neti_stack_fini.
947ddc9b1aSDarren Reed */
957ddc9b1aSDarren Reed static void *
neti_stack_init(netstackid_t stackid,netstack_t * ns)967ddc9b1aSDarren Reed neti_stack_init(netstackid_t stackid, netstack_t *ns)
977ddc9b1aSDarren Reed {
987ddc9b1aSDarren Reed net_instance_int_t *dup;
997ddc9b1aSDarren Reed net_instance_int_t *n;
1007ddc9b1aSDarren Reed neti_stack_t *nts;
1017ddc9b1aSDarren Reed
1027ddc9b1aSDarren Reed nts = kmem_zalloc(sizeof (*nts), KM_SLEEP);
1037ddc9b1aSDarren Reed LIST_INIT(&nts->nts_instances);
1047ddc9b1aSDarren Reed nts->nts_id = (netid_t)stackid;
1057ddc9b1aSDarren Reed nts->nts_stackid = stackid;
1067ddc9b1aSDarren Reed nts->nts_netstack = ns;
1077ddc9b1aSDarren Reed nts->nts_zoneid = netstackid_to_zoneid(stackid);
1087ddc9b1aSDarren Reed nts->nts_flags = NSF_ZONE_CREATE;
1097ddc9b1aSDarren Reed cv_init(&nts->nts_cv, NULL, CV_DRIVER, NULL);
1107ddc9b1aSDarren Reed mutex_init(&nts->nts_lock, NULL, MUTEX_DRIVER, NULL);
1117ddc9b1aSDarren Reed
1127ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
1137ddc9b1aSDarren Reed LIST_INSERT_HEAD(&neti_stack_list, nts, nts_next);
1147ddc9b1aSDarren Reed
1157ddc9b1aSDarren Reed LIST_FOREACH(n, &neti_instance_list, nini_next) {
1167ddc9b1aSDarren Reed /*
1177ddc9b1aSDarren Reed * This function returns with the NSS_CREATE_NEEDED flag
1187ddc9b1aSDarren Reed * set in "dup", so it is adequately prepared for the
1197ddc9b1aSDarren Reed * upcoming apply.
1207ddc9b1aSDarren Reed */
1217ddc9b1aSDarren Reed dup = net_instance_int_create(n->nini_instance, n);
1227ddc9b1aSDarren Reed
1237ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
1247ddc9b1aSDarren Reed LIST_INSERT_HEAD(&nts->nts_instances, dup, nini_next);
1257ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
1267ddc9b1aSDarren Reed }
1277ddc9b1aSDarren Reed
1287ddc9b1aSDarren Reed neti_apply_all_instances(nts, neti_stack_apply_create);
1297ddc9b1aSDarren Reed
1307ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
1317ddc9b1aSDarren Reed nts->nts_flags &= ~NSF_ZONE_CREATE;
1327ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
1337ddc9b1aSDarren Reed
1347ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
1357ddc9b1aSDarren Reed
1367ddc9b1aSDarren Reed return (nts);
1377ddc9b1aSDarren Reed }
1387ddc9b1aSDarren Reed
1397ddc9b1aSDarren Reed /*
1407ddc9b1aSDarren Reed * Run the shutdown for all of the hooks.
1417ddc9b1aSDarren Reed */
1427ddc9b1aSDarren Reed /*ARGSUSED*/
1437ddc9b1aSDarren Reed static void
neti_stack_shutdown(netstackid_t stackid,void * arg)1447ddc9b1aSDarren Reed neti_stack_shutdown(netstackid_t stackid, void *arg)
1457ddc9b1aSDarren Reed {
1467ddc9b1aSDarren Reed neti_stack_t *nts = arg;
1477ddc9b1aSDarren Reed net_instance_int_t *n;
1487ddc9b1aSDarren Reed struct net_data *nd;
1497ddc9b1aSDarren Reed
1507ddc9b1aSDarren Reed ASSERT(nts != NULL);
1517ddc9b1aSDarren Reed
1527ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
1537ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
1547ddc9b1aSDarren Reed /*
1557ddc9b1aSDarren Reed * Walk through all of the protocol stacks and mark them as shutting
1567ddc9b1aSDarren Reed * down.
1577ddc9b1aSDarren Reed */
1587ddc9b1aSDarren Reed LIST_FOREACH(nd, &nts->nts_netd_head, netd_list) {
1597ddc9b1aSDarren Reed nd->netd_condemned = 1;
1607ddc9b1aSDarren Reed }
1617ddc9b1aSDarren Reed
1627ddc9b1aSDarren Reed /*
1637ddc9b1aSDarren Reed * Now proceed to see which callbacks are waiting to hear about the
1647ddc9b1aSDarren Reed * impending shutdown...
1657ddc9b1aSDarren Reed */
1667ddc9b1aSDarren Reed LIST_FOREACH(n, &nts->nts_instances, nini_next) {
1677ddc9b1aSDarren Reed if (n->nini_instance->nin_shutdown == NULL) {
1687ddc9b1aSDarren Reed /*
1697ddc9b1aSDarren Reed * If there is no shutdown function registered,
1707ddc9b1aSDarren Reed * fake that we have completed it.
1717ddc9b1aSDarren Reed */
1727ddc9b1aSDarren Reed n->nini_flags |= NSS_SHUTDOWN_COMPLETED;
1737ddc9b1aSDarren Reed continue;
1747ddc9b1aSDarren Reed }
1757ddc9b1aSDarren Reed
1767ddc9b1aSDarren Reed /*
1777ddc9b1aSDarren Reed * We need to ensure that we don't try and shutdown something
1787ddc9b1aSDarren Reed * that is already in the process of being shutdown or
1797ddc9b1aSDarren Reed * destroyed. If it is still being created, that's ok, the
1807ddc9b1aSDarren Reed * shtudown flag is added to the mix of things to do.
1817ddc9b1aSDarren Reed */
1827ddc9b1aSDarren Reed if ((n->nini_flags & (NSS_DESTROY_ALL|NSS_SHUTDOWN_ALL)) == 0)
1837ddc9b1aSDarren Reed n->nini_flags |= NSS_SHUTDOWN_NEEDED;
1847ddc9b1aSDarren Reed }
1857ddc9b1aSDarren Reed nts->nts_flags |= NSF_ZONE_SHUTDOWN;
1867ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
1877ddc9b1aSDarren Reed
1887ddc9b1aSDarren Reed neti_apply_all_instances(nts, neti_stack_apply_shutdown);
1897ddc9b1aSDarren Reed
1907ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
1917ddc9b1aSDarren Reed
1927ddc9b1aSDarren Reed nts->nts_netstack = NULL;
193*8ad74188SDarren Reed nts->nts_flags &= ~NSF_ZONE_SHUTDOWN;
1947ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
1957ddc9b1aSDarren Reed
1967ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
1977ddc9b1aSDarren Reed ASSERT(nts != NULL);
1987ddc9b1aSDarren Reed }
1997ddc9b1aSDarren Reed
2007ddc9b1aSDarren Reed /*
2017ddc9b1aSDarren Reed * Free the neti stack instance.
2027ddc9b1aSDarren Reed * This function relies on the netstack framework only calling the _destroy
2037ddc9b1aSDarren Reed * callback once for each stackid. The netstack framework also provides us
2047ddc9b1aSDarren Reed * with assurance that nobody else will be doing any work (_create, _shutdown)
2057ddc9b1aSDarren Reed * on it, so there is no need to set and use flags to guard against
2067ddc9b1aSDarren Reed * simultaneous execution (ie. no need to set NSF_CLOSING.)
2077ddc9b1aSDarren Reed * What is required, however, is to make sure that we don't corrupt the
2087ddc9b1aSDarren Reed * list of neti_stack_t's for other code that walks it.
2097ddc9b1aSDarren Reed */
2107ddc9b1aSDarren Reed /*ARGSUSED*/
2117ddc9b1aSDarren Reed static void
neti_stack_fini(netstackid_t stackid,void * arg)2127ddc9b1aSDarren Reed neti_stack_fini(netstackid_t stackid, void *arg)
2137ddc9b1aSDarren Reed {
2147ddc9b1aSDarren Reed neti_stack_t *nts = arg;
2157ddc9b1aSDarren Reed net_instance_int_t *n;
2167ddc9b1aSDarren Reed struct net_data *nd;
2177ddc9b1aSDarren Reed
2187ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
219*8ad74188SDarren Reed mutex_enter(&nts->nts_lock);
220*8ad74188SDarren Reed
2217ddc9b1aSDarren Reed LIST_REMOVE(nts, nts_next);
2227ddc9b1aSDarren Reed
2237ddc9b1aSDarren Reed /*
2247ddc9b1aSDarren Reed * Walk through all of the protocol stacks and mark them as being
2257ddc9b1aSDarren Reed * destroyed.
2267ddc9b1aSDarren Reed */
2277ddc9b1aSDarren Reed LIST_FOREACH(nd, &nts->nts_netd_head, netd_list) {
2287ddc9b1aSDarren Reed nd->netd_condemned = 2;
2297ddc9b1aSDarren Reed }
2307ddc9b1aSDarren Reed
2317ddc9b1aSDarren Reed LIST_FOREACH(n, &nts->nts_instances, nini_next) {
2327ddc9b1aSDarren Reed ASSERT((n->nini_flags & NSS_SHUTDOWN_ALL) != 0);
2337ddc9b1aSDarren Reed if ((n->nini_flags & NSS_DESTROY_ALL) == 0)
2347ddc9b1aSDarren Reed n->nini_flags |= NSS_DESTROY_NEEDED;
2357ddc9b1aSDarren Reed }
2367ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
2377ddc9b1aSDarren Reed
2387ddc9b1aSDarren Reed neti_apply_all_instances(nts, neti_stack_apply_destroy);
2397ddc9b1aSDarren Reed
2407ddc9b1aSDarren Reed while (!LIST_EMPTY(&nts->nts_instances)) {
2417ddc9b1aSDarren Reed n = LIST_FIRST(&nts->nts_instances);
2427ddc9b1aSDarren Reed LIST_REMOVE(n, nini_next);
2437ddc9b1aSDarren Reed
2447ddc9b1aSDarren Reed net_instance_int_free(n);
2457ddc9b1aSDarren Reed }
246*8ad74188SDarren Reed mutex_exit(&neti_stack_lock);
2477ddc9b1aSDarren Reed
2487ddc9b1aSDarren Reed ASSERT(LIST_EMPTY(&nts->nts_netd_head));
2497ddc9b1aSDarren Reed
2507ddc9b1aSDarren Reed mutex_destroy(&nts->nts_lock);
2517ddc9b1aSDarren Reed cv_destroy(&nts->nts_cv);
2527ddc9b1aSDarren Reed
2537ddc9b1aSDarren Reed kmem_free(nts, sizeof (*nts));
2547ddc9b1aSDarren Reed }
2557ddc9b1aSDarren Reed
2567ddc9b1aSDarren Reed static net_instance_int_t *
net_instance_int_create(net_instance_t * nin,net_instance_int_t * parent)2577ddc9b1aSDarren Reed net_instance_int_create(net_instance_t *nin, net_instance_int_t *parent)
2587ddc9b1aSDarren Reed {
2597ddc9b1aSDarren Reed net_instance_int_t *nini;
2607ddc9b1aSDarren Reed
2617ddc9b1aSDarren Reed nini = kmem_zalloc(sizeof (net_instance_int_t), KM_SLEEP);
2627ddc9b1aSDarren Reed nini->nini_instance = nin;
2637ddc9b1aSDarren Reed nini->nini_parent = parent;
2647ddc9b1aSDarren Reed if (parent != NULL) {
2657ddc9b1aSDarren Reed /*
2667ddc9b1aSDarren Reed * If the parent pointer is non-NULL then we take that as
2677ddc9b1aSDarren Reed * an indication that the net_instance_int_t is being
2687ddc9b1aSDarren Reed * created for an active instance and there will expect
2697ddc9b1aSDarren Reed * the create function to be called. In contrast, if
2707ddc9b1aSDarren Reed * parent is NULL then this code assumes the object is
2717ddc9b1aSDarren Reed * being prepared for insertion onto the master list of
2727ddc9b1aSDarren Reed * callbacks to be called when an instance is created, etc.
2737ddc9b1aSDarren Reed */
2747ddc9b1aSDarren Reed parent->nini_ref++;
2757ddc9b1aSDarren Reed nini->nini_flags |= NSS_CREATE_NEEDED;
2767ddc9b1aSDarren Reed }
2777ddc9b1aSDarren Reed
2787ddc9b1aSDarren Reed cv_init(&nini->nini_cv, NULL, CV_DRIVER, NULL);
2797ddc9b1aSDarren Reed
2807ddc9b1aSDarren Reed return (nini);
2817ddc9b1aSDarren Reed }
2827ddc9b1aSDarren Reed
283*8ad74188SDarren Reed /*
284*8ad74188SDarren Reed * Free'ing of a net_instance_int_t is only to be done when we know nobody
285*8ad74188SDarren Reed * else has is using it. For both parents and clones, this is indicated by
286*8ad74188SDarren Reed * nini_ref being greater than 0, however, nini_ref is managed differently
287*8ad74188SDarren Reed * for its two uses. For parents, nini_ref is increased when a new clone is
288*8ad74188SDarren Reed * created and it is decremented here. For clones, nini_ref is adjusted by
289*8ad74188SDarren Reed * code elsewhere (e.g. in neti_stack_apply_*) and is not changed here.
290*8ad74188SDarren Reed */
2917ddc9b1aSDarren Reed static void
net_instance_int_free(net_instance_int_t * nini)2927ddc9b1aSDarren Reed net_instance_int_free(net_instance_int_t *nini)
2937ddc9b1aSDarren Reed {
294*8ad74188SDarren Reed /*
295*8ad74188SDarren Reed * This mutex guards the use of nini_ref.
296*8ad74188SDarren Reed */
297*8ad74188SDarren Reed ASSERT(mutex_owned(&neti_stack_lock));
2987ddc9b1aSDarren Reed
299*8ad74188SDarren Reed /*
300*8ad74188SDarren Reed * For 'parent' structures, nini_ref will drop to 0 when
301*8ad74188SDarren Reed * the last clone has been free'd... but for clones, it
302*8ad74188SDarren Reed * is possible for nini_ref to be non-zero if we get in
303*8ad74188SDarren Reed * here when all the locks have been given up to execute
304*8ad74188SDarren Reed * a callback or wait_for_nini_inprogress. In that case,
305*8ad74188SDarren Reed * we do not want to free the structure and just indicate
306*8ad74188SDarren Reed * that it is on the "doomed" list, thus we set the
307*8ad74188SDarren Reed * condemned flag.
308*8ad74188SDarren Reed */
309*8ad74188SDarren Reed if (nini->nini_parent != NULL) {
310*8ad74188SDarren Reed if (nini->nini_ref > 0)
311*8ad74188SDarren Reed nini->nini_condemned = B_TRUE;
3127ddc9b1aSDarren Reed nini->nini_parent->nini_ref--;
313*8ad74188SDarren Reed if (nini->nini_parent->nini_ref == 0)
314*8ad74188SDarren Reed net_instance_int_free(nini->nini_parent);
315*8ad74188SDarren Reed nini->nini_parent = NULL;
316*8ad74188SDarren Reed }
3177ddc9b1aSDarren Reed
318*8ad74188SDarren Reed if (nini->nini_ref == 0) {
319*8ad74188SDarren Reed cv_destroy(&nini->nini_cv);
3207ddc9b1aSDarren Reed kmem_free(nini, sizeof (*nini));
3217ddc9b1aSDarren Reed }
322*8ad74188SDarren Reed }
3237ddc9b1aSDarren Reed
3247ddc9b1aSDarren Reed net_instance_t *
net_instance_alloc(const int version)3257ddc9b1aSDarren Reed net_instance_alloc(const int version)
3267ddc9b1aSDarren Reed {
3277ddc9b1aSDarren Reed net_instance_t *nin;
3287ddc9b1aSDarren Reed
3297ddc9b1aSDarren Reed if (version != NETINFO_VERSION)
3307ddc9b1aSDarren Reed return (NULL);
3317ddc9b1aSDarren Reed
3327ddc9b1aSDarren Reed nin = kmem_zalloc(sizeof (net_instance_t), KM_SLEEP);
3337ddc9b1aSDarren Reed nin->nin_version = version;
3347ddc9b1aSDarren Reed
3357ddc9b1aSDarren Reed return (nin);
3367ddc9b1aSDarren Reed }
3377ddc9b1aSDarren Reed
3387ddc9b1aSDarren Reed void
net_instance_free(net_instance_t * nin)3397ddc9b1aSDarren Reed net_instance_free(net_instance_t *nin)
3407ddc9b1aSDarren Reed {
3417ddc9b1aSDarren Reed kmem_free(nin, sizeof (*nin));
3427ddc9b1aSDarren Reed }
3437ddc9b1aSDarren Reed
3447ddc9b1aSDarren Reed int
net_instance_register(net_instance_t * nin)3457ddc9b1aSDarren Reed net_instance_register(net_instance_t *nin)
3467ddc9b1aSDarren Reed {
3477ddc9b1aSDarren Reed net_instance_int_t *parent;
3487ddc9b1aSDarren Reed net_instance_int_t *tmp;
3497ddc9b1aSDarren Reed neti_stack_t *nts;
3507ddc9b1aSDarren Reed
3517ddc9b1aSDarren Reed ASSERT(nin->nin_name != NULL);
3527ddc9b1aSDarren Reed
3537ddc9b1aSDarren Reed if (nin->nin_create == NULL || nin->nin_destroy == NULL)
3547ddc9b1aSDarren Reed return (DDI_FAILURE);
3557ddc9b1aSDarren Reed
3567ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
3577ddc9b1aSDarren Reed /*
3587ddc9b1aSDarren Reed * Search for duplicate, either on the global list or on any
3597ddc9b1aSDarren Reed * of the known instances.
3607ddc9b1aSDarren Reed */
3617ddc9b1aSDarren Reed LIST_FOREACH(tmp, &neti_instance_list, nini_next) {
3627ddc9b1aSDarren Reed if (strcmp(nin->nin_name, tmp->nini_instance->nin_name) == 0) {
3637ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
3647ddc9b1aSDarren Reed return (DDI_FAILURE);
3657ddc9b1aSDarren Reed }
3667ddc9b1aSDarren Reed }
3677ddc9b1aSDarren Reed
3687ddc9b1aSDarren Reed /*
3697ddc9b1aSDarren Reed * Now insert and activate.
3707ddc9b1aSDarren Reed */
3717ddc9b1aSDarren Reed parent = net_instance_int_create(nin, NULL);
3727ddc9b1aSDarren Reed ASSERT(parent != NULL);
3737ddc9b1aSDarren Reed LIST_INSERT_HEAD(&neti_instance_list, parent, nini_next);
3747ddc9b1aSDarren Reed
3757ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
3767ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
3777ddc9b1aSDarren Reed /*
3787ddc9b1aSDarren Reed * If shutdown of the zone has begun then do not add a new
3797ddc9b1aSDarren Reed * instance of the object being registered.
3807ddc9b1aSDarren Reed */
3817ddc9b1aSDarren Reed if ((nts->nts_flags & NSF_ZONE_SHUTDOWN) ||
3827ddc9b1aSDarren Reed (nts->nts_netstack == NULL)) {
3837ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
3847ddc9b1aSDarren Reed continue;
3857ddc9b1aSDarren Reed }
386*8ad74188SDarren Reed
3877ddc9b1aSDarren Reed /*
3887ddc9b1aSDarren Reed * This function returns with the NSS_CREATE_NEEDED flag
3897ddc9b1aSDarren Reed * set in "dup", so it is adequately prepared for the
3907ddc9b1aSDarren Reed * upcoming apply.
3917ddc9b1aSDarren Reed */
3927ddc9b1aSDarren Reed tmp = net_instance_int_create(nin, parent);
3937ddc9b1aSDarren Reed ASSERT(tmp != NULL);
3947ddc9b1aSDarren Reed LIST_INSERT_HEAD(&nts->nts_instances, tmp, nini_next);
3957ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
3967ddc9b1aSDarren Reed
3977ddc9b1aSDarren Reed }
3987ddc9b1aSDarren Reed
3997ddc9b1aSDarren Reed neti_apply_all_stacks(parent, neti_stack_apply_create);
4007ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
4017ddc9b1aSDarren Reed
4027ddc9b1aSDarren Reed return (DDI_SUCCESS);
4037ddc9b1aSDarren Reed }
4047ddc9b1aSDarren Reed
4057ddc9b1aSDarren Reed /*
4067ddc9b1aSDarren Reed * While net_instance_register() isn't likely to be racing against itself,
4077ddc9b1aSDarren Reed * net_instance_unregister() can be entered from various directions that
4087ddc9b1aSDarren Reed * can compete: shutdown of a zone, unloading of a module (and it calling
4097ddc9b1aSDarren Reed * _unregister() as part of that) and the module doing an _unregister()
4107ddc9b1aSDarren Reed * anyway.
4117ddc9b1aSDarren Reed */
4127ddc9b1aSDarren Reed int
net_instance_unregister(net_instance_t * nin)4137ddc9b1aSDarren Reed net_instance_unregister(net_instance_t *nin)
4147ddc9b1aSDarren Reed {
4157ddc9b1aSDarren Reed net_instance_int_t *parent;
4167ddc9b1aSDarren Reed net_instance_int_t *tmp;
4177ddc9b1aSDarren Reed neti_stack_t *nts;
4187ddc9b1aSDarren Reed
4197ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
4207ddc9b1aSDarren Reed
4217ddc9b1aSDarren Reed LIST_FOREACH(tmp, &neti_instance_list, nini_next) {
4227ddc9b1aSDarren Reed if (strcmp(tmp->nini_instance->nin_name, nin->nin_name) == 0) {
4237ddc9b1aSDarren Reed LIST_REMOVE(tmp, nini_next);
4247ddc9b1aSDarren Reed break;
4257ddc9b1aSDarren Reed }
4267ddc9b1aSDarren Reed }
4277ddc9b1aSDarren Reed
4287ddc9b1aSDarren Reed if (tmp == NULL) {
4297ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
4307ddc9b1aSDarren Reed return (DDI_FAILURE);
4317ddc9b1aSDarren Reed }
4327ddc9b1aSDarren Reed parent = tmp;
4337ddc9b1aSDarren Reed
4347ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
4357ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
4367ddc9b1aSDarren Reed LIST_FOREACH(tmp, &nts->nts_instances, nini_next) {
4377ddc9b1aSDarren Reed if (tmp->nini_parent != parent)
4387ddc9b1aSDarren Reed continue;
4397ddc9b1aSDarren Reed /*
4407ddc9b1aSDarren Reed * Netstack difference:
4417ddc9b1aSDarren Reed * In netstack.c, there is a check for
4427ddc9b1aSDarren Reed * NSS_CREATE_COMPLETED before setting the other
4437ddc9b1aSDarren Reed * _NEEDED flags. If we consider that a list
4447ddc9b1aSDarren Reed * member must always have at least the _CREATE_NEEDED
4457ddc9b1aSDarren Reed * flag set and that wait_for_nini_inprogress will
4467ddc9b1aSDarren Reed * also wait for that flag to be cleared in both of
4477ddc9b1aSDarren Reed * the shutdown and destroy apply functions.
4487ddc9b1aSDarren Reed *
4497ddc9b1aSDarren Reed * It is possible to optimize out the case where
4507ddc9b1aSDarren Reed * all three _NEEDED flags are set to being able
4517ddc9b1aSDarren Reed * to pretend everything has been done and just
4527ddc9b1aSDarren Reed * set all three _COMPLETE flags. This makes a
4537ddc9b1aSDarren Reed * special case that we then need to consider in
4547ddc9b1aSDarren Reed * other locations, so for the sake of simplicity,
4557ddc9b1aSDarren Reed * we leave it as it is.
4567ddc9b1aSDarren Reed */
4577ddc9b1aSDarren Reed if ((tmp->nini_flags & NSS_SHUTDOWN_ALL) == 0)
4587ddc9b1aSDarren Reed tmp->nini_flags |= NSS_SHUTDOWN_NEEDED;
4597ddc9b1aSDarren Reed if ((tmp->nini_flags & NSS_DESTROY_ALL) == 0)
4607ddc9b1aSDarren Reed tmp->nini_flags |= NSS_DESTROY_NEEDED;
461*8ad74188SDarren Reed break;
4627ddc9b1aSDarren Reed }
4637ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
4647ddc9b1aSDarren Reed }
4657ddc9b1aSDarren Reed
4667ddc9b1aSDarren Reed /*
4677ddc9b1aSDarren Reed * Each of these functions ensures that the requisite _COMPLETED
4687ddc9b1aSDarren Reed * flag is present before calling the apply function. So we are
4697ddc9b1aSDarren Reed * guaranteed to have NSS_CREATE_COMPLETED|NSS_SHUTDOWN_COMPLETED
4707ddc9b1aSDarren Reed * both set after the first call here and when the second completes,
4717ddc9b1aSDarren Reed * NSS_DESTROY_COMPLETED is also set.
4727ddc9b1aSDarren Reed */
4737ddc9b1aSDarren Reed neti_apply_all_stacks(parent, neti_stack_apply_shutdown);
4747ddc9b1aSDarren Reed neti_apply_all_stacks(parent, neti_stack_apply_destroy);
4757ddc9b1aSDarren Reed
4767ddc9b1aSDarren Reed /*
4777ddc9b1aSDarren Reed * Remove the instance callback information from each stack.
4787ddc9b1aSDarren Reed */
4797ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
4807ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
4817ddc9b1aSDarren Reed LIST_FOREACH(tmp, &nts->nts_instances, nini_next) {
4827ddc9b1aSDarren Reed if ((tmp->nini_parent == parent) &&
4837ddc9b1aSDarren Reed (tmp->nini_flags & NSS_SHUTDOWN_COMPLETED) &&
4847ddc9b1aSDarren Reed (tmp->nini_flags & NSS_DESTROY_COMPLETED)) {
4857ddc9b1aSDarren Reed /*
4867ddc9b1aSDarren Reed * There should only be one entry that has a
4877ddc9b1aSDarren Reed * matching nini_parent so there is no need to
4887ddc9b1aSDarren Reed * worry about continuing a loop where we are
4897ddc9b1aSDarren Reed * free'ing the structure holding the 'next'
4907ddc9b1aSDarren Reed * pointer.
4917ddc9b1aSDarren Reed */
4927ddc9b1aSDarren Reed LIST_REMOVE(tmp, nini_next);
4937ddc9b1aSDarren Reed net_instance_int_free(tmp);
4947ddc9b1aSDarren Reed break;
4957ddc9b1aSDarren Reed }
4967ddc9b1aSDarren Reed }
4977ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
4987ddc9b1aSDarren Reed }
4997ddc9b1aSDarren Reed
500*8ad74188SDarren Reed mutex_exit(&neti_stack_lock);
5017ddc9b1aSDarren Reed
5027ddc9b1aSDarren Reed return (DDI_SUCCESS);
5037ddc9b1aSDarren Reed }
5047ddc9b1aSDarren Reed
5057ddc9b1aSDarren Reed static void
neti_apply_all_instances(neti_stack_t * nts,napplyfn_t * applyfn)5067ddc9b1aSDarren Reed neti_apply_all_instances(neti_stack_t *nts, napplyfn_t *applyfn)
5077ddc9b1aSDarren Reed {
5087ddc9b1aSDarren Reed net_instance_int_t *n;
5097ddc9b1aSDarren Reed
5107ddc9b1aSDarren Reed ASSERT(mutex_owned(&neti_stack_lock));
5117ddc9b1aSDarren Reed
5127ddc9b1aSDarren Reed n = LIST_FIRST(&nts->nts_instances);
5137ddc9b1aSDarren Reed while (n != NULL) {
514*8ad74188SDarren Reed if ((applyfn)(nts, n->nini_parent)) {
5157ddc9b1aSDarren Reed /* Lock dropped - restart at head */
5167ddc9b1aSDarren Reed n = LIST_FIRST(&nts->nts_instances);
5177ddc9b1aSDarren Reed } else {
5187ddc9b1aSDarren Reed n = LIST_NEXT(n, nini_next);
5197ddc9b1aSDarren Reed }
5207ddc9b1aSDarren Reed }
5217ddc9b1aSDarren Reed }
5227ddc9b1aSDarren Reed
5237ddc9b1aSDarren Reed static void
neti_apply_all_stacks(void * parent,napplyfn_t * applyfn)5247ddc9b1aSDarren Reed neti_apply_all_stacks(void *parent, napplyfn_t *applyfn)
5257ddc9b1aSDarren Reed {
5267ddc9b1aSDarren Reed neti_stack_t *nts;
5277ddc9b1aSDarren Reed
5287ddc9b1aSDarren Reed ASSERT(mutex_owned(&neti_stack_lock));
5297ddc9b1aSDarren Reed
5307ddc9b1aSDarren Reed nts = LIST_FIRST(&neti_stack_list);
5317ddc9b1aSDarren Reed while (nts != NULL) {
5327ddc9b1aSDarren Reed /*
5337ddc9b1aSDarren Reed * This function differs, in that it doesn't have a call to
5347ddc9b1aSDarren Reed * a "wait_creator" call, from the zsd/netstack code. The
5357ddc9b1aSDarren Reed * waiting is pushed into the apply functions which cause
5367ddc9b1aSDarren Reed * the waiting to be done in wait_for_nini_progress with
5377ddc9b1aSDarren Reed * the passing in of cmask.
5387ddc9b1aSDarren Reed */
539*8ad74188SDarren Reed if ((applyfn)(nts, parent)) {
5407ddc9b1aSDarren Reed /* Lock dropped - restart at head */
5417ddc9b1aSDarren Reed nts = LIST_FIRST(&neti_stack_list);
5427ddc9b1aSDarren Reed } else {
5437ddc9b1aSDarren Reed nts = LIST_NEXT(nts, nts_next);
5447ddc9b1aSDarren Reed }
5457ddc9b1aSDarren Reed }
5467ddc9b1aSDarren Reed }
5477ddc9b1aSDarren Reed
5487ddc9b1aSDarren Reed static boolean_t
neti_stack_apply_create(neti_stack_t * nts,void * parent)549*8ad74188SDarren Reed neti_stack_apply_create(neti_stack_t *nts, void *parent)
5507ddc9b1aSDarren Reed {
5517ddc9b1aSDarren Reed void *result;
5527ddc9b1aSDarren Reed boolean_t dropped = B_FALSE;
5537ddc9b1aSDarren Reed net_instance_int_t *tmp;
5547ddc9b1aSDarren Reed net_instance_t *nin;
5557ddc9b1aSDarren Reed
5567ddc9b1aSDarren Reed ASSERT(parent != NULL);
557*8ad74188SDarren Reed ASSERT(mutex_owned(&neti_stack_lock));
5587ddc9b1aSDarren Reed
5597ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
5607ddc9b1aSDarren Reed
5617ddc9b1aSDarren Reed LIST_FOREACH(tmp, &nts->nts_instances, nini_next) {
5627ddc9b1aSDarren Reed if (tmp->nini_parent == parent)
5637ddc9b1aSDarren Reed break;
5647ddc9b1aSDarren Reed }
5657ddc9b1aSDarren Reed if (tmp == NULL) {
5667ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
5677ddc9b1aSDarren Reed return (dropped);
5687ddc9b1aSDarren Reed }
5697ddc9b1aSDarren Reed
570*8ad74188SDarren Reed tmp->nini_ref++;
571*8ad74188SDarren Reed
572*8ad74188SDarren Reed if (wait_for_nini_inprogress(nts, tmp, 0))
5737ddc9b1aSDarren Reed dropped = B_TRUE;
5747ddc9b1aSDarren Reed
575*8ad74188SDarren Reed if ((tmp->nini_flags & NSS_CREATE_NEEDED) && !tmp->nini_condemned) {
5767ddc9b1aSDarren Reed nin = tmp->nini_instance;
5777ddc9b1aSDarren Reed tmp->nini_flags &= ~NSS_CREATE_NEEDED;
5787ddc9b1aSDarren Reed tmp->nini_flags |= NSS_CREATE_INPROGRESS;
5797ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__create__inprogress,
5807ddc9b1aSDarren Reed neti_stack_t *, nts, net_instance_int_t *, tmp);
5817ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
582*8ad74188SDarren Reed mutex_exit(&neti_stack_lock);
5837ddc9b1aSDarren Reed dropped = B_TRUE;
5847ddc9b1aSDarren Reed
5857ddc9b1aSDarren Reed ASSERT(tmp->nini_created == NULL);
5867ddc9b1aSDarren Reed ASSERT(nin->nin_create != NULL);
5877ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__create__start,
5887ddc9b1aSDarren Reed netstackid_t, nts->nts_id,
5897ddc9b1aSDarren Reed neti_stack_t *, nts);
5907ddc9b1aSDarren Reed result = (nin->nin_create)(nts->nts_id);
5917ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__create__end,
5927ddc9b1aSDarren Reed void *, result, neti_stack_t *, nts);
5937ddc9b1aSDarren Reed
5947ddc9b1aSDarren Reed ASSERT(result != NULL);
595*8ad74188SDarren Reed mutex_enter(&neti_stack_lock);
5967ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
5977ddc9b1aSDarren Reed tmp->nini_created = result;
5987ddc9b1aSDarren Reed tmp->nini_flags &= ~NSS_CREATE_INPROGRESS;
5997ddc9b1aSDarren Reed tmp->nini_flags |= NSS_CREATE_COMPLETED;
6007ddc9b1aSDarren Reed cv_broadcast(&tmp->nini_cv);
6017ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__create__completed,
6027ddc9b1aSDarren Reed neti_stack_t *, nts, net_instance_int_t *, tmp);
6037ddc9b1aSDarren Reed }
604*8ad74188SDarren Reed tmp->nini_ref--;
605*8ad74188SDarren Reed
606*8ad74188SDarren Reed if (tmp->nini_condemned) {
607*8ad74188SDarren Reed net_instance_int_free(tmp);
608*8ad74188SDarren Reed dropped = B_TRUE;
609*8ad74188SDarren Reed }
6107ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
6117ddc9b1aSDarren Reed return (dropped);
6127ddc9b1aSDarren Reed }
6137ddc9b1aSDarren Reed
6147ddc9b1aSDarren Reed
6157ddc9b1aSDarren Reed static boolean_t
neti_stack_apply_shutdown(neti_stack_t * nts,void * parent)616*8ad74188SDarren Reed neti_stack_apply_shutdown(neti_stack_t *nts, void *parent)
6177ddc9b1aSDarren Reed {
6187ddc9b1aSDarren Reed boolean_t dropped = B_FALSE;
6197ddc9b1aSDarren Reed net_instance_int_t *tmp;
6207ddc9b1aSDarren Reed net_instance_t *nin;
6217ddc9b1aSDarren Reed
6227ddc9b1aSDarren Reed ASSERT(parent != NULL);
623*8ad74188SDarren Reed ASSERT(mutex_owned(&neti_stack_lock));
6247ddc9b1aSDarren Reed
6257ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
6267ddc9b1aSDarren Reed
6277ddc9b1aSDarren Reed LIST_FOREACH(tmp, &nts->nts_instances, nini_next) {
6287ddc9b1aSDarren Reed if (tmp->nini_parent == parent)
6297ddc9b1aSDarren Reed break;
6307ddc9b1aSDarren Reed }
6317ddc9b1aSDarren Reed if (tmp == NULL) {
6327ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
6337ddc9b1aSDarren Reed return (dropped);
6347ddc9b1aSDarren Reed }
635*8ad74188SDarren Reed ASSERT((tmp->nini_flags & NSS_SHUTDOWN_ALL) != 0);
6367ddc9b1aSDarren Reed
637*8ad74188SDarren Reed tmp->nini_ref++;
638*8ad74188SDarren Reed
639*8ad74188SDarren Reed if (wait_for_nini_inprogress(nts, tmp, NSS_CREATE_NEEDED))
6407ddc9b1aSDarren Reed dropped = B_TRUE;
6417ddc9b1aSDarren Reed
6427ddc9b1aSDarren Reed nin = tmp->nini_instance;
6437ddc9b1aSDarren Reed if (nin->nin_shutdown == NULL) {
6447ddc9b1aSDarren Reed /*
6457ddc9b1aSDarren Reed * If there is no shutdown function, fake having completed it.
6467ddc9b1aSDarren Reed */
6477ddc9b1aSDarren Reed if (tmp->nini_flags & NSS_SHUTDOWN_NEEDED) {
6487ddc9b1aSDarren Reed tmp->nini_flags &= ~NSS_SHUTDOWN_NEEDED;
6497ddc9b1aSDarren Reed tmp->nini_flags |= NSS_SHUTDOWN_COMPLETED;
6507ddc9b1aSDarren Reed }
651*8ad74188SDarren Reed tmp->nini_ref--;
652*8ad74188SDarren Reed
653*8ad74188SDarren Reed if (tmp->nini_condemned) {
654*8ad74188SDarren Reed net_instance_int_free(tmp);
655*8ad74188SDarren Reed dropped = B_TRUE;
656*8ad74188SDarren Reed }
6577ddc9b1aSDarren Reed
6587ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
6597ddc9b1aSDarren Reed return (dropped);
6607ddc9b1aSDarren Reed }
6617ddc9b1aSDarren Reed
662*8ad74188SDarren Reed if ((tmp->nini_flags & NSS_SHUTDOWN_NEEDED) && !tmp->nini_condemned) {
6637ddc9b1aSDarren Reed ASSERT((tmp->nini_flags & NSS_CREATE_COMPLETED) != 0);
6647ddc9b1aSDarren Reed tmp->nini_flags &= ~NSS_SHUTDOWN_NEEDED;
6657ddc9b1aSDarren Reed tmp->nini_flags |= NSS_SHUTDOWN_INPROGRESS;
6667ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__shutdown__inprogress,
6677ddc9b1aSDarren Reed neti_stack_t *, nts, net_instance_int_t *, tmp);
6687ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
669*8ad74188SDarren Reed mutex_exit(&neti_stack_lock);
6707ddc9b1aSDarren Reed dropped = B_TRUE;
6717ddc9b1aSDarren Reed
6727ddc9b1aSDarren Reed ASSERT(nin->nin_shutdown != NULL);
6737ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__shutdown__start,
6747ddc9b1aSDarren Reed netstackid_t, nts->nts_id,
6757ddc9b1aSDarren Reed neti_stack_t *, nts);
6767ddc9b1aSDarren Reed (nin->nin_shutdown)(nts->nts_id, tmp->nini_created);
6777ddc9b1aSDarren Reed DTRACE_PROBE1(neti__stack__shutdown__end,
6787ddc9b1aSDarren Reed neti_stack_t *, nts);
6797ddc9b1aSDarren Reed
680*8ad74188SDarren Reed mutex_enter(&neti_stack_lock);
6817ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
6827ddc9b1aSDarren Reed tmp->nini_flags &= ~NSS_SHUTDOWN_INPROGRESS;
6837ddc9b1aSDarren Reed tmp->nini_flags |= NSS_SHUTDOWN_COMPLETED;
6847ddc9b1aSDarren Reed cv_broadcast(&tmp->nini_cv);
6857ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__shutdown__completed,
6867ddc9b1aSDarren Reed neti_stack_t *, nts, net_instance_int_t *, tmp);
6877ddc9b1aSDarren Reed }
6887ddc9b1aSDarren Reed ASSERT((tmp->nini_flags & NSS_SHUTDOWN_COMPLETED) != 0);
689*8ad74188SDarren Reed tmp->nini_ref--;
690*8ad74188SDarren Reed
691*8ad74188SDarren Reed if (tmp->nini_condemned) {
692*8ad74188SDarren Reed net_instance_int_free(tmp);
693*8ad74188SDarren Reed dropped = B_TRUE;
694*8ad74188SDarren Reed }
6957ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
6967ddc9b1aSDarren Reed return (dropped);
6977ddc9b1aSDarren Reed }
6987ddc9b1aSDarren Reed
6997ddc9b1aSDarren Reed static boolean_t
neti_stack_apply_destroy(neti_stack_t * nts,void * parent)700*8ad74188SDarren Reed neti_stack_apply_destroy(neti_stack_t *nts, void *parent)
7017ddc9b1aSDarren Reed {
7027ddc9b1aSDarren Reed boolean_t dropped = B_FALSE;
7037ddc9b1aSDarren Reed net_instance_int_t *tmp;
7047ddc9b1aSDarren Reed net_instance_t *nin;
7057ddc9b1aSDarren Reed
7067ddc9b1aSDarren Reed ASSERT(parent != NULL);
707*8ad74188SDarren Reed ASSERT(mutex_owned(&neti_stack_lock));
7087ddc9b1aSDarren Reed
7097ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
7107ddc9b1aSDarren Reed
7117ddc9b1aSDarren Reed LIST_FOREACH(tmp, &nts->nts_instances, nini_next) {
7127ddc9b1aSDarren Reed if (tmp->nini_parent == parent)
7137ddc9b1aSDarren Reed break;
7147ddc9b1aSDarren Reed }
7157ddc9b1aSDarren Reed if (tmp == NULL) {
7167ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
7177ddc9b1aSDarren Reed return (dropped);
7187ddc9b1aSDarren Reed }
7197ddc9b1aSDarren Reed
720*8ad74188SDarren Reed tmp->nini_ref++;
721*8ad74188SDarren Reed
7227ddc9b1aSDarren Reed /*
7237ddc9b1aSDarren Reed * We pause here so that when we continue we know that we're the
7247ddc9b1aSDarren Reed * only one doing anything active with this node.
7257ddc9b1aSDarren Reed */
726*8ad74188SDarren Reed if (wait_for_nini_inprogress(nts, tmp,
7277ddc9b1aSDarren Reed NSS_CREATE_NEEDED|NSS_SHUTDOWN_NEEDED))
7287ddc9b1aSDarren Reed dropped = B_TRUE;
7297ddc9b1aSDarren Reed
730*8ad74188SDarren Reed if ((tmp->nini_flags & NSS_DESTROY_NEEDED) && !tmp->nini_condemned) {
7317ddc9b1aSDarren Reed ASSERT((tmp->nini_flags & NSS_SHUTDOWN_COMPLETED) != 0);
7327ddc9b1aSDarren Reed nin = tmp->nini_instance;
7337ddc9b1aSDarren Reed tmp->nini_flags &= ~NSS_DESTROY_NEEDED;
7347ddc9b1aSDarren Reed tmp->nini_flags |= NSS_DESTROY_INPROGRESS;
7357ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__destroy__inprogress,
7367ddc9b1aSDarren Reed neti_stack_t *, nts, net_instance_int_t *, tmp);
7377ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
738*8ad74188SDarren Reed mutex_exit(&neti_stack_lock);
7397ddc9b1aSDarren Reed dropped = B_TRUE;
7407ddc9b1aSDarren Reed
7417ddc9b1aSDarren Reed ASSERT(nin->nin_destroy != NULL);
7427ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__destroy__start,
7437ddc9b1aSDarren Reed netstackid_t, nts->nts_id,
7447ddc9b1aSDarren Reed neti_stack_t *, nts);
7457ddc9b1aSDarren Reed (nin->nin_destroy)(nts->nts_id, tmp->nini_created);
7467ddc9b1aSDarren Reed DTRACE_PROBE1(neti__stack__destroy__end,
7477ddc9b1aSDarren Reed neti_stack_t *, nts);
7487ddc9b1aSDarren Reed
749*8ad74188SDarren Reed mutex_enter(&neti_stack_lock);
7507ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
7517ddc9b1aSDarren Reed tmp->nini_flags &= ~NSS_DESTROY_INPROGRESS;
7527ddc9b1aSDarren Reed tmp->nini_flags |= NSS_DESTROY_COMPLETED;
7537ddc9b1aSDarren Reed cv_broadcast(&tmp->nini_cv);
7547ddc9b1aSDarren Reed DTRACE_PROBE2(neti__stack__destroy__completed,
7557ddc9b1aSDarren Reed neti_stack_t *, nts, net_instance_int_t *, tmp);
7567ddc9b1aSDarren Reed }
757*8ad74188SDarren Reed tmp->nini_ref--;
758*8ad74188SDarren Reed
759*8ad74188SDarren Reed if (tmp->nini_condemned) {
760*8ad74188SDarren Reed net_instance_int_free(tmp);
761*8ad74188SDarren Reed dropped = B_TRUE;
762*8ad74188SDarren Reed }
7637ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
7647ddc9b1aSDarren Reed return (dropped);
7657ddc9b1aSDarren Reed }
7667ddc9b1aSDarren Reed
7677ddc9b1aSDarren Reed static boolean_t
wait_for_nini_inprogress(neti_stack_t * nts,net_instance_int_t * nini,uint32_t cmask)768*8ad74188SDarren Reed wait_for_nini_inprogress(neti_stack_t *nts, net_instance_int_t *nini,
769*8ad74188SDarren Reed uint32_t cmask)
7707ddc9b1aSDarren Reed {
7717ddc9b1aSDarren Reed boolean_t dropped = B_FALSE;
7727ddc9b1aSDarren Reed
773*8ad74188SDarren Reed ASSERT(mutex_owned(&neti_stack_lock));
7747ddc9b1aSDarren Reed
7757ddc9b1aSDarren Reed while (nini->nini_flags & (NSS_ALL_INPROGRESS|cmask)) {
776*8ad74188SDarren Reed DTRACE_PROBE2(neti__wait__nini__inprogress,
7777ddc9b1aSDarren Reed neti_stack_t *, nts, net_instance_int_t *, nini);
7787ddc9b1aSDarren Reed dropped = B_TRUE;
779*8ad74188SDarren Reed mutex_exit(&neti_stack_lock);
7807ddc9b1aSDarren Reed
7817ddc9b1aSDarren Reed cv_wait(&nini->nini_cv, &nts->nts_lock);
7827ddc9b1aSDarren Reed
7837ddc9b1aSDarren Reed /* First drop netstack_lock to preserve order */
7847ddc9b1aSDarren Reed mutex_exit(&nts->nts_lock);
785*8ad74188SDarren Reed DTRACE_PROBE2(wait__nini__inprogress__pause,
786*8ad74188SDarren Reed neti_stack_t *, nts, net_instance_int_t *, nini);
787*8ad74188SDarren Reed mutex_enter(&neti_stack_lock);
7887ddc9b1aSDarren Reed mutex_enter(&nts->nts_lock);
7897ddc9b1aSDarren Reed }
790*8ad74188SDarren Reed DTRACE_PROBE2(neti__wait__nini__inprogress__complete,
791*8ad74188SDarren Reed neti_stack_t *, nts, net_instance_int_t *, nini);
7927ddc9b1aSDarren Reed return (dropped);
7937ddc9b1aSDarren Reed }
7947ddc9b1aSDarren Reed
7957ddc9b1aSDarren Reed /* ======================================================================= */
7967ddc9b1aSDarren Reed
7977ddc9b1aSDarren Reed netid_t
net_zoneidtonetid(zoneid_t zoneid)7987ddc9b1aSDarren Reed net_zoneidtonetid(zoneid_t zoneid)
7997ddc9b1aSDarren Reed {
8007ddc9b1aSDarren Reed
8017ddc9b1aSDarren Reed neti_stack_t *nts;
8027ddc9b1aSDarren Reed
8037ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
8047ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
8057ddc9b1aSDarren Reed if (nts->nts_zoneid == zoneid) {
8067ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8077ddc9b1aSDarren Reed return (nts->nts_id);
8087ddc9b1aSDarren Reed }
8097ddc9b1aSDarren Reed }
8107ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8117ddc9b1aSDarren Reed
8127ddc9b1aSDarren Reed return (-1);
8137ddc9b1aSDarren Reed }
8147ddc9b1aSDarren Reed
8157ddc9b1aSDarren Reed zoneid_t
net_getzoneidbynetid(netid_t netid)8167ddc9b1aSDarren Reed net_getzoneidbynetid(netid_t netid)
8177ddc9b1aSDarren Reed {
8187ddc9b1aSDarren Reed neti_stack_t *nts;
8197ddc9b1aSDarren Reed
8207ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
8217ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
8227ddc9b1aSDarren Reed if (nts->nts_id == netid) {
8237ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8247ddc9b1aSDarren Reed return (nts->nts_zoneid);
8257ddc9b1aSDarren Reed }
8267ddc9b1aSDarren Reed }
8277ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8287ddc9b1aSDarren Reed
8297ddc9b1aSDarren Reed return (-1);
8307ddc9b1aSDarren Reed }
8317ddc9b1aSDarren Reed
8327ddc9b1aSDarren Reed netstackid_t
net_getnetstackidbynetid(netid_t netid)8337ddc9b1aSDarren Reed net_getnetstackidbynetid(netid_t netid)
8347ddc9b1aSDarren Reed {
8357ddc9b1aSDarren Reed neti_stack_t *nts;
8367ddc9b1aSDarren Reed
8377ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
8387ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
8397ddc9b1aSDarren Reed if (nts->nts_id == netid) {
8407ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8417ddc9b1aSDarren Reed return (nts->nts_stackid);
8427ddc9b1aSDarren Reed }
8437ddc9b1aSDarren Reed }
8447ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8457ddc9b1aSDarren Reed
8467ddc9b1aSDarren Reed return (-1);
8477ddc9b1aSDarren Reed }
8487ddc9b1aSDarren Reed
8497ddc9b1aSDarren Reed netid_t
net_getnetidbynetstackid(netstackid_t netstackid)8507ddc9b1aSDarren Reed net_getnetidbynetstackid(netstackid_t netstackid)
8517ddc9b1aSDarren Reed {
8527ddc9b1aSDarren Reed neti_stack_t *nts;
8537ddc9b1aSDarren Reed
8547ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
8557ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
8567ddc9b1aSDarren Reed if (nts->nts_stackid == netstackid) {
8577ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8587ddc9b1aSDarren Reed return (nts->nts_id);
8597ddc9b1aSDarren Reed }
8607ddc9b1aSDarren Reed }
8617ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8627ddc9b1aSDarren Reed
8637ddc9b1aSDarren Reed return (-1);
8647ddc9b1aSDarren Reed }
8657ddc9b1aSDarren Reed
8667ddc9b1aSDarren Reed neti_stack_t *
net_getnetistackbyid(netid_t netid)8677ddc9b1aSDarren Reed net_getnetistackbyid(netid_t netid)
8687ddc9b1aSDarren Reed {
8697ddc9b1aSDarren Reed neti_stack_t *nts;
8707ddc9b1aSDarren Reed
8717ddc9b1aSDarren Reed mutex_enter(&neti_stack_lock);
8727ddc9b1aSDarren Reed LIST_FOREACH(nts, &neti_stack_list, nts_next) {
8737ddc9b1aSDarren Reed if (nts->nts_id == netid) {
8747ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8757ddc9b1aSDarren Reed return (nts);
8767ddc9b1aSDarren Reed }
8777ddc9b1aSDarren Reed }
8787ddc9b1aSDarren Reed mutex_exit(&neti_stack_lock);
8797ddc9b1aSDarren Reed
8807ddc9b1aSDarren Reed return (NULL);
8817ddc9b1aSDarren Reed }
8827ddc9b1aSDarren Reed
8837ddc9b1aSDarren Reed int
net_instance_notify_register(netid_t netid,hook_notify_fn_t callback,void * arg)8847ddc9b1aSDarren Reed net_instance_notify_register(netid_t netid, hook_notify_fn_t callback,
8857ddc9b1aSDarren Reed void *arg)
8867ddc9b1aSDarren Reed {
8877ddc9b1aSDarren Reed
8887ddc9b1aSDarren Reed return (hook_stack_notify_register(net_getnetstackidbynetid(netid),
8897ddc9b1aSDarren Reed callback, arg));
8907ddc9b1aSDarren Reed }
8917ddc9b1aSDarren Reed
8927ddc9b1aSDarren Reed int
net_instance_notify_unregister(netid_t netid,hook_notify_fn_t callback)8937ddc9b1aSDarren Reed net_instance_notify_unregister(netid_t netid, hook_notify_fn_t callback)
8947ddc9b1aSDarren Reed {
8957ddc9b1aSDarren Reed
8967ddc9b1aSDarren Reed return (hook_stack_notify_unregister(net_getnetstackidbynetid(netid),
8977ddc9b1aSDarren Reed callback));
8987ddc9b1aSDarren Reed }
899