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} |
|