usr/src/uts/common/inet/ip/ip_ndp.c
author masputra
Sat, 22 Oct 2005 22:50:14 -0700
changeset 741 40027a3621ac
parent 0 68f95e015346
child 980 253cff0301e4
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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
#include <sys/stream.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#include <sys/stropts.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/strlog.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/dlpi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/sockio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/tiuser.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/tihdr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/socket.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/ddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/vtrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/zone.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <net/if.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <net/if_types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <net/if_dl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <net/route.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/sockio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <netinet/in.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <netinet/in_systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <netinet/ip6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <netinet/icmp6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include <inet/common.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <inet/mi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <inet/mib2.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <inet/nd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <inet/arp.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <inet/ip.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <inet/ip_multi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <inet/ip_if.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <inet/ip_ire.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#include <inet/ip_rts.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <inet/ip6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <inet/ip_ndp.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
#include <inet/ipsec_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <inet/ipsec_info.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
 * Function names with nce_ prefix are static while function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
 * names with ndp_ prefix are used by rest of the IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
static	boolean_t nce_cmp_ll_addr(nce_t *nce, char *new_ll_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
    uint32_t ll_addr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
static	void	nce_fastpath(nce_t *nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
static	void	nce_ire_delete(nce_t *nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
static	void	nce_ire_delete1(ire_t *ire, char *nce_arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
static	void 	nce_set_ll(nce_t *nce, uchar_t *ll_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
static	nce_t	*nce_lookup_addr(ill_t *ill, const in6_addr_t *addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
static	nce_t	*nce_lookup_mapping(ill_t *ill, const in6_addr_t *addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
static	void	nce_make_mapping(nce_t *nce, uchar_t *addrpos,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
    uchar_t *addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
static	int	nce_set_multicast(ill_t *ill, const in6_addr_t *addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
static	void	nce_queue_mp(nce_t *nce, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
static	void	nce_report1(nce_t *nce, uchar_t *mp_arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
static	mblk_t	*nce_udreq_alloc(ill_t *ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
static	void	nce_update(nce_t *nce, uint16_t new_state,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
    uchar_t *new_ll_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
static	uint32_t	nce_solicit(nce_t *nce, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
static	boolean_t	nce_xmit(ill_t *ill, uint32_t operation,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
    ill_t *hwaddr_ill, boolean_t use_lla_addr, const in6_addr_t *sender,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
    const in6_addr_t *target, int flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
static	void	lla2ascii(uint8_t *lla, int addrlen, uchar_t *buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
extern void	th_trace_rrecord(th_trace_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
#ifdef NCE_DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
void	nce_trace_inactive(nce_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
/* NDP Cache Entry Hash Table */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
#define	NCE_TABLE_SIZE	256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
static	nce_t	*nce_hash_tbl[NCE_TABLE_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
static	nce_t	*nce_mask_entries;	/* mask not all ones */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
static	int	ndp_g_walker = 0;	/* # of active thread */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
					/* walking nce hash list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
/* ndp_g_walker_cleanup will be true, when deletion have to be defered */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
static	boolean_t	ndp_g_walker_cleanup = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
#ifdef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
#define	IN6_IS_ADDR_MC_SOLICITEDNODE(addr) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	((((addr)->s6_addr32[0] & 0xff020000) == 0xff020000) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
	((addr)->s6_addr32[1] == 0x0) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	((addr)->s6_addr32[2] == 0x00000001) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
	((addr)->s6_addr32[3] & 0xff000000) == 0xff000000)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
#else	/* _BIG_ENDIAN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
#define	IN6_IS_ADDR_MC_SOLICITEDNODE(addr) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	((((addr)->s6_addr32[0] & 0x000002ff) == 0x000002ff) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	((addr)->s6_addr32[1] == 0x0) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
	((addr)->s6_addr32[2] == 0x01000000) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
	((addr)->s6_addr32[3] & 0x000000ff) == 0x000000ff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
#define	NCE_HASH_PTR(addr) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
	(&(nce_hash_tbl[NCE_ADDR_HASH_V6(addr, NCE_TABLE_SIZE)]))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
 * NDP Cache Entry creation routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 * Mapped entries will never do NUD .
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 * This routine must always be called with ndp_g_lock held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 * Prior to return, nce_refcnt is incremented.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
ndp_add(ill_t *ill, uchar_t *hw_addr, const in6_addr_t *addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
    const in6_addr_t *mask, const in6_addr_t *extract_mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
    uint32_t hw_extract_start, uint16_t flags, uint16_t state,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
    nce_t **newnce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
static	nce_t		nce_nil;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	nce_t		*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	mblk_t		*template;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	nce_t		**ncep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	boolean_t	dropped = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
	ASSERT(MUTEX_HELD(&ndp_g_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
	if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
		ip0dbg(("ndp_add: no addr\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
	if ((flags & ~NCE_EXTERNAL_FLAGS_MASK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
		ip0dbg(("ndp_add: flags = %x\n", (int)flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	if (IN6_IS_ADDR_UNSPECIFIED(extract_mask) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	    (flags & NCE_F_MAPPING)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
		ip0dbg(("ndp_add: extract mask zero for mapping"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	 * Allocate the mblk to hold the nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	 * XXX This can come out of a separate cache - nce_cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
	 * We don't need the mp anymore as there are no more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
	 * "qwriter"s
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
	mp = allocb(sizeof (nce_t), BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
		return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	nce = (nce_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
	mp->b_wptr = (uchar_t *)&nce[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	*nce = nce_nil;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	 * This one holds link layer address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
	if (ill->ill_net_type == IRE_IF_RESOLVER) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
		template = nce_udreq_alloc(ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
		ASSERT((ill->ill_net_type == IRE_IF_NORESOLVER));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
		ASSERT((ill->ill_resolver_mp != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
		template = copyb(ill->ill_resolver_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
	if (template == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
		freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
		return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	nce->nce_ill = ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
	nce->nce_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
	nce->nce_state = state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
	nce->nce_pcnt = ND_MAX_UNICAST_SOLICIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	nce->nce_rcnt = ill->ill_xmit_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
	nce->nce_addr = *addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
	nce->nce_mask = *mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
	nce->nce_extract_mask = *extract_mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	nce->nce_ll_extract_start = hw_extract_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	nce->nce_fp_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	nce->nce_res_mp = template;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	if (state == ND_REACHABLE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
		nce->nce_last = TICK_TO_MSEC(lbolt64);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
		nce->nce_last = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	nce->nce_qd_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	nce->nce_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
	if (hw_addr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
		nce_set_ll(nce, hw_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
	/* This one is for nce getting created */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	nce->nce_refcnt = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	mutex_init(&nce->nce_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	if (nce->nce_flags & NCE_F_MAPPING) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
		ASSERT(IN6_IS_ADDR_MULTICAST(addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
		ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&nce->nce_mask));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
		ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&nce->nce_extract_mask));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
		ncep = &nce_mask_entries;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
		ncep = ((nce_t **)NCE_HASH_PTR(*addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
#ifdef NCE_DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
	bzero(nce->nce_trace, sizeof (th_trace_t *) * IP_TR_HASH_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
	 * Atomically ensure that the ill is not CONDEMNED, before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
	 * adding the NCE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
	mutex_enter(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
	if (ill->ill_state_flags & ILL_CONDEMNED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
		mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
		freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
	if ((nce->nce_next = *ncep) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
		nce->nce_next->nce_ptpn = &nce->nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
	*ncep = nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
	nce->nce_ptpn = ncep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
	*newnce = nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
	/* This one is for nce being used by an active thread */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
	NCE_REFHOLD(*newnce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
	/* Bump up the number of nce's referencing this ill */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
	ill->ill_nce_cnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
	mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
	 * Before we insert the nce, honor the UNSOL_ADV flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
	 * We cannot hold the ndp_g_lock and call nce_xmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
	 * which does a putnext.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	if (flags & NCE_F_UNSOL_ADV) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
		flags |= NDP_ORIDE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
		 * We account for the transmit below by assigning one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
		 * less than the ndd variable. Subsequent decrements
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
		 * are done in ndp_timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
		nce->nce_unsolicit_count = ip_ndp_unsolicit_count - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
		dropped = nce_xmit(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
		    ND_NEIGHBOR_ADVERT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
		    ill,	/* ill to be used for extracting ill_nd_lla */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
		    B_TRUE,	/* use ill_nd_lla */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
		    addr,	/* Source and target of the advertisement pkt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
		    &ipv6_all_hosts_mcast, /* Destination of the packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
		    flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
		if (dropped)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
			nce->nce_unsolicit_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
		if (nce->nce_unsolicit_count != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
			nce->nce_timeout_id = timeout(ndp_timer, nce,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
			    MSEC_TO_TICK(ip_ndp_unsolicit_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
		mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   282
	/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   283
	 * If the hw_addr is NULL, typically for ND_INCOMPLETE nces, then
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   284
	 * we call nce_fastpath as soon as the nce is resolved in ndp_process.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   285
	 * We call nce_fastpath from nce_update if the link layer address of
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   286
	 * the peer changes from nce_update
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   287
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   288
	if (hw_addr != NULL || ill->ill_net_type == IRE_IF_NORESOLVER)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   289
		nce_fastpath(nce);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   290
	return (0);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
ndp_lookup_then_add(ill_t *ill, uchar_t *hw_addr, const in6_addr_t *addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
    const in6_addr_t *mask, const in6_addr_t *extract_mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
    uint32_t hw_extract_start, uint16_t flags, uint16_t state,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
    nce_t **newnce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
	int	err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
	nce_t	*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
	mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
	nce = nce_lookup_addr(ill, addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
	if (nce == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
		err = ndp_add(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
		    hw_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
		    addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
		    mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
		    extract_mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
		    hw_extract_start,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
		    flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
		    state,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
		    newnce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
		*newnce = nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
		err = EEXIST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
 * Remove all the CONDEMNED nces from the appropriate hash table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
 * We create a private list of NCEs, these may have ires pointing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
 * to them, so the list will be passed through to clean up dependent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
 * ires and only then we can do NCE_REFRELE which can make NCE inactive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
nce_remove(nce_t *nce, nce_t **free_nce_list)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
	nce_t *nce1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
	nce_t **ptpn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
	ASSERT(MUTEX_HELD(&ndp_g_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
	ASSERT(ndp_g_walker == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
	for (; nce; nce = nce1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
		nce1 = nce->nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
		if (nce->nce_flags & NCE_F_CONDEMNED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
			ptpn = nce->nce_ptpn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
			nce1 = nce->nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
			if (nce1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
				nce1->nce_ptpn = ptpn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
			*ptpn = nce1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
			nce->nce_ptpn = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
			nce->nce_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
			nce->nce_next = *free_nce_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
			*free_nce_list = nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
 * 1. Mark the nce CONDEMNED. This ensures that no new nce_lookup()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
 *    will return this NCE. Also no new IREs will be created that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
 *    point to this NCE (See ire_add_v6).  Also no new timeouts will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
 *    be started (See NDP_RESTART_TIMER).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
 * 2. Cancel any currently running timeouts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
 * 3. If there is an ndp walker, return. The walker will do the cleanup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
 *    This ensures that walkers see a consistent list of NCEs while walking.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
 * 4. Otherwise remove the NCE from the list of NCEs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
 * 5. Delete all IREs pointing to this NCE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
ndp_delete(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	nce_t	**ptpn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
	nce_t	*nce1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
	/* Serialize deletes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
	if (nce->nce_flags & NCE_F_CONDEMNED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
		/* Some other thread is doing the delete */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	 * Caller has a refhold. Also 1 ref for being in the list. Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
	 * refcnt has to be >= 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	ASSERT(nce->nce_refcnt >= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
	nce->nce_flags |= NCE_F_CONDEMNED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
	nce_fastpath_list_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
	 * Cancel any running timer. Timeout can't be restarted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
	 * since CONDEMNED is set. Can't hold nce_lock across untimeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	 * Passing invalid timeout id is fine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
	if (nce->nce_timeout_id != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
		(void) untimeout(nce->nce_timeout_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
		nce->nce_timeout_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	if (nce->nce_ptpn == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
		 * The last ndp walker has already removed this nce from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
		 * the list after we marked the nce CONDEMNED and before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
		 * we grabbed the ndp_g_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
	if (ndp_g_walker > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
		 * Can't unlink. The walker will clean up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
		ndp_g_walker_cleanup = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
	 * Now remove the nce from the list. NDP_RESTART_TIMER won't restart
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
	 * the timer since it is marked CONDEMNED.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
	ptpn = nce->nce_ptpn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
	nce1 = nce->nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
	if (nce1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
		nce1->nce_ptpn = ptpn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
	*ptpn = nce1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	nce->nce_ptpn = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
	nce->nce_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
	mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
	nce_ire_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
ndp_inactive(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
	mblk_t		**mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
	ill_t		*ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
	ASSERT(nce->nce_refcnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
	ASSERT(nce->nce_fastpath == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
	/* Free all nce allocated messages */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
	mpp = &nce->nce_first_mp_to_free;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
		while (*mpp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
			mblk_t  *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
			mp = *mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
			*mpp = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
			mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
			mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
	} while (mpp++ != &nce->nce_last_mp_to_free);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
#ifdef NCE_DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
	nce_trace_inactive(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
	ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
	mutex_enter(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
	ill->ill_nce_cnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
	 * If the number of nce's associated with this ill have dropped
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
	 * to zero, check whether we need to restart any operation that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
	 * is waiting for this to happen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
	if (ill->ill_nce_cnt == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
		/* ipif_ill_refrele_tail drops the ill_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
		ipif_ill_refrele_tail(ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
		mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
	mutex_destroy(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
	freeb(nce->nce_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
 * ndp_walk routine.  Delete the nce if it is associated with the ill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
 * that is going away.  Always called as a writer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
ndp_delete_per_ill(nce_t *nce, uchar_t *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
	if ((nce != NULL) && nce->nce_ill == (ill_t *)arg) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
		ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
 * Walk a list of to be inactive NCEs and blow away all the ires.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
nce_ire_delete_list(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
	nce_t *nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	ASSERT(nce != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
	while (nce != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
		nce_next = nce->nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
		nce->nce_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
		 * It is possible for the last ndp walker (this thread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
		 * to come here after ndp_delete has marked the nce CONDEMNED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
		 * and before it has removed the nce from the fastpath list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
		 * or called untimeout. So we need to do it here. It is safe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
		 * for both ndp_delete and this thread to do it twice or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
		 * even simultaneously since each of the threads has a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
		 * reference on the nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
		nce_fastpath_list_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
		 * Cancel any running timer. Timeout can't be restarted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
		 * since CONDEMNED is set. Can't hold nce_lock across untimeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		 * Passing invalid timeout id is fine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
		if (nce->nce_timeout_id != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
			(void) untimeout(nce->nce_timeout_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
			nce->nce_timeout_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
		ire_walk_ill_v6(MATCH_IRE_ILL | MATCH_IRE_TYPE, IRE_CACHE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
		    nce_ire_delete1, (char *)nce, nce->nce_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
		NCE_REFRELE_NOTR(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
		nce = nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
 * Delete an ire when the nce goes away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
nce_ire_delete(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
	ire_walk_ill_v6(MATCH_IRE_ILL | MATCH_IRE_TYPE, IRE_CACHE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
	    nce_ire_delete1, (char *)nce, nce->nce_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
	NCE_REFRELE_NOTR(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
 * ire_walk routine used to delete every IRE that shares this nce
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
nce_ire_delete1(ire_t *ire, char *nce_arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
	nce_t	*nce = (nce_t *)nce_arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	ASSERT(ire->ire_type == IRE_CACHE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
	if (ire->ire_nce == nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
		ire_delete(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
 * Cache entry lookup.  Try to find an nce matching the parameters passed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
 * If one is found, the refcnt on the nce will be incremented.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
nce_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
ndp_lookup(ill_t *ill, const in6_addr_t *addr, boolean_t caller_holds_lock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
	nce_t	*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
	if (!caller_holds_lock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
		mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
	nce = nce_lookup_addr(ill, addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
	if (nce == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
		nce = nce_lookup_mapping(ill, addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	if (!caller_holds_lock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	return (nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
 * Cache entry lookup.  Try to find an nce matching the parameters passed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
 * Look only for exact entries (no mappings).  If an nce is found, increment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
 * the hold count on that nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
static nce_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
nce_lookup_addr(ill_t *ill, const in6_addr_t *addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
	nce_t	*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
	ASSERT(MUTEX_HELD(&ndp_g_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
	if (IN6_IS_ADDR_UNSPECIFIED(addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
	nce = *((nce_t **)NCE_HASH_PTR(*addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
	for (; nce != NULL; nce = nce->nce_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
		if (nce->nce_ill == ill) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
			if (IN6_ARE_ADDR_EQUAL(&nce->nce_addr, addr) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
			    IN6_ARE_ADDR_EQUAL(&nce->nce_mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
			    &ipv6_all_ones)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
				mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
				if (!(nce->nce_flags & NCE_F_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
					NCE_REFHOLD_LOCKED(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
					mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
				mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
	return (nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
 * Cache entry lookup.  Try to find an nce matching the parameters passed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
 * Look only for mappings.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
static nce_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
nce_lookup_mapping(ill_t *ill, const in6_addr_t *addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
	nce_t	*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
	ASSERT(MUTEX_HELD(&ndp_g_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
	if (!IN6_IS_ADDR_MULTICAST(addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
	nce = nce_mask_entries;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
	for (; nce != NULL; nce = nce->nce_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
		if (nce->nce_ill == ill &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
		    (V6_MASK_EQ(*addr, nce->nce_mask, nce->nce_addr))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
			mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
			if (!(nce->nce_flags & NCE_F_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
				NCE_REFHOLD_LOCKED(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
				mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
	return (nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
 * Process passed in parameters either from an incoming packet or via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
 * user ioctl.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
ndp_process(nce_t *nce, uchar_t *hw_addr, uint32_t flag, boolean_t is_adv)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
	ill_t	*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
	uint32_t hw_addr_len = ill->ill_nd_lla_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
	boolean_t ll_updated = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
	boolean_t ll_changed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
	 * No updates of link layer address or the neighbor state is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
	 * allowed, when the cache is in NONUD state.  This still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
	 * allows for responding to reachability solicitation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	if (nce->nce_state == ND_INCOMPLETE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
		if (hw_addr == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
		nce_set_ll(nce, hw_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
		 * Update nce state and send the queued packets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
		 * back to ip this time ire will be added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
		if (flag & ND_NA_FLAG_SOLICITED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
			nce_update(nce, ND_REACHABLE, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
			nce_update(nce, ND_STALE, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
		nce_fastpath(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
		mp = nce->nce_qd_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
		nce->nce_qd_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
		while (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
			mblk_t *nxt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
			nxt_mp = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
			mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
			if (mp->b_prev != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
				ill_t   *inbound_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
				queue_t *fwdq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
				uint_t ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
				ifindex = (uint_t)(uintptr_t)mp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
				inbound_ill = ill_lookup_on_ifindex(ifindex,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
				    B_TRUE, NULL, NULL, NULL, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
				if (inbound_ill == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
					mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
					fwdq = inbound_ill->ill_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
				mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
				 * Send a forwarded packet back into ip_rput_v6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
				 * just as in ire_send_v6().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
				 * Extract the queue from b_prev (set in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
				 * ip_rput_data_v6).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
				if (fwdq != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
					 * Forwarded packets hop count will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
					 * get decremented in ip_rput_data_v6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
					put(fwdq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
					 * Send locally originated packets back
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
					 * into * ip_wput_v6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
					put(ill->ill_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
				ill_refrele(inbound_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
				put(ill->ill_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
			mp = nxt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
	ll_changed = nce_cmp_ll_addr(nce, (char *)hw_addr, hw_addr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
	if (!is_adv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
		/* If this is a SOLICITATION request only */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
		if (ll_changed)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
			nce_update(nce, ND_STALE, hw_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
	if (!(flag & ND_NA_FLAG_OVERRIDE) && ll_changed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
		/* If in any other state than REACHABLE, ignore */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		if (nce->nce_state == ND_REACHABLE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
			nce_update(nce, ND_STALE, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
		if (ll_changed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
			nce_update(nce, ND_UNCHANGED, hw_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
			ll_updated = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
		if (flag & ND_NA_FLAG_SOLICITED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
			nce_update(nce, ND_REACHABLE, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
			if (ll_updated) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
				nce_update(nce, ND_STALE, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
		if (!(flag & ND_NA_FLAG_ROUTER) && (nce->nce_flags &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
		    NCE_F_ISROUTER)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
			ire_t *ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
			 * Router turned to host.  We need to remove the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
			 * entry as well as any default route that may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
			 * using this as a next hop.  This is required by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
			 * section 7.2.5 of RFC 2461.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
			ire = ire_ftable_lookup_v6(&ipv6_all_zeros,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
			    &ipv6_all_zeros, &nce->nce_addr, IRE_DEFAULT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
			    nce->nce_ill->ill_ipif, NULL, ALL_ZONES, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
			    MATCH_IRE_ILL | MATCH_IRE_TYPE | MATCH_IRE_GW |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
			    MATCH_IRE_DEFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
			if (ire != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
				ip_rts_rtmsg(RTM_DELETE, ire, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
				ire_delete(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
				ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
			ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
 * Pass arg1 to the pfi supplied, along with each nce in existence.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
 * ndp_walk() places a REFHOLD on the nce and drops the lock when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
 * walking the hash list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
ndp_walk_impl(ill_t *ill, pfi_t pfi, uchar_t *arg1, boolean_t trace)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
	nce_t	*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
	nce_t	*nce1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	nce_t	**ncep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	nce_t	*free_nce_list = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
	mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
	ndp_g_walker++;	/* Prevent ndp_delete from unlink and free of NCE */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
	mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
	for (ncep = nce_hash_tbl; ncep < A_END(nce_hash_tbl); ncep++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
		for (nce = *ncep; nce; nce = nce1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
			nce1 = nce->nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
			if (ill == NULL || nce->nce_ill == ill) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
				if (trace) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
					NCE_REFHOLD(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
					(*pfi)(nce, arg1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
					NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
					NCE_REFHOLD_NOTR(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
					(*pfi)(nce, arg1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
					NCE_REFRELE_NOTR(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
	for (nce = nce_mask_entries; nce; nce = nce1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
		nce1 = nce->nce_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
		if (ill == NULL || nce->nce_ill == ill) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
			if (trace) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
				NCE_REFHOLD(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
				(*pfi)(nce, arg1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
				NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
				NCE_REFHOLD_NOTR(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
				(*pfi)(nce, arg1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
				NCE_REFRELE_NOTR(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
	mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
	ndp_g_walker--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
	 * While NCE's are removed from global list they are placed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	 * in a private list, to be passed to nce_ire_delete_list().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
	 * The reason is, there may be ires pointing to this nce
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
	 * which needs to cleaned up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
	if (ndp_g_walker_cleanup && ndp_g_walker == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
		/* Time to delete condemned entries */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
		for (ncep = nce_hash_tbl; ncep < A_END(nce_hash_tbl); ncep++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
			nce = *ncep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
			if (nce != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
				nce_remove(nce, &free_nce_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
		nce = nce_mask_entries;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
		if (nce != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
			nce_remove(nce, &free_nce_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
		ndp_g_walker_cleanup = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
	mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	if (free_nce_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
		nce_ire_delete_list(free_nce_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
ndp_walk(ill_t *ill, pfi_t pfi, uchar_t *arg1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
	ndp_walk_impl(ill, pfi, arg1, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
 * Prepend the zoneid using an ipsec_out_t for later use by functions like
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
 * ip_rput_v6() after neighbor discovery has taken place.  If the message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
 * block already has a M_CTL at the front of it, then simply set the zoneid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
 * appropriately.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
ndp_prepend_zone(mblk_t *mp, zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
	mblk_t		*first_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
	ipsec_out_t	*io;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
	if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
		io = (ipsec_out_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
		ASSERT(io->ipsec_out_type == IPSEC_OUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
		io->ipsec_out_zoneid = zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
	first_mp = ipsec_alloc_ipsec_out();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
	if (first_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
	io = (ipsec_out_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
	/* This is not a secure packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
	io->ipsec_out_secure = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
	io->ipsec_out_zoneid = zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
	first_mp->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
	return (first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
 * Process resolve requests.  Handles both mapped entries
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
 * as well as cases that needs to be send out on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
 * Lookup a NCE for a given IRE.  Regardless of whether one exists
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
 * or one is created, we defer making ire point to nce until the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
 * ire is actually added at which point the nce_refcnt on the nce is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
 * incremented.  This is done primarily to have symmetry between ire_add()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
 * and ire_delete() which decrements the nce_refcnt, when an ire is deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
ndp_resolver(ill_t *ill, const in6_addr_t *dst, mblk_t *mp, zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
	nce_t		*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
	int		err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
	uint32_t	ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
	mblk_t		*mp_nce = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
	if (IN6_IS_ADDR_MULTICAST(dst)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
		err = nce_set_multicast(ill, dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
	err = ndp_lookup_then_add(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
	    NULL,	/* No hardware address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
	    dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
	    &ipv6_all_ones,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
	    &ipv6_all_zeros,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
	    0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
	    (ill->ill_flags & ILLF_NONUD) ? NCE_F_NONUD : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
	    ND_INCOMPLETE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
	    &nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
	switch (err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
		 * New cache entry was created. Make sure that the state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
		 * is not ND_INCOMPLETE. It can be in some other state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
		 * even before we send out the solicitation as we could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
		 * get un-solicited advertisements.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
		 * If this is an XRESOLV interface, simply return 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
		 * since we don't want to solicit just yet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
		if (ill->ill_flags & ILLF_XRESOLV) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
		rw_enter(&ill_g_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
		if (nce->nce_state != ND_INCOMPLETE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
			rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
		mp_nce = ndp_prepend_zone(mp, zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
		if (mp_nce == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
			/* The caller will free mp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
			rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
			ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
		ms = nce_solicit(nce, mp_nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
		rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
		if (ms == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
			/* The caller will free mp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
			if (mp_nce != mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
				freeb(mp_nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
			ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
			return (EBUSY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
		NDP_RESTART_TIMER(nce, (clock_t)ms);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
		return (EINPROGRESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
	case EEXIST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
		/* Resolution in progress just queue the packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
		if (nce->nce_state == ND_INCOMPLETE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
			mp_nce = ndp_prepend_zone(mp, zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
			if (mp_nce == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
				err = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
				nce_queue_mp(nce, mp_nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
				err = EINPROGRESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
			 * Any other state implies we have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
			 * a nce but IRE needs to be added ...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
			 * ire_add_v6() will take care of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
			 * the case when the nce becomes CONDEMNED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
			 * before the ire is added to the table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
			err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
		ip1dbg(("ndp_resolver: Can't create NCE %d\n", err));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
 * When there is no resolver, the link layer template is passed in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
 * the IRE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
 * Lookup a NCE for a given IRE.  Regardless of whether one exists
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
 * or one is created, we defer making ire point to nce until the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
 * ire is actually added at which point the nce_refcnt on the nce is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
 * incremented.  This is done primarily to have symmetry between ire_add()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
 * and ire_delete() which decrements the nce_refcnt, when an ire is deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
ndp_noresolver(ill_t *ill, const in6_addr_t *dst)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
	nce_t		*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
	int		err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
	if (IN6_IS_ADDR_MULTICAST(dst)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
		err = nce_set_multicast(ill, dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
	err = ndp_lookup_then_add(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
	    NULL,	/* hardware address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
	    dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
	    &ipv6_all_ones,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
	    &ipv6_all_zeros,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
	    0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
	    (ill->ill_flags & ILLF_NONUD) ? NCE_F_NONUD : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
	    ND_REACHABLE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
	    &nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
	switch (err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
		 * Cache entry with a proper resolver cookie was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
		 * created.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
	case EEXIST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
		err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
		ip1dbg(("ndp_noresolver: Can't create NCE %d\n", err));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
 * For each interface an entry is added for the unspecified multicast group.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
 * Here that mapping is used to form the multicast cache entry for a particular
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
 * multicast destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
nce_set_multicast(ill_t *ill, const in6_addr_t *dst)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
	nce_t		*mnce;	/* Multicast mapping entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
	nce_t		*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
	uchar_t		*hw_addr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
	int		err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
	ASSERT(!(IN6_IS_ADDR_UNSPECIFIED(dst)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
	mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
	nce = nce_lookup_addr(ill, dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
	if (nce != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
	/* No entry, now lookup for a mapping this should never fail */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
	mnce = nce_lookup_mapping(ill, dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
	if (mnce == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
		/* Something broken for the interface. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
		return (ESRCH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
	ASSERT(mnce->nce_flags & NCE_F_MAPPING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
	if (ill->ill_net_type == IRE_IF_RESOLVER) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
		 * For IRE_IF_RESOLVER a hardware mapping can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
		 * generated, for IRE_IF_NORESOLVER, resolution cookie
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
		 * in the ill is copied in ndp_add().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
		hw_addr = kmem_alloc(ill->ill_nd_lla_len, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
		if (hw_addr == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
			mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
			NCE_REFRELE(mnce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
		nce_make_mapping(mnce, hw_addr, (uchar_t *)dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
	NCE_REFRELE(mnce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
	 * IRE_IF_NORESOLVER type simply copies the resolution
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
	 * cookie passed in.  So no hw_addr is needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
	err = ndp_add(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
	    hw_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
	    dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
	    &ipv6_all_ones,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
	    &ipv6_all_zeros,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
	    0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
	    NCE_F_NONUD,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
	    ND_REACHABLE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
	    &nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
	mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
	if (hw_addr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
		kmem_free(hw_addr, ill->ill_nd_lla_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
	if (err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
		ip1dbg(("nce_set_multicast: create failed" "%d\n", err));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
	NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
 * Return the link layer address, and any flags of a nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
ndp_query(ill_t *ill, struct lif_nd_req *lnr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
	nce_t		*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
	in6_addr_t	*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
	sin6_t		*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
	dl_unitdata_req_t	*dl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
	sin6 = (sin6_t *)&lnr->lnr_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
	addr =  &sin6->sin6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
	nce = ndp_lookup(ill, addr, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
	if (nce == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
		return (ESRCH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
	/* If in INCOMPLETE state, no link layer address is available yet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
	if (nce->nce_state == ND_INCOMPLETE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
	dl = (dl_unitdata_req_t *)nce->nce_res_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
	if (ill->ill_flags & ILLF_XRESOLV)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
		lnr->lnr_hdw_len = dl->dl_dest_addr_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
		lnr->lnr_hdw_len = ill->ill_nd_lla_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
	ASSERT(NCE_LL_ADDR_OFFSET(ill) + lnr->lnr_hdw_len <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
	    sizeof (lnr->lnr_hdw_addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
	bcopy(nce->nce_res_mp->b_rptr + NCE_LL_ADDR_OFFSET(ill),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
	    (uchar_t *)&lnr->lnr_hdw_addr, lnr->lnr_hdw_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
	if (nce->nce_flags & NCE_F_ISROUTER)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
		lnr->lnr_flags = NDF_ISROUTER_ON;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
	if (nce->nce_flags & NCE_F_PROXY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
		lnr->lnr_flags |= NDF_PROXY_ON;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
	if (nce->nce_flags & NCE_F_ANYCAST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
		lnr->lnr_flags |= NDF_ANYCAST_ON;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
	NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
 * Send Enable/Disable multicast reqs to driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
ndp_mcastreq(ill_t *ill, const in6_addr_t *addr, uint32_t hw_addr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
    uint32_t hw_addr_offset, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
	nce_t		*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
	uchar_t		*hw_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
	ASSERT(ill->ill_net_type == IRE_IF_RESOLVER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
	hw_addr = mi_offset_paramc(mp, hw_addr_offset, hw_addr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
	if (hw_addr == NULL || !IN6_IS_ADDR_MULTICAST(addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
	mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
	nce = nce_lookup_mapping(ill, addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
	if (nce == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
		return (ESRCH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
	mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
	 * Update dl_addr_length and dl_addr_offset for primitives that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
	 * have physical addresses as opposed to full saps
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
	switch (((union DL_primitives *)mp->b_rptr)->dl_primitive) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
	case DL_ENABMULTI_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
		/* Track the state if this is the first enabmulti */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
		if (ill->ill_dlpi_multicast_state == IDMS_UNKNOWN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
			ill->ill_dlpi_multicast_state = IDMS_INPROGRESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
		ip1dbg(("ndp_mcastreq: ENABMULTI\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
	case DL_DISABMULTI_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
		ip1dbg(("ndp_mcastreq: DISABMULTI\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
		ip1dbg(("ndp_mcastreq: default\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
	nce_make_mapping(nce, hw_addr, (uchar_t *)addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
	NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
	putnext(ill->ill_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
 * Send a neighbor solicitation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
 * Returns number of milliseconds after which we should either rexmit or abort.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
 * Return of zero means we should abort.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
 * The caller holds the nce_lock to protect nce_qd_mp and nce_rcnt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
 * NOTE: This routine drops nce_lock (and later reacquires it) when sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
 * the packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
 * NOTE: This routine does not consume mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
uint32_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
nce_solicit(nce_t *nce, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
	ill_t		*ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
	ill_t		*src_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
	in6_addr_t	src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
	in6_addr_t	dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
	ipif_t		*ipif;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
	ip6i_t		*ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
	boolean_t	dropped = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
	ASSERT(RW_READ_HELD(&ill_g_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
	ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
	if (nce->nce_rcnt == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
		ASSERT(nce->nce_qd_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
		mp = nce->nce_qd_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
		nce_queue_mp(nce, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
	/* Handle ip_newroute_v6 giving us IPSEC packets */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
	if (mp->b_datap->db_type == M_CTL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
	ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
	if (ip6h->ip6_nxt == IPPROTO_RAW) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
		 * This message should have been pulled up already in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
		 * ip_wput_v6. We can't do pullups here because the message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
		 * could be from the nce_qd_mp which could have b_next/b_prev
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
		 * non-NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
		ip6i = (ip6i_t *)ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
		ASSERT((mp->b_wptr - (uchar_t *)ip6i) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
			    sizeof (ip6i_t) + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
		ip6h = (ip6_t *)(mp->b_rptr + sizeof (ip6i_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
	src = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
	 * If the src of outgoing packet is one of the assigned interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
	 * addresses use it, otherwise we will pick the source address below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
	src_ill = ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
	if (!IN6_IS_ADDR_UNSPECIFIED(&src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
		if (ill->ill_group != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
			src_ill = ill->ill_group->illgrp_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
		for (; src_ill != NULL; src_ill = src_ill->ill_group_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
			for (ipif = src_ill->ill_ipif; ipif != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
			    ipif = ipif->ipif_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
				if (IN6_ARE_ADDR_EQUAL(&src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
				    &ipif->ipif_v6lcl_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
			if (ipif != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
		if (src_ill == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
			/* May be a forwarding packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
			src_ill = ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
			src = ipv6_all_zeros;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
	dst = nce->nce_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
	 * If source address is unspecified, nce_xmit will choose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
	 * one for us and initialize the hardware address also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
	 * appropriately.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
	if (IN6_IS_ADDR_UNSPECIFIED(&src))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
		src_ill  = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
	nce->nce_rcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
	rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
	dropped = nce_xmit(ill, ND_NEIGHBOR_SOLICIT, src_ill, B_TRUE, &src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
	    &dst, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
	rw_enter(&ill_g_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
	if (dropped)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
		nce->nce_rcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
	return (ill->ill_reachable_retrans_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
ndp_input_solicit(ill_t *ill, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
	nd_neighbor_solicit_t *ns;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
	uint32_t	hlen = ill->ill_nd_lla_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
	uchar_t		*haddr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
	icmp6_t		*icmp_nd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	nce_t		*our_nce = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
	in6_addr_t	target;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
	in6_addr_t	src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
	int		flag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
	nd_opt_hdr_t	*opt = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
	boolean_t	bad_solicit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
	mib2_ipv6IfIcmpEntry_t	*mib = ill->ill_icmp6_mib;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
	ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
	icmp_nd = (icmp6_t *)(mp->b_rptr + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
	len = mp->b_wptr - mp->b_rptr - IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
	src = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
	ns = (nd_neighbor_solicit_t *)icmp_nd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
	target = ns->nd_ns_target;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
	if (IN6_IS_ADDR_MULTICAST(&target)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
		if (ip_debug > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
			/* ip1dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
			pr_addr_dbg("ndp_input_solicit: Target is"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
			    " multicast! %s\n", AF_INET6, &target);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
		bad_solicit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
	if (len > sizeof (nd_neighbor_solicit_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
		/* Options present */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
		opt = (nd_opt_hdr_t *)&ns[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
		len -= sizeof (nd_neighbor_solicit_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
		if (!ndp_verify_optlen(opt, len)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
			ip1dbg(("ndp_input_solicit: Bad opt len\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
			bad_solicit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
	if (IN6_IS_ADDR_UNSPECIFIED(&src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
		/* Check to see if this is a valid DAD solicitation */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
		if (!IN6_IS_ADDR_MC_SOLICITEDNODE(&ip6h->ip6_dst)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
			if (ip_debug > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
				/* ip1dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
				pr_addr_dbg("ndp_input_solicit: IPv6 "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
				    "Destination is not solicited node "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
				    "multicast %s\n", AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
				    &ip6h->ip6_dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
			bad_solicit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
	our_nce = ndp_lookup(ill, &target, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
	 * If this is a valid Solicitation, a permanent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
	 * entry should exist in the cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
	if (our_nce == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
	    !(our_nce->nce_flags & NCE_F_PERMANENT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
		ip1dbg(("ndp_input_solicit: Wrong target in NS?!"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
		    "ifname=%s ", ill->ill_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
		if (ip_debug > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
			/* ip1dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
			pr_addr_dbg(" dst %s\n", AF_INET6, &target);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
		bad_solicit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
	/* At this point we should have a verified NS per spec */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
	if (opt != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
		opt = ndp_get_option(opt, len, ND_OPT_SOURCE_LINKADDR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
		if (opt != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
			 * No source link layer address option should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
			 * be present in a valid DAD request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
			if (IN6_IS_ADDR_UNSPECIFIED(&src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
				ip1dbg(("ndp_input_solicit: source link-layer "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
				    "address option present with an "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
				    "unspecified source. \n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
				bad_solicit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
			haddr = (uchar_t *)&opt[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
			if (hlen > opt->nd_opt_len * 8 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
			    hlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
				bad_solicit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
	/* Set override flag, it will be reset later if need be. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
	flag |= NDP_ORIDE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
	if (!IN6_IS_ADDR_MULTICAST(&ip6h->ip6_dst)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
		flag |= NDP_UNICAST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
	 * Create/update the entry for the soliciting node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
	 * or respond to outstanding queries, don't if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
	 * the source is unspecified address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
	if (!IN6_IS_ADDR_UNSPECIFIED(&src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
		int	err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
		nce_t	*nnce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
		err = ndp_lookup_then_add(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
		    haddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
		    &src,	/* Soliciting nodes address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
		    &ipv6_all_ones,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
		    &ipv6_all_zeros,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
		    0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
		    0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
		    ND_STALE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
		    &nnce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
		switch (err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
		case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
			/* done with this entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
			NCE_REFRELE(nnce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
		case EEXIST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
			 * B_FALSE indicates this is not an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
			 * an advertisement.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
			ndp_process(nnce, haddr, 0, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
			NCE_REFRELE(nnce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
			ip1dbg(("ndp_input_solicit: Can't create NCE %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
			    err));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
		flag |= NDP_SOLICITED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
		 * This is a DAD req, multicast the advertisement
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
		 * to the all-nodes address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
		src = ipv6_all_hosts_mcast;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
	if (our_nce->nce_flags & NCE_F_ISROUTER)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
		flag |= NDP_ISROUTER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
	if (our_nce->nce_flags & NCE_F_PROXY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
		flag &= ~NDP_ORIDE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
	/* Response to a solicitation */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
	(void) nce_xmit(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
	    ND_NEIGHBOR_ADVERT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
	    ill,	/* ill to be used for extracting ill_nd_lla */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
	    B_TRUE,	/* use ill_nd_lla */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
	    &target,	/* Source and target of the advertisement pkt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
	    &src,	/* IP Destination (source of original pkt) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
	    flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
	if (bad_solicit)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
		BUMP_MIB(mib, ipv6IfIcmpInBadNeighborSolicitations);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
	if (our_nce != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
		NCE_REFRELE(our_nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
ndp_input_advert(ill_t *ill, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
	nd_neighbor_advert_t *na;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
	uint32_t	hlen = ill->ill_nd_lla_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
	uchar_t		*haddr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
	icmp6_t		*icmp_nd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
	nce_t		*dst_nce = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
	in6_addr_t	target;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
	nd_opt_hdr_t	*opt = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
	mib2_ipv6IfIcmpEntry_t	*mib = ill->ill_icmp6_mib;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
	ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
	icmp_nd = (icmp6_t *)(mp->b_rptr + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
	len = mp->b_wptr - mp->b_rptr - IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
	na = (nd_neighbor_advert_t *)icmp_nd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
	if (IN6_IS_ADDR_MULTICAST(&ip6h->ip6_dst) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
	    (na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
		ip1dbg(("ndp_input_advert: Target is multicast but the "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
		    "solicited flag is not zero\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
		BUMP_MIB(mib, ipv6IfIcmpInBadNeighborAdvertisements);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
	target = na->nd_na_target;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
	if (IN6_IS_ADDR_MULTICAST(&target)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
		ip1dbg(("ndp_input_advert: Target is multicast!\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
		BUMP_MIB(mib, ipv6IfIcmpInBadNeighborAdvertisements);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
	if (len > sizeof (nd_neighbor_advert_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
		opt = (nd_opt_hdr_t *)&na[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
		if (!ndp_verify_optlen(opt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
		    len - sizeof (nd_neighbor_advert_t))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
			BUMP_MIB(mib, ipv6IfIcmpInBadNeighborAdvertisements);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
		/* At this point we have a verified NA per spec */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
		len -= sizeof (nd_neighbor_advert_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
		opt = ndp_get_option(opt, len, ND_OPT_TARGET_LINKADDR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
		if (opt != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
			haddr = (uchar_t *)&opt[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
			if (hlen > opt->nd_opt_len * 8 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
			    hlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
				BUMP_MIB(mib,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
				    ipv6IfIcmpInBadNeighborAdvertisements);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
	 * If this interface is part of the group look at all the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
	 * ills in the group.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	rw_enter(&ill_g_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
	if (ill->ill_group != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
		ill = ill->ill_group->illgrp_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
	for (; ill != NULL; ill = ill->ill_group_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
		mutex_enter(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
		if (!ILL_CAN_LOOKUP(ill)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
			mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
		ill_refhold_locked(ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
		mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
		dst_nce = ndp_lookup(ill, &target, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
		/* We have to drop the lock since ndp_process calls put* */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
		rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
		if (dst_nce != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
			if (na->nd_na_flags_reserved &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
			    ND_NA_FLAG_ROUTER) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
				dst_nce->nce_flags |= NCE_F_ISROUTER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
			/* B_TRUE indicates this an advertisement */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
			ndp_process(dst_nce, haddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
				na->nd_na_flags_reserved, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
			NCE_REFRELE(dst_nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
		rw_enter(&ill_g_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
		ill_refrele(ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
	rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
 * Process NDP neighbor solicitation/advertisement messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
 * The checksum has already checked o.k before reaching here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
ndp_input(ill_t *ill, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
	icmp6_t		*icmp_nd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
	mib2_ipv6IfIcmpEntry_t	*mib = ill->ill_icmp6_mib;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
	if (!pullupmsg(mp, -1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
		ip1dbg(("ndp_input: pullupmsg failed\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
		BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
	ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
	if (ip6h->ip6_hops != IPV6_MAX_HOPS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
		ip1dbg(("ndp_input: hoplimit != IPV6_MAX_HOPS\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
		BUMP_MIB(mib, ipv6IfIcmpBadHoplimit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
	 * NDP does not accept any extension headers between the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
	 * IP header and the ICMP header since e.g. a routing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
	 * header could be dangerous.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
	 * This assumes that any AH or ESP headers are removed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
	 * by ip prior to passing the packet to ndp_input.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
	if (ip6h->ip6_nxt != IPPROTO_ICMPV6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
		ip1dbg(("ndp_input: Wrong next header 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
		    ip6h->ip6_nxt));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
		BUMP_MIB(mib, ipv6IfIcmpInErrors);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
	icmp_nd = (icmp6_t *)(mp->b_rptr + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
	ASSERT(icmp_nd->icmp6_type == ND_NEIGHBOR_SOLICIT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
	    icmp_nd->icmp6_type == ND_NEIGHBOR_ADVERT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
	if (icmp_nd->icmp6_code != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
		ip1dbg(("ndp_input: icmp6 code != 0 \n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
		BUMP_MIB(mib, ipv6IfIcmpInErrors);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
	len = mp->b_wptr - mp->b_rptr - IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
	 * Make sure packet length is large enough for either
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
	 * a NS or a NA icmp packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
	if (len <  sizeof (struct icmp6_hdr) + sizeof (struct in6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
		ip1dbg(("ndp_input: packet too short\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
		BUMP_MIB(mib, ipv6IfIcmpInErrors);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
	if (icmp_nd->icmp6_type == ND_NEIGHBOR_SOLICIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
		ndp_input_solicit(ill, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
		ndp_input_advert(ill, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
 * nce_xmit is called to form and transmit a ND solicitation or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
 * advertisement ICMP packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
 * If source address is unspecified, appropriate source address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
 * and link layer address will be chosen here. This function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
 * *always* sends the link layer option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
 * It returns B_FALSE only if it does a successful put() to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
 * corresponding ill's ill_wq otherwise returns B_TRUE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
nce_xmit(ill_t *ill, uint32_t operation, ill_t *hwaddr_ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
    boolean_t use_nd_lla, const in6_addr_t *sender, const in6_addr_t *target,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
    int flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
	uint32_t	len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	icmp6_t 	*icmp6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
	nd_opt_hdr_t	*opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
	uint_t		plen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
	ip6i_t		*ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
	ipif_t		*src_ipif = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
	 * If we have a unspecified source(sender) address, select a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
	 * proper source address for the solicitation here itself so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
	 * that we can initialize the h/w address correctly. This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
	 * needed for interface groups as source address can come from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
	 * the whole group and the h/w address initialized from ill will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
	 * be wrong if the source address comes from a different ill.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
	 * Note that the NA never comes here with the unspecified source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
	 * address. The following asserts that whenever the source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
	 * address is specified, the haddr also should be specified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
	ASSERT(IN6_IS_ADDR_UNSPECIFIED(sender) || (hwaddr_ill != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
	if (IN6_IS_ADDR_UNSPECIFIED(sender)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
		ASSERT(operation != ND_NEIGHBOR_ADVERT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
		 * Pick a source address for this solicitation, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
		 * restrict the selection to addresses assigned to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
		 * output interface (or interface group).  We do this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
		 * because the destination will create a neighbor cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
		 * entry for the source address of this packet, so the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
		 * source address had better be a valid neighbor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
		src_ipif = ipif_select_source_v6(ill, target, B_TRUE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
		    IPV6_PREFER_SRC_DEFAULT, GLOBAL_ZONEID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
		if (src_ipif == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
			char buf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
			ip0dbg(("nce_xmit: No source ipif for dst %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
			    inet_ntop(AF_INET6, (char *)target, buf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
			    sizeof (buf))));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
		sender = &src_ipif->ipif_v6src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
		hwaddr_ill = src_ipif->ipif_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
	plen = (sizeof (nd_opt_hdr_t) + ill->ill_nd_lla_len + 7)/8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
	 * Always make sure that the NS/NA packets don't get load
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
	 * spread. This is needed so that the probe packets sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
	 * by the in.mpathd daemon can really go out on the desired
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
	 * interface. Probe packets are made to go out on a desired
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
	 * interface by including a ip6i with ATTACH_IF flag. As these
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
	 * packets indirectly end up sending/receiving NS/NA packets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
	 * (neighbor doing NUD), we have to make sure that NA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
	 * also go out on the same interface.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
	len = IPV6_HDR_LEN + sizeof (ip6i_t) + sizeof (nd_neighbor_advert_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
	    plen * 8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
	mp = allocb(len,  BPRI_LO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
		if (src_ipif != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
			ipif_refrele(src_ipif);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
	bzero((char *)mp->b_rptr, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
	mp->b_wptr = mp->b_rptr + len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
	ip6i = (ip6i_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
	ip6i->ip6i_vcf = IPV6_DEFAULT_VERS_AND_FLOW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
	ip6i->ip6i_nxt = IPPROTO_RAW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
	ip6i->ip6i_flags = IP6I_ATTACH_IF | IP6I_HOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
	ip6i->ip6i_ifindex = ill->ill_phyint->phyint_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
	ip6h = (ip6_t *)(mp->b_rptr + sizeof (ip6i_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
	ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
	ip6h->ip6_plen = htons(len - IPV6_HDR_LEN - sizeof (ip6i_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
	ip6h->ip6_nxt = IPPROTO_ICMPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
	ip6h->ip6_hops = IPV6_MAX_HOPS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
	ip6h->ip6_dst = *target;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
	icmp6 = (icmp6_t *)&ip6h[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
	opt = (nd_opt_hdr_t *)((uint8_t *)ip6h + IPV6_HDR_LEN +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
	    sizeof (nd_neighbor_advert_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
	if (operation == ND_NEIGHBOR_SOLICIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
		nd_neighbor_solicit_t *ns = (nd_neighbor_solicit_t *)icmp6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
		opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
		ip6h->ip6_src = *sender;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
		ns->nd_ns_target = *target;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
		if (!(flag & NDP_UNICAST)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
			/* Form multicast address of the target */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
			ip6h->ip6_dst = ipv6_solicited_node_mcast;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
			ip6h->ip6_dst.s6_addr32[3] |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
			    ns->nd_ns_target.s6_addr32[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
		nd_neighbor_advert_t *na = (nd_neighbor_advert_t *)icmp6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
		opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
		ip6h->ip6_src = *sender;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
		na->nd_na_target = *sender;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
		if (flag & NDP_ISROUTER)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
			na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
		if (flag & NDP_SOLICITED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
			na->nd_na_flags_reserved |= ND_NA_FLAG_SOLICITED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
		if (flag & NDP_ORIDE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
			na->nd_na_flags_reserved |= ND_NA_FLAG_OVERRIDE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
	/* Fill in link layer address and option len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
	opt->nd_opt_len = (uint8_t)plen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
	mutex_enter(&hwaddr_ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
	bcopy(use_nd_lla ? hwaddr_ill->ill_nd_lla : hwaddr_ill->ill_phys_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
	    &opt[1], hwaddr_ill->ill_nd_lla_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
	mutex_exit(&hwaddr_ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
	icmp6->icmp6_type = (uint8_t)operation;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
	icmp6->icmp6_code = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
	 * Prepare for checksum by putting icmp length in the icmp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
	 * checksum field. The checksum is calculated in ip_wput_v6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
	icmp6->icmp6_cksum = ip6h->ip6_plen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
	if (src_ipif != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
		ipif_refrele(src_ipif);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
	if (canput(ill->ill_wq)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
		put(ill->ill_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
 * Make a link layer address (does not include the SAP) from an nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
 * To form the link layer address, use the last four bytes of ipv6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
 * address passed in and the fixed offset stored in nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
nce_make_mapping(nce_t *nce, uchar_t *addrpos, uchar_t *addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
	uchar_t *mask, *to;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
	ill_t	*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
	int 	len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
	if (ill->ill_net_type == IRE_IF_NORESOLVER)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
	ASSERT(nce->nce_res_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
	ASSERT(ill->ill_net_type == IRE_IF_RESOLVER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
	ASSERT(nce->nce_flags & NCE_F_MAPPING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1796
	ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&nce->nce_extract_mask));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
	ASSERT(addr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
	bcopy(nce->nce_res_mp->b_rptr + NCE_LL_ADDR_OFFSET(ill),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
	    addrpos, ill->ill_nd_lla_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
	len = MIN((int)ill->ill_nd_lla_len - nce->nce_ll_extract_start,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
	    IPV6_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
	mask = (uchar_t *)&nce->nce_extract_mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
	mask += (IPV6_ADDR_LEN - len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
	addr += (IPV6_ADDR_LEN - len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
	to = addrpos + nce->nce_ll_extract_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
	while (len-- > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
		*to++ |= *mask++ & *addr++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
 * Pass a cache report back out via NDD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
ndp_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *ioc_cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
	(void) mi_mpprintf(mp, "ifname      hardware addr    flags"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
			"     proto addr/mask");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
	ndp_walk(NULL, (pfi_t)nce_report1, (uchar_t *)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
 * convert a link level address of arbitrary length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
 * to an ascii string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
 * The caller *must* have already verified that the string buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
 * is large enough to hold the entire string, including trailing NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
lla2ascii(uint8_t *lla, int addrlen, uchar_t *buf)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
	uchar_t	addrbyte[8];	/* needs to hold ascii for a byte plus a NULL */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
	size_t	len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
	buf[0] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
	for (i = 0; i < addrlen; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
		addrbyte[0] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
		(void) sprintf((char *)addrbyte, "%02x:", (lla[i] & 0xff));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
		len = strlen((const char *)addrbyte);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
		bcopy(addrbyte, buf, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
		buf = buf + len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
	*--buf = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
 * Add a single line to the NDP Cache Entry Report.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
nce_report1(nce_t *nce, uchar_t *mp_arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
	ill_t		*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
	char		local_buf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
	uchar_t		flags_buf[10];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
	uint32_t	flags = nce->nce_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
	mblk_t		*mp = (mblk_t *)mp_arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
	uchar_t		*h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
	uchar_t		*m = flags_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
	in6_addr_t	v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
	 * Lock the nce to protect nce_res_mp from being changed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
	 * if an external resolver address resolution completes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
	 * while nce_res_mp is being accessed here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
	 * Deal with all address formats, not just Ethernet-specific
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
	 * In addition, make sure that the mblk has enough space
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
	 * before writing to it. If is doesn't, allocate a new one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
	v6addr = nce->nce_mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
	if (flags & NCE_F_PERMANENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
		*m++ = 'P';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
	if (flags & NCE_F_ISROUTER)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
		*m++ = 'R';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
	if (flags & NCE_F_MAPPING)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
		*m++ = 'M';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
	*m = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
	if (ill->ill_net_type == IRE_IF_RESOLVER) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
		size_t		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
		uchar_t		*addr_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
		dl_unitdata_req_t	*dl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
		h = nce->nce_res_mp->b_rptr + NCE_LL_ADDR_OFFSET(ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
		dl = (dl_unitdata_req_t *)nce->nce_res_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
		if (ill->ill_flags & ILLF_XRESOLV)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
			addrlen = (3 * (dl->dl_dest_addr_length));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
			addrlen = (3 * (ill->ill_nd_lla_len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
		if (addrlen <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
			(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
			    "%8s %9s %5s %s/%d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
			    ill->ill_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
			    "None",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
			    (uchar_t *)&flags_buf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
			    inet_ntop(AF_INET6, (char *)&nce->nce_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
				(char *)local_buf, sizeof (local_buf)),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
				ip_mask_to_plen_v6(&v6addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
			 * Convert the hardware/lla address to ascii
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
			addr_buf = kmem_zalloc(addrlen, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
			if (addr_buf == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
				mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
			if (ill->ill_flags & ILLF_XRESOLV)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
				lla2ascii((uint8_t *)h, dl->dl_dest_addr_length,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
				    addr_buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
				lla2ascii((uint8_t *)h, ill->ill_nd_lla_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
				    addr_buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
			(void) mi_mpprintf(mp, "%8s %17s %5s %s/%d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
			    ill->ill_name, addr_buf, (uchar_t *)&flags_buf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
			    inet_ntop(AF_INET6, (char *)&nce->nce_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
				(char *)local_buf, sizeof (local_buf)),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
				ip_mask_to_plen_v6(&v6addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
			kmem_free(addr_buf, addrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
		(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
		    "%8s %9s %5s %s/%d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
		    ill->ill_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
		    "None",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
		    (uchar_t *)&flags_buf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
		    inet_ntop(AF_INET6, (char *)&nce->nce_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
			(char *)local_buf, sizeof (local_buf)),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
			ip_mask_to_plen_v6(&v6addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
nce_udreq_alloc(ill_t *ill)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
	mblk_t	*template_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
	dl_unitdata_req_t *dlur;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
	int	sap_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
	sap_length = ill->ill_sap_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
	template_mp = ip_dlpi_alloc(sizeof (dl_unitdata_req_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
	    ill->ill_nd_lla_len + ABS(sap_length), DL_UNITDATA_REQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
	if (template_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
	dlur = (dl_unitdata_req_t *)template_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
	dlur->dl_priority.dl_min = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
	dlur->dl_priority.dl_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
	dlur->dl_dest_addr_length = ABS(sap_length) + ill->ill_nd_lla_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
	dlur->dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
	/* Copy in the SAP value. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
	NCE_LL_SAP_COPY(ill, template_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
	return (template_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
 * NDP retransmit timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
 * This timer goes off when:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
 * a. It is time to retransmit NS for resolver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
 * b. It is time to send reachability probes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
ndp_timer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
	nce_t		*nce = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
	ill_t		*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
	uint32_t	ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
	char		addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
	boolean_t	dropped = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
	 * The timer has to be cancelled by ndp_delete before doing the final
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
	 * refrele. So the NCE is guaranteed to exist when the timer runs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
	 * until it clears the timeout_id. Before clearing the timeout_id
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
	 * bump up the refcnt so that we can continue to use the nce
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
	ASSERT(nce != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
	 * Grab the ill_g_lock now itself to avoid lock order problems.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
	 * nce_solicit needs ill_g_lock to be able to traverse ills
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
	rw_enter(&ill_g_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
	NCE_REFHOLD_LOCKED(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
	nce->nce_timeout_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
	 * Check the reachability state first.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
	switch (nce->nce_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
	case ND_DELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
		rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
		nce->nce_state = ND_PROBE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
		(void) nce_xmit(ill, ND_NEIGHBOR_SOLICIT, NULL, B_FALSE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
		    &ipv6_all_zeros, &nce->nce_addr, NDP_UNICAST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
		if (ip_debug > 3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
			/* ip2dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
			pr_addr_dbg("ndp_timer: state for %s changed "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
			    "to PROBE\n", AF_INET6, &nce->nce_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
		NDP_RESTART_TIMER(nce, ill->ill_reachable_retrans_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
	case ND_PROBE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
		/* must be retransmit timer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
		rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
		nce->nce_pcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
		ASSERT(nce->nce_pcnt < ND_MAX_UNICAST_SOLICIT &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
		    nce->nce_pcnt >= -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
		if (nce->nce_pcnt == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
			/* Wait RetransTimer, before deleting the entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
			ip2dbg(("ndp_timer: pcount=%x dst %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
			    nce->nce_pcnt, inet_ntop(AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
			    &nce->nce_addr, addrbuf, sizeof (addrbuf))));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
			NDP_RESTART_TIMER(nce, ill->ill_reachable_retrans_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
			 * As per RFC2461, the nce gets deleted after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
			 * MAX_UNICAST_SOLICIT unsuccessful re-transmissions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
			 * Note that the first unicast solicitation is sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
			 * during the DELAY state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
			if (nce->nce_pcnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
				ip2dbg(("ndp_timer: pcount=%x dst %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
				    nce->nce_pcnt, inet_ntop(AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
				    &nce->nce_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
				    addrbuf, sizeof (addrbuf))));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
				mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
				dropped = nce_xmit(ill, ND_NEIGHBOR_SOLICIT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
				    NULL, B_FALSE, &ipv6_all_zeros,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
				    &nce->nce_addr, NDP_UNICAST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
				if (dropped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
					mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
					nce->nce_pcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
					mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
				NDP_RESTART_TIMER(nce,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
				    ill->ill_reachable_retrans_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
				/* No hope, delete the nce */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
				nce->nce_state = ND_UNREACHABLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
				mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
				if (ip_debug > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
					/* ip1dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
					pr_addr_dbg("ndp_timer: Delete IRE for"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
					    " dst %s\n", AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
					    &nce->nce_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
				ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
	case ND_INCOMPLETE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
		 * Must be resolvers retransmit timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
		for (mp = nce->nce_qd_mp; mp != NULL; mp = mp->b_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
			ip6i_t	*ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
			ip6_t	*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
			mblk_t *data_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
			 * Walk the list of packets queued, and see if there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
			 * are any multipathing probe packets. Such packets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
			 * are always queued at the head. Since this is a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
			 * retransmit timer firing, mark such packets as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
			 * delayed in ND resolution. This info will be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
			 * in ip_wput_v6(). Multipathing probe packets will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2081
			 * always have an ip6i_t. Once we hit a packet without
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
			 * it, we can break out of this loop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
			if (mp->b_datap->db_type == M_CTL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
				data_mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
				data_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
			ip6h = (ip6_t *)data_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
			if (ip6h->ip6_nxt != IPPROTO_RAW)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
			 * This message should have been pulled up already in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
			 * ip_wput_v6. We can't do pullups here because the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
			 * b_next/b_prev is non-NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
			ip6i = (ip6i_t *)ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
			ASSERT((data_mp->b_wptr - (uchar_t *)ip6i) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
			    sizeof (ip6i_t) + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
			/* Mark this packet as delayed due to ND resolution */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
			if (ip6i->ip6i_flags & IP6I_DROP_IFDELAYED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
				ip6i->ip6i_flags |= IP6I_ND_DELAYED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
		if (nce->nce_qd_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
			ms = nce_solicit(nce, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
			rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
			if (ms == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
				if (nce->nce_state != ND_REACHABLE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
					mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
					nce_resolv_failed(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
					ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
					mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
				mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
				NDP_RESTART_TIMER(nce, (clock_t)ms);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
		rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
	case ND_REACHABLE :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
		rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
		if (nce->nce_flags & NCE_F_UNSOL_ADV &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
		    nce->nce_unsolicit_count != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
			nce->nce_unsolicit_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
			dropped = nce_xmit(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
			    ND_NEIGHBOR_ADVERT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
			    ill,	/* ill to be used for hw addr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
			    B_FALSE,	/* use ill_phys_addr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
			    &nce->nce_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
			    &ipv6_all_hosts_mcast,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
			    nce->nce_flags | NDP_ORIDE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
			if (dropped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
				mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
				nce->nce_unsolicit_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
				mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
			if (nce->nce_unsolicit_count != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
				NDP_RESTART_TIMER(nce,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
				    ip_ndp_unsolicit_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
		rw_exit(&ill_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
 * Set a link layer address from the ll_addr passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
 * Copy SAP from ill.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
nce_set_ll(nce_t *nce, uchar_t *ll_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
	ill_t	*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
	uchar_t	*woffset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
	ASSERT(ll_addr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
	/* Always called before fast_path_probe */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
  2175
	ASSERT(nce->nce_fp_mp == NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
	if (ill->ill_sap_length != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
		 * Copy the SAP type specified in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
		 * request into the xmit template.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
		NCE_LL_SAP_COPY(ill, nce->nce_res_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
	if (ill->ill_phys_addr_length > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
		 * The bcopy() below used to be called for the physical address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
		 * length rather than the link layer address length. For
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
		 * ethernet and many other media, the phys_addr and lla are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
		 * identical.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
		 * However, with xresolv interfaces being introduced, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
		 * phys_addr and lla are no longer the same, and the physical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
		 * address may not have any useful meaning, so we use the lla
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
		 * for IPv6 address resolution and destination addressing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
		 * For PPP or other interfaces with a zero length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
		 * physical address, don't do anything here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2196
		 * The bcopy() with a zero phys_addr length was previously
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
		 * a no-op for interfaces with a zero-length physical address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
		 * Using the lla for them would change the way they operate.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
		 * Doing nothing in such cases preserves expected behavior.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
		woffset = nce->nce_res_mp->b_rptr + NCE_LL_ADDR_OFFSET(ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
		bcopy(ll_addr, woffset, ill->ill_nd_lla_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
nce_cmp_ll_addr(nce_t *nce, char *ll_addr, uint32_t ll_addr_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
	ill_t	*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
	uchar_t	*ll_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
	ASSERT(nce->nce_res_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
	if (ll_addr == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
	ll_offset = nce->nce_res_mp->b_rptr + NCE_LL_ADDR_OFFSET(ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
	if (bcmp(ll_addr, (char *)ll_offset, ll_addr_len) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
 * Updates the link layer address or the reachability state of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
 * a cache entry.  Reset probe counter if needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
nce_update(nce_t *nce, uint16_t new_state, uchar_t *new_ll_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
	ill_t	*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
	boolean_t need_stop_timer = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
	boolean_t need_fastpath_update = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
	 * If this interface does not do NUD, there is no point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
	 * in allowing an update to the cache entry.  Although
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
	 * we will respond to NS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
	 * The only time we accept an update for a resolver when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
	 * NUD is turned off is when it has just been created.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
	 * Non-Resolvers will always be created as REACHABLE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2240
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2241
	if (new_state != ND_UNCHANGED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
		if ((nce->nce_flags & NCE_F_NONUD) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
		    (nce->nce_state != ND_INCOMPLETE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
		ASSERT((int16_t)new_state >= ND_STATE_VALID_MIN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
		ASSERT((int16_t)new_state <= ND_STATE_VALID_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
		need_stop_timer = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
		if (new_state == ND_REACHABLE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
			nce->nce_last = TICK_TO_MSEC(lbolt64);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
		else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
			/* We force NUD in this case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
			nce->nce_last = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
		nce->nce_state = new_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
		nce->nce_pcnt = ND_MAX_UNICAST_SOLICIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
	 * In case of fast path we need to free the the fastpath
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
	 * M_DATA and do another probe.  Otherwise we can just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
	 * overwrite the DL_UNITDATA_REQ data, noting we'll lose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
	 * whatever packets that happens to be transmitting at the time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
	if (new_ll_addr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
		ASSERT(nce->nce_res_mp->b_rptr + NCE_LL_ADDR_OFFSET(ill) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
		    ill->ill_nd_lla_len <= nce->nce_res_mp->b_wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
		bcopy(new_ll_addr, nce->nce_res_mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
		    NCE_LL_ADDR_OFFSET(ill), ill->ill_nd_lla_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
		if (nce->nce_fp_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
			freemsg(nce->nce_fp_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
			nce->nce_fp_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
		}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
  2272
		need_fastpath_update = B_TRUE;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
	if (need_stop_timer) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
		(void) untimeout(nce->nce_timeout_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
		nce->nce_timeout_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
	if (need_fastpath_update)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
		nce_fastpath(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
nce_queue_mp(nce_t *nce, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
	uint_t	count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
	mblk_t  **mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
	boolean_t head_insert = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
	ip6_t	*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
	ip6i_t	*ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
	mblk_t *data_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
	if (mp->b_datap->db_type == M_CTL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
		data_mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
		data_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
	ip6h = (ip6_t *)data_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
	if (ip6h->ip6_nxt == IPPROTO_RAW) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
		 * This message should have been pulled up already in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
		 * ip_wput_v6. We can't do pullups here because the message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
		 * could be from the nce_qd_mp which could have b_next/b_prev
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
		 * non-NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
		ip6i = (ip6i_t *)ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
		ASSERT((data_mp->b_wptr - (uchar_t *)ip6i) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
			    sizeof (ip6i_t) + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
		 * Multipathing probe packets have IP6I_DROP_IFDELAYED set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
		 * This has 2 aspects mentioned below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
		 * 1. Perform head insertion in the nce_qd_mp for these packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
		 * This ensures that next retransmit of ND solicitation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
		 * will use the interface specified by the probe packet,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
		 * for both NS and NA. This corresponds to the src address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
		 * in the IPv6 packet. If we insert at tail, we will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
		 * depending on the packet at the head for successful
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
		 * ND resolution. This is not reliable, because the interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
		 * on which the NA arrives could be different from the interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
		 * on which the NS was sent, and if the receiving interface is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
		 * failed, it will appear that the sending interface is also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
		 * failed, causing in.mpathd to misdiagnose this as link
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
		 * failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
		 * 2. Drop the original packet, if the ND resolution did not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
		 * succeed in the first attempt. However we will create the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
		 * nce and the ire, as soon as the ND resolution succeeds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
		 * We don't gain anything by queueing multiple probe packets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
		 * and sending them back-to-back once resolution succeeds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
		 * It is sufficient to send just 1 packet after ND resolution
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
		 * succeeds. Since mpathd is sending down probe packets at a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
		 * constant rate, we don't need to send the queued packet. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
		 * need to queue it only for NDP resolution. The benefit of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
		 * dropping the probe packets that were delayed in ND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
		 * resolution, is that in.mpathd will not see inflated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
		 * RTT. If the ND resolution does not succeed within
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
		 * in.mpathd's failure detection time, mpathd may detect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
		 * a failure, and it does not matter whether the packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
		 * was queued or dropped.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
		if (ip6i->ip6i_flags & IP6I_DROP_IFDELAYED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
			head_insert = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
	for (mpp = &nce->nce_qd_mp; *mpp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
	    mpp = &(*mpp)->b_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
		if (++count >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
		    nce->nce_ill->ill_max_buf) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
			mblk_t *tmp = nce->nce_qd_mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
			nce->nce_qd_mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
			nce->nce_qd_mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
			freemsg(nce->nce_qd_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
			ip1dbg(("nce_queue_mp: pkt dropped\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
			nce->nce_qd_mp = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
	/* put this on the list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
	if (head_insert) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
		mp->b_next = nce->nce_qd_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
		nce->nce_qd_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
		*mpp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
 * Called when address resolution failed due to a timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
 * Send an ICMP unreachable in response to all queued packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
nce_resolv_failed(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
	mblk_t	*mp, *nxt_mp, *first_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
	char	buf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
	ip6_t *ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
	zoneid_t zoneid = GLOBAL_ZONEID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
	ip1dbg(("nce_resolv_failed: dst %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
	    inet_ntop(AF_INET6, (char *)&nce->nce_addr, buf, sizeof (buf))));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
	mp = nce->nce_qd_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
	nce->nce_qd_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
	while (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
		nxt_mp = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
		mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
		mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
		first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
		if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
			ipsec_out_t *io = (ipsec_out_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
			ASSERT(io->ipsec_out_type == IPSEC_OUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
			zoneid = io->ipsec_out_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
			ASSERT(zoneid != ALL_ZONES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
			mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
		if (ip6h->ip6_nxt == IPPROTO_RAW) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
			ip6i_t *ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
			 * This message should have been pulled up already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
			 * in ip_wput_v6. ip_hdr_complete_v6 assumes that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
			 * the header is pulled up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
			ip6i = (ip6i_t *)ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
			ASSERT((mp->b_wptr - (uchar_t *)ip6i) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
			    sizeof (ip6i_t) + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
			mp->b_rptr += sizeof (ip6i_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
		 * Ignore failure since icmp_unreachable_v6 will silently
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
		 * drop packets with an unspecified source address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
		(void) ip_hdr_complete_v6((ip6_t *)mp->b_rptr, zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
		icmp_unreachable_v6(nce->nce_ill->ill_wq, first_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
		    ICMP6_DST_UNREACH_ADDR, B_FALSE, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
		mp = nxt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
 * Called by SIOCSNDP* ioctl to add/change an nce entry
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
 * and the corresponding attributes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
 * Disallow states other than ND_REACHABLE or ND_STALE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
ndp_sioc_update(ill_t *ill, lif_nd_req_t *lnr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
	sin6_t		*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
	in6_addr_t	*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
	nce_t		*nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
	uint16_t	new_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
	uint16_t	old_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
	int		inflags = lnr->lnr_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
	if ((lnr->lnr_state_create != ND_REACHABLE) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
	    (lnr->lnr_state_create != ND_STALE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
	sin6 = (sin6_t *)&lnr->lnr_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
	addr = &sin6->sin6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
	mutex_enter(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
	/* We know it can not be mapping so just look in the hash table */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
	nce = nce_lookup_addr(ill, addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
	if (nce != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2451
		new_flags = nce->nce_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
	switch (inflags & (NDF_ISROUTER_ON|NDF_ISROUTER_OFF)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
	case NDF_ISROUTER_ON:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
		new_flags |= NCE_F_ISROUTER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
	case NDF_ISROUTER_OFF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
		new_flags &= ~NCE_F_ISROUTER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
	case (NDF_ISROUTER_OFF|NDF_ISROUTER_ON):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
		if (nce != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
	switch (inflags & (NDF_ANYCAST_ON|NDF_ANYCAST_OFF)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
	case NDF_ANYCAST_ON:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
		new_flags |= NCE_F_ANYCAST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
	case NDF_ANYCAST_OFF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
		new_flags &= ~NCE_F_ANYCAST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
	case (NDF_ANYCAST_OFF|NDF_ANYCAST_ON):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
		if (nce != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
	switch (inflags & (NDF_PROXY_ON|NDF_PROXY_OFF)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
	case NDF_PROXY_ON:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
		new_flags |= NCE_F_PROXY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
	case NDF_PROXY_OFF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
		new_flags &= ~NCE_F_PROXY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
	case (NDF_PROXY_OFF|NDF_PROXY_ON):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
		if (nce != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
			NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
	if (nce == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
		err = ndp_add(ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
		    (uchar_t *)lnr->lnr_hdw_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
		    addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
		    &ipv6_all_ones,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
		    &ipv6_all_zeros,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
		    0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
		    new_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
		    lnr->lnr_state_create,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
		    &nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
		if (err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
			mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
			ip1dbg(("ndp_sioc_update: Can't create NCE %d\n", err));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
			return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
	old_flags = nce->nce_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
	if (old_flags & NCE_F_ISROUTER && !(new_flags & NCE_F_ISROUTER)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
		 * Router turned to host, delete all ires.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
		 * XXX Just delete the entry, but we need to add too.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
		nce->nce_flags &= ~NCE_F_ISROUTER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
		mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
		ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
		NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
	mutex_exit(&ndp_g_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
	nce->nce_flags = new_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
	 * Note that we ignore the state at this point, which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
	 * should be either STALE or REACHABLE.  Instead we let
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
	 * the link layer address passed in to determine the state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
	 * much like incoming packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
	ndp_process(nce, (uchar_t *)lnr->lnr_hdw_addr, 0, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
	NCE_REFRELE(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
 * If the device driver supports it, we make nce_fp_mp to have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
 * an M_DATA prepend.  Otherwise nce_fp_mp will be null.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
 * The caller insures there is hold on nce for this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
 * Note that since ill_fastpath_probe() copies the mblk there is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
 * no need for the hold beyond this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
nce_fastpath(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
	ill_t	*ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
	int res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
	if (nce->nce_fp_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
		/* Already contains fastpath info */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
	if (nce->nce_res_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
		nce_fastpath_list_add(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
		res = ill_fastpath_probe(ill, nce->nce_res_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
		 * EAGAIN is an indication of a transient error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
		 * i.e. allocation failure etc. leave the nce in the list it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
		 * will be updated when another probe happens for another ire
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
		 * if not it will be taken out of the list when the ire is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
		 * deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
		if (res != 0 && res != EAGAIN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
			nce_fastpath_list_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
 * Drain the list of nce's waiting for fastpath response.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
nce_fastpath_list_dispatch(ill_t *ill, boolean_t (*func)(nce_t *, void  *),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
    void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
	nce_t *next_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
	nce_t *current_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
	nce_t *first_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
	nce_t *prev_nce = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
	mutex_enter(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
	first_nce = current_nce = (nce_t *)ill->ill_fastpath_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
	while (current_nce != (nce_t *)&ill->ill_fastpath_list) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
		next_nce = current_nce->nce_fastpath;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
		 * Take it off the list if we're flushing, or if the callback
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
		 * routine tells us to do so.  Otherwise, leave the nce in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
		 * fastpath list to handle any pending response from the lower
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
		 * layer.  We can't drain the list when the callback routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
		 * comparison failed, because the response is asynchronous in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
		 * nature, and may not arrive in the same order as the list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
		 * insertion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
		if (func == NULL || func(current_nce, arg)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
			current_nce->nce_fastpath = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
			if (current_nce == first_nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
				ill->ill_fastpath_list = first_nce = next_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
				prev_nce->nce_fastpath = next_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
			/* previous element that is still in the list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
			prev_nce = current_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
		current_nce = next_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
	mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2616
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
 * Add nce to the nce fastpath list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2620
nce_fastpath_list_add(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2621
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2622
	ill_t *ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
	ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
	mutex_enter(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
	 * if nce has not been deleted and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
	 * is not already in the list add it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
	if (!(nce->nce_flags & NCE_F_CONDEMNED) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
	    (nce->nce_fastpath == NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2636
		nce->nce_fastpath = (nce_t *)ill->ill_fastpath_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
		ill->ill_fastpath_list = nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
	mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
 * remove nce from the nce fastpath list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2646
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2647
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2648
nce_fastpath_list_delete(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2649
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2650
	nce_t *nce_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2652
	ill_t *ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2653
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2654
	ill = nce->nce_ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2655
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2656
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2657
	mutex_enter(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2658
	if (nce->nce_fastpath == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2659
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2661
	ASSERT(ill->ill_fastpath_list != &ill->ill_fastpath_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2663
	if (ill->ill_fastpath_list == nce) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2664
		ill->ill_fastpath_list = nce->nce_fastpath;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2665
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2666
		nce_ptr = ill->ill_fastpath_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2667
		while (nce_ptr != (nce_t *)&ill->ill_fastpath_list) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2668
			if (nce_ptr->nce_fastpath == nce) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2669
				nce_ptr->nce_fastpath = nce->nce_fastpath;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2670
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2671
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2672
			nce_ptr = nce_ptr->nce_fastpath;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2673
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
	nce->nce_fastpath = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
	mutex_exit(&ill->ill_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
 * Update all NCE's that are not in fastpath mode and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
 * have an nce_fp_mp that matches mp. mp->b_cont contains
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
 * the fastpath header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
 * Returns TRUE if entry should be dequeued, or FALSE otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
ndp_fastpath_update(nce_t *nce, void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
	mblk_t 	*mp, *fp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
	uchar_t	*mp_rptr, *ud_mp_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
	mblk_t	*ud_mp = nce->nce_res_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
	ptrdiff_t	cmplen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
	if (nce->nce_flags & NCE_F_MAPPING)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
	if ((nce->nce_fp_mp != NULL) || (ud_mp == NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
	ip2dbg(("ndp_fastpath_update: trying\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
	mp = (mblk_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
	mp_rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
	cmplen = mp->b_wptr - mp_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
	ASSERT(cmplen >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
	ud_mp_rptr = ud_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
	 * The nce is locked here to prevent any other threads
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
	 * from accessing and changing nce_res_mp when the IPv6 address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
	 * becomes resolved to an lla while we're in the middle
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
	 * of looking at and comparing the hardware address (lla).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
	 * It is also locked to prevent multiple threads in nce_fastpath_update
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
	 * from examining nce_res_mp atthe same time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
	if (ud_mp->b_wptr - ud_mp_rptr != cmplen ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
	    bcmp((char *)mp_rptr, (char *)ud_mp_rptr, cmplen) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2720
		 * Don't take the ire off the fastpath list yet,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2721
		 * since the response may come later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2722
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2723
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2724
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2725
	/* Matched - install mp as the fastpath mp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2726
	ip1dbg(("ndp_fastpath_update: match\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2727
	fp_mp = dupb(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2728
	if (fp_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2729
		nce->nce_fp_mp = fp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2730
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2731
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2732
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2733
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2735
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2736
 * This function handles the DL_NOTE_FASTPATH_FLUSH notification from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
 * driver.  Note that it assumes IP is exclusive...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2738
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2739
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2740
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2741
ndp_fastpath_flush(nce_t *nce, char *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2742
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2743
	if (nce->nce_flags & NCE_F_MAPPING)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2744
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2745
	/* No fastpath info? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2746
	if (nce->nce_fp_mp == NULL || nce->nce_res_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2747
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2748
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2749
	/* Just delete the NCE... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2750
	ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2751
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2753
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2754
 * Return a pointer to a given option in the packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2755
 * Assumes that option part of the packet have already been validated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2756
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2757
nd_opt_hdr_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2758
ndp_get_option(nd_opt_hdr_t *opt, int optlen, int opt_type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2759
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2760
	while (optlen > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2761
		if (opt->nd_opt_type == opt_type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2762
			return (opt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2763
		optlen -= 8 * opt->nd_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2764
		opt = (struct nd_opt_hdr *)((char *)opt + 8 * opt->nd_opt_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2765
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2766
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2767
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2769
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2770
 * Verify all option lengths present are > 0, also check to see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2771
 * if the option lengths and packet length are consistent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2772
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2773
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2774
ndp_verify_optlen(nd_opt_hdr_t *opt, int optlen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2775
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2776
	ASSERT(opt != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2777
	while (optlen > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2778
		if (opt->nd_opt_len == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2779
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2780
		optlen -= 8 * opt->nd_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2781
		if (optlen < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2782
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2783
		opt = (struct nd_opt_hdr *)((char *)opt + 8 * opt->nd_opt_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2784
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2785
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2786
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2789
 * ndp_walk function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2790
 * Free a fraction of the NCE cache entries.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
 * A fraction of zero means to not free any in that category.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
ndp_cache_reclaim(nce_t *nce, char *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
	nce_cache_reclaim_t *ncr = (nce_cache_reclaim_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2797
	uint_t	rand;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2798
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2799
	if (nce->nce_flags & NCE_F_PERMANENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2800
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
	rand = (uint_t)lbolt +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
	    NCE_ADDR_HASH_V6(nce->nce_addr, NCE_TABLE_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
	if (ncr->ncr_host != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
	    (rand/ncr->ncr_host)*ncr->ncr_host == rand) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
		ndp_delete(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2811
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
 * ndp_walk function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
 * Count the number of NCEs that can be deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
 * These would be hosts but not routers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
ndp_cache_count(nce_t *nce, char *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2819
	ncc_cache_count_t *ncc = (ncc_cache_count_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
	if (nce->nce_flags & NCE_F_PERMANENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
	ncc->ncc_total++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
	if (!(nce->nce_flags & NCE_F_ISROUTER))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
		ncc->ncc_host++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
#ifdef NCE_DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
th_trace_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
th_trace_nce_lookup(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
	int bucket_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2834
	th_trace_t *th_trace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2836
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
	bucket_id = IP_TR_HASH(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
	ASSERT(bucket_id < IP_TR_HASH_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
	for (th_trace = nce->nce_trace[bucket_id]; th_trace != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
	    th_trace = th_trace->th_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
		if (th_trace->th_id == curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
			return (th_trace);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2847
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
nce_trace_ref(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
	int bucket_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
	th_trace_t *th_trace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
	 * Attempt to locate the trace buffer for the curthread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
	 * If it does not exist, then allocate a new trace buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
	 * and link it in list of trace bufs for this ipif, at the head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2862
	if (nce->nce_trace_disable == B_TRUE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2863
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
	th_trace = th_trace_nce_lookup(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
	if (th_trace == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
		bucket_id = IP_TR_HASH(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
		th_trace = (th_trace_t *)kmem_zalloc(sizeof (th_trace_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
		    KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
		if (th_trace == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
			nce->nce_trace_disable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
			nce_trace_inactive(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2875
		th_trace->th_id = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2876
		th_trace->th_next = nce->nce_trace[bucket_id];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2877
		th_trace->th_prev = &nce->nce_trace[bucket_id];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2878
		if (th_trace->th_next != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2879
			th_trace->th_next->th_prev = &th_trace->th_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
		nce->nce_trace[bucket_id] = th_trace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2881
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2882
	ASSERT(th_trace->th_refcnt < TR_BUF_MAX - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2883
	th_trace->th_refcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2884
	th_trace_rrecord(th_trace);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2885
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2887
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2888
nce_untrace_ref(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2889
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2890
	th_trace_t *th_trace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2891
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2892
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2894
	if (nce->nce_trace_disable == B_TRUE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2895
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2896
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2897
	th_trace = th_trace_nce_lookup(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2898
	ASSERT(th_trace != NULL && th_trace->th_refcnt > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2899
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
	th_trace_rrecord(th_trace);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
	th_trace->th_refcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
nce_trace_inactive(nce_t *nce)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
	th_trace_t *th_trace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
	ASSERT(MUTEX_HELD(&nce->nce_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
	for (i = 0; i < IP_TR_HASH_MAX; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2913
		while (nce->nce_trace[i] != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
			th_trace = nce->nce_trace[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
			/* unlink th_trace and free it */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
			nce->nce_trace[i] = th_trace->th_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
			if (th_trace->th_next != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
				th_trace->th_next->th_prev =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
				    &nce->nce_trace[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
			th_trace->th_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
			th_trace->th_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
			kmem_free(th_trace, sizeof (th_trace_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2928
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
nce_thread_exit(nce_t *nce, caddr_t arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
	th_trace_t	*th_trace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
	mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2937
	th_trace = th_trace_nce_lookup(nce);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2939
	if (th_trace == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
		mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2941
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2942
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2943
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
	ASSERT(th_trace->th_refcnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
	/* unlink th_trace and free it */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
	*th_trace->th_prev = th_trace->th_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
	if (th_trace->th_next != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
		th_trace->th_next->th_prev = th_trace->th_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2950
	th_trace->th_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
	th_trace->th_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
	kmem_free(th_trace, sizeof (th_trace_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
	mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
#endif