ip_ndp.c (309fa174) ip_ndp.c (c793af95)
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

--- 56 unchanged lines hidden (view full) ---

65 */
66
67static boolean_t nce_cmp_ll_addr(nce_t *nce, char *new_ll_addr,
68 uint32_t ll_addr_len);
69static void nce_fastpath(nce_t *nce);
70static void nce_ire_delete(nce_t *nce);
71static void nce_ire_delete1(ire_t *ire, char *nce_arg);
72static void nce_set_ll(nce_t *nce, uchar_t *ll_addr);
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

--- 56 unchanged lines hidden (view full) ---

65 */
66
67static boolean_t nce_cmp_ll_addr(nce_t *nce, char *new_ll_addr,
68 uint32_t ll_addr_len);
69static void nce_fastpath(nce_t *nce);
70static void nce_ire_delete(nce_t *nce);
71static void nce_ire_delete1(ire_t *ire, char *nce_arg);
72static void nce_set_ll(nce_t *nce, uchar_t *ll_addr);
73static nce_t *nce_lookup_addr(ill_t *ill, const in6_addr_t *addr);
73static nce_t *nce_lookup_addr(ill_t *, const in6_addr_t *, nce_t *);
74static nce_t *nce_lookup_mapping(ill_t *ill, const in6_addr_t *addr);
75static void nce_make_mapping(nce_t *nce, uchar_t *addrpos,
76 uchar_t *addr);
77static int nce_set_multicast(ill_t *ill, const in6_addr_t *addr);
78static void nce_queue_mp(nce_t *nce, mblk_t *mp);
79static void nce_report1(nce_t *nce, uchar_t *mp_arg);
80static mblk_t *nce_udreq_alloc(ill_t *ill);
81static void nce_update(nce_t *nce, uint16_t new_state,
82 uchar_t *new_ll_addr);
83static uint32_t nce_solicit(nce_t *nce, mblk_t *mp);
84static boolean_t nce_xmit(ill_t *ill, uint32_t operation,
85 ill_t *hwaddr_ill, boolean_t use_lla_addr, const in6_addr_t *sender,
86 const in6_addr_t *target, int flag);
87static void lla2ascii(uint8_t *lla, int addrlen, uchar_t *buf);
88extern void th_trace_rrecord(th_trace_t *);
74static nce_t *nce_lookup_mapping(ill_t *ill, const in6_addr_t *addr);
75static void nce_make_mapping(nce_t *nce, uchar_t *addrpos,
76 uchar_t *addr);
77static int nce_set_multicast(ill_t *ill, const in6_addr_t *addr);
78static void nce_queue_mp(nce_t *nce, mblk_t *mp);
79static void nce_report1(nce_t *nce, uchar_t *mp_arg);
80static mblk_t *nce_udreq_alloc(ill_t *ill);
81static void nce_update(nce_t *nce, uint16_t new_state,
82 uchar_t *new_ll_addr);
83static uint32_t nce_solicit(nce_t *nce, mblk_t *mp);
84static boolean_t nce_xmit(ill_t *ill, uint32_t operation,
85 ill_t *hwaddr_ill, boolean_t use_lla_addr, const in6_addr_t *sender,
86 const in6_addr_t *target, int flag);
87static void lla2ascii(uint8_t *lla, int addrlen, uchar_t *buf);
88extern void th_trace_rrecord(th_trace_t *);
89static int ndp_lookup_then_add_v6(ill_t *, uchar_t *,
90 const in6_addr_t *, const in6_addr_t *, const in6_addr_t *,
91 uint32_t, uint16_t, uint16_t, nce_t **, mblk_t *, mblk_t *);
92static int ndp_lookup_then_add_v4(ill_t *, uchar_t *,
93 const in_addr_t *, const in_addr_t *, const in_addr_t *,
94 uint32_t, uint16_t, uint16_t, nce_t **, mblk_t *, mblk_t *);
95static int ndp_add_v6(ill_t *, uchar_t *, const in6_addr_t *,
96 const in6_addr_t *, const in6_addr_t *, uint32_t, uint16_t, uint16_t,
97 nce_t **);
98static int ndp_add_v4(ill_t *, uchar_t *, const in_addr_t *,
99 const in_addr_t *, const in_addr_t *, uint32_t, uint16_t, uint16_t,
100 nce_t **, mblk_t *, mblk_t *);
89
101
102
90#ifdef NCE_DEBUG
91void nce_trace_inactive(nce_t *);
92#endif
93
103#ifdef NCE_DEBUG
104void nce_trace_inactive(nce_t *);
105#endif
106
94/* NDP Cache Entry Hash Table */
95#define NCE_TABLE_SIZE 256
96static nce_t *nce_hash_tbl[NCE_TABLE_SIZE];
97static nce_t *nce_mask_entries; /* mask not all ones */
98static int ndp_g_walker = 0; /* # of active thread */
99 /* walking nce hash list */
100/* ndp_g_walker_cleanup will be true, when deletion have to be defered */
101static boolean_t ndp_g_walker_cleanup = B_FALSE;
107ndp_g_t ndp4, ndp6;
102
108
103#define NCE_HASH_PTR(addr) \
104 (&(nce_hash_tbl[NCE_ADDR_HASH_V6(addr, NCE_TABLE_SIZE)]))
109#define NCE_HASH_PTR_V4(addr) \
110 (&(ndp4.nce_hash_tbl[IRE_ADDR_HASH(addr, NCE_TABLE_SIZE)]))
105
111
112#define NCE_HASH_PTR_V6(addr) \
113 (&(ndp6.nce_hash_tbl[NCE_ADDR_HASH_V6(addr, NCE_TABLE_SIZE)]))
114
115int
116ndp_add(ill_t *ill, uchar_t *hw_addr, const void *addr,
117 const void *mask, const void *extract_mask,
118 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
119 nce_t **newnce, mblk_t *fp_mp, mblk_t *res_mp)
120{
121 int status;
122
123 if (ill->ill_isv6)
124 status = ndp_add_v6(ill, hw_addr, (in6_addr_t *)addr,
125 (in6_addr_t *)mask, (in6_addr_t *)extract_mask,
126 hw_extract_start, flags, state, newnce);
127 else
128 status = ndp_add_v4(ill, hw_addr, (in_addr_t *)addr,
129 (in_addr_t *)mask, (in_addr_t *)extract_mask,
130 hw_extract_start, flags, state, newnce, fp_mp, res_mp);
131 return (status);
132}
133
106/*
107 * NDP Cache Entry creation routine.
108 * Mapped entries will never do NUD .
134/*
135 * NDP Cache Entry creation routine.
136 * Mapped entries will never do NUD .
109 * This routine must always be called with ndp_g_lock held.
137 * This routine must always be called with ndp6.ndp_g_lock held.
110 * Prior to return, nce_refcnt is incremented.
111 */
138 * Prior to return, nce_refcnt is incremented.
139 */
112int
113ndp_add(ill_t *ill, uchar_t *hw_addr, const in6_addr_t *addr,
140static int
141ndp_add_v6(ill_t *ill, uchar_t *hw_addr, const in6_addr_t *addr,
114 const in6_addr_t *mask, const in6_addr_t *extract_mask,
115 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
116 nce_t **newnce)
117{
142 const in6_addr_t *mask, const in6_addr_t *extract_mask,
143 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
144 nce_t **newnce)
145{
118static nce_t nce_nil;
146 static nce_t nce_nil;
119 nce_t *nce;
120 mblk_t *mp;
121 mblk_t *template;
122 nce_t **ncep;
123 boolean_t dropped = B_FALSE;
124
147 nce_t *nce;
148 mblk_t *mp;
149 mblk_t *template;
150 nce_t **ncep;
151 boolean_t dropped = B_FALSE;
152
125 ASSERT(MUTEX_HELD(&ndp_g_lock));
126 ASSERT(ill != NULL);
153 ASSERT(MUTEX_HELD(&ndp6.ndp_g_lock));
154 ASSERT(ill != NULL && ill->ill_isv6);
127 if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
128 ip0dbg(("ndp_add: no addr\n"));
129 return (EINVAL);
130 }
131 if ((flags & ~NCE_EXTERNAL_FLAGS_MASK)) {
132 ip0dbg(("ndp_add: flags = %x\n", (int)flags));
133 return (EINVAL);
134 }

--- 27 unchanged lines hidden (view full) ---

162 ASSERT((ill->ill_resolver_mp != NULL));
163 template = copyb(ill->ill_resolver_mp);
164 }
165 if (template == NULL) {
166 freeb(mp);
167 return (ENOMEM);
168 }
169 nce->nce_ill = ill;
155 if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
156 ip0dbg(("ndp_add: no addr\n"));
157 return (EINVAL);
158 }
159 if ((flags & ~NCE_EXTERNAL_FLAGS_MASK)) {
160 ip0dbg(("ndp_add: flags = %x\n", (int)flags));
161 return (EINVAL);
162 }

--- 27 unchanged lines hidden (view full) ---

190 ASSERT((ill->ill_resolver_mp != NULL));
191 template = copyb(ill->ill_resolver_mp);
192 }
193 if (template == NULL) {
194 freeb(mp);
195 return (ENOMEM);
196 }
197 nce->nce_ill = ill;
198 nce->nce_ipversion = IPV6_VERSION;
170 nce->nce_flags = flags;
171 nce->nce_state = state;
172 nce->nce_pcnt = ND_MAX_UNICAST_SOLICIT;
173 nce->nce_rcnt = ill->ill_xmit_count;
174 nce->nce_addr = *addr;
175 nce->nce_mask = *mask;
176 nce->nce_extract_mask = *extract_mask;
177 nce->nce_ll_extract_start = hw_extract_start;

--- 9 unchanged lines hidden (view full) ---

187 nce_set_ll(nce, hw_addr);
188 /* This one is for nce getting created */
189 nce->nce_refcnt = 1;
190 mutex_init(&nce->nce_lock, NULL, MUTEX_DEFAULT, NULL);
191 if (nce->nce_flags & NCE_F_MAPPING) {
192 ASSERT(IN6_IS_ADDR_MULTICAST(addr));
193 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&nce->nce_mask));
194 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&nce->nce_extract_mask));
199 nce->nce_flags = flags;
200 nce->nce_state = state;
201 nce->nce_pcnt = ND_MAX_UNICAST_SOLICIT;
202 nce->nce_rcnt = ill->ill_xmit_count;
203 nce->nce_addr = *addr;
204 nce->nce_mask = *mask;
205 nce->nce_extract_mask = *extract_mask;
206 nce->nce_ll_extract_start = hw_extract_start;

--- 9 unchanged lines hidden (view full) ---

