ip_ndp.h revision 11042:2d6e217af1b4
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#ifndef	_INET_IP_NDP_H
27#define	_INET_IP_NDP_H
28
29#include <sys/mutex.h>
30#include <sys/stream.h>
31#include <netinet/in.h>
32#include <netinet/icmp6.h>
33#include <inet/ip.h>
34#include <inet/ip2mac.h>
35
36/*
37 * Internal definitions for the kernel implementation of the IPv6
38 * Neighbor Discovery Protocol (NDP) and Address Resolution Protocol (ARP).
39 */
40
41#ifdef	__cplusplus
42extern "C" {
43#endif
44
45#ifdef _KERNEL
46#define	NCE_TABLE_SIZE	256
47/*
48 * callbacks set up with ip2mac interface, waiting for result
49 * of neighbor resolution.
50 */
51typedef struct ncec_cb_s {
52	list_node_t		ncec_cb_node;	/* next entry in list */
53	void			*ncec_cb_id;
54	uint32_t		ncec_cb_flags;
55	ip2mac_callback_t	*ncec_cb_func;
56	void			*ncec_cb_arg;
57} ncec_cb_t;
58
59#define	NCE_CB_DISPATCHED	0x00000001
60
61/*
62 * Core information tracking Neighbor Reachability is tracked in the
63 * ncec_s/ncec_t. The information contained in the ncec_t does not contain
64 * any link-specific details other than the pointer to the ill_t itself.
65 * The link-specific information is tracked in the nce_t structure.
66 */
67struct ncec_s {
68	struct	ncec_s	*ncec_next;	/* Hash chain next pointer */
69	struct	ncec_s	**ncec_ptpn;	/* Pointer to previous next */
70	struct 	ill_s	*ncec_ill;	/* Associated ill */
71	uint16_t	ncec_flags;	/* See below */
72	uint16_t	ncec_state;	/* See reachability states in if.h */
73	int16_t		ncec_pcnt;	/* Probe counter */
74	uint16_t	ncec_rcnt;	/* Retransmit counter */
75	in6_addr_t	ncec_addr;	/* address of the nighbor */
76	uchar_t		*ncec_lladdr;
77	mblk_t		*ncec_qd_mp;	/* Head outgoing queued packets */
78	uint64_t	ncec_last;	/* Time last reachable in msec */
79	uint32_t	ncec_refcnt;	/* ncec active usage count */
80	kmutex_t	ncec_lock;	/* See comments on top for what */
81					/* this field protects */
82	int		ncec_unsolicit_count; /* Unsolicited Adv count */
83	timeout_id_t	ncec_timeout_id;
84	uchar_t		ncec_ipversion;	/* IPv4(ARP)/IPv6(NDP) version */
85	uint_t		ncec_defense_count;	/* number of NDP conflicts */
86	uint_t		ncec_last_time_defended; /* last time defended (secs) */
87	uint64_t	ncec_init_time; /* time when it was set to ND_INITIAL */
88	boolean_t	ncec_trace_disable;	/* True when alloc fails */
89	/*
90	 * interval to keep track of DAD probes.
91	 */
92	clock_t		ncec_xmit_interval;
93	ip_stack_t	*ncec_ipst;	/* Does not have a netstack_hold */
94	list_t		ncec_cb;	/* callbacks waiting for resolution */
95	uint_t		ncec_cb_walker_cnt;
96	uint_t		ncec_nprobes;
97	uint_t		ncec_lladdr_length;
98};
99
100/*
101 * The nce_t list hangs off the ill_s and tracks information that depends
102 * on the underlying physical link. Thus when the ill goes down,
103 * the nce_t list has to be flushed. This is  done as part of ill_delete()
104 *
105 * When the fastpath ack comes back in ill_fastpath_ack we call
106 * nce_fastpath_update to update the nce_t. We never actually
107 * flush the fastpath list, which is kept as an index into the
108 * ncec_t structures.
109 *
110 * when we ndp_delete, we remove the nce entries pointing
111 * at the dying ncec from the ill_fastpath_list chain.
112 *
113 */
114struct nce_s	{
115	list_node_t	nce_node;
116	ill_t		*nce_ill;
117	boolean_t	nce_is_condemned;
118	in6_addr_t	nce_addr;
119	/*
120	 * link-layer specific fields below
121	 */
122	mblk_t		*nce_dlur_mp;	/* DL_UNITDATA_REQ mp */
123	mblk_t		*nce_fp_mp;	/* fast path mp */
124	struct ncec_s	*nce_common;
125	kmutex_t	nce_lock;
126	uint32_t	nce_refcnt;
127	uint_t		nce_ipif_cnt;	/* number of ipifs with the nce_addr */
128					/* as their local address */
129};
130
131/*
132 * The ndp_g_t structure contains protocol specific information needed
133 * to synchronize and manage neighbor cache entries for IPv4 and IPv6.
134 * There are 2 such structures, ips_ndp4 and ips_ndp6.
135 * ips_ndp6 contains the data structures needed for IPv6 Neighbor Discovery.
136 * ips_ndp4 contains the data structures for IPv4 ARP.
137 *
138 * Locking notes:
139 * ndp_g_lock protects neighbor cache tables access and
140 * insertion/removal of cache entries into/from these tables. The ncec_lock
141 * and nce_lock protect fields in the ncec_t and nce_t structures.
142 * Should there be a need to obtain nce[c]_lock and ndp_g_lock, ndp_g_lock is
143 * acquired first.
144 */
145typedef	struct ndp_g_s {
146	kmutex_t	ndp_g_lock;	/* Lock protecting  cache hash table */
147	ncec_t		*nce_hash_tbl[NCE_TABLE_SIZE];
148	int		ndp_g_walker; /* # of active thread walking hash list */
149	boolean_t	ndp_g_walker_cleanup; /* true implies defer deletion. */
150} ndp_g_t;
151
152/* ncec_flags  */
153#define	NCE_F_MYADDR		0x1	/* ipif exists for the ncec_addr */
154#define	NCE_F_UNVERIFIED	0x2	/* DAD in progress. */
155#define	NCE_F_ISROUTER		0x4
156#define	NCE_F_FAST		0x8
157
158/*
159 * NCE_F_NONUD is used to disable IPv6 Neighbor Unreachability Detection or
160 * IPv4 aging and maps to the ATF_PERM flag for arp(1m)
161 */
162#define	NCE_F_NONUD		0x10
163
164#define	NCE_F_ANYCAST		0x20
165#define	NCE_F_CONDEMNED		0x40
166#define	NCE_F_UNSOL_ADV		0x80
167#define	NCE_F_BCAST		0x100
168#define	NCE_F_MCAST		0x200
169
170/*
171 * NCE_F_PUBLISH is set for all ARP/ND entries that we announce. This
172 * includes locally configured addresses as well as those that we proxy for.
173 */
174#define	NCE_F_PUBLISH		0x400
175
176/*
177 * NCE_F_AUTHORITY is set for any address that we have authoritatitve
178 * information for. This includes locally configured addresses as well
179 * as statically configured arp entries that are set up using the "permanent"
180 * option described in arp(1m). The NCE_F_AUTHORITY asserts that we would
181 * reject any updates for that nce's (host, link-layer-address) information
182 */
183#define	NCE_F_AUTHORITY		0x800
184
185#define	NCE_F_DELAYED		0x1000 /* rescheduled on dad_defend_rate */
186#define	NCE_F_STATIC		0x2000
187
188/* State REACHABLE, STALE, DELAY or PROBE */
189#define	NCE_ISREACHABLE(ncec)			\
190	(((((ncec)->ncec_state) >= ND_REACHABLE) &&	\
191	((ncec)->ncec_state) <= ND_PROBE))
192
193#define	NCE_ISCONDEMNED(ncec)	((ncec)->ncec_flags & NCE_F_CONDEMNED)
194
195/* NDP flags set in SOL/ADV requests */
196#define	NDP_UNICAST		0x1
197#define	NDP_ISROUTER		0x2
198#define	NDP_SOLICITED		0x4
199#define	NDP_ORIDE		0x8
200#define	NDP_PROBE		0x10
201
202/* Number of packets queued in NDP for a neighbor */
203#define	ND_MAX_Q		4
204
205/*
206 * Structure for nce_update_hw_changed;
207 */
208typedef struct {
209	ipaddr_t hwm_addr;	/* IPv4 address */
210	uint_t	hwm_hwlen;	/* Length of hardware address (may be 0) */
211	uchar_t *hwm_hwaddr;	/* Pointer to new hardware address, if any */
212	int	hwm_flags;
213} nce_hw_map_t;
214
215/* When SAP is greater than zero address appears before SAP */
216#define	NCE_LL_ADDR_OFFSET(ill)	(((ill)->ill_sap_length) < 0 ? \
217	(sizeof (dl_unitdata_req_t)) : \
218	((sizeof (dl_unitdata_req_t)) + (ABS((ill)->ill_sap_length))))
219
220#define	NCE_LL_SAP_OFFSET(ill) (((ill)->ill_sap_length) < 0 ? \
221	((sizeof (dl_unitdata_req_t)) + ((ill)->ill_phys_addr_length)) : \
222	(sizeof (dl_unitdata_req_t)))
223
224#define	NCE_MYADDR(ncec)	(((ncec)->ncec_flags & NCE_F_MYADDR) != 0)
225
226/*
227 * NCE_PUBLISH() identifies the addresses that we are publishing. This
228 * includes locally configured address (NCE_MYADDR()) as well as those that
229 * we are proxying.
230 */
231#define	NCE_PUBLISH(ncec) ((ncec->ncec_flags & NCE_F_PUBLISH) != 0)
232
233#ifdef _BIG_ENDIAN
234#define	NCE_LL_SAP_COPY(ill, mp) \
235	{ \
236	size_t abs_sap_len = ABS((ill)->ill_sap_length); \
237	if (abs_sap_len > 0) { \
238		ASSERT(abs_sap_len <= sizeof (uint32_t)); \
239		ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \
240		    abs_sap_len <= ((mp)->b_wptr)); \
241		bcopy((uint8_t *)&(ill)->ill_sap + sizeof (ill->ill_sap) - \
242		    abs_sap_len, \
243		    ((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \
244		    abs_sap_len); \
245	} \
246	}
247#else
248#define	NCE_LL_SAP_COPY(ill, mp) \
249	{ \
250	size_t abs_sap_len = ABS((ill)->ill_sap_length); \
251	if (abs_sap_len > 0) { \
252		uint32_t abs_sap_len = ABS((ill)->ill_sap_length); \
253		ASSERT(abs_sap_len <= sizeof (uint32_t)); \
254		ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \
255		    abs_sap_len <= ((mp)->b_wptr)); \
256		bcopy(&((ill)->ill_sap), \
257		((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \
258		abs_sap_len); \
259	} \
260	}
261#endif
262
263/*
264 * Exclusive-or the 6 bytes that are likely to contain the MAC
265 * address. Assumes table_size does not exceed 256.
266 * Assumes EUI-64 format for good hashing.
267 */
268#define	NCE_ADDR_HASH_V6(addr, table_size)				\
269	(((addr).s6_addr8[8] ^ (addr).s6_addr8[9] ^			\
270	(addr).s6_addr8[10] ^ (addr).s6_addr8[13] ^			\
271	(addr).s6_addr8[14] ^ (addr).s6_addr8[15]) % (table_size))
272
273/* NDP Cache Entry Hash Table */
274#define	NCE_TABLE_SIZE	256
275
276extern	void	ip_nce_reclaim(void *);
277extern	void	ncec_delete(ncec_t *);
278extern	void	ncec_delete_per_ill(ncec_t *, uchar_t *);
279extern	void	nce_fastpath_update(ill_t *, mblk_t  *);
280extern	nd_opt_hdr_t *ndp_get_option(nd_opt_hdr_t *, int, int);
281extern	void	ncec_inactive(ncec_t *);
282extern	void	ndp_input(mblk_t *, ip_recv_attr_t *);
283extern	ncec_t	*ncec_lookup_illgrp_v6(ill_t *, const in6_addr_t *);
284extern	ncec_t	*ncec_lookup_illgrp_v4(ill_t *, const in_addr_t *);
285extern	nce_t	*nce_lookup_v4(ill_t *, const in_addr_t *);
286extern	nce_t	*nce_lookup_v6(ill_t *, const in6_addr_t *);
287extern	void	nce_make_unreachable(ncec_t *);
288extern	mblk_t	*ndp_mcastreq(ill_t *, const in6_addr_t *, uint32_t, uint32_t,
289    mblk_t *);
290extern  nce_t	*ndp_nce_init(ill_t *, const in6_addr_t *, int);
291extern  void	nce_process(ncec_t *, uchar_t *, uint32_t, boolean_t);
292extern	int	ndp_query(ill_t *, lif_nd_req_t *);
293extern	int	ndp_sioc_update(ill_t *, lif_nd_req_t *);
294extern	boolean_t	ndp_verify_optlen(nd_opt_hdr_t *, int);
295extern	void	nce_timer(void *);
296extern	void	ncec_walk(ill_t *, pfi_t, void *, ip_stack_t *);
297extern	void	ncec_walk_common(ndp_g_t *, ill_t *, pfi_t,
298    void *, boolean_t);
299extern	boolean_t	nce_restart_dad(ncec_t *);
300extern	void	ndp_resolv_failed(ncec_t *);
301extern	void	arp_resolv_failed(ncec_t *);
302extern	void	nce_fastpath_list_delete(ill_t *, ncec_t *, list_t *);
303extern	void	nce_queue_mp(ncec_t *, mblk_t *, boolean_t);
304extern	void	nce_update_hw_changed(ncec_t *, void *);
305extern	int	nce_lookup_then_add_v6(ill_t *, uchar_t *, uint_t,
306    const in6_addr_t *, uint16_t, uint16_t, nce_t **);
307extern	int	nce_lookup_then_add_v4(ill_t *, uchar_t *, uint_t,
308    const in_addr_t *, uint16_t, uint16_t, nce_t **);
309extern boolean_t nce_cmp_ll_addr(const ncec_t *, const uchar_t *, uint32_t);
310extern void	nce_update(ncec_t *, uint16_t, uchar_t *);
311extern nce_t   *nce_lookup_mapping(ill_t *, const in6_addr_t *);
312
313extern void	nce_restart_timer(ncec_t *, uint_t);
314extern void	ncec_refrele(ncec_t *);
315extern void	ncec_refhold(ncec_t *);
316extern void	ncec_refrele_notr(ncec_t *);
317extern void	ncec_refhold_notr(ncec_t *);
318extern void	nce_resolv_ok(ncec_t *);
319extern uint32_t	ndp_solicit(ncec_t *, in6_addr_t, ill_t *);
320extern boolean_t ip_nce_conflict(mblk_t *, ip_recv_attr_t *, ncec_t *);
321extern boolean_t ndp_announce(ncec_t *);
322extern void	ip_nce_lookup_and_update(ipaddr_t *, ipif_t *, ip_stack_t *,
323    uchar_t *, int, int);
324extern void	nce_refrele(nce_t *);
325extern void	nce_refhold(nce_t *);
326extern void	nce_delete(nce_t *);
327extern void	nce_flush(ill_t *, boolean_t);
328extern void	nce_walk(ill_t *, pfi_t, void *);
329extern void	ip_ndp_resolve(struct ncec_s *);
330extern void	ip_addr_recover(ipsq_t *, queue_t *, mblk_t *, void *);
331
332#ifdef DEBUG
333extern	void	nce_trace_ref(ncec_t *);
334extern	void	nce_untrace_ref(ncec_t *);
335#endif
336
337#endif	/* _KERNEL */
338
339#ifdef	__cplusplus
340}
341#endif
342
343#endif	/* _INET_IP_NDP_H */
344