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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #ifndef _INET_IP_NDP_H
27 #define _INET_IP_NDP_H
29 #include <sys/mutex.h>
30 #include <sys/stream.h>
31 #include <netinet/in.h>
32 #include <netinet/icmp6.h>
34 #include <inet/ip2mac.h>
37 * Internal definitions for the kernel implementation of the IPv6
38 * Neighbor Discovery Protocol (NDP) and Address Resolution Protocol (ARP).
46 #define NCE_TABLE_SIZE 256
48 * callbacks set up with ip2mac interface, waiting for result
49 * of neighbor resolution.
51 typedef struct ncec_cb_s
{
52 list_node_t ncec_cb_node
; /* next entry in list */
54 uint32_t ncec_cb_flags
;
55 ip2mac_callback_t
*ncec_cb_func
;
59 #define NCE_CB_DISPATCHED 0x00000001
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.
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 */
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 */
90 * interval to keep track of DAD probes.
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
;
97 uint_t ncec_lladdr_length
;
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()
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
110 * when we ndp_delete, we remove the nce entries pointing
111 * at the dying ncec from the ill_fastpath_list chain.
115 list_node_t nce_node
;
117 boolean_t nce_is_condemned
;
120 * link-layer specific fields below
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
;
127 uint_t nce_ipif_cnt
; /* number of ipifs with the nce_addr */
128 /* as their local address */
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.
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
145 typedef 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. */
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
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)
162 #define NCE_F_NONUD 0x10
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
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.
174 #define NCE_F_PUBLISH 0x400
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
183 #define NCE_F_AUTHORITY 0x800
185 #define NCE_F_DELAYED 0x1000 /* rescheduled on dad_defend_rate */
186 #define NCE_F_STATIC 0x2000
188 /* State REACHABLE, STALE, DELAY or PROBE */
189 #define NCE_ISREACHABLE(ncec) \
190 (((((ncec)->ncec_state) >= ND_REACHABLE) && \
191 ((ncec)->ncec_state) <= ND_PROBE))
193 #define NCE_ISCONDEMNED(ncec) ((ncec)->ncec_flags & NCE_F_CONDEMNED)
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
202 /* Number of packets queued in NDP for a neighbor */
206 * Structure for nce_update_hw_changed;
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 */
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))))
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)))
224 #define NCE_MYADDR(ncec) (((ncec)->ncec_flags & NCE_F_MYADDR) != 0)
227 * NCE_PUBLISH() identifies the addresses that we are publishing. This
228 * includes locally configured address (NCE_MYADDR()) as well as those that
231 #define NCE_PUBLISH(ncec) ((ncec->ncec_flags & NCE_F_PUBLISH) != 0)
234 #define NCE_LL_SAP_COPY(ill, mp) \
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) - \
243 ((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \
248 #define NCE_LL_SAP_COPY(ill, mp) \
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)), \
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.
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))
273 /* NDP Cache Entry Hash Table */
274 #define NCE_TABLE_SIZE 256
276 extern void ip_nce_reclaim(void *);
277 extern void ncec_delete(ncec_t
*);
278 extern void ncec_delete_per_ill(ncec_t
*, uchar_t
*);
279 extern void nce_fastpath_update(ill_t
*, mblk_t
*);
280 extern nd_opt_hdr_t
*ndp_get_option(nd_opt_hdr_t
*, int, int);
281 extern void ncec_inactive(ncec_t
*);
282 extern void ndp_input(mblk_t
*, ip_recv_attr_t
*);
283 extern ncec_t
*ncec_lookup_illgrp_v6(ill_t
*, const in6_addr_t
*);
284 extern ncec_t
*ncec_lookup_illgrp_v4(ill_t
*, const in_addr_t
*);
285 extern nce_t
*nce_lookup_v4(ill_t
*, const in_addr_t
*);
286 extern nce_t
*nce_lookup_v6(ill_t
*, const in6_addr_t
*);
287 extern void nce_make_unreachable(ncec_t
*);
288 extern mblk_t
*ndp_mcastreq(ill_t
*, const in6_addr_t
*, uint32_t, uint32_t,
290 extern nce_t
*ndp_nce_init(ill_t
*, const in6_addr_t
*, int);
291 extern void nce_process(ncec_t
*, uchar_t
*, uint32_t, boolean_t
);
292 extern int ndp_query(ill_t
*, lif_nd_req_t
*);
293 extern int ndp_sioc_update(ill_t
*, lif_nd_req_t
*);
294 extern boolean_t
ndp_verify_optlen(nd_opt_hdr_t
*, int);
295 extern void nce_timer(void *);
296 extern void ncec_walk(ill_t
*, pfi_t
, void *, ip_stack_t
*);
297 extern void ncec_walk_common(ndp_g_t
*, ill_t
*, pfi_t
,
299 extern boolean_t
nce_restart_dad(ncec_t
*);
300 extern void ndp_resolv_failed(ncec_t
*);
301 extern void arp_resolv_failed(ncec_t
*);
302 extern void nce_fastpath_list_delete(ill_t
*, ncec_t
*, list_t
*);
303 extern void nce_queue_mp(ncec_t
*, mblk_t
*, boolean_t
);
304 extern void nce_update_hw_changed(ncec_t
*, void *);
305 extern int nce_lookup_then_add_v6(ill_t
*, uchar_t
*, uint_t
,
306 const in6_addr_t
*, uint16_t, uint16_t, nce_t
**);
307 extern int nce_lookup_then_add_v4(ill_t
*, uchar_t
*, uint_t
,
308 const in_addr_t
*, uint16_t, uint16_t, nce_t
**);
309 extern boolean_t
nce_cmp_ll_addr(const ncec_t
*, const uchar_t
*, uint32_t);
310 extern void nce_update(ncec_t
*, uint16_t, uchar_t
*);
311 extern nce_t
*nce_lookup_mapping(ill_t
*, const in6_addr_t
*);
313 extern void nce_restart_timer(ncec_t
*, uint_t
);
314 extern void ncec_refrele(ncec_t
*);
315 extern void ncec_refhold(ncec_t
*);
316 extern void ncec_refrele_notr(ncec_t
*);
317 extern void ncec_refhold_notr(ncec_t
*);
318 extern void nce_resolv_ok(ncec_t
*);
319 extern uint32_t ndp_solicit(ncec_t
*, in6_addr_t
, ill_t
*);
320 extern boolean_t
ip_nce_conflict(mblk_t
*, ip_recv_attr_t
*, ncec_t
*);
321 extern boolean_t
ndp_announce(ncec_t
*);
322 extern void ip_nce_lookup_and_update(ipaddr_t
*, ipif_t
*, ip_stack_t
*,
323 uchar_t
*, int, int);
324 extern void nce_refrele(nce_t
*);
325 extern void nce_refhold(nce_t
*);
326 extern void nce_delete(nce_t
*);
327 extern void nce_flush(ill_t
*, boolean_t
);
328 extern void nce_walk(ill_t
*, pfi_t
, void *);
329 extern void ip_ndp_resolve(struct ncec_s
*);
330 extern void ip_addr_recover(ipsq_t
*, queue_t
*, mblk_t
*, void *);
333 extern void nce_trace_ref(ncec_t
*);
334 extern void nce_untrace_ref(ncec_t
*);
343 #endif /* _INET_IP_NDP_H */