usr/src/uts/common/inet/inet_common.c
author masputra
Sat, 22 Oct 2005 22:50:14 -0700
changeset 741 40027a3621ac
parent 0 68f95e015346
child 5815 837c8cd4d6b6
permissions -rw-r--r--
PSARC 2005/082 Yosemite: UDP Performance Enhancement 4796051 Solaris needs a more complete HW checksumming support 4905227 duplicate macros in ipclassifier.h and ip.h 4915681 need hardware checksum offload for the case of IP/UDP reassembly 6201076 outbound flow-control dysfunctional, ip to ce using mdt 6223331 ipv6 flow control may corrupt UDP packets 6223809 16-bit aligned IP header should be allowed for all x86 platforms 6275398 Galaxy hangs when running lmbench 6281836 Yosemite project integration into Solaris 6281885 xge needs to support IPv6 checksum offload 6282776 IPv6 NCE fast path is not created for incoming solicitation 6304890 IP transmit-side checksum logic needs to be tightened 6304902 IP6_IN_NOCKSUM is obsolete and should be torched 6304904 UDP should reject TI_GETPEERNAME for non-connected endpoint 6306768 IP and UDP device and module definitions need to be centralized

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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
 * or http://www.opensolaris.org/os/licensing.
 * 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 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * Minor number allocation for various protocol modules.
 */

#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/mutex.h>
#include <sys/ddi.h>
#include <sys/types.h>
#include <sys/mkdev.h>
#include <sys/param.h>
#include <inet/common.h>

typedef struct inet_arena {
	vmem_t *ineta_arena;	/* Minor number arena */
	minor_t ineta_maxminor;	/* max minor number in the arena */
} inet_arena_t;

/* Maximum minor number to use */
static minor_t inet_maxminor = INET_MAXMINOR;

void *
inet_minor_create(char *name, dev_t min_dev, int kmflags)
{
	inet_arena_t *arena = kmem_alloc(sizeof (inet_arena_t), kmflags);

	if (arena != NULL) {
		arena->ineta_maxminor = MIN(MAXMIN32, inet_maxminor);
		arena->ineta_arena = vmem_create(name,
		    (void *)min_dev, arena->ineta_maxminor - min_dev + 1,
		    1, NULL, NULL, NULL, 1, kmflags | VMC_IDENTIFIER);

		if (arena->ineta_arena == NULL) {
			kmem_free(arena, sizeof (inet_arena_t));
			arena = NULL;
		}
	}

	return (arena);
}

void
inet_minor_destroy(void *a)
{
	inet_arena_t *arena = (inet_arena_t *)a;

	if (arena != NULL) {
		vmem_destroy(arena->ineta_arena);
		kmem_free(arena, sizeof (inet_arena_t));
	}
}

dev_t
inet_minor_alloc(void *a)
{
	inet_arena_t *arena = (inet_arena_t *)a;
	dev_t dev;

	while ((dev = (dev_t)vmem_alloc(arena->ineta_arena, 1,
		    VM_NOSLEEP)) == 0) {
		if (arena->ineta_maxminor >= inet_maxminor)
			return (0);
		if (vmem_add(arena->ineta_arena,
		    (void *)(uintptr_t)(arena->ineta_maxminor + 1),
		    inet_maxminor - arena->ineta_maxminor, VM_NOSLEEP) == NULL)
			return (0);
		arena->ineta_maxminor = inet_maxminor;
	}
	return (dev);
}

void
inet_minor_free(void *a, dev_t dev)
{
	ASSERT((dev != OPENFAIL) && (dev != 0) && (dev <= inet_maxminor));
	vmem_free(((inet_arena_t *)a)->ineta_arena, (void *)dev, 1);
}

/*
 * This function is used to free a message that has gone through
 * mi_copyin processing which modifies the M_IOCTL mblk's b_next
 * and b_prev pointers. We use this function to set b_next/b_prev
 * to NULL and free them.
 */
void
inet_freemsg(mblk_t *mp)
{
	mblk_t	*bp = mp;

	for (; bp != NULL; bp = bp->b_cont) {
		bp->b_prev = NULL;
		bp->b_next = NULL;
	}
	freemsg(mp);
}