/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
static void neti_apply_all_stacks(void *, napplyfn_t *);
void
{
/*
* We want to be informed each time a netstack is created or
* destroyed in the kernel.
*/
}
void
{
}
/*
* Initialize the neti stack instance. Because this is called out of the
* netstack framework, it is not possible for it to be called twice with
* the same values for (stackid,ns). The same also applies to the other
* two functions used with netstack_register: neti_stack_shutdown and
* neti_stack_fini.
*/
static void *
{
/*
* This function returns with the NSS_CREATE_NEEDED flag
* set in "dup", so it is adequately prepared for the
* upcoming apply.
*/
}
return (nts);
}
/*
* Run the shutdown for all of the hooks.
*/
/*ARGSUSED*/
static void
{
/*
* Walk through all of the protocol stacks and mark them as shutting
* down.
*/
}
/*
* Now proceed to see which callbacks are waiting to hear about the
* impending shutdown...
*/
/*
* If there is no shutdown function registered,
* fake that we have completed it.
*/
n->nini_flags |= NSS_SHUTDOWN_COMPLETED;
continue;
}
/*
* We need to ensure that we don't try and shutdown something
* that is already in the process of being shutdown or
* destroyed. If it is still being created, that's ok, the
* shtudown flag is added to the mix of things to do.
*/
n->nini_flags |= NSS_SHUTDOWN_NEEDED;
}
}
/*
* Free the neti stack instance.
* This function relies on the netstack framework only calling the _destroy
* callback once for each stackid. The netstack framework also provides us
* with assurance that nobody else will be doing any work (_create, _shutdown)
* on it, so there is no need to set and use flags to guard against
* simultaneous execution (ie. no need to set NSF_CLOSING.)
* What is required, however, is to make sure that we don't corrupt the
* list of neti_stack_t's for other code that walks it.
*/
/*ARGSUSED*/
static void
{
/*
* Walk through all of the protocol stacks and mark them as being
* destroyed.
*/
}
if ((n->nini_flags & NSS_DESTROY_ALL) == 0)
n->nini_flags |= NSS_DESTROY_NEEDED;
}
LIST_REMOVE(n, nini_next);
}
}
static net_instance_int_t *
{
/*
* If the parent pointer is non-NULL then we take that as
* an indication that the net_instance_int_t is being
* created for an active instance and there will expect
* the create function to be called. In contrast, if
* parent is NULL then this code assumes the object is
* being prepared for insertion onto the master list of
* callbacks to be called when an instance is created, etc.
*/
}
return (nini);
}
/*
* Free'ing of a net_instance_int_t is only to be done when we know nobody
* else has is using it. For both parents and clones, this is indicated by
* nini_ref being greater than 0, however, nini_ref is managed differently
* for its two uses. For parents, nini_ref is increased when a new clone is
* created and it is decremented here. For clones, nini_ref is adjusted by
* code elsewhere (e.g. in neti_stack_apply_*) and is not changed here.
*/
static void
{
/*
* This mutex guards the use of nini_ref.
*/
/*
* For 'parent' structures, nini_ref will drop to 0 when
* the last clone has been free'd... but for clones, it
* is possible for nini_ref to be non-zero if we get in
* here when all the locks have been given up to execute
* a callback or wait_for_nini_inprogress. In that case,
* we do not want to free the structure and just indicate
* that it is on the "doomed" list, thus we set the
* condemned flag.
*/
}
}
}
{
if (version != NETINFO_VERSION)
return (NULL);
return (nin);
}
void
{
}
int
{
return (DDI_FAILURE);
/*
* Search for duplicate, either on the global list or on any
* of the known instances.
*/
return (DDI_FAILURE);
}
}
/*
* Now insert and activate.
*/
/*
* If shutdown of the zone has begun then do not add a new
* instance of the object being registered.
*/
continue;
}
/*
* This function returns with the NSS_CREATE_NEEDED flag
* set in "dup", so it is adequately prepared for the
* upcoming apply.
*/
}
return (DDI_SUCCESS);
}
/*
* While net_instance_register() isn't likely to be racing against itself,
* net_instance_unregister() can be entered from various directions that
* can compete: shutdown of a zone, unloading of a module (and it calling
* _unregister() as part of that) and the module doing an _unregister()
* anyway.
*/
int
{
break;
}
}
return (DDI_FAILURE);
}
continue;
/*
* Netstack difference:
* In netstack.c, there is a check for
* NSS_CREATE_COMPLETED before setting the other
* _NEEDED flags. If we consider that a list
* member must always have at least the _CREATE_NEEDED
* flag set and that wait_for_nini_inprogress will
* also wait for that flag to be cleared in both of
* the shutdown and destroy apply functions.
*
* It is possible to optimize out the case where
* all three _NEEDED flags are set to being able
* to pretend everything has been done and just
* set all three _COMPLETE flags. This makes a
* special case that we then need to consider in
* other locations, so for the sake of simplicity,
* we leave it as it is.
*/
break;
}
}
/*
* Each of these functions ensures that the requisite _COMPLETED
* flag is present before calling the apply function. So we are
* guaranteed to have NSS_CREATE_COMPLETED|NSS_SHUTDOWN_COMPLETED
* both set after the first call here and when the second completes,
* NSS_DESTROY_COMPLETED is also set.
*/
/*
* Remove the instance callback information from each stack.
*/
/*
* There should only be one entry that has a
* matching nini_parent so there is no need to
* worry about continuing a loop where we are
* free'ing the structure holding the 'next'
* pointer.
*/
break;
}
}
}
return (DDI_SUCCESS);
}
static void
{
while (n != NULL) {
/* Lock dropped - restart at head */
} else {
}
}
}
static void
{
/*
* This function differs, in that it doesn't have a call to
* waiting is pushed into the apply functions which cause
* the waiting to be done in wait_for_nini_progress with
* the passing in of cmask.
*/
/* Lock dropped - restart at head */
} else {
}
}
}
static boolean_t
{
void *result;
break;
}
return (dropped);
}
neti_stack_t *, nts);
}
if (tmp->nini_condemned) {
}
return (dropped);
}
static boolean_t
{
break;
}
return (dropped);
}
/*
* If there is no shutdown function, fake having completed it.
*/
}
if (tmp->nini_condemned) {
}
return (dropped);
}
neti_stack_t *, nts);
neti_stack_t *, nts);
}
if (tmp->nini_condemned) {
}
return (dropped);
}
static boolean_t
{
break;
}
return (dropped);
}
/*
* We pause here so that when we continue we know that we're the
* only one doing anything active with this node.
*/
neti_stack_t *, nts);
neti_stack_t *, nts);
}
if (tmp->nini_condemned) {
}
return (dropped);
}
static boolean_t
{
/* First drop netstack_lock to preserve order */
}
return (dropped);
}
/* ======================================================================= */
{
}
}
return (-1);
}
{
return (nts->nts_zoneid);
}
}
return (-1);
}
{
return (nts->nts_stackid);
}
}
return (-1);
}
{
}
}
return (-1);
}
{
return (nts);
}
}
return (NULL);
}
int
void *arg)
{
}
int
{
callback));
}