netstack.c revision f4b3ec61df05330d25f55a36b975b4d7519fdeb1
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * CDDL HEADER START
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * The contents of this file are subject to the terms of the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Common Development and Distribution License (the "License").
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * You may not use this file except in compliance with the License.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * See the License for the specific language governing permissions
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * and limitations under the License.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * When distributing Covered Code, include this CDDL HEADER in each
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If applicable, add the following below this CDDL HEADER, with the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * fields enclosed by brackets "[]" replaced with your own identifying
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * information: Portions Copyright [yyyy] [name of copyright owner]
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * CDDL HEADER END
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Use is subject to license terms.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh#pragma ident "%Z%%M% %I% %E% SMI"
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * What we use so that the zones framework can tell us about new zones,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * which we use to create new stacks.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic int netstack_initialized = 0;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Track the registered netstacks.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * The global lock protects
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - ns_reg
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - the list starting at netstack_head and following the netstack_next
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * pointers.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Registry of netstacks with their create/shutdown/destory functions.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Global list of existing stacks. We use this when a new zone with
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * an exclusive IP instance is created.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note that in some cases a netstack_t needs to stay around after the zone
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * has gone away. This is because there might be outstanding references
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * (from TCP TIME_WAIT connections, IPsec state, etc). The netstack_t data
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * structure and all the foo_stack_t's hanging off of it will be cleaned up
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * when the last reference to it is dropped.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * However, the same zone might be rebooted. That is handled using the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * assumption that the zones framework picks a new zoneid each time a zone
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * is (re)booted. We assert for that condition in netstack_zone_create().
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Thus the old netstack_t can take its time for things to time out.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * To support kstat_create_netstack() using kstat_zone_add we need
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * to track both
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - all zoneids that use the global/shared stack
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - all kstats that have been added for the shared stack
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic kmutex_t netstack_shared_lock; /* protects the following two */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void netstack_zone_shutdown(zoneid_t zoneid, void *arg);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void netstack_zone_destroy(zoneid_t zoneid, void *arg);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void netstack_do_create(void);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void netstack_do_shutdown(void);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void netstack_do_destroy(void);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh mutex_init(&netstack_shared_lock, NULL, MUTEX_DEFAULT, NULL);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * We want to be informed each time a zone is created or
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * destroyed in the kernel, so we can maintain the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * stack instance information.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh zone_key_create(&netstack_zone_key, netstack_zone_create,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Register a new module with the framework.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * This registers interest in changes to the set of netstacks.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * The createfn and destroyfn are required, but the shutdownfn can be
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note that due to the current zsd implementation, when the create
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * function is called the zone isn't fully present, thus functions
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * like zone_find_by_* will fail, hence the create function can not
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * use many zones kernel functions including zcmn_err().
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Determine the set of stacks that exist before we drop the lock.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set CREATE_NEEDED for each of those.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstacks which have been deleted will have NSS_CREATE_COMPLETED
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * set, but check NSF_CLOSING to be sure.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh (ns->netstack_m_state[moduleid] & NSS_CREATE_ALL) == 0) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the create function for each stack that has CREATE_NEEDED.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set CREATE_INPROGRESS, drop lock, and after done,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * set CREATE_COMPLETE
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Determine the set of stacks that exist before we drop the lock.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set SHUTDOWN_NEEDED and DESTROY_NEEDED for each of those.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh (ns->netstack_m_state[moduleid] & NSS_CREATE_COMPLETED) &&
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh (ns->netstack_m_state[moduleid] & NSS_SHUTDOWN_ALL) == 0) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh (ns->netstack_m_state[moduleid] & NSS_CREATE_COMPLETED) &&
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh (ns->netstack_m_state[moduleid] & NSS_DESTROY_ALL) == 0) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Clear the netstack_m_state so that we can handle this module
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * being loaded again.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ns->netstack_m_state[moduleid] & NSS_DESTROY_COMPLETED) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Lookup and/or allocate a netstack for this zone.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void *
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Look for the stack instance for the global */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Allocate even if it isn't needed; simplifies locking */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns = (netstack_t *)kmem_zalloc(sizeof (netstack_t), KM_SLEEP);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Look if there is a matching stack instance */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Should never find a pre-existing exclusive stack
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Record that we have a new shared stack zone */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Not found */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh mutex_init(&ns->netstack_lock, NULL, MUTEX_DEFAULT, NULL);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns->netstack_refcnt = 1; /* Decremented by netstack_zone_destroy */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Determine the set of module create functions that need to be
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * called before we drop the lock.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (i = 0; i < NS_MAX; i++) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh/* ARGSUSED */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Stack instance being used by other zone */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Determine the set of stacks that exist before we drop the lock.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set SHUTDOWN_NEEDED for each of those.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (i = 0; i < NS_MAX; i++) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Call the shutdown function for all registered modules */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Common routine to release a zone.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If this was the last zone using the stack instance then prepare to
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * have the refcnt dropping to zero free the zone.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh/* ARGSUSED */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Stack instance being used by other zone */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Record that we a shared stack zone has gone away */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set CLOSING so that netstack_find_by will not find it
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * and decrement the reference count.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh DTRACE_PROBE1(netstack__dec__numzones, netstack_t *, ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* No other thread can call zone_destroy for this stack */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Decrease refcnt to account for the one in netstack_zone_init()
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Called when the reference count drops to zero.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the destroy functions for each registered module.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If the shutdown callback wasn't called earlier (e.g., if this is
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * a netstack shared between multiple zones), then we call it now.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (i = 0; i < NS_MAX; i++) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Determine the set of stacks that exist before we drop the lock.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set DESTROY_NEEDED for each of those.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (i = 0; i < NS_MAX; i++) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the create function for the ns and moduleid if CREATE_NEEDED
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * When it calls it, it drops the netstack_lock held by the caller,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * and returns true to tell the caller it needs to re-evalute the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhnetstack_apply_create(kmutex_t *lockp, netstack_t *ns, int moduleid)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ns->netstack_m_state[moduleid] & NSS_CREATE_NEEDED) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns->netstack_m_state[moduleid] &= ~NSS_CREATE_INPROGRESS;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the shutdown function for the ns and moduleid if SHUTDOWN_NEEDED
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * When it calls it, it drops the netstack_lock held by the caller,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * and returns true to tell the caller it needs to re-evalute the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhnetstack_apply_shutdown(kmutex_t *lockp, netstack_t *ns, int moduleid)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ns->netstack_m_state[moduleid] & NSS_SHUTDOWN_NEEDED) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns->netstack_m_state[moduleid] |= NSS_SHUTDOWN_INPROGRESS;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh (ns_reg[moduleid].nr_shutdown)(stackid, netstack_module);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns->netstack_m_state[moduleid] &= ~NSS_SHUTDOWN_INPROGRESS;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns->netstack_m_state[moduleid] |= NSS_SHUTDOWN_COMPLETED;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the destroy function for the ns and moduleid if DESTROY_NEEDED
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * When it calls it, it drops the netstack_lock held by the caller,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * and returns true to tell the caller it needs to re-evalute the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhnetstack_apply_destroy(kmutex_t *lockp, netstack_t *ns, int moduleid)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (ns->netstack_m_state[moduleid] & NSS_DESTROY_NEEDED) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns->netstack_m_state[moduleid] |= NSS_DESTROY_INPROGRESS;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* XXX race against unregister? */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh ns->netstack_m_state[moduleid] &= ~NSS_DESTROY_INPROGRESS;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh boolean_t (*applyfn)(kmutex_t *, netstack_t *, int moduleid))
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (i = 0; i < NS_MAX; i++) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh "LD for %p/%d, %d\n",
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If at least one applyfn call caused lockp to be dropped,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * then we don't follow netstack_next after reacquiring the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * lock, even if it is possible to do so without any hazards.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * This is because we want the design to allow for the list of
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstacks threaded by netstack_next to change in any
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * arbitrary way during the time the 'lockp' was dropped.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * It is safe to restart the loop at *headp since
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * the applyfn changes netstack_m_state as it processes
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * things, so a subsequent pass through will have no
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * effect in applyfn, hence the loop will terminate
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * in at worst O(N^2).
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh "Lock Dropped for %p/%d, %d\n",
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh/* Like above, but in the reverse order of moduleids */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh boolean_t (*applyfn)(kmutex_t *, netstack_t *, int moduleid))
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh "LD for %p/%d, %d\n",
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If at least one applyfn call caused lockp to be dropped,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * then we don't follow netstack_next after reacquiring the
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * lock, even if it is possible to do so without any hazards.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * This is because we want the design to allow for the list of
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstacks threaded by netstack_next to change in any
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * arbitrary way during the time the 'lockp' was dropped.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * It is safe to restart the loop at *headp since
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * the applyfn changes netstack_m_state as it processes
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * things, so a subsequent pass through will have no
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * effect in applyfn, hence the loop will terminate
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * in at worst O(N^2).
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh "Lock Dropped for %p/%d, %d\n",
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Apply a function to all module/netstack combinations.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * The applyfn returns true if it had dropped the locks.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh boolean_t (*applyfn)(kmutex_t *, netstack_t *, int moduleid))
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh apply_loop_reverse(&netstack_head, &netstack_g_lock, applyfn);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Run the create function for all modules x stack combinations
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * that have NSS_CREATE_NEEDED set.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the create function for each stack that has CREATE_NEEDED.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set CREATE_INPROGRESS, drop lock, and after done,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * set CREATE_COMPLETE
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Run the shutdown function for all modules x stack combinations
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * that have NSS_SHUTDOWN_NEEDED set.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the shutdown function for each stack that has SHUTDOWN_NEEDED.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set SHUTDOWN_INPROGRESS, drop lock, and after done,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * set SHUTDOWN_COMPLETE
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Run the destroy function for all modules x stack combinations
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * that have NSS_DESTROY_NEEDED set.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Call the destroy function for each stack that has DESTROY_NEEDED.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Set DESTROY_INPROGRESS, drop lock, and after done,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * set DESTROY_COMPLETE
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Since a netstack_t is never reused (when a zone is rebooted it gets
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * a new zoneid == netstackid i.e. a new netstack_t is allocated) we leave
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_m_state the way it is i.e. with NSS_DESTROY_COMPLETED set.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Have to walk the moduleids in reverse order since some
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * modules make implicit assumptions about the order
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Get the stack instance used in caller's zone.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Increases the reference count, caller must do a netstack_rele.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * It can't be called after zone_destroy() has started.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Find a stack instance given the cred.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * This is used by the modules to potentially allow for a future when
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * something other than the zoneid is used to determine the stack.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Handle the case when cr_zone is NULL */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* For performance ... */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Find a stack instance given the zoneid.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Increases the reference count if found; caller must do a
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_rele().
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If there is no exact match then assume the shared stack instance
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * matches.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Skip the unitialized ones.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Find a stack instance given the zoneid.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Increases the reference count if found; caller must do a
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_rele().
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If there is no exact match then assume the shared stack instance
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * matches.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Skip the unitialized ones.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * NOTE: The caller must hold zonehash_lock.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Find a stack instance given the stackid with exact match?
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Increases the reference count if found; caller must do a
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_rele().
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Skip the unitialized ones.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * As we drop the lock additional netstack_rele()s can come in
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * and decrement the refcnt to zero and free the netstack_t.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Store pointers in local variables and if we were not the last
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * then don't reference the netstack_t after that.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Time to call the destroy functions and free up
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * the structure
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Finally remove from list of netstacks */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * To support kstat_create_netstack() using kstat_zone_add we need
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * to track both
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - all zoneids that use the global/shared stack
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - all kstats that have been added for the shared stack
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhkstat_create_netstack(char *ks_module, int ks_instance, char *ks_name,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ks);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (kstat_create_zone(ks_module, ks_instance, ks_name,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhkstat_delete_netstack(kstat_t *ks, netstackid_t ks_netstackid)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh sz = (struct shared_zone_list *)kmem_zalloc(sizeof (*sz), KM_SLEEP);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Insert in list */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Perform kstat_zone_add for each existing shared stack kstat.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note: Holds netstack_shared_lock lock across kstat_zone_add.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (sk = netstack_shared_kstats; sk != NULL; sk = sk->sk_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Find in list */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* We must find it */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Perform kstat_zone_remove for each existing shared stack kstat.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note: Holds netstack_shared_lock lock across kstat_zone_remove.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (sk = netstack_shared_kstats; sk != NULL; sk = sk->sk_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh sk = (struct shared_kstat_list *)kmem_zalloc(sizeof (*sk), KM_SLEEP);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Insert in list */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Perform kstat_zone_add for each existing shared stack zone.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note: Holds netstack_shared_lock lock across kstat_zone_add.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (sz = netstack_shared_zones; sz != NULL; sz = sz->sz_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dhstatic void
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Find in list */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Must find it */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Perform kstat_zone_remove for each existing shared stack kstat.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Note: Holds netstack_shared_lock lock across kstat_zone_remove.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (sz = netstack_shared_zones; sz != NULL; sz = sz->sz_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * If a zoneid is part of the shared zone, return true
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (sz = netstack_shared_zones; sz != NULL; sz = sz->sz_next) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Hide the fact that zoneids and netstackids are allocated from
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * the same space in the current implementation.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * XXX could add checks that the stackid/zoneids are valid...
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Simplistic support for walking all the handles.
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * Example usage:
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_handle_t nh;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_t *ns;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_next_init(&nh);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * while ((ns = netstack_next(&nh)) != NULL) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * do something;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_rele(ns);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * netstack_next_fini(&nh);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh/* ARGSUSED */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Walk skipping *handle number of instances */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* Look if there is a matching stack instance */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh for (i = 0; i < end; i++) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* skip those with that aren't really here */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if ((ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING)) == 0) {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return (ns);