ip_ndp.h revision 1676:37f4a3e2bd99
1323134Sdes/* 298937Sdes * CDDL HEADER START 398937Sdes * 498937Sdes * The contents of this file are subject to the terms of the 598937Sdes * Common Development and Distribution License (the "License"). 6225825Sdes * You may not use this file except in compliance with the License. 798937Sdes * 898937Sdes * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9294332Sdes * or http://www.opensolaris.org/os/licensing. 1098937Sdes * See the License for the specific language governing permissions 1198937Sdes * and limitations under the License. 1298937Sdes * 1398937Sdes * When distributing Covered Code, include this CDDL HEADER in each 1498937Sdes * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15225825Sdes * If applicable, add the following below this CDDL HEADER, with the 16225825Sdes * fields enclosed by brackets "[]" replaced with your own identifying 17225825Sdes * information: Portions Copyright [yyyy] [name of copyright owner] 18225825Sdes * 19294332Sdes * CDDL HEADER END 20225825Sdes */ 21225825Sdes/* 22225825Sdes * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23225825Sdes * Use is subject to license terms. 24225825Sdes */ 25225825Sdes 26239849Sdes#ifndef _INET_IP_NDP_H 27239849Sdes#define _INET_IP_NDP_H 28239849Sdes 29323129Sdes#pragma ident "%Z%%M% %I% %E% SMI" 30323134Sdes 31323129Sdes/* 32323129Sdes * Internal definitions for the kernel implementation of the IPv6 33323129Sdes * Neighbor Discovery Protocol (NDP). 34323129Sdes */ 35294332Sdes 36239849Sdes#ifdef __cplusplus 37239849Sdesextern "C" { 38239849Sdes#endif 39239849Sdes 40239849Sdes#ifdef _KERNEL 41239849Sdes/* 42 * ndp_g_lock protects neighbor cache tables access and 43 * insertion/removal of cache entries into/from these tables. 44 * nce_lock protects nce_pcnt, nce_rcnt, nce_qd_mp nce_state, 45 * nce_res_mp, nce_refcnt and nce_last. 46 * nce_refcnt is incremented for every ire pointing to this nce and 47 * every time ndp_lookup() finds an nce. 48 * Should there be a need to obtain nce_lock and ndp_g_lock, ndp_g_lock is 49 * acquired first. 50 * To avoid becoming exclusive when deleting NCEs, ndp_walk() routine holds 51 * the ndp_g_lock (i.e global lock) and marks NCEs to be deleted with 52 * NCE_F_CONDEMNED. When all active users of such NCEs are gone the walk 53 * routine passes a list for deletion to nce_ire_delete_list(). 54 */ 55kmutex_t ndp_g_lock; /* Lock protecting nighbor cache hash table */ 56/* NDP Cache Entry */ 57typedef struct nce_s { 58 struct nce_s *nce_next; /* Hash chain next pointer */ 59 struct nce_s **nce_ptpn; /* Pointer to previous next */ 60 struct ill_s *nce_ill; /* Associated ill */ 61 uint16_t nce_flags; /* See below */ 62 uint16_t nce_state; /* See reachability states in if.h */ 63 int16_t nce_pcnt; /* Probe counter */ 64 uint16_t nce_rcnt; /* Retransmit counter */ 65 in6_addr_t nce_addr; /* address of the nighbor */ 66 in6_addr_t nce_mask; /* If not all ones, mask allows an */ 67 /* entry to respond to requests for a group of addresses, for */ 68 /* instantance multicast addresses */ 69 in6_addr_t nce_extract_mask; /* For mappings */ 70 uint32_t nce_ll_extract_start; /* For mappings */ 71#define nce_first_mp_to_free nce_fp_mp 72 mblk_t *nce_fp_mp; /* link layer fast path mp */ 73 mblk_t *nce_res_mp; /* DL_UNITDATA_REQ or link layer mp */ 74 mblk_t *nce_qd_mp; /* Head outgoing queued packets */ 75#define nce_last_mp_to_free nce_qd_mp 76 mblk_t *nce_timer_mp; /* NDP timer mblk */ 77 mblk_t *nce_mp; /* mblk we are in, last to be freed */ 78 uint64_t nce_last; /* Time last reachable in msec */ 79 uint32_t nce_refcnt; /* nce active usage count */ 80 kmutex_t nce_lock; /* See comments on top for what */ 81 /* this field protects */ 82 int nce_unsolicit_count; /* Unsolicited Adv count */ 83 struct nce_s *nce_fastpath; /* for fastpath list */ 84 timeout_id_t nce_timeout_id; 85#ifdef NCE_DEBUG 86 th_trace_t *nce_trace[IP_TR_HASH_MAX]; 87 boolean_t nce_trace_disable; /* True when alloc fails */ 88#endif 89} nce_t; 90 91/* nce_flags */ 92#define NCE_F_PERMANENT 0x1 93#define NCE_F_MAPPING 0x2 94#define NCE_F_ISROUTER 0x4 95#define NCE_F_PROXY 0x8 96#define NCE_F_NONUD 0x10 97#define NCE_F_ANYCAST 0x20 98#define NCE_F_CONDEMNED 0x40 99#define NCE_F_UNSOL_ADV 0x80 100 101#define NCE_EXTERNAL_FLAGS_MASK \ 102 (NCE_F_PERMANENT | NCE_F_MAPPING | NCE_F_ISROUTER | NCE_F_NONUD | \ 103 NCE_F_ANYCAST | NCE_F_UNSOL_ADV) 104 105/* State REACHABLE, STALE, DELAY or PROBE */ 106#define NCE_ISREACHABLE(nce) \ 107 (((((nce)->nce_state) >= ND_REACHABLE) && \ 108 ((nce)->nce_state) <= ND_PROBE)) 109 110/* NDP flags set in SOL/ADV requests */ 111#define NDP_UNICAST 0x1 112#define NDP_ISROUTER 0x2 113#define NDP_SOLICITED 0x4 114#define NDP_ORIDE 0x8 115 116/* Number of packets queued in NDP for a neighbor */ 117#define ND_MAX_Q 4 118 119 120#ifdef NCE_DEBUG 121#define NCE_TRACE_REF(nce) nce_trace_ref(nce) 122#define NCE_UNTRACE_REF(nce) nce_untrace_ref(nce) 123#else 124#define NCE_TRACE_REF(nce) 125#define NCE_UNTRACE_REF(nce) 126#endif 127 128#define NCE_REFHOLD(nce) { \ 129 mutex_enter(&(nce)->nce_lock); \ 130 (nce)->nce_refcnt++; \ 131 ASSERT((nce)->nce_refcnt != 0); \ 132 NCE_TRACE_REF(nce); \ 133 mutex_exit(&(nce)->nce_lock); \ 134} 135 136#define NCE_REFHOLD_NOTR(nce) { \ 137 mutex_enter(&(nce)->nce_lock); \ 138 (nce)->nce_refcnt++; \ 139 ASSERT((nce)->nce_refcnt != 0); \ 140 mutex_exit(&(nce)->nce_lock); \ 141} 142 143#define NCE_REFHOLD_LOCKED(nce) { \ 144 ASSERT(MUTEX_HELD(&(nce)->nce_lock)); \ 145 (nce)->nce_refcnt++; \ 146 NCE_TRACE_REF(nce); \ 147} 148 149/* nce_inactive destroys the mutex thus no mutex_exit is needed */ 150#define NCE_REFRELE(nce) { \ 151 mutex_enter(&(nce)->nce_lock); \ 152 NCE_UNTRACE_REF(nce); \ 153 ASSERT((nce)->nce_refcnt != 0); \ 154 if (--(nce)->nce_refcnt == 0) \ 155 ndp_inactive(nce); \ 156 else { \ 157 mutex_exit(&(nce)->nce_lock);\ 158 } \ 159} 160 161#define NCE_REFRELE_NOTR(nce) { \ 162 mutex_enter(&(nce)->nce_lock); \ 163 ASSERT((nce)->nce_refcnt != 0); \ 164 if (--(nce)->nce_refcnt == 0) \ 165 ndp_inactive(nce); \ 166 else { \ 167 mutex_exit(&(nce)->nce_lock);\ 168 } \ 169} 170 171#define NDP_RESTART_TIMER(nce, ms) { \ 172 ASSERT(!MUTEX_HELD(&(nce)->nce_lock)); \ 173 if ((nce)->nce_timeout_id != 0) { \ 174 /* Ok to untimeout bad id. we don't hold a lock. */ \ 175 (void) untimeout((nce)->nce_timeout_id); \ 176 } \ 177 mutex_enter(&(nce)->nce_lock); \ 178 /* Don't start the timer if the nce has been deleted */ \ 179 if (!((nce)->nce_flags & NCE_F_CONDEMNED)) \ 180 nce->nce_timeout_id = timeout(ndp_timer, nce, \ 181 MSEC_TO_TICK(ms) == 0 ? 1 : MSEC_TO_TICK(ms)); \ 182 mutex_exit(&(nce)->nce_lock); \ 183} 184 185/* Structure for ndp_cache_count() */ 186typedef struct { 187 int ncc_total; /* Total number of NCEs */ 188 int ncc_host; /* NCE entries without R bit set */ 189} ncc_cache_count_t; 190 191/* 192 * Structure of ndp_cache_reclaim(). Each field is a fraction i.e. 1 means 193 * reclaim all, N means reclaim 1/Nth of all entries, 0 means reclaim none. 194 */ 195typedef struct { 196 int ncr_host; /* Fraction for host entries */ 197} nce_cache_reclaim_t; 198 199/* When SAP is greater than zero address appears before SAP */ 200#define NCE_LL_ADDR_OFFSET(ill) (((ill)->ill_sap_length) < 0 ? \ 201 (sizeof (dl_unitdata_req_t)) : \ 202 ((sizeof (dl_unitdata_req_t)) + (ABS((ill)->ill_sap_length)))) 203 204#define NCE_LL_SAP_OFFSET(ill) (((ill)->ill_sap_length) < 0 ? \ 205 ((sizeof (dl_unitdata_req_t)) + ((ill)->ill_phys_addr_length)) : \ 206 (sizeof (dl_unitdata_req_t))) 207 208#ifdef _BIG_ENDIAN 209#define NCE_LL_SAP_COPY(ill, mp) \ 210 { \ 211 size_t abs_sap_len = ABS((ill)->ill_sap_length); \ 212 if (abs_sap_len > 0) { \ 213 ASSERT(abs_sap_len <= sizeof (uint32_t)); \ 214 ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \ 215 abs_sap_len <= ((mp)->b_wptr)); \ 216 bcopy((uint8_t *)&(ill)->ill_sap + sizeof (ill->ill_sap) - \ 217 abs_sap_len, \ 218 ((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \ 219 abs_sap_len); \ 220 } \ 221 } 222#else 223#define NCE_LL_SAP_COPY(ill, mp) \ 224 { \ 225 size_t abs_sap_len = ABS((ill)->ill_sap_length); \ 226 if (abs_sap_len > 0) { \ 227 uint32_t abs_sap_len = ABS((ill)->ill_sap_length); \ 228 ASSERT(abs_sap_len <= sizeof (uint32_t)); \ 229 ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \ 230 abs_sap_len <= ((mp)->b_wptr)); \ 231 bcopy(&((ill)->ill_sap), \ 232 ((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \ 233 abs_sap_len); \ 234 } \ 235 } 236#endif 237 238/* 239 * Exclusive-or the 6 bytes that are likely to contain the MAC 240 * address. Assumes table_size does not exceed 256. 241 * Assumes EUI-64 format for good hashing. 242 */ 243#define NCE_ADDR_HASH_V6(addr, table_size) \ 244 (((addr).s6_addr8[8] ^ (addr).s6_addr8[9] ^ \ 245 (addr).s6_addr8[10] ^ (addr).s6_addr8[13] ^ \ 246 (addr).s6_addr8[14] ^ (addr).s6_addr8[15]) % (table_size)) 247 248extern void ndp_cache_count(nce_t *, char *); 249extern void ndp_cache_reclaim(nce_t *, char *); 250extern void ndp_delete(nce_t *); 251extern void ndp_delete_per_ill(nce_t *, uchar_t *); 252extern void ndp_fastpath_flush(nce_t *, char *); 253extern boolean_t ndp_fastpath_update(nce_t *, void *); 254extern nd_opt_hdr_t *ndp_get_option(nd_opt_hdr_t *, int, int); 255extern void ndp_inactive(nce_t *); 256extern void ndp_input(ill_t *, mblk_t *); 257extern nce_t *ndp_lookup(ill_t *, const in6_addr_t *, boolean_t); 258extern int ndp_lookup_then_add(ill_t *, uchar_t *, const in6_addr_t *, 259 const in6_addr_t *, const in6_addr_t *, uint32_t, uint16_t, 260 uint16_t, nce_t **); 261extern int ndp_mcastreq(ill_t *, const in6_addr_t *, uint32_t, uint32_t, 262 mblk_t *); 263extern int ndp_noresolver(ill_t *, const in6_addr_t *); 264extern void ndp_process(nce_t *, uchar_t *, uint32_t, boolean_t); 265extern int ndp_query(ill_t *, lif_nd_req_t *); 266extern int ndp_report(queue_t *, mblk_t *, caddr_t, cred_t *); 267extern int ndp_resolver(ill_t *, const in6_addr_t *, mblk_t *, zoneid_t); 268extern int ndp_sioc_update(ill_t *, lif_nd_req_t *); 269extern boolean_t ndp_verify_optlen(nd_opt_hdr_t *, int); 270extern void ndp_timer(void *); 271extern void ndp_walk(ill_t *, pfi_t, void *); 272extern void ndp_walk_impl(ill_t *, pfi_t, void *, boolean_t); 273extern int ndp_add(ill_t *, uchar_t *, const in6_addr_t *, 274 const in6_addr_t *, const in6_addr_t *, 275 uint32_t, uint16_t, uint16_t, nce_t **); 276extern void nce_resolv_failed(nce_t *); 277extern void nce_fastpath_list_add(nce_t *); 278extern void nce_fastpath_list_delete(nce_t *); 279extern void nce_fastpath_list_dispatch(ill_t *, 280 boolean_t (*)(nce_t *, void *), void *); 281#ifdef NCE_DEBUG 282extern void nce_trace_inactive(nce_t *); 283extern void nce_trace_ref(nce_t *); 284extern void nce_untrace_ref(nce_t *); 285extern int nce_thread_exit(nce_t *, caddr_t); 286#endif 287 288#endif /* _KERNEL */ 289 290#ifdef __cplusplus 291} 292#endif 293 294#endif /* _INET_IP_NDP_H */ 295