216 nce_set_ll(nce, hw_addr);
217 /* This one is for nce getting created */
218 nce->nce_refcnt = 1;
219 mutex_init(&nce->nce_lock, NULL, MUTEX_DEFAULT, NULL);
220 if (nce->nce_flags & NCE_F_MAPPING) {
221 ASSERT(IN6_IS_ADDR_MULTICAST(addr));
222 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&nce->nce_mask));
223 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&nce->nce_extract_mask));
195 ncep = &nce_mask_entries;
224 ncep = &ndp6.nce_mask_entries;
196 } else {
225 } else {
197 ncep = ((nce_t **)NCE_HASH_PTR(*addr));
226 ncep = ((nce_t **)NCE_HASH_PTR_V6(*addr));
198 }
199
200#ifdef NCE_DEBUG
201 bzero(nce->nce_trace, sizeof (th_trace_t *) * IP_TR_HASH_MAX);
202#endif
203 /*
204 * Atomically ensure that the ill is not CONDEMNED, before
205 * adding the NCE.

--- 24 unchanged lines hidden (view full) ---

230 if (flags & NCE_F_UNSOL_ADV) {
231 flags |= NDP_ORIDE;
232 /*
233 * We account for the transmit below by assigning one
234 * less than the ndd variable. Subsequent decrements
235 * are done in ndp_timer.
236 */
237 mutex_enter(&nce->nce_lock);
227 }
228
229#ifdef NCE_DEBUG
230 bzero(nce->nce_trace, sizeof (th_trace_t *) * IP_TR_HASH_MAX);
231#endif
232 /*
233 * Atomically ensure that the ill is not CONDEMNED, before
234 * adding the NCE.

--- 24 unchanged lines hidden (view full) ---

259 if (flags & NCE_F_UNSOL_ADV) {
260 flags |= NDP_ORIDE;
261 /*
262 * We account for the transmit below by assigning one
263 * less than the ndd variable. Subsequent decrements
264 * are done in ndp_timer.
265 */
266 mutex_enter(&nce->nce_lock);
238 mutex_exit(&ndp_g_lock);
267 mutex_exit(&ndp6.ndp_g_lock);
239 nce->nce_unsolicit_count = ip_ndp_unsolicit_count - 1;
240 mutex_exit(&nce->nce_lock);
241 dropped = nce_xmit(ill,
242 ND_NEIGHBOR_ADVERT,
243 ill, /* ill to be used for extracting ill_nd_lla */
244 B_TRUE, /* use ill_nd_lla */
245 addr, /* Source and target of the advertisement pkt */
246 &ipv6_all_hosts_mcast, /* Destination of the packet */
247 flags);
248 mutex_enter(&nce->nce_lock);
249 if (dropped)
250 nce->nce_unsolicit_count++;
251 if (nce->nce_unsolicit_count != 0) {
252 nce->nce_timeout_id = timeout(ndp_timer, nce,
253 MSEC_TO_TICK(ip_ndp_unsolicit_interval));
254 }
255 mutex_exit(&nce->nce_lock);
268 nce->nce_unsolicit_count = ip_ndp_unsolicit_count - 1;
269 mutex_exit(&nce->nce_lock);
270 dropped = nce_xmit(ill,
271 ND_NEIGHBOR_ADVERT,
272 ill, /* ill to be used for extracting ill_nd_lla */
273 B_TRUE, /* use ill_nd_lla */
274 addr, /* Source and target of the advertisement pkt */
275 &ipv6_all_hosts_mcast, /* Destination of the packet */
276 flags);
277 mutex_enter(&nce->nce_lock);
278 if (dropped)
279 nce->nce_unsolicit_count++;
280 if (nce->nce_unsolicit_count != 0) {
281 nce->nce_timeout_id = timeout(ndp_timer, nce,
282 MSEC_TO_TICK(ip_ndp_unsolicit_interval));
283 }
284 mutex_exit(&nce->nce_lock);
256 mutex_enter(&ndp_g_lock);
285 mutex_enter(&ndp6.ndp_g_lock);
257 }
258 /*
259 * If the hw_addr is NULL, typically for ND_INCOMPLETE nces, then
260 * we call nce_fastpath as soon as the nce is resolved in ndp_process.
261 * We call nce_fastpath from nce_update if the link layer address of
262 * the peer changes from nce_update
263 */
264 if (hw_addr != NULL || ill->ill_net_type == IRE_IF_NORESOLVER)
265 nce_fastpath(nce);
266 return (0);
267}
268
269int
286 }
287 /*
288 * If the hw_addr is NULL, typically for ND_INCOMPLETE nces, then
289 * we call nce_fastpath as soon as the nce is resolved in ndp_process.
290 * We call nce_fastpath from nce_update if the link layer address of
291 * the peer changes from nce_update
292 */
293 if (hw_addr != NULL || ill->ill_net_type == IRE_IF_NORESOLVER)
294 nce_fastpath(nce);
295 return (0);
296}
297
298int
270ndp_lookup_then_add(ill_t *ill, uchar_t *hw_addr, const in6_addr_t *addr,
299ndp_lookup_then_add(ill_t *ill, uchar_t *hw_addr, const void *addr,
300 const void *mask, const void *extract_mask,
301 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
302 nce_t **newnce, mblk_t *fp_mp, mblk_t *res_mp)
303{
304 int status;
305
306 if (ill->ill_isv6) {
307 status = ndp_lookup_then_add_v6(ill, hw_addr,
308 (in6_addr_t *)addr, (in6_addr_t *)mask,
309 (in6_addr_t *)extract_mask, hw_extract_start, flags,
310 state, newnce, fp_mp, res_mp);
311 } else {
312 status = ndp_lookup_then_add_v4(ill, hw_addr,
313 (in_addr_t *)addr, (in_addr_t *)mask,
314 (in_addr_t *)extract_mask, hw_extract_start, flags,
315 state, newnce, fp_mp, res_mp);
316 }
317
318 return (status);
319}
320
321static int
322ndp_lookup_then_add_v6(ill_t *ill, uchar_t *hw_addr, const in6_addr_t *addr,
271 const in6_addr_t *mask, const in6_addr_t *extract_mask,
272 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
323 const in6_addr_t *mask, const in6_addr_t *extract_mask,
324 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
273 nce_t **newnce)
325 nce_t **newnce, mblk_t *fp_mp, mblk_t *res_mp)
274{
275 int err = 0;
276 nce_t *nce;
277
326{
327 int err = 0;
328 nce_t *nce;
329
278 mutex_enter(&ndp_g_lock);
279 nce = nce_lookup_addr(ill, addr);
330 ASSERT(ill != NULL && ill->ill_isv6);
331 mutex_enter(&ndp6.ndp_g_lock);
332 nce = *((nce_t **)NCE_HASH_PTR_V6(*addr)); /* head of v6 hash table */
333 nce = nce_lookup_addr(ill, addr, nce);
280 if (nce == NULL) {
281 err = ndp_add(ill,
282 hw_addr,
283 addr,
284 mask,
285 extract_mask,
286 hw_extract_start,
287 flags,
288 state,
334 if (nce == NULL) {
335 err = ndp_add(ill,
336 hw_addr,
337 addr,
338 mask,
339 extract_mask,
340 hw_extract_start,
341 flags,
342 state,
289 newnce);
343 newnce,
344 fp_mp,
345 res_mp);
290 } else {
291 *newnce = nce;
292 err = EEXIST;
293 }
346 } else {
347 *newnce = nce;
348 err = EEXIST;
349 }
294 mutex_exit(&ndp_g_lock);
350 mutex_exit(&ndp6.ndp_g_lock);
295 return (err);
296}
297
298/*
299 * Remove all the CONDEMNED nces from the appropriate hash table.
300 * We create a private list of NCEs, these may have ires pointing
301 * to them, so the list will be passed through to clean up dependent
302 * ires and only then we can do NCE_REFRELE which can make NCE inactive.
303 */
304static void
351 return (err);
352}
353
354/*
355 * Remove all the CONDEMNED nces from the appropriate hash table.
356 * We create a private list of NCEs, these may have ires pointing
357 * to them, so the list will be passed through to clean up dependent
358 * ires and only then we can do NCE_REFRELE which can make NCE inactive.
359 */
360static void
305nce_remove(nce_t *nce, nce_t **free_nce_list)
361nce_remove(ndp_g_t *ndp, nce_t *nce, nce_t **free_nce_list)
306{
307 nce_t *nce1;
308 nce_t **ptpn;
309
362{
363 nce_t *nce1;
364 nce_t **ptpn;
365
310 ASSERT(MUTEX_HELD(&ndp_g_lock));
311 ASSERT(ndp_g_walker == 0);
366 ASSERT(MUTEX_HELD(&ndp->ndp_g_lock));
367 ASSERT(ndp->ndp_g_walker == 0);
312 for (; nce; nce = nce1) {
313 nce1 = nce->nce_next;
314 mutex_enter(&nce->nce_lock);
315 if (nce->nce_flags & NCE_F_CONDEMNED) {
316 ptpn = nce->nce_ptpn;
317 nce1 = nce->nce_next;
318 if (nce1 != NULL)
319 nce1->nce_ptpn = ptpn;

--- 18 unchanged lines hidden (view full) ---

338 * 4. Otherwise remove the NCE from the list of NCEs
339 * 5. Delete all IREs pointing to this NCE.
340 */
341void
342ndp_delete(nce_t *nce)
343{
344 nce_t **ptpn;
345 nce_t *nce1;
368 for (; nce; nce = nce1) {
369 nce1 = nce->nce_next;
370 mutex_enter(&nce->nce_lock);
371 if (nce->nce_flags & NCE_F_CONDEMNED) {
372 ptpn = nce->nce_ptpn;
373 nce1 = nce->nce_next;
374 if (nce1 != NULL)
375 nce1->nce_ptpn = ptpn;

--- 18 unchanged lines hidden (view full) ---

394 * 4. Otherwise remove the NCE from the list of NCEs
395 * 5. Delete all IREs pointing to this NCE.
396 */
397void
398ndp_delete(nce_t *nce)
399{
400 nce_t **ptpn;
401 nce_t *nce1;
402 int ipversion = nce->nce_ipversion;
403 ndp_g_t *ndp = (ipversion == IPV4_VERSION ? &ndp4 : &ndp6);
346
347 /* Serialize deletes */
348 mutex_enter(&nce->nce_lock);
349 if (nce->nce_flags & NCE_F_CONDEMNED) {
350 /* Some other thread is doing the delete */
351 mutex_exit(&nce->nce_lock);
352 return;
353 }

--- 12 unchanged lines hidden (view full) ---

366 * since CONDEMNED is set. Can't hold nce_lock across untimeout.
367 * Passing invalid timeout id is fine.
368 */
369 if (nce->nce_timeout_id != 0) {
370 (void) untimeout(nce->nce_timeout_id);
371 nce->nce_timeout_id = 0;
372 }
373
404
405 /* Serialize deletes */
406 mutex_enter(&nce->nce_lock);
407 if (nce->nce_flags & NCE_F_CONDEMNED) {
408 /* Some other thread is doing the delete */
409 mutex_exit(&nce->nce_lock);
410 return;
411 }

--- 12 unchanged lines hidden (view full) ---

424 * since CONDEMNED is set. Can't hold nce_lock across untimeout.
425 * Passing invalid timeout id is fine.
426 */
427 if (nce->nce_timeout_id != 0) {
428 (void) untimeout(nce->nce_timeout_id);
429 nce->nce_timeout_id = 0;
430 }
431
374 mutex_enter(&ndp_g_lock);
432 mutex_enter(&ndp->ndp_g_lock);
375 if (nce->nce_ptpn == NULL) {
376 /*
377 * The last ndp walker has already removed this nce from
378 * the list after we marked the nce CONDEMNED and before
433 if (nce->nce_ptpn == NULL) {
434 /*
435 * The last ndp walker has already removed this nce from
436 * the list after we marked the nce CONDEMNED and before
379 * we grabbed the ndp_g_lock.
437 * we grabbed the global lock.
380 */
438 */
381 mutex_exit(&ndp_g_lock);
439 mutex_exit(&ndp->ndp_g_lock);
382 return;
383 }
440 return;
441 }
384 if (ndp_g_walker > 0) {
442 if (ndp->ndp_g_walker > 0) {
385 /*
386 * Can't unlink. The walker will clean up
387 */
443 /*
444 * Can't unlink. The walker will clean up
445 */
388 ndp_g_walker_cleanup = B_TRUE;
389 mutex_exit(&ndp_g_lock);
446 ndp->ndp_g_walker_cleanup = B_TRUE;
447 mutex_exit(&ndp->ndp_g_lock);
390 return;
391 }
392
393 /*
394 * Now remove the nce from the list. NDP_RESTART_TIMER won't restart
395 * the timer since it is marked CONDEMNED.
396 */
397 ptpn = nce->nce_ptpn;
398 nce1 = nce->nce_next;
399 if (nce1 != NULL)
400 nce1->nce_ptpn = ptpn;
401 *ptpn = nce1;
402 nce->nce_ptpn = NULL;
403 nce->nce_next = NULL;
448 return;
449 }
450
451 /*
452 * Now remove the nce from the list. NDP_RESTART_TIMER won't restart
453 * the timer since it is marked CONDEMNED.
454 */
455 ptpn = nce->nce_ptpn;
456 nce1 = nce->nce_next;
457 if (nce1 != NULL)
458 nce1->nce_ptpn = ptpn;
459 *ptpn = nce1;
460 nce->nce_ptpn = NULL;
461 nce->nce_next = NULL;
404 mutex_exit(&ndp_g_lock);
462 mutex_exit(&ndp->ndp_g_lock);
405
406 nce_ire_delete(nce);
407}
408
409void
410ndp_inactive(nce_t *nce)
411{
412 mblk_t **mpp;

--- 78 unchanged lines hidden (view full) ---

491 * Cancel any running timer. Timeout can't be restarted
492 * since CONDEMNED is set. Can't hold nce_lock across untimeout.
493 * Passing invalid timeout id is fine.
494 */
495 if (nce->nce_timeout_id != 0) {
496 (void) untimeout(nce->nce_timeout_id);
497 nce->nce_timeout_id = 0;
498 }
463
464 nce_ire_delete(nce);
465}
466
467void
468ndp_inactive(nce_t *nce)
469{
470 mblk_t **mpp;

--- 78 unchanged lines hidden (view full) ---

549 * Cancel any running timer. Timeout can't be restarted
550 * since CONDEMNED is set. Can't hold nce_lock across untimeout.
551 * Passing invalid timeout id is fine.
552 */
553 if (nce->nce_timeout_id != 0) {
554 (void) untimeout(nce->nce_timeout_id);
555 nce->nce_timeout_id = 0;
556 }
557 /*
558 * We might hit this func thus in the v4 case:
559 * ipif_down->ipif_ndp_down->ndp_walk
560 */
499
561
500 ire_walk_ill_v6(MATCH_IRE_ILL | MATCH_IRE_TYPE, IRE_CACHE,
501 nce_ire_delete1, (char *)nce, nce->nce_ill);
562 if (nce->nce_ipversion == IPV4_VERSION) {
563 ire_walk_ill_v4(MATCH_IRE_ILL | MATCH_IRE_TYPE,
564 IRE_CACHE, nce_ire_delete1,
565 (char *)nce, nce->nce_ill);
566 } else {
567 ASSERT(nce->nce_ipversion == IPV6_VERSION);
568 ire_walk_ill_v6(MATCH_IRE_ILL | MATCH_IRE_TYPE,
569 IRE_CACHE, nce_ire_delete1,
570 (char *)nce, nce->nce_ill);
571 }
502 NCE_REFRELE_NOTR(nce);
503 nce = nce_next;
504 }
505}
506
507/*
508 * Delete an ire when the nce goes away.
509 */
510/* ARGSUSED */
511static void
512nce_ire_delete(nce_t *nce)
513{
572 NCE_REFRELE_NOTR(nce);
573 nce = nce_next;
574 }
575}
576
577/*
578 * Delete an ire when the nce goes away.
579 */
580/* ARGSUSED */
581static void
582nce_ire_delete(nce_t *nce)
583{
514 ire_walk_ill_v6(MATCH_IRE_ILL | MATCH_IRE_TYPE, IRE_CACHE,
515 nce_ire_delete1, (char *)nce, nce->nce_ill);
516 NCE_REFRELE_NOTR(nce);
584 if (nce->nce_ipversion == IPV6_VERSION) {
585 ire_walk_ill_v6(MATCH_IRE_ILL | MATCH_IRE_TYPE, IRE_CACHE,
586 nce_ire_delete1, (char *)nce, nce->nce_ill);
587 NCE_REFRELE_NOTR(nce);
588 } else {
589 ire_walk_ill_v4(MATCH_IRE_ILL | MATCH_IRE_TYPE, IRE_CACHE,
590 nce_ire_delete1, (char *)nce, nce->nce_ill);
591 NCE_REFRELE_NOTR(nce);
592 }
517}
518
519/*
520 * ire_walk routine used to delete every IRE that shares this nce
521 */
522static void
523nce_ire_delete1(ire_t *ire, char *nce_arg)
524{
525 nce_t *nce = (nce_t *)nce_arg;
526
527 ASSERT(ire->ire_type == IRE_CACHE);
528
593}
594
595/*
596 * ire_walk routine used to delete every IRE that shares this nce
597 */
598static void
599nce_ire_delete1(ire_t *ire, char *nce_arg)
600{
601 nce_t *nce = (nce_t *)nce_arg;
602
603 ASSERT(ire->ire_type == IRE_CACHE);
604
529 if (ire->ire_nce == nce)
605 if (ire->ire_nce == nce) {
606 ASSERT(ire->ire_ipversion == nce->nce_ipversion);
530 ire_delete(ire);
607 ire_delete(ire);
608 }
531}
532
533/*
609}
610
611/*
534 * Cache entry lookup. Try to find an nce matching the parameters passed.
612 * IPv6 Cache entry lookup. Try to find an nce matching the parameters passed.
535 * If one is found, the refcnt on the nce will be incremented.
536 */
537nce_t *
613 * If one is found, the refcnt on the nce will be incremented.
614 */
615nce_t *
538ndp_lookup(ill_t *ill, const in6_addr_t *addr, boolean_t caller_holds_lock)
616ndp_lookup_v6(ill_t *ill, const in6_addr_t *addr, boolean_t caller_holds_lock)
539{
540 nce_t *nce;
541
617{
618 nce_t *nce;
619
542 if (!caller_holds_lock)
543 mutex_enter(&ndp_g_lock);
544 nce = nce_lookup_addr(ill, addr);
620 ASSERT(ill != NULL && ill->ill_isv6);
621 if (!caller_holds_lock) {
622 mutex_enter(&ndp6.ndp_g_lock);
623 }
624 nce = *((nce_t **)NCE_HASH_PTR_V6(*addr)); /* head of v6 hash table */
625 nce = nce_lookup_addr(ill, addr, nce);
545 if (nce == NULL)
546 nce = nce_lookup_mapping(ill, addr);
547 if (!caller_holds_lock)
626 if (nce == NULL)
627 nce = nce_lookup_mapping(ill, addr);
628 if (!caller_holds_lock)
548 mutex_exit(&ndp_g_lock);
629 mutex_exit(&ndp6.ndp_g_lock);
549 return (nce);
550}
630 return (nce);
631}
632/*
633 * IPv4 Cache entry lookup. Try to find an nce matching the parameters passed.
634 * If one is found, the refcnt on the nce will be incremented.
635 * Since multicast mappings are handled in arp, there are no nce_mcast_entries
636 * so we skip the nce_lookup_mapping call.
637 * XXX TODO: if the nce is found to be ND_STALE, ndp_delete it and return NULL
638 */
639nce_t *
640ndp_lookup_v4(ill_t *ill, const in_addr_t *addr, boolean_t caller_holds_lock)
641{
642 nce_t *nce;
643 in6_addr_t addr6;
551
644
645 if (!caller_holds_lock) {
646 mutex_enter(&ndp4.ndp_g_lock);
647 }
648 nce = *((nce_t **)NCE_HASH_PTR_V4(*addr)); /* head of v6 hash table */
649 IN6_IPADDR_TO_V4MAPPED(*addr, &addr6);
650 nce = nce_lookup_addr(ill, &addr6, nce);
651 if (!caller_holds_lock)
652 mutex_exit(&ndp4.ndp_g_lock);
653 return (nce);
654}
655
552/*
553 * Cache entry lookup. Try to find an nce matching the parameters passed.
554 * Look only for exact entries (no mappings). If an nce is found, increment
656/*
657 * Cache entry lookup. Try to find an nce matching the parameters passed.
658 * Look only for exact entries (no mappings). If an nce is found, increment
555 * the hold count on that nce.
659 * the hold count on that nce. The caller passes in the start of the
660 * appropriate hash table, and must be holding the appropriate global
661 * lock (ndp_g_lock).
556 */
557static nce_t *
662 */
663static nce_t *
558nce_lookup_addr(ill_t *ill, const in6_addr_t *addr)
664nce_lookup_addr(ill_t *ill, const in6_addr_t *addr, nce_t *nce)
559{
665{
560 nce_t *nce;
666 ndp_g_t *ndp = (ill->ill_isv6 ? &ndp6 : &ndp4);
561
562 ASSERT(ill != NULL);
667
668 ASSERT(ill != NULL);
563 ASSERT(MUTEX_HELD(&ndp_g_lock));
669 ASSERT(MUTEX_HELD(&ndp->ndp_g_lock));
564 if (IN6_IS_ADDR_UNSPECIFIED(addr))
565 return (NULL);
670 if (IN6_IS_ADDR_UNSPECIFIED(addr))
671 return (NULL);
566 nce = *((nce_t **)NCE_HASH_PTR(*addr));
567 for (; nce != NULL; nce = nce->nce_next) {
568 if (nce->nce_ill == ill) {
569 if (IN6_ARE_ADDR_EQUAL(&nce->nce_addr, addr) &&
570 IN6_ARE_ADDR_EQUAL(&nce->nce_mask,
571 &ipv6_all_ones)) {
572 mutex_enter(&nce->nce_lock);
573 if (!(nce->nce_flags & NCE_F_CONDEMNED)) {
574 NCE_REFHOLD_LOCKED(nce);

--- 11 unchanged lines hidden (view full) ---

586 * Cache entry lookup. Try to find an nce matching the parameters passed.
587 * Look only for mappings.
588 */
589static nce_t *
590nce_lookup_mapping(ill_t *ill, const in6_addr_t *addr)
591{
592 nce_t *nce;
593
672 for (; nce != NULL; nce = nce->nce_next) {
673 if (nce->nce_ill == ill) {
674 if (IN6_ARE_ADDR_EQUAL(&nce->nce_addr, addr) &&
675 IN6_ARE_ADDR_EQUAL(&nce->nce_mask,
676 &ipv6_all_ones)) {
677 mutex_enter(&nce->nce_lock);
678 if (!(nce->nce_flags & NCE_F_CONDEMNED)) {
679 NCE_REFHOLD_LOCKED(nce);

--- 11 unchanged lines hidden (view full) ---

691 * Cache entry lookup. Try to find an nce matching the parameters passed.
692 * Look only for mappings.
693 */
694static nce_t *
695nce_lookup_mapping(ill_t *ill, const in6_addr_t *addr)
696{
697 nce_t *nce;
698
594 ASSERT(ill != NULL);
595 ASSERT(MUTEX_HELD(&ndp_g_lock));
699 ASSERT(ill != NULL && ill->ill_isv6);
700 ASSERT(MUTEX_HELD(&ndp6.ndp_g_lock));
596 if (!IN6_IS_ADDR_MULTICAST(addr))
597 return (NULL);
701 if (!IN6_IS_ADDR_MULTICAST(addr))
702 return (NULL);
598 nce = nce_mask_entries;
703 nce = ndp6.nce_mask_entries;
599 for (; nce != NULL; nce = nce->nce_next)
600 if (nce->nce_ill == ill &&
601 (V6_MASK_EQ(*addr, nce->nce_mask, nce->nce_addr))) {
602 mutex_enter(&nce->nce_lock);
603 if (!(nce->nce_flags & NCE_F_CONDEMNED)) {
604 NCE_REFHOLD_LOCKED(nce);
605 mutex_exit(&nce->nce_lock);
606 break;

--- 11 unchanged lines hidden (view full) ---

618ndp_process(nce_t *nce, uchar_t *hw_addr, uint32_t flag, boolean_t is_adv)
619{
620 ill_t *ill = nce->nce_ill;
621 uint32_t hw_addr_len = ill->ill_nd_lla_len;
622 mblk_t *mp;
623 boolean_t ll_updated = B_FALSE;
624 boolean_t ll_changed;
625
704 for (; nce != NULL; nce = nce->nce_next)
705 if (nce->nce_ill == ill &&
706 (V6_MASK_EQ(*addr, nce->nce_mask, nce->nce_addr))) {
707 mutex_enter(&nce->nce_lock);
708 if (!(nce->nce_flags & NCE_F_CONDEMNED)) {
709 NCE_REFHOLD_LOCKED(nce);
710 mutex_exit(&nce->nce_lock);
711 break;

--- 11 unchanged lines hidden (view full) ---

723ndp_process(nce_t *nce, uchar_t *hw_addr, uint32_t flag, boolean_t is_adv)
724{
725 ill_t *ill = nce->nce_ill;
726 uint32_t hw_addr_len = ill->ill_nd_lla_len;
727 mblk_t *mp;
728 boolean_t ll_updated = B_FALSE;
729 boolean_t ll_changed;
730
731 ASSERT(nce->nce_ipversion == IPV6_VERSION);
626 /*
627 * No updates of link layer address or the neighbor state is
628 * allowed, when the cache is in NONUD state. This still
629 * allows for responding to reachability solicitation.
630 */
631 mutex_enter(&nce->nce_lock);
632 if (nce->nce_state == ND_INCOMPLETE) {
633 if (hw_addr == NULL) {

--- 118 unchanged lines hidden (view full) ---

752}
753
754/*
755 * Pass arg1 to the pfi supplied, along with each nce in existence.
756 * ndp_walk() places a REFHOLD on the nce and drops the lock when
757 * walking the hash list.
758 */
759void
732 /*
733 * No updates of link layer address or the neighbor state is
734 * allowed, when the cache is in NONUD state. This still
735 * allows for responding to reachability solicitation.
736 */
737 mutex_enter(&nce->nce_lock);
738 if (nce->nce_state == ND_INCOMPLETE) {
739 if (hw_addr == NULL) {

--- 118 unchanged lines hidden (view full) ---

858}
859
860/*
861 * Pass arg1 to the pfi supplied, along with each nce in existence.
862 * ndp_walk() places a REFHOLD on the nce and drops the lock when
863 * walking the hash list.
864 */
865void
760ndp_walk_impl(ill_t *ill, pfi_t pfi, void *arg1, boolean_t trace)
866ndp_walk_common(ndp_g_t *ndp, ill_t *ill, pfi_t pfi, void *arg1,
867 boolean_t trace)
761{
762
763 nce_t *nce;
764 nce_t *nce1;
765 nce_t **ncep;
766 nce_t *free_nce_list = NULL;
767
868{
869
870 nce_t *nce;
871 nce_t *nce1;
872 nce_t **ncep;
873 nce_t *free_nce_list = NULL;
874
768 mutex_enter(&ndp_g_lock);
769 ndp_g_walker++; /* Prevent ndp_delete from unlink and free of NCE */
770 mutex_exit(&ndp_g_lock);
771 for (ncep = nce_hash_tbl; ncep < A_END(nce_hash_tbl); ncep++) {
772 for (nce = *ncep; nce; nce = nce1) {
875 mutex_enter(&ndp->ndp_g_lock);
876 /* Prevent ndp_delete from unlink and free of NCE */
877 ndp->ndp_g_walker++;
878 mutex_exit(&ndp->ndp_g_lock);
879 for (ncep = ndp->nce_hash_tbl;
880 ncep < A_END(ndp->nce_hash_tbl); ncep++) {
881 for (nce = *ncep; nce != NULL; nce = nce1) {
773 nce1 = nce->nce_next;
774 if (ill == NULL || nce->nce_ill == ill) {
775 if (trace) {
776 NCE_REFHOLD(nce);
777 (*pfi)(nce, arg1);
778 NCE_REFRELE(nce);
779 } else {
780 NCE_REFHOLD_NOTR(nce);
781 (*pfi)(nce, arg1);
782 NCE_REFRELE_NOTR(nce);
783 }
784 }
785 }
786 }
882 nce1 = nce->nce_next;
883 if (ill == NULL || nce->nce_ill == ill) {
884 if (trace) {
885 NCE_REFHOLD(nce);
886 (*pfi)(nce, arg1);
887 NCE_REFRELE(nce);
888 } else {
889 NCE_REFHOLD_NOTR(nce);
890 (*pfi)(nce, arg1);
891 NCE_REFRELE_NOTR(nce);
892 }
893 }
894 }
895 }
787 for (nce = nce_mask_entries; nce; nce = nce1) {
896 for (nce = ndp->nce_mask_entries; nce != NULL; nce = nce1) {
788 nce1 = nce->nce_next;
789 if (ill == NULL || nce->nce_ill == ill) {
790 if (trace) {
791 NCE_REFHOLD(nce);
792 (*pfi)(nce, arg1);
793 NCE_REFRELE(nce);
794 } else {
795 NCE_REFHOLD_NOTR(nce);
796 (*pfi)(nce, arg1);
797 NCE_REFRELE_NOTR(nce);
798 }
799 }
800 }
897 nce1 = nce->nce_next;
898 if (ill == NULL || nce->nce_ill == ill) {
899 if (trace) {
900 NCE_REFHOLD(nce);
901 (*pfi)(nce, arg1);
902 NCE_REFRELE(nce);
903 } else {
904 NCE_REFHOLD_NOTR(nce);
905 (*pfi)(nce, arg1);
906 NCE_REFRELE_NOTR(nce);
907 }
908 }
909 }
801 mutex_enter(&ndp_g_lock);
802 ndp_g_walker--;
910 mutex_enter(&ndp->ndp_g_lock);
911 ndp->ndp_g_walker--;
803 /*
804 * While NCE's are removed from global list they are placed
805 * in a private list, to be passed to nce_ire_delete_list().
806 * The reason is, there may be ires pointing to this nce
807 * which needs to cleaned up.
808 */
912 /*
913 * While NCE's are removed from global list they are placed
914 * in a private list, to be passed to nce_ire_delete_list().
915 * The reason is, there may be ires pointing to this nce
916 * which needs to cleaned up.
917 */
809 if (ndp_g_walker_cleanup && ndp_g_walker == 0) {
918 if (ndp->ndp_g_walker_cleanup && ndp->ndp_g_walker == 0) {
810 /* Time to delete condemned entries */
919 /* Time to delete condemned entries */
811 for (ncep = nce_hash_tbl; ncep < A_END(nce_hash_tbl); ncep++) {
920 for (ncep = ndp->nce_hash_tbl;
921 ncep < A_END(ndp->nce_hash_tbl); ncep++) {
812 nce = *ncep;
813 if (nce != NULL) {
922 nce = *ncep;
923 if (nce != NULL) {
814 nce_remove(nce, &free_nce_list);
924 nce_remove(ndp, nce, &free_nce_list);
815 }
816 }
925 }
926 }
817 nce = nce_mask_entries;
927 nce = ndp->nce_mask_entries;
818 if (nce != NULL) {
928 if (nce != NULL) {
819 nce_remove(nce, &free_nce_list);
929 nce_remove(ndp, nce, &free_nce_list);
820 }
930 }
821 ndp_g_walker_cleanup = B_FALSE;
931 ndp->ndp_g_walker_cleanup = B_FALSE;
822 }
932 }
823 mutex_exit(&ndp_g_lock);
933 mutex_exit(&ndp->ndp_g_lock);
824
825 if (free_nce_list != NULL) {
826 nce_ire_delete_list(free_nce_list);
827 }
828}
829
830void
831ndp_walk(ill_t *ill, pfi_t pfi, void *arg1)
832{
934
935 if (free_nce_list != NULL) {
936 nce_ire_delete_list(free_nce_list);
937 }
938}
939
940void
941ndp_walk(ill_t *ill, pfi_t pfi, void *arg1)
942{
833 ndp_walk_impl(ill, pfi, arg1, B_TRUE);
943 ndp_walk_common(&ndp4, ill, pfi, arg1, B_TRUE);
944 ndp_walk_common(&ndp6, ill, pfi, arg1, B_TRUE);
834}
835
836/*
837 * Prepend the zoneid using an ipsec_out_t for later use by functions like
838 * ip_rput_v6() after neighbor discovery has taken place. If the message
839 * block already has a M_CTL at the front of it, then simply set the zoneid
840 * appropriately.
841 */

--- 35 unchanged lines hidden (view full) ---

877ndp_resolver(ill_t *ill, const in6_addr_t *dst, mblk_t *mp, zoneid_t zoneid)
878{
879 nce_t *nce;
880 int err = 0;
881 uint32_t ms;
882 mblk_t *mp_nce = NULL;
883
884 ASSERT(ill != NULL);
945}
946
947/*
948 * Prepend the zoneid using an ipsec_out_t for later use by functions like
949 * ip_rput_v6() after neighbor discovery has taken place. If the message
950 * block already has a M_CTL at the front of it, then simply set the zoneid
951 * appropriately.
952 */

--- 35 unchanged lines hidden (view full) ---

988ndp_resolver(ill_t *ill, const in6_addr_t *dst, mblk_t *mp, zoneid_t zoneid)
989{
990 nce_t *nce;
991 int err = 0;
992 uint32_t ms;
993 mblk_t *mp_nce = NULL;
994
995 ASSERT(ill != NULL);
996 ASSERT(ill->ill_isv6);
885 if (IN6_IS_ADDR_MULTICAST(dst)) {
886 err = nce_set_multicast(ill, dst);
887 return (err);
888 }
889 err = ndp_lookup_then_add(ill,
890 NULL, /* No hardware address */
891 dst,
892 &ipv6_all_ones,
893 &ipv6_all_zeros,
894 0,
895 (ill->ill_flags & ILLF_NONUD) ? NCE_F_NONUD : 0,
896 ND_INCOMPLETE,
997 if (IN6_IS_ADDR_MULTICAST(dst)) {
998 err = nce_set_multicast(ill, dst);
999 return (err);
1000 }
1001 err = ndp_lookup_then_add(ill,
1002 NULL, /* No hardware address */
1003 dst,
1004 &ipv6_all_ones,
1005 &ipv6_all_zeros,
1006 0,
1007 (ill->ill_flags & ILLF_NONUD) ? NCE_F_NONUD : 0,
1008 ND_INCOMPLETE,
897 &nce);
1009 &nce,
1010 NULL, /* let ndp_add figure out fastpath mp and dlureq_mp for v6 */
1011 NULL);
898
899 switch (err) {
900 case 0:
901 /*
902 * New cache entry was created. Make sure that the state
903 * is not ND_INCOMPLETE. It can be in some other state
904 * even before we send out the solicitation as we could
905 * get un-solicited advertisements.

--- 79 unchanged lines hidden (view full) ---

985 */
986int
987ndp_noresolver(ill_t *ill, const in6_addr_t *dst)
988{
989 nce_t *nce;
990 int err = 0;
991
992 ASSERT(ill != NULL);
1012
1013 switch (err) {
1014 case 0:
1015 /*
1016 * New cache entry was created. Make sure that the state
1017 * is not ND_INCOMPLETE. It can be in some other state
1018 * even before we send out the solicitation as we could
1019 * get un-solicited advertisements.

--- 79 unchanged lines hidden (view full) ---

1099 */
1100int
1101ndp_noresolver(ill_t *ill, const in6_addr_t *dst)
1102{
1103 nce_t *nce;
1104 int err = 0;
1105
1106 ASSERT(ill != NULL);
1107 ASSERT(ill->ill_isv6);
993 if (IN6_IS_ADDR_MULTICAST(dst)) {
994 err = nce_set_multicast(ill, dst);
995 return (err);
996 }
997
998 err = ndp_lookup_then_add(ill,
999 NULL, /* hardware address */
1000 dst,
1001 &ipv6_all_ones,
1002 &ipv6_all_zeros,
1003 0,
1004 (ill->ill_flags & ILLF_NONUD) ? NCE_F_NONUD : 0,
1005 ND_REACHABLE,
1108 if (IN6_IS_ADDR_MULTICAST(dst)) {
1109 err = nce_set_multicast(ill, dst);
1110 return (err);
1111 }
1112
1113 err = ndp_lookup_then_add(ill,
1114 NULL, /* hardware address */
1115 dst,
1116 &ipv6_all_ones,
1117 &ipv6_all_zeros,
1118 0,
1119 (ill->ill_flags & ILLF_NONUD) ? NCE_F_NONUD : 0,
1120 ND_REACHABLE,
1006 &nce);
1121 &nce,
1122 NULL, /* let ndp_add figure out fp_mp/dlureq_mp for v6 */
1123 NULL);
1007
1008 switch (err) {
1009 case 0:
1010 /*
1011 * Cache entry with a proper resolver cookie was
1012 * created.
1013 */
1014 NCE_REFRELE(nce);

--- 18 unchanged lines hidden (view full) ---

1033nce_set_multicast(ill_t *ill, const in6_addr_t *dst)
1034{
1035 nce_t *mnce; /* Multicast mapping entry */
1036 nce_t *nce;
1037 uchar_t *hw_addr = NULL;
1038 int err = 0;
1039
1040 ASSERT(ill != NULL);
1124
1125 switch (err) {
1126 case 0:
1127 /*
1128 * Cache entry with a proper resolver cookie was
1129 * created.
1130 */
1131 NCE_REFRELE(nce);

--- 18 unchanged lines hidden (view full) ---

1150nce_set_multicast(ill_t *ill, const in6_addr_t *dst)
1151{
1152 nce_t *mnce; /* Multicast mapping entry */
1153 nce_t *nce;
1154 uchar_t *hw_addr = NULL;
1155 int err = 0;
1156
1157 ASSERT(ill != NULL);
1158 ASSERT(ill->ill_isv6);
1041 ASSERT(!(IN6_IS_ADDR_UNSPECIFIED(dst)));
1042
1159 ASSERT(!(IN6_IS_ADDR_UNSPECIFIED(dst)));
1160
1043 mutex_enter(&ndp_g_lock);
1044 nce = nce_lookup_addr(ill, dst);
1161 mutex_enter(&ndp6.ndp_g_lock);
1162 nce = *((nce_t **)NCE_HASH_PTR_V6(*dst));
1163 nce = nce_lookup_addr(ill, dst, nce);
1045 if (nce != NULL) {
1164 if (nce != NULL) {
1046 mutex_exit(&ndp_g_lock);
1165 mutex_exit(&ndp6.ndp_g_lock);
1047 NCE_REFRELE(nce);
1048 return (0);
1049 }
1050 /* No entry, now lookup for a mapping this should never fail */
1051 mnce = nce_lookup_mapping(ill, dst);
1052 if (mnce == NULL) {
1053 /* Something broken for the interface. */
1166 NCE_REFRELE(nce);
1167 return (0);
1168 }
1169 /* No entry, now lookup for a mapping this should never fail */
1170 mnce = nce_lookup_mapping(ill, dst);
1171 if (mnce == NULL) {
1172 /* Something broken for the interface. */
1054 mutex_exit(&ndp_g_lock);
1173 mutex_exit(&ndp6.ndp_g_lock);
1055 return (ESRCH);
1056 }
1057 ASSERT(mnce->nce_flags & NCE_F_MAPPING);
1058 if (ill->ill_net_type == IRE_IF_RESOLVER) {
1059 /*
1060 * For IRE_IF_RESOLVER a hardware mapping can be
1061 * generated, for IRE_IF_NORESOLVER, resolution cookie
1062 * in the ill is copied in ndp_add().
1063 */
1064 hw_addr = kmem_alloc(ill->ill_nd_lla_len, KM_NOSLEEP);
1065 if (hw_addr == NULL) {
1174 return (ESRCH);
1175 }
1176 ASSERT(mnce->nce_flags & NCE_F_MAPPING);
1177 if (ill->ill_net_type == IRE_IF_RESOLVER) {
1178 /*
1179 * For IRE_IF_RESOLVER a hardware mapping can be
1180 * generated, for IRE_IF_NORESOLVER, resolution cookie
1181 * in the ill is copied in ndp_add().
1182 */
1183 hw_addr = kmem_alloc(ill->ill_nd_lla_len, KM_NOSLEEP);
1184 if (hw_addr == NULL) {
1066 mutex_exit(&ndp_g_lock);
1185 mutex_exit(&ndp6.ndp_g_lock);
1067 NCE_REFRELE(mnce);
1068 return (ENOMEM);
1069 }
1070 nce_make_mapping(mnce, hw_addr, (uchar_t *)dst);
1071 }
1072 NCE_REFRELE(mnce);
1073 /*
1074 * IRE_IF_NORESOLVER type simply copies the resolution
1075 * cookie passed in. So no hw_addr is needed.
1076 */
1077 err = ndp_add(ill,
1078 hw_addr,
1079 dst,
1080 &ipv6_all_ones,
1081 &ipv6_all_zeros,
1082 0,
1083 NCE_F_NONUD,
1084 ND_REACHABLE,
1186 NCE_REFRELE(mnce);
1187 return (ENOMEM);
1188 }
1189 nce_make_mapping(mnce, hw_addr, (uchar_t *)dst);
1190 }
1191 NCE_REFRELE(mnce);
1192 /*
1193 * IRE_IF_NORESOLVER type simply copies the resolution
1194 * cookie passed in. So no hw_addr is needed.
1195 */
1196 err = ndp_add(ill,
1197 hw_addr,
1198 dst,
1199 &ipv6_all_ones,
1200 &ipv6_all_zeros,
1201 0,
1202 NCE_F_NONUD,
1203 ND_REACHABLE,
1085 &nce);
1086 mutex_exit(&ndp_g_lock);
1204 &nce,
1205 NULL,
1206 NULL);
1207 mutex_exit(&ndp6.ndp_g_lock);
1087 if (hw_addr != NULL)
1088 kmem_free(hw_addr, ill->ill_nd_lla_len);
1089 if (err != 0) {
1090 ip1dbg(("nce_set_multicast: create failed" "%d\n", err));
1091 return (err);
1092 }
1093 NCE_REFRELE(nce);
1094 return (0);

--- 5 unchanged lines hidden (view full) ---

1100int
1101ndp_query(ill_t *ill, struct lif_nd_req *lnr)
1102{
1103 nce_t *nce;
1104 in6_addr_t *addr;
1105 sin6_t *sin6;
1106 dl_unitdata_req_t *dl;
1107
1208 if (hw_addr != NULL)
1209 kmem_free(hw_addr, ill->ill_nd_lla_len);
1210 if (err != 0) {
1211 ip1dbg(("nce_set_multicast: create failed" "%d\n", err));
1212 return (err);
1213 }
1214 NCE_REFRELE(nce);
1215 return (0);

--- 5 unchanged lines hidden (view full) ---

1221int
1222ndp_query(ill_t *ill, struct lif_nd_req *lnr)
1223{
1224 nce_t *nce;
1225 in6_addr_t *addr;
1226 sin6_t *sin6;
1227 dl_unitdata_req_t *dl;
1228
1108 ASSERT(ill != NULL);
1229 ASSERT(ill != NULL && ill->ill_isv6);
1109 sin6 = (sin6_t *)&lnr->lnr_addr;
1110 addr = &sin6->sin6_addr;
1111
1230 sin6 = (sin6_t *)&lnr->lnr_addr;
1231 addr = &sin6->sin6_addr;
1232
1112 nce = ndp_lookup(ill, addr, B_FALSE);
1233 nce = ndp_lookup_v6(ill, addr, B_FALSE);
1113 if (nce == NULL)
1114 return (ESRCH);
1115 /* If in INCOMPLETE state, no link layer address is available yet */
1116 if (nce->nce_state == ND_INCOMPLETE)
1117 goto done;
1118 dl = (dl_unitdata_req_t *)nce->nce_res_mp->b_rptr;
1119 if (ill->ill_flags & ILLF_XRESOLV)
1120 lnr->lnr_hdw_len = dl->dl_dest_addr_length;

--- 19 unchanged lines hidden (view full) ---

1140 */
1141int
1142ndp_mcastreq(ill_t *ill, const in6_addr_t *addr, uint32_t hw_addr_len,
1143 uint32_t hw_addr_offset, mblk_t *mp)
1144{
1145 nce_t *nce;
1146 uchar_t *hw_addr;
1147
1234 if (nce == NULL)
1235 return (ESRCH);
1236 /* If in INCOMPLETE state, no link layer address is available yet */
1237 if (nce->nce_state == ND_INCOMPLETE)
1238 goto done;
1239 dl = (dl_unitdata_req_t *)nce->nce_res_mp->b_rptr;
1240 if (ill->ill_flags & ILLF_XRESOLV)
1241 lnr->lnr_hdw_len = dl->dl_dest_addr_length;

--- 19 unchanged lines hidden (view full) ---

1261 */
1262int
1263ndp_mcastreq(ill_t *ill, const in6_addr_t *addr, uint32_t hw_addr_len,
1264 uint32_t hw_addr_offset, mblk_t *mp)
1265{
1266 nce_t *nce;
1267 uchar_t *hw_addr;
1268
1148 ASSERT(ill != NULL);
1269 ASSERT(ill != NULL && ill->ill_isv6);
1149 ASSERT(ill->ill_net_type == IRE_IF_RESOLVER);
1150 hw_addr = mi_offset_paramc(mp, hw_addr_offset, hw_addr_len);
1151 if (hw_addr == NULL || !IN6_IS_ADDR_MULTICAST(addr)) {
1152 freemsg(mp);
1153 return (EINVAL);
1154 }
1270 ASSERT(ill->ill_net_type == IRE_IF_RESOLVER);
1271 hw_addr = mi_offset_paramc(mp, hw_addr_offset, hw_addr_len);
1272 if (hw_addr == NULL || !IN6_IS_ADDR_MULTICAST(addr)) {
1273 freemsg(mp);
1274 return (EINVAL);
1275 }
1155 mutex_enter(&ndp_g_lock);
1276 mutex_enter(&ndp6.ndp_g_lock);
1156 nce = nce_lookup_mapping(ill, addr);
1157 if (nce == NULL) {
1277 nce = nce_lookup_mapping(ill, addr);
1278 if (nce == NULL) {
1158 mutex_exit(&ndp_g_lock);
1279 mutex_exit(&ndp6.ndp_g_lock);
1159 freemsg(mp);
1160 return (ESRCH);
1161 }
1280 freemsg(mp);
1281 return (ESRCH);
1282 }
1162 mutex_exit(&ndp_g_lock);
1283 mutex_exit(&ndp6.ndp_g_lock);
1163 /*
1164 * Update dl_addr_length and dl_addr_offset for primitives that
1165 * have physical addresses as opposed to full saps
1166 */
1167 switch (((union DL_primitives *)mp->b_rptr)->dl_primitive) {
1168 case DL_ENABMULTI_REQ:
1169 /* Track the state if this is the first enabmulti */
1170 if (ill->ill_dlpi_multicast_state == IDMS_UNKNOWN)

--- 167 unchanged lines hidden (view full) ---

1338 "multicast %s\n", AF_INET6,
1339 &ip6h->ip6_dst);
1340 }
1341 bad_solicit = B_TRUE;
1342 goto done;
1343 }
1344 }
1345
1284 /*
1285 * Update dl_addr_length and dl_addr_offset for primitives that
1286 * have physical addresses as opposed to full saps
1287 */
1288 switch (((union DL_primitives *)mp->b_rptr)->dl_primitive) {
1289 case DL_ENABMULTI_REQ:
1290 /* Track the state if this is the first enabmulti */
1291 if (ill->ill_dlpi_multicast_state == IDMS_UNKNOWN)

--- 167 unchanged lines hidden (view full) ---

1459 "multicast %s\n", AF_INET6,
1460 &ip6h->ip6_dst);
1461 }
1462 bad_solicit = B_TRUE;
1463 goto done;
1464 }
1465 }
1466
1346 our_nce = ndp_lookup(ill, &target, B_FALSE);
1467 our_nce = ndp_lookup_v6(ill, &target, B_FALSE);
1347 /*
1348 * If this is a valid Solicitation, a permanent
1349 * entry should exist in the cache
1350 */
1351 if (our_nce == NULL ||
1352 !(our_nce->nce_flags & NCE_F_PERMANENT)) {
1353 ip1dbg(("ndp_input_solicit: Wrong target in NS?!"
1354 "ifname=%s ", ill->ill_name));

--- 30 unchanged lines hidden (view full) ---

1385 }
1386 /*
1387 * haddr can be NULL if no options are present,
1388 * or no Source link layer address is present in,
1389 * recvd NDP options of solicitation message.
1390 */
1391 if (haddr == NULL) {
1392 nce_t *nnce;
1468 /*
1469 * If this is a valid Solicitation, a permanent
1470 * entry should exist in the cache
1471 */
1472 if (our_nce == NULL ||
1473 !(our_nce->nce_flags & NCE_F_PERMANENT)) {
1474 ip1dbg(("ndp_input_solicit: Wrong target in NS?!"
1475 "ifname=%s ", ill->ill_name));

--- 30 unchanged lines hidden (view full) ---

1506 }
1507 /*
1508 * haddr can be NULL if no options are present,
1509 * or no Source link layer address is present in,
1510 * recvd NDP options of solicitation message.
1511 */
1512 if (haddr == NULL) {
1513 nce_t *nnce;
1393 mutex_enter(&ndp_g_lock);
1394 nnce = nce_lookup_addr(ill, &src);
1395 mutex_exit(&ndp_g_lock);
1514 mutex_enter(&ndp6.ndp_g_lock);
1515 nnce = *((nce_t **)NCE_HASH_PTR_V6(src));
1516 nnce = nce_lookup_addr(ill, &src, nnce);
1517 mutex_exit(&ndp6.ndp_g_lock);
1396
1397 if (nnce == NULL) {
1398 in6_addr_t dst = ipv6_solicited_node_mcast;
1399
1400 /* Form solicited node multicast address */
1401 dst.s6_addr32[3] |= src.s6_addr32[3];
1402 (void) nce_xmit(ill,
1403 ND_NEIGHBOR_SOLICIT,

--- 16 unchanged lines hidden (view full) ---

1420 * Create/update the entry for the soliciting node.
1421 * or respond to outstanding queries, don't if
1422 * the source is unspecified address.
1423 */
1424 if (!IN6_IS_ADDR_UNSPECIFIED(&src)) {
1425 int err = 0;
1426 nce_t *nnce;
1427
1518
1519 if (nnce == NULL) {
1520 in6_addr_t dst = ipv6_solicited_node_mcast;
1521
1522 /* Form solicited node multicast address */
1523 dst.s6_addr32[3] |= src.s6_addr32[3];
1524 (void) nce_xmit(ill,
1525 ND_NEIGHBOR_SOLICIT,

--- 16 unchanged lines hidden (view full) ---

1542 * Create/update the entry for the soliciting node.
1543 * or respond to outstanding queries, don't if
1544 * the source is unspecified address.
1545 */
1546 if (!IN6_IS_ADDR_UNSPECIFIED(&src)) {
1547 int err = 0;
1548 nce_t *nnce;
1549
1550 ASSERT(ill->ill_isv6);
1428 err = ndp_lookup_then_add(ill,
1429 haddr,
1430 &src, /* Soliciting nodes address */
1431 &ipv6_all_ones,
1432 &ipv6_all_zeros,
1433 0,
1434 0,
1435 ND_STALE,
1551 err = ndp_lookup_then_add(ill,
1552 haddr,
1553 &src, /* Soliciting nodes address */
1554 &ipv6_all_ones,
1555 &ipv6_all_zeros,
1556 0,
1557 0,
1558 ND_STALE,
1436 &nnce);
1559 &nnce,
1560 NULL,
1561 NULL);
1437 switch (err) {
1438 case 0:
1439 /* done with this entry */
1440 NCE_REFRELE(nnce);
1441 break;
1442 case EEXIST:
1443 /*
1444 * B_FALSE indicates this is not an

--- 97 unchanged lines hidden (view full) ---

1542 for (; ill != NULL; ill = ill->ill_group_next) {
1543 mutex_enter(&ill->ill_lock);
1544 if (!ILL_CAN_LOOKUP(ill)) {
1545 mutex_exit(&ill->ill_lock);
1546 continue;
1547 }
1548 ill_refhold_locked(ill);
1549 mutex_exit(&ill->ill_lock);
1562 switch (err) {
1563 case 0:
1564 /* done with this entry */
1565 NCE_REFRELE(nnce);
1566 break;
1567 case EEXIST:
1568 /*
1569 * B_FALSE indicates this is not an

--- 97 unchanged lines hidden (view full) ---

1667 for (; ill != NULL; ill = ill->ill_group_next) {
1668 mutex_enter(&ill->ill_lock);
1669 if (!ILL_CAN_LOOKUP(ill)) {
1670 mutex_exit(&ill->ill_lock);
1671 continue;
1672 }
1673 ill_refhold_locked(ill);
1674 mutex_exit(&ill->ill_lock);
1550 dst_nce = ndp_lookup(ill, &target, B_FALSE);
1675 dst_nce = ndp_lookup_v6(ill, &target, B_FALSE);
1551 /* We have to drop the lock since ndp_process calls put* */
1552 rw_exit(&ill_g_lock);
1553 if (dst_nce != NULL) {
1554 if (na->nd_na_flags_reserved &
1555 ND_NA_FLAG_ROUTER) {
1556 dst_nce->nce_flags |= NCE_F_ISROUTER;
1557 }
1558 /* B_TRUE indicates this an advertisement */

--- 308 unchanged lines hidden (view full) ---

1867 * Lock the nce to protect nce_res_mp from being changed
1868 * if an external resolver address resolution completes
1869 * while nce_res_mp is being accessed here.
1870 *
1871 * Deal with all address formats, not just Ethernet-specific
1872 * In addition, make sure that the mblk has enough space
1873 * before writing to it. If is doesn't, allocate a new one.
1874 */
1676 /* We have to drop the lock since ndp_process calls put* */
1677 rw_exit(&ill_g_lock);
1678 if (dst_nce != NULL) {
1679 if (na->nd_na_flags_reserved &
1680 ND_NA_FLAG_ROUTER) {
1681 dst_nce->nce_flags |= NCE_F_ISROUTER;
1682 }
1683 /* B_TRUE indicates this an advertisement */

--- 308 unchanged lines hidden (view full) ---

1992 * Lock the nce to protect nce_res_mp from being changed
1993 * if an external resolver address resolution completes
1994 * while nce_res_mp is being accessed here.
1995 *
1996 * Deal with all address formats, not just Ethernet-specific
1997 * In addition, make sure that the mblk has enough space
1998 * before writing to it. If is doesn't, allocate a new one.
1999 */
2000 if (nce->nce_ipversion == IPV4_VERSION)
2001 /* Don't include v4 nce_ts in NDP cache entry report */
2002 return;
2003
1875 ASSERT(ill != NULL);
1876 v6addr = nce->nce_mask;
1877 if (flags & NCE_F_PERMANENT)
1878 *m++ = 'P';
1879 if (flags & NCE_F_ISROUTER)
1880 *m++ = 'R';
1881 if (flags & NCE_F_MAPPING)
1882 *m++ = 'M';

--- 58 unchanged lines hidden (view full) ---

1941
1942mblk_t *
1943nce_udreq_alloc(ill_t *ill)
1944{
1945 mblk_t *template_mp = NULL;
1946 dl_unitdata_req_t *dlur;
1947 int sap_length;
1948
2004 ASSERT(ill != NULL);
2005 v6addr = nce->nce_mask;
2006 if (flags & NCE_F_PERMANENT)
2007 *m++ = 'P';
2008 if (flags & NCE_F_ISROUTER)
2009 *m++ = 'R';
2010 if (flags & NCE_F_MAPPING)
2011 *m++ = 'M';

--- 58 unchanged lines hidden (view full) ---

2070
2071mblk_t *
2072nce_udreq_alloc(ill_t *ill)
2073{
2074 mblk_t *template_mp = NULL;
2075 dl_unitdata_req_t *dlur;
2076 int sap_length;
2077
2078 ASSERT(ill->ill_isv6);
2079
1949 sap_length = ill->ill_sap_length;
1950 template_mp = ip_dlpi_alloc(sizeof (dl_unitdata_req_t) +
1951 ill->ill_nd_lla_len + ABS(sap_length), DL_UNITDATA_REQ);
1952 if (template_mp == NULL)
1953 return (NULL);
1954
1955 dlur = (dl_unitdata_req_t *)template_mp->b_rptr;
1956 dlur->dl_priority.dl_min = 0;

--- 272 unchanged lines hidden (view full) ---

2229static void
2230nce_update(nce_t *nce, uint16_t new_state, uchar_t *new_ll_addr)
2231{
2232 ill_t *ill = nce->nce_ill;
2233 boolean_t need_stop_timer = B_FALSE;
2234 boolean_t need_fastpath_update = B_FALSE;
2235
2236 ASSERT(MUTEX_HELD(&nce->nce_lock));
2080 sap_length = ill->ill_sap_length;
2081 template_mp = ip_dlpi_alloc(sizeof (dl_unitdata_req_t) +
2082 ill->ill_nd_lla_len + ABS(sap_length), DL_UNITDATA_REQ);
2083 if (template_mp == NULL)
2084 return (NULL);
2085
2086 dlur = (dl_unitdata_req_t *)template_mp->b_rptr;
2087 dlur->dl_priority.dl_min = 0;

--- 272 unchanged lines hidden (view full) ---

2360static void
2361nce_update(nce_t *nce, uint16_t new_state, uchar_t *new_ll_addr)
2362{
2363 ill_t *ill = nce->nce_ill;
2364 boolean_t need_stop_timer = B_FALSE;
2365 boolean_t need_fastpath_update = B_FALSE;
2366
2367 ASSERT(MUTEX_HELD(&nce->nce_lock));
2368 ASSERT(nce->nce_ipversion == IPV6_VERSION);
2237 /*
2238 * If this interface does not do NUD, there is no point
2239 * in allowing an update to the cache entry. Although
2240 * we will respond to NS.
2241 * The only time we accept an update for a resolver when
2242 * NUD is turned off is when it has just been created.
2243 * Non-Resolvers will always be created as REACHABLE.
2244 */

--- 35 unchanged lines hidden (view full) ---

2280 (void) untimeout(nce->nce_timeout_id);
2281 nce->nce_timeout_id = 0;
2282 }
2283 if (need_fastpath_update)
2284 nce_fastpath(nce);
2285 mutex_enter(&nce->nce_lock);
2286}
2287
2369 /*
2370 * If this interface does not do NUD, there is no point
2371 * in allowing an update to the cache entry. Although
2372 * we will respond to NS.
2373 * The only time we accept an update for a resolver when
2374 * NUD is turned off is when it has just been created.
2375 * Non-Resolvers will always be created as REACHABLE.
2376 */

--- 35 unchanged lines hidden (view full) ---

2412 (void) untimeout(nce->nce_timeout_id);
2413 nce->nce_timeout_id = 0;
2414 }
2415 if (need_fastpath_update)
2416 nce_fastpath(nce);
2417 mutex_enter(&nce->nce_lock);
2418}
2419
2288static void
2289nce_queue_mp(nce_t *nce, mblk_t *mp)
2420void
2421nce_queue_mp_common(nce_t *nce, mblk_t *mp, boolean_t head_insert)
2290{
2291 uint_t count = 0;
2292 mblk_t **mpp;
2422{
2423 uint_t count = 0;
2424 mblk_t **mpp;
2425
2426 ASSERT(MUTEX_HELD(&nce->nce_lock));
2427
2428 for (mpp = &nce->nce_qd_mp; *mpp != NULL;
2429 mpp = &(*mpp)->b_next) {
2430 if (++count >
2431 nce->nce_ill->ill_max_buf) {
2432 mblk_t *tmp = nce->nce_qd_mp->b_next;
2433
2434 nce->nce_qd_mp->b_next = NULL;
2435 nce->nce_qd_mp->b_prev = NULL;
2436 freemsg(nce->nce_qd_mp);
2437 nce->nce_qd_mp = tmp;
2438 }
2439 }
2440 /* put this on the list */
2441 if (head_insert) {
2442 mp->b_next = nce->nce_qd_mp;
2443 nce->nce_qd_mp = mp;
2444 } else {
2445 *mpp = mp;
2446 }
2447}
2448
2449static void
2450nce_queue_mp(nce_t *nce, mblk_t *mp)
2451{
2293 boolean_t head_insert = B_FALSE;
2294 ip6_t *ip6h;
2295 ip6i_t *ip6i;
2296 mblk_t *data_mp;
2297
2298 ASSERT(MUTEX_HELD(&nce->nce_lock));
2299
2300 if (mp->b_datap->db_type == M_CTL)

--- 41 unchanged lines hidden (view full) ---

2342 * in.mpathd's failure detection time, mpathd may detect
2343 * a failure, and it does not matter whether the packet
2344 * was queued or dropped.
2345 */
2346 if (ip6i->ip6i_flags & IP6I_DROP_IFDELAYED)
2347 head_insert = B_TRUE;
2348 }
2349
2452 boolean_t head_insert = B_FALSE;
2453 ip6_t *ip6h;
2454 ip6i_t *ip6i;
2455 mblk_t *data_mp;
2456
2457 ASSERT(MUTEX_HELD(&nce->nce_lock));
2458
2459 if (mp->b_datap->db_type == M_CTL)

--- 41 unchanged lines hidden (view full) ---

2501 * in.mpathd's failure detection time, mpathd may detect
2502 * a failure, and it does not matter whether the packet
2503 * was queued or dropped.
2504 */
2505 if (ip6i->ip6i_flags & IP6I_DROP_IFDELAYED)
2506 head_insert = B_TRUE;
2507 }
2508
2350 for (mpp = &nce->nce_qd_mp; *mpp != NULL;
2351 mpp = &(*mpp)->b_next) {
2352 if (++count >
2353 nce->nce_ill->ill_max_buf) {
2354 mblk_t *tmp = nce->nce_qd_mp->b_next;
2355
2356 nce->nce_qd_mp->b_next = NULL;
2357 nce->nce_qd_mp->b_prev = NULL;
2358 freemsg(nce->nce_qd_mp);
2359 ip1dbg(("nce_queue_mp: pkt dropped\n"));
2360 nce->nce_qd_mp = tmp;
2361 }
2362 }
2363 /* put this on the list */
2364 if (head_insert) {
2365 mp->b_next = nce->nce_qd_mp;
2366 nce->nce_qd_mp = mp;
2367 } else {
2368 *mpp = mp;
2369 }
2509 nce_queue_mp_common(nce, mp, head_insert);
2370}
2371
2372/*
2373 * Called when address resolution failed due to a timeout.
2374 * Send an ICMP unreachable in response to all queued packets.
2375 */
2376void
2377nce_resolv_failed(nce_t *nce)

--- 58 unchanged lines hidden (view full) ---

2436 sin6_t *sin6;
2437 in6_addr_t *addr;
2438 nce_t *nce;
2439 int err;
2440 uint16_t new_flags = 0;
2441 uint16_t old_flags = 0;
2442 int inflags = lnr->lnr_flags;
2443
2510}
2511
2512/*
2513 * Called when address resolution failed due to a timeout.
2514 * Send an ICMP unreachable in response to all queued packets.
2515 */
2516void
2517nce_resolv_failed(nce_t *nce)

--- 58 unchanged lines hidden (view full) ---

2576 sin6_t *sin6;
2577 in6_addr_t *addr;
2578 nce_t *nce;
2579 int err;
2580 uint16_t new_flags = 0;
2581 uint16_t old_flags = 0;
2582 int inflags = lnr->lnr_flags;
2583
2584 ASSERT(ill->ill_isv6);
2444 if ((lnr->lnr_state_create != ND_REACHABLE) &&
2445 (lnr->lnr_state_create != ND_STALE))
2446 return (EINVAL);
2447
2448 sin6 = (sin6_t *)&lnr->lnr_addr;
2449 addr = &sin6->sin6_addr;
2450
2585 if ((lnr->lnr_state_create != ND_REACHABLE) &&
2586 (lnr->lnr_state_create != ND_STALE))
2587 return (EINVAL);
2588
2589 sin6 = (sin6_t *)&lnr->lnr_addr;
2590 addr = &sin6->sin6_addr;
2591
2451 mutex_enter(&ndp_g_lock);
2592 mutex_enter(&ndp6.ndp_g_lock);
2452 /* We know it can not be mapping so just look in the hash table */
2593 /* We know it can not be mapping so just look in the hash table */
2453 nce = nce_lookup_addr(ill, addr);
2594 nce = *((nce_t **)NCE_HASH_PTR_V6(*addr));
2595 nce = nce_lookup_addr(ill, addr, nce);
2454 if (nce != NULL)
2455 new_flags = nce->nce_flags;
2456
2457 switch (inflags & (NDF_ISROUTER_ON|NDF_ISROUTER_OFF)) {
2458 case NDF_ISROUTER_ON:
2459 new_flags |= NCE_F_ISROUTER;
2460 break;
2461 case NDF_ISROUTER_OFF:
2462 new_flags &= ~NCE_F_ISROUTER;
2463 break;
2464 case (NDF_ISROUTER_OFF|NDF_ISROUTER_ON):
2596 if (nce != NULL)
2597 new_flags = nce->nce_flags;
2598
2599 switch (inflags & (NDF_ISROUTER_ON|NDF_ISROUTER_OFF)) {
2600 case NDF_ISROUTER_ON:
2601 new_flags |= NCE_F_ISROUTER;
2602 break;
2603 case NDF_ISROUTER_OFF:
2604 new_flags &= ~NCE_F_ISROUTER;
2605 break;
2606 case (NDF_ISROUTER_OFF|NDF_ISROUTER_ON):
2465 mutex_exit(&ndp_g_lock);
2607 mutex_exit(&ndp6.ndp_g_lock);
2466 if (nce != NULL)
2467 NCE_REFRELE(nce);
2468 return (EINVAL);
2469 }
2470
2471 switch (inflags & (NDF_ANYCAST_ON|NDF_ANYCAST_OFF)) {
2472 case NDF_ANYCAST_ON:
2473 new_flags |= NCE_F_ANYCAST;
2474 break;
2475 case NDF_ANYCAST_OFF:
2476 new_flags &= ~NCE_F_ANYCAST;
2477 break;
2478 case (NDF_ANYCAST_OFF|NDF_ANYCAST_ON):
2608 if (nce != NULL)
2609 NCE_REFRELE(nce);
2610 return (EINVAL);
2611 }
2612
2613 switch (inflags & (NDF_ANYCAST_ON|NDF_ANYCAST_OFF)) {
2614 case NDF_ANYCAST_ON:
2615 new_flags |= NCE_F_ANYCAST;
2616 break;
2617 case NDF_ANYCAST_OFF:
2618 new_flags &= ~NCE_F_ANYCAST;
2619 break;
2620 case (NDF_ANYCAST_OFF|NDF_ANYCAST_ON):
2479 mutex_exit(&ndp_g_lock);
2621 mutex_exit(&ndp6.ndp_g_lock);
2480 if (nce != NULL)
2481 NCE_REFRELE(nce);
2482 return (EINVAL);
2483 }
2484
2485 switch (inflags & (NDF_PROXY_ON|NDF_PROXY_OFF)) {
2486 case NDF_PROXY_ON:
2487 new_flags |= NCE_F_PROXY;
2488 break;
2489 case NDF_PROXY_OFF:
2490 new_flags &= ~NCE_F_PROXY;
2491 break;
2492 case (NDF_PROXY_OFF|NDF_PROXY_ON):
2622 if (nce != NULL)
2623 NCE_REFRELE(nce);
2624 return (EINVAL);
2625 }
2626
2627 switch (inflags & (NDF_PROXY_ON|NDF_PROXY_OFF)) {
2628 case NDF_PROXY_ON:
2629 new_flags |= NCE_F_PROXY;
2630 break;
2631 case NDF_PROXY_OFF:
2632 new_flags &= ~NCE_F_PROXY;
2633 break;
2634 case (NDF_PROXY_OFF|NDF_PROXY_ON):
2493 mutex_exit(&ndp_g_lock);
2635 mutex_exit(&ndp6.ndp_g_lock);
2494 if (nce != NULL)
2495 NCE_REFRELE(nce);
2496 return (EINVAL);
2497 }
2498
2499 if (nce == NULL) {
2500 err = ndp_add(ill,
2501 (uchar_t *)lnr->lnr_hdw_addr,
2502 addr,
2503 &ipv6_all_ones,
2504 &ipv6_all_zeros,
2505 0,
2506 new_flags,
2507 lnr->lnr_state_create,
2636 if (nce != NULL)
2637 NCE_REFRELE(nce);
2638 return (EINVAL);
2639 }
2640
2641 if (nce == NULL) {
2642 err = ndp_add(ill,
2643 (uchar_t *)lnr->lnr_hdw_addr,
2644 addr,
2645 &ipv6_all_ones,
2646 &ipv6_all_zeros,
2647 0,
2648 new_flags,
2649 lnr->lnr_state_create,
2508 &nce);
2650 &nce,
2651 NULL,
2652 NULL);
2509 if (err != 0) {
2653 if (err != 0) {
2510 mutex_exit(&ndp_g_lock);
2654 mutex_exit(&ndp6.ndp_g_lock);
2511 ip1dbg(("ndp_sioc_update: Can't create NCE %d\n", err));
2512 return (err);
2513 }
2514 }
2515 old_flags = nce->nce_flags;
2516 if (old_flags & NCE_F_ISROUTER && !(new_flags & NCE_F_ISROUTER)) {
2517 /*
2518 * Router turned to host, delete all ires.
2519 * XXX Just delete the entry, but we need to add too.
2520 */
2521 nce->nce_flags &= ~NCE_F_ISROUTER;
2655 ip1dbg(("ndp_sioc_update: Can't create NCE %d\n", err));
2656 return (err);
2657 }
2658 }
2659 old_flags = nce->nce_flags;
2660 if (old_flags & NCE_F_ISROUTER && !(new_flags & NCE_F_ISROUTER)) {
2661 /*
2662 * Router turned to host, delete all ires.
2663 * XXX Just delete the entry, but we need to add too.
2664 */
2665 nce->nce_flags &= ~NCE_F_ISROUTER;
2522 mutex_exit(&ndp_g_lock);
2666 mutex_exit(&ndp6.ndp_g_lock);
2523 ndp_delete(nce);
2524 NCE_REFRELE(nce);
2525 return (0);
2526 }
2667 ndp_delete(nce);
2668 NCE_REFRELE(nce);
2669 return (0);
2670 }
2527 mutex_exit(&ndp_g_lock);
2671 mutex_exit(&ndp6.ndp_g_lock);
2528
2529 mutex_enter(&nce->nce_lock);
2530 nce->nce_flags = new_flags;
2531 mutex_exit(&nce->nce_lock);
2532 /*
2533 * Note that we ignore the state at this point, which
2534 * should be either STALE or REACHABLE. Instead we let
2535 * the link layer address passed in to determine the state

--- 46 unchanged lines hidden (view full) ---

2582 void *arg)
2583{
2584
2585 nce_t *next_nce;
2586 nce_t *current_nce;
2587 nce_t *first_nce;
2588 nce_t *prev_nce = NULL;
2589
2672
2673 mutex_enter(&nce->nce_lock);
2674 nce->nce_flags = new_flags;
2675 mutex_exit(&nce->nce_lock);
2676 /*
2677 * Note that we ignore the state at this point, which
2678 * should be either STALE or REACHABLE. Instead we let
2679 * the link layer address passed in to determine the state

--- 46 unchanged lines hidden (view full) ---

2726 void *arg)
2727{
2728
2729 nce_t *next_nce;
2730 nce_t *current_nce;
2731 nce_t *first_nce;
2732 nce_t *prev_nce = NULL;
2733
2590 ASSERT(ill != NULL);
2734 ASSERT(ill != NULL && ill->ill_isv6);
2591
2592 mutex_enter(&ill->ill_lock);
2593 first_nce = current_nce = (nce_t *)ill->ill_fastpath_list;
2594 while (current_nce != (nce_t *)&ill->ill_fastpath_list) {
2595 next_nce = current_nce->nce_fastpath;
2596 /*
2597 * Take it off the list if we're flushing, or if the callback
2598 * routine tells us to do so. Otherwise, leave the nce in the

--- 22 unchanged lines hidden (view full) ---

2621 * Add nce to the nce fastpath list.
2622 */
2623void
2624nce_fastpath_list_add(nce_t *nce)
2625{
2626 ill_t *ill;
2627
2628 ill = nce->nce_ill;
2735
2736 mutex_enter(&ill->ill_lock);
2737 first_nce = current_nce = (nce_t *)ill->ill_fastpath_list;
2738 while (current_nce != (nce_t *)&ill->ill_fastpath_list) {
2739 next_nce = current_nce->nce_fastpath;
2740 /*
2741 * Take it off the list if we're flushing, or if the callback
2742 * routine tells us to do so. Otherwise, leave the nce in the

--- 22 unchanged lines hidden (view full) ---

2765 * Add nce to the nce fastpath list.
2766 */
2767void
2768nce_fastpath_list_add(nce_t *nce)
2769{
2770 ill_t *ill;
2771
2772 ill = nce->nce_ill;
2629 ASSERT(ill != NULL);
2773 ASSERT(ill != NULL && ill->ill_isv6);
2630
2631 mutex_enter(&ill->ill_lock);
2632 mutex_enter(&nce->nce_lock);
2633
2634 /*
2635 * if nce has not been deleted and
2636 * is not already in the list add it.
2637 */

--- 14 unchanged lines hidden (view full) ---

2652nce_fastpath_list_delete(nce_t *nce)
2653{
2654 nce_t *nce_ptr;
2655
2656 ill_t *ill;
2657
2658 ill = nce->nce_ill;
2659 ASSERT(ill != NULL);
2774
2775 mutex_enter(&ill->ill_lock);
2776 mutex_enter(&nce->nce_lock);
2777
2778 /*
2779 * if nce has not been deleted and
2780 * is not already in the list add it.
2781 */

--- 14 unchanged lines hidden (view full) ---

2796nce_fastpath_list_delete(nce_t *nce)
2797{
2798 nce_t *nce_ptr;
2799
2800 ill_t *ill;
2801
2802 ill = nce->nce_ill;
2803 ASSERT(ill != NULL);
2804 if (!ill->ill_isv6) {
2805 /*
2806 * v4 nce_t's do not have nce_fastpath set.
2807 */
2808 return;
2809 }
2660
2661 mutex_enter(&ill->ill_lock);
2662 if (nce->nce_fastpath == NULL)
2663 goto done;
2664
2665 ASSERT(ill->ill_fastpath_list != &ill->ill_fastpath_list);
2666
2667 if (ill->ill_fastpath_list == nce) {

--- 285 unchanged lines hidden (view full) ---

2953 th_trace->th_next->th_prev = th_trace->th_prev;
2954 th_trace->th_next = NULL;
2955 th_trace->th_prev = NULL;
2956 kmem_free(th_trace, sizeof (th_trace_t));
2957 mutex_exit(&nce->nce_lock);
2958 return (0);
2959}
2960#endif
2810
2811 mutex_enter(&ill->ill_lock);
2812 if (nce->nce_fastpath == NULL)
2813 goto done;
2814
2815 ASSERT(ill->ill_fastpath_list != &ill->ill_fastpath_list);
2816
2817 if (ill->ill_fastpath_list == nce) {

--- 285 unchanged lines hidden (view full) ---

3103 th_trace->th_next->th_prev = th_trace->th_prev;
3104 th_trace->th_next = NULL;
3105 th_trace->th_prev = NULL;
3106 kmem_free(th_trace, sizeof (th_trace_t));
3107 mutex_exit(&nce->nce_lock);
3108 return (0);
3109}
3110#endif
3111
3112/*
3113 * Called when address resolution fails due to a timeout.
3114 * Send an ICMP unreachable in response to all queued packets.
3115 */
3116void
3117arp_resolv_failed(nce_t *nce)
3118{
3119 mblk_t *mp, *nxt_mp, *first_mp;
3120 char buf[INET6_ADDRSTRLEN];
3121 zoneid_t zoneid = GLOBAL_ZONEID;
3122 struct in_addr ipv4addr;
3123
3124 IN6_V4MAPPED_TO_INADDR(&nce->nce_addr, &ipv4addr);
3125 ip3dbg(("arp_resolv_failed: dst %s\n",
3126 inet_ntop(AF_INET, &ipv4addr, buf, sizeof (buf))));
3127 mutex_enter(&nce->nce_lock);
3128 mp = nce->nce_qd_mp;
3129 nce->nce_qd_mp = NULL;
3130 mutex_exit(&nce->nce_lock);
3131
3132 while (mp != NULL) {
3133 nxt_mp = mp->b_next;
3134 mp->b_next = NULL;
3135 mp->b_prev = NULL;
3136
3137 first_mp = mp;
3138 /*
3139 * Send icmp unreachable messages
3140 * to the hosts.
3141 */
3142 (void) ip_hdr_complete((ipha_t *)mp->b_rptr, zoneid);
3143 ip3dbg(("arp_resolv_failed: Calling icmp_unreachable\n"));
3144 icmp_unreachable(nce->nce_ill->ill_wq, first_mp,
3145 ICMP_HOST_UNREACHABLE);
3146 mp = nxt_mp;
3147 }
3148}
3149
3150static int
3151ndp_lookup_then_add_v4(ill_t *ill, uchar_t *hw_addr, const in_addr_t *addr,
3152 const in_addr_t *mask, const in_addr_t *extract_mask,
3153 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
3154 nce_t **newnce, mblk_t *fp_mp, mblk_t *res_mp)
3155{
3156 int err = 0;
3157 nce_t *nce;
3158 in6_addr_t addr6;
3159
3160 mutex_enter(&ndp4.ndp_g_lock);
3161 nce = *((nce_t **)NCE_HASH_PTR_V4(*addr));
3162 IN6_IPADDR_TO_V4MAPPED(*addr, &addr6);
3163 nce = nce_lookup_addr(ill, &addr6, nce);
3164 if (nce == NULL) {
3165 err = ndp_add_v4(ill,
3166 hw_addr,
3167 addr,
3168 mask,
3169 extract_mask,
3170 hw_extract_start,
3171 flags,
3172 state,
3173 newnce,
3174 fp_mp,
3175 res_mp);
3176 } else {
3177 *newnce = nce;
3178 err = EEXIST;
3179 }
3180 mutex_exit(&ndp4.ndp_g_lock);
3181 return (err);
3182}
3183
3184/*
3185 * NDP Cache Entry creation routine for IPv4.
3186 * Mapped entries are handled in arp.
3187 * This routine must always be called with ndp4.ndp_g_lock held.
3188 * Prior to return, nce_refcnt is incremented.
3189 */
3190static int
3191ndp_add_v4(ill_t *ill, uchar_t *hw_addr, const in_addr_t *addr,
3192 const in_addr_t *mask, const in_addr_t *extract_mask,
3193 uint32_t hw_extract_start, uint16_t flags, uint16_t state,
3194 nce_t **newnce, mblk_t *fp_mp, mblk_t *res_mp)
3195{
3196 static nce_t nce_nil;
3197 nce_t *nce;
3198 mblk_t *mp;
3199 mblk_t *template;
3200 nce_t **ncep;
3201
3202 ASSERT(MUTEX_HELD(&ndp4.ndp_g_lock));
3203 ASSERT(ill != NULL);
3204 if ((flags & ~NCE_EXTERNAL_FLAGS_MASK)) {
3205 return (EINVAL);
3206 }
3207 ASSERT((flags & NCE_F_MAPPING) == 0);
3208 ASSERT(extract_mask == NULL);
3209 /*
3210 * Allocate the mblk to hold the nce.
3211 */
3212 mp = allocb(sizeof (nce_t), BPRI_MED);
3213 if (mp == NULL)
3214 return (ENOMEM);
3215
3216 nce = (nce_t *)mp->b_rptr;
3217 mp->b_wptr = (uchar_t *)&nce[1];
3218 *nce = nce_nil;
3219
3220 /*
3221 * This one holds link layer address; if res_mp has been provided
3222 * by the caller, accept it without any further checks. Otherwise,
3223 * for V4, we fill it up with ill_resolver_mp here, then in
3224 * in ire_arpresolve(), we fill it up with the ARP query
3225 * once its formulated.
3226 */
3227 if (res_mp != NULL) {
3228 template = res_mp;
3229 } else {
3230 template = copyb(ill->ill_resolver_mp);
3231 }
3232 if (template == NULL) {
3233 freeb(mp);
3234 return (ENOMEM);
3235 }
3236 nce->nce_ill = ill;
3237 nce->nce_ipversion = IPV4_VERSION;
3238 nce->nce_flags = flags;
3239 nce->nce_state = state;
3240 nce->nce_pcnt = ND_MAX_UNICAST_SOLICIT;
3241 nce->nce_rcnt = ill->ill_xmit_count;
3242 IN6_IPADDR_TO_V4MAPPED(*addr, &nce->nce_addr);
3243 if (*mask == IP_HOST_MASK) {
3244 nce->nce_mask = ipv6_all_ones;
3245 } else {
3246 IN6_IPADDR_TO_V4MAPPED(*mask, &nce->nce_mask);
3247 }
3248 nce->nce_extract_mask = ipv6_all_zeros;
3249 nce->nce_ll_extract_start = hw_extract_start;
3250 nce->nce_fp_mp = (fp_mp? fp_mp : NULL);
3251 nce->nce_res_mp = template;
3252 if (state == ND_REACHABLE)
3253 nce->nce_last = TICK_TO_MSEC(lbolt64);
3254 else
3255 nce->nce_last = 0;
3256 nce->nce_qd_mp = NULL;
3257 nce->nce_mp = mp;
3258 if (hw_addr != NULL)
3259 nce_set_ll(nce, hw_addr);
3260 /* This one is for nce getting created */
3261 nce->nce_refcnt = 1;
3262 mutex_init(&nce->nce_lock, NULL, MUTEX_DEFAULT, NULL);
3263 ncep = ((nce_t **)NCE_HASH_PTR_V4(*addr));
3264
3265#ifdef NCE_DEBUG
3266 bzero(nce->nce_trace, sizeof (th_trace_t *) * IP_TR_HASH_MAX);
3267#endif
3268 /*
3269 * Atomically ensure that the ill is not CONDEMNED, before
3270 * adding the NCE.
3271 */
3272 mutex_enter(&ill->ill_lock);
3273 if (ill->ill_state_flags & ILL_CONDEMNED) {
3274 mutex_exit(&ill->ill_lock);
3275 freeb(mp);
3276 if (res_mp == NULL) {
3277 /*
3278 * template was locally allocated. need to free it.
3279 */
3280 freeb(template);
3281 }
3282 return (EINVAL);
3283 }
3284 if ((nce->nce_next = *ncep) != NULL)
3285 nce->nce_next->nce_ptpn = &nce->nce_next;
3286 *ncep = nce;
3287 nce->nce_ptpn = ncep;
3288 *newnce = nce;
3289 /* This one is for nce being used by an active thread */
3290 NCE_REFHOLD(*newnce);
3291
3292 /* Bump up the number of nce's referencing this ill */
3293 ill->ill_nce_cnt++;
3294 mutex_exit(&ill->ill_lock);
3295 return (0);
3296}
3297
3298void
3299ndp_flush_qd_mp(nce_t *nce)
3300{
3301 mblk_t *qd_mp, *qd_next;
3302
3303 ASSERT(MUTEX_HELD(&nce->nce_lock));
3304 qd_mp = nce->nce_qd_mp;
3305 nce->nce_qd_mp = NULL;
3306 while (qd_mp != NULL) {
3307 qd_next = qd_mp->b_next;
3308 qd_mp->b_next = NULL;
3309 qd_mp->b_prev = NULL;
3310 freemsg(qd_mp);
3311 qd_mp = qd_next;
3312 }
3313}
3314
3315nce_t *
3316nce_reinit(nce_t *nce)
3317{
3318 nce_t *newnce = NULL;
3319 in_addr_t nce_addr, nce_mask;
3320
3321 IN6_V4MAPPED_TO_IPADDR(&nce->nce_addr, nce_addr);
3322 IN6_V4MAPPED_TO_IPADDR(&nce->nce_mask, nce_mask);
3323 /*
3324 * delete the old one. this will get rid of any ire's pointing
3325 * at this nce.
3326 */
3327 ndp_delete(nce);
3328 /*
3329 * create a new nce with the same addr and mask.
3330 */
3331 mutex_enter(&ndp4.ndp_g_lock);
3332 (void) ndp_add_v4(nce->nce_ill, NULL, &nce_addr, &nce_mask, NULL, 0, 0,
3333 ND_INITIAL, &newnce, NULL, NULL);
3334 mutex_exit(&ndp4.ndp_g_lock);
3335 /*
3336 * refrele the old nce.
3337 */
3338 NCE_REFRELE(nce);
3339 return (newnce);
3340}