Lines Matching refs:ncec

88  * in to the ncec*add* functions.
109 static void nce_cleanup_list(ncec_t *ncec);
110 static void nce_set_ll(ncec_t *ncec, uchar_t *ll_addr);
171 nce_dad(ncec_t *ncec, ill_t *src_ill, boolean_t send_probe)
176 ASSERT(!(ncec->ncec_flags & NCE_F_MCAST));
177 ASSERT(!(ncec->ncec_flags & NCE_F_BCAST));
178 if (ncec->ncec_ipversion == IPV6_VERSION) {
180 ncec->ncec_lladdr, ncec->ncec_lladdr_length,
181 &ipv6_all_zeros, &ncec->ncec_addr, NDP_PROBE);
186 dropped = arp_probe(ncec);
189 probe_interval = nce_fuzz_interval(ncec->ncec_xmit_interval,
193 mutex_enter(&ncec->ncec_lock);
194 ncec->ncec_pcnt--;
195 mutex_exit(&ncec->ncec_lock);
197 nce_restart_timer(ncec, probe_interval);
201 * Compute default flags to use for an advertisement of this ncec's address.
204 nce_advert_flags(const ncec_t *ncec)
208 if (ncec->ncec_flags & NCE_F_ISROUTER)
210 if (!(ncec->ncec_flags & NCE_F_ANYCAST))
247 ncec_t *ncec = nce->nce_common;
249 uchar_t *hw_addr = ncec->ncec_lladdr;
250 uint_t hw_addr_len = ncec->ncec_lladdr_length;
251 ill_t *ill = ncec->ncec_ill;
253 uint16_t flags = ncec->ncec_flags;
259 * we call nce_fastpath as soon as the ncec is resolved in nce_process.
263 if (NCE_PUBLISH(ncec) || !NCE_ISREACHABLE(ncec) ||
269 if (NCE_PUBLISH(ncec) && ncec->ncec_state == ND_PROBE) {
280 nce_dad(ncec, hwaddr_ill, B_TRUE);
288 mutex_enter(&ncec->ncec_lock);
289 ncec->ncec_unsolicit_count =
291 mutex_exit(&ncec->ncec_lock);
296 &ncec->ncec_addr, /* Source and target of the adv */
298 nce_advert_flags(ncec));
299 mutex_enter(&ncec->ncec_lock);
301 ncec->ncec_unsolicit_count++;
303 ncec->ncec_last_time_defended = ddi_get_lbolt();
304 if (ncec->ncec_unsolicit_count != 0) {
305 nce_start_timer(ncec,
308 mutex_exit(&ncec->ncec_lock);
317 * IPMP notes: the ncec for non-local (i.e., !NCE_MYADDR(ncec) addresses
418 nce_remove(ndp_g_t *ndp, ncec_t *ncec, ncec_t **free_nce_list)
425 for (; ncec; ncec = ncec1) {
426 ncec1 = ncec->ncec_next;
427 mutex_enter(&ncec->ncec_lock);
428 if (NCE_ISCONDEMNED(ncec)) {
429 ptpn = ncec->ncec_ptpn;
430 ncec1 = ncec->ncec_next;
434 ncec->ncec_ptpn = NULL;
435 ncec->ncec_next = NULL;
436 ncec->ncec_next = *free_nce_list;
437 *free_nce_list = ncec;
439 mutex_exit(&ncec->ncec_lock);
453 ncec_delete(ncec_t *ncec)
457 int ipversion = ncec->ncec_ipversion;
459 ip_stack_t *ipst = ncec->ncec_ipst;
467 mutex_enter(&ncec->ncec_lock);
468 if (NCE_ISCONDEMNED(ncec)) {
470 mutex_exit(&ncec->ncec_lock);
477 ASSERT(ncec->ncec_refcnt >= 2);
478 ncec->ncec_flags |= NCE_F_CONDEMNED;
479 mutex_exit(&ncec->ncec_lock);
483 nce_fastpath_list_delete(ncec->ncec_ill, ncec, NULL);
486 ncec_cb_dispatch(ncec);
493 if (ncec->ncec_timeout_id != 0) {
494 (void) untimeout(ncec->ncec_timeout_id);
495 ncec->ncec_timeout_id = 0;
499 if (ncec->ncec_ptpn == NULL) {
501 * The last ndp walker has already removed this ncec from
502 * the list after we marked the ncec CONDEMNED and before
518 * Now remove the ncec from the list. nce_restart_timer won't restart
521 ptpn = ncec->ncec_ptpn;
522 ncec1 = ncec->ncec_next;
526 ncec->ncec_ptpn = NULL;
527 ncec->ncec_next = NULL;
531 ncec_refrele_notr(ncec);
535 ncec_inactive(ncec_t *ncec)
538 ill_t *ill = ncec->ncec_ill;
539 ip_stack_t *ipst = ncec->ncec_ipst;
541 ASSERT(ncec->ncec_refcnt == 0);
542 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
545 if (NCE_ISCONDEMNED(ncec))
549 mpp = &ncec->ncec_qd_mp;
561 ASSERT(list_is_empty(&ncec->ncec_cb));
562 list_destroy(&ncec->ncec_cb);
566 if (ncec->ncec_lladdr_length > 0)
567 kmem_free(ncec->ncec_lladdr, ncec->ncec_lladdr_length);
570 ncec_trace_cleanup(ncec);
575 (char *), "ncec", (void *), ncec);
577 ncec->ncec_ill = NULL;
579 * If the number of ncec's associated with this ill have dropped
590 mutex_destroy(&ncec->ncec_lock);
591 kmem_cache_free(ncec_cache, ncec);
595 * ncec_walk routine. Delete the ncec if it is associated with the ill
599 ncec_delete_per_ill(ncec_t *ncec, uchar_t *arg)
601 if ((ncec != NULL) && ncec->ncec_ill == (ill_t *)arg) {
602 ncec_delete(ncec);
610 nce_cleanup_list(ncec_t *ncec)
614 ASSERT(ncec != NULL);
615 while (ncec != NULL) {
616 ncec_next = ncec->ncec_next;
617 ncec->ncec_next = NULL;
621 * to come here after ncec_delete has marked the ncec CONDEMNED
622 * and before it has removed the ncec from the fastpath list
626 * reference on the ncec.
628 nce_fastpath_list_delete(ncec->ncec_ill, ncec, NULL);
635 if (ncec->ncec_timeout_id != 0) {
636 (void) untimeout(ncec->ncec_timeout_id);
637 ncec->ncec_timeout_id = 0;
640 ncec_refrele_notr(ncec);
641 ncec = ncec_next;
649 nce_restart_dad(ncec_t *ncec)
654 if (ncec == NULL)
656 ill = ncec->ncec_ill;
657 mutex_enter(&ncec->ncec_lock);
658 if (ncec->ncec_state == ND_PROBE) {
659 mutex_exit(&ncec->ncec_lock);
661 } else if (ncec->ncec_state == ND_REACHABLE) {
662 ASSERT(ncec->ncec_lladdr != NULL);
663 ncec->ncec_state = ND_PROBE;
664 ncec->ncec_pcnt = ND_MAX_UNICAST_SOLICIT;
669 mutex_exit(&ncec->ncec_lock);
672 ncec->ncec_lladdr, ncec->ncec_lladdr_length);
676 nce_dad(ncec, hwaddr_ill, B_TRUE);
679 mutex_exit(&ncec->ncec_lock);
686 * IPv6 Cache entry lookup. Try to find an ncec matching the parameters passed.
687 * If one is found, the refcnt on the ncec will be incremented.
692 ncec_t *ncec;
699 ncec = *((ncec_t **)NCE_HASH_PTR_V6(ipst, *addr));
700 ncec = ncec_lookup_illgrp(ill, addr, ncec);
703 return (ncec);
706 * IPv4 Cache entry lookup. Try to find an ncec matching the parameters passed.
707 * If one is found, the refcnt on the ncec will be incremented.
712 ncec_t *ncec = NULL;
720 ncec = *((ncec_t **)NCE_HASH_PTR_V4(ipst, *addr));
722 ncec = ncec_lookup_illgrp(ill, &addr6, ncec);
725 return (ncec);
729 * Cache entry lookup. Try to find an ncec matching the parameters passed.
730 * If an ncec is found, increment the hold count on that ncec.
739 ncec_lookup_illgrp(ill_t *ill, const in6_addr_t *addr, ncec_t *ncec)
753 for (; ncec != NULL; ncec = ncec->ncec_next) {
754 if (ncec->ncec_ill == ill ||
755 IS_IN_SAME_ILLGRP(ill, ncec->ncec_ill)) {
756 if (IN6_ARE_ADDR_EQUAL(&ncec->ncec_addr, addr)) {
757 mutex_enter(&ncec->ncec_lock);
758 if (!NCE_ISCONDEMNED(ncec)) {
759 ncec_refhold_locked(ncec);
760 mutex_exit(&ncec->ncec_lock);
763 mutex_exit(&ncec->ncec_lock);
767 return (ncec);
826 * Router turned to host. We need to make sure that cached copies of the ncec
831 * Note that the ncec itself probably has valid link-layer information for the
832 * nexthop, so that there is no reason to delete the ncec, as long as the
836 ncec_router_to_host(ncec_t *ncec)
839 ip_stack_t *ipst = ncec->ncec_ipst;
841 mutex_enter(&ncec->ncec_lock);
842 ncec->ncec_flags &= ~NCE_F_ISROUTER;
843 mutex_exit(&ncec->ncec_lock);
846 &ncec->ncec_addr, IRE_DEFAULT, ncec->ncec_ill, ALL_ZONES, NULL,
860 nce_process(ncec_t *ncec, uchar_t *hw_addr, uint32_t flag, boolean_t is_adv)
862 ill_t *ill = ncec->ncec_ill;
868 ASSERT(ncec->ncec_ipversion == IPV6_VERSION);
874 mutex_enter(&ncec->ncec_lock);
875 if (ncec->ncec_state == ND_INCOMPLETE) {
877 mutex_exit(&ncec->ncec_lock);
880 nce_set_ll(ncec, hw_addr);
882 * Update ncec state and send the queued packets
886 nce_update(ncec, ND_REACHABLE, NULL);
888 nce_update(ncec, ND_STALE, NULL);
890 mutex_exit(&ncec->ncec_lock);
891 nce = nce_fastpath(ncec, B_TRUE, NULL);
892 nce_resolv_ok(ncec);
897 ll_changed = nce_cmp_ll_addr(ncec, hw_addr, hw_addr_len);
901 nce_update(ncec, ND_STALE, hw_addr);
902 mutex_exit(&ncec->ncec_lock);
903 ncec_cb_dispatch(ncec);
908 if (ncec->ncec_state == ND_REACHABLE) {
909 nce_update(ncec, ND_STALE, NULL);
911 mutex_exit(&ncec->ncec_lock);
912 ncec_cb_dispatch(ncec);
916 nce_update(ncec, ND_UNCHANGED, hw_addr);
920 nce_update(ncec, ND_REACHABLE, NULL);
923 nce_update(ncec, ND_STALE, NULL);
926 mutex_exit(&ncec->ncec_lock);
927 if (!(flag & ND_NA_FLAG_ROUTER) && (ncec->ncec_flags &
929 ncec_router_to_host(ncec);
931 ncec_cb_dispatch(ncec);
937 * Pass arg1 to the pfi supplied, along with each ncec in existence.
938 * ncec_walk() places a REFHOLD on the ncec and drops the lock when
945 ncec_t *ncec;
956 for (ncec = *ncep; ncec != NULL; ncec = ncec1) {
957 ncec1 = ncec->ncec_next;
958 if (ill == NULL || ncec->ncec_ill == ill) {
960 ncec_refhold(ncec);
961 (*pfi)(ncec, arg1);
962 ncec_refrele(ncec);
964 ncec_refhold_notr(ncec);
965 (*pfi)(ncec, arg1);
966 ncec_refrele_notr(ncec);
977 ncec = *ncep;
978 if (ncec != NULL) {
979 nce_remove(ndp, ncec, &free_nce_list);
1066 * Return the link layer address, and any flags of a ncec.
1071 ncec_t *ncec;
1085 ncec = ncec_lookup_illgrp_v6(ill, addr);
1086 if (ncec == NULL)
1089 if (!NCE_ISREACHABLE(ncec)) {
1090 ncec_refrele(ncec);
1094 bcopy(ncec->ncec_lladdr, (uchar_t *)&lnr->lnr_hdw_addr,
1096 if (ncec->ncec_flags & NCE_F_ISROUTER)
1098 if (ncec->ncec_flags & NCE_F_ANYCAST)
1100 if (ncec->ncec_flags & NCE_F_STATIC)
1102 ncec_refrele(ncec);
1143 ip_ndp_resolve(ncec_t *ncec)
1150 src_ill = nce_resolve_src(ncec, &sender6);
1153 ms = ncec->ncec_ill->ill_reachable_retrans_time;
1154 nce_restart_timer(ncec, (clock_t)ms);
1157 if (ncec->ncec_ipversion == IPV4_VERSION)
1159 mutex_enter(&ncec->ncec_lock);
1160 if (ncec->ncec_ipversion == IPV6_VERSION)
1161 ms = ndp_solicit(ncec, sender6, src_ill);
1163 ms = arp_request(ncec, sender4, src_ill);
1164 mutex_exit(&ncec->ncec_lock);
1166 if (ncec->ncec_state != ND_REACHABLE) {
1167 if (ncec->ncec_ipversion == IPV6_VERSION)
1168 ndp_resolv_failed(ncec);
1170 arp_resolv_failed(ncec);
1171 ASSERT((ncec->ncec_flags & NCE_F_STATIC) == 0);
1172 nce_make_unreachable(ncec);
1173 ncec_delete(ncec);
1176 nce_restart_timer(ncec, (clock_t)ms);
1194 ndp_solicit(ncec_t *ncec, in6_addr_t src, ill_t *ill)
1199 ASSERT(ncec->ncec_ipversion == IPV6_VERSION);
1200 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
1202 if (ncec->ncec_rcnt == 0)
1205 dst = ncec->ncec_addr;
1206 ncec->ncec_rcnt--;
1207 mutex_exit(&ncec->ncec_lock);
1210 mutex_enter(&ncec->ncec_lock);
1212 ncec->ncec_rcnt++;
1213 return (ncec->ncec_ill->ill_reachable_retrans_time);
1507 * that tearing down the ipif also means deleting the ncec through ipif_down, so
1508 * it's not possible to do recovery by just restarting the ncec timer. Instead,
1558 ip_nce_conflict(mblk_t *mp, ip_recv_attr_t *ira, ncec_t *ncec)
1571 ipif = ipif_lookup_addr_v6(&ncec->ncec_addr, ill, ALL_ZONES,
1581 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, ncec_addr);
1601 elapsed = (drv_hztousec(now - ncec->ncec_last_time_defended))/1000000;
1602 mutex_enter(&ncec->ncec_lock);
1603 if ((defs = ncec->ncec_defense_count) > 0 &&
1609 ncec->ncec_defense_count = defs = 0;
1611 ncec->ncec_defense_count++;
1612 ncec->ncec_last_time_defended = now;
1613 mutex_exit(&ncec->ncec_lock);
2300 nce_make_unreachable(ncec_t *ncec)
2302 mutex_enter(&ncec->ncec_lock);
2303 ncec->ncec_state = ND_UNREACHABLE;
2304 mutex_exit(&ncec->ncec_lock);
2316 ncec_t *ncec = arg;
2317 ill_t *ill = ncec->ncec_ill, *src_ill;
2320 ip_stack_t *ipst = ncec->ncec_ipst;
2321 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
2329 * bump up the refcnt so that we can continue to use the ncec
2331 ASSERT(ncec != NULL);
2332 mutex_enter(&ncec->ncec_lock);
2333 ncec_refhold_locked(ncec);
2334 ncec->ncec_timeout_id = 0;
2335 mutex_exit(&ncec->ncec_lock);
2337 src_ill = nce_resolve_src(ncec, &sender6);
2341 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, sender4);
2346 &ncec->ncec_addr, addrbuf, sizeof (addrbuf))));
2348 nce_restart_timer(ncec, ill->ill_reachable_retrans_time);
2349 ncec_refrele(ncec);
2355 mutex_enter(&ncec->ncec_lock);
2359 switch (ncec->ncec_state) {
2361 ASSERT(ncec->ncec_lladdr != NULL);
2362 ncec->ncec_state = ND_PROBE;
2363 ncec->ncec_pcnt = ND_MAX_UNICAST_SOLICIT;
2365 mutex_exit(&ncec->ncec_lock);
2369 &sender6, &ncec->ncec_addr,
2372 dropped = (arp_request(ncec, sender4, src_ill) == 0);
2373 mutex_exit(&ncec->ncec_lock);
2376 mutex_enter(&ncec->ncec_lock);
2377 ncec->ncec_pcnt--;
2378 mutex_exit(&ncec->ncec_lock);
2383 "to PROBE\n", AF_INET6, &ncec->ncec_addr);
2385 nce_restart_timer(ncec, ill->ill_reachable_retrans_time);
2389 ASSERT(ncec->ncec_pcnt >= -1);
2390 if (ncec->ncec_pcnt > 0) {
2392 * As per RFC2461, the ncec gets deleted after
2398 ncec->ncec_pcnt,
2400 &ncec->ncec_addr, addrbuf, sizeof (addrbuf))));
2401 if (NCE_PUBLISH(ncec)) {
2402 mutex_exit(&ncec->ncec_lock);
2409 nce_dad(ncec, src_ill, B_TRUE);
2413 mutex_exit(&ncec->ncec_lock);
2418 &sender6, &ncec->ncec_addr,
2426 dropped = (arp_request(ncec, sender4,
2428 mutex_exit(&ncec->ncec_lock);
2431 mutex_enter(&ncec->ncec_lock);
2432 ncec->ncec_pcnt--;
2433 mutex_exit(&ncec->ncec_lock);
2435 nce_restart_timer(ncec,
2438 } else if (ncec->ncec_pcnt < 0) {
2439 /* No hope, delete the ncec */
2441 ncec->ncec_state = ND_UNREACHABLE;
2442 mutex_exit(&ncec->ncec_lock);
2447 &ncec->ncec_addr);
2450 if ((ncec->ncec_flags & NCE_F_STATIC) == 0)
2451 ncec_delete(ncec);
2453 } else if (!NCE_PUBLISH(ncec)) {
2459 ASSERT((ncec->ncec_flags & NCE_F_NONUD) == 0);
2461 ncec->ncec_pcnt, inet_ntop(AF_INET6,
2462 &ncec->ncec_addr, addrbuf, sizeof (addrbuf))));
2463 ncec->ncec_pcnt--;
2464 mutex_exit(&ncec->ncec_lock);
2466 nce_restart_timer(ncec,
2477 ncec->ncec_state = ND_REACHABLE;
2478 ncec->ncec_flags &= ~NCE_F_UNVERIFIED;
2479 mutex_exit(&ncec->ncec_lock);
2482 &ncec->ncec_addr, ill, ipst);
2484 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr,
2512 if (ncec->ncec_unsolicit_count > 0) {
2513 ncec->ncec_unsolicit_count--;
2515 dropped = ndp_announce(ncec);
2517 dropped = arp_announce(ncec);
2521 ncec->ncec_unsolicit_count++;
2523 ncec->ncec_last_time_defended =
2526 if (ncec->ncec_unsolicit_count > 0) {
2527 nce_restart_timer(ncec,
2530 nce_restart_timer(ncec, DEFENSE_INTERVAL(isv6));
2539 ncec->ncec_state = ND_REACHABLE;
2540 mutex_exit(&ncec->ncec_lock);
2554 prevmpp = &ncec->ncec_qd_mp;
2555 for (mp = ncec->ncec_qd_mp; mp != NULL; mp = nextmp) {
2558 if (IS_UNDER_IPMP(ill) && ncec->ncec_nprobes > 0) {
2560 ncec->ncec_nprobes--;
2570 mutex_exit(&ncec->ncec_lock);
2571 ip_ndp_resolve(ncec);
2575 if (((ncec->ncec_flags & NCE_F_UNSOL_ADV) &&
2576 ncec->ncec_unsolicit_count != 0) ||
2577 (NCE_PUBLISH(ncec) && DEFENSE_INTERVAL(isv6) != 0)) {
2578 if (ncec->ncec_unsolicit_count > 0) {
2579 ncec->ncec_unsolicit_count--;
2580 mutex_exit(&ncec->ncec_lock);
2588 mutex_exit(&ncec->ncec_lock);
2589 rate_limit = ill_defend_rate_limit(ill, ncec);
2591 nce_restart_timer(ncec,
2597 dropped = ndp_announce(ncec);
2599 dropped = arp_announce(ncec);
2601 mutex_enter(&ncec->ncec_lock);
2603 ncec->ncec_unsolicit_count++;
2605 ncec->ncec_last_time_defended =
2608 mutex_exit(&ncec->ncec_lock);
2609 if (ncec->ncec_unsolicit_count != 0) {
2610 nce_restart_timer(ncec,
2613 nce_restart_timer(ncec, DEFENSE_INTERVAL(isv6));
2616 mutex_exit(&ncec->ncec_lock);
2620 mutex_exit(&ncec->ncec_lock);
2624 ncec_refrele(ncec);
2633 nce_set_ll(ncec_t *ncec, uchar_t *ll_addr)
2635 ill_t *ill = ncec->ncec_ill;
2656 bcopy(ll_addr, ncec->ncec_lladdr, ill->ill_nd_lla_len);
2661 nce_cmp_ll_addr(const ncec_t *ncec, const uchar_t *ll_addr,
2664 ASSERT(ncec->ncec_lladdr != NULL);
2667 if (bcmp(ll_addr, ncec->ncec_lladdr, ll_addr_len) != 0)
2677 nce_update(ncec_t *ncec, uint16_t new_state, uchar_t *new_ll_addr)
2679 ill_t *ill = ncec->ncec_ill;
2685 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
2695 if ((ncec->ncec_flags & NCE_F_NONUD) &&
2696 (ncec->ncec_state != ND_INCOMPLETE))
2702 ncec->ncec_last = TICK_TO_MSEC(ddi_get_lbolt64());
2705 ncec->ncec_last = 0;
2707 ncec->ncec_state = new_state;
2708 ncec->ncec_pcnt = ND_MAX_UNICAST_SOLICIT;
2709 ASSERT(ncec->ncec_lladdr != NULL || new_state == ND_INITIAL ||
2712 if (need_stop_timer || (ncec->ncec_flags & NCE_F_STATIC)) {
2713 tid = ncec->ncec_timeout_id;
2714 ncec->ncec_timeout_id = 0;
2722 bcopy(new_ll_addr, ncec->ncec_lladdr,
2726 mutex_exit(&ncec->ncec_lock);
2727 if (need_stop_timer || (ncec->ncec_flags & NCE_F_STATIC)) {
2737 nce_fastpath_list_delete(ncec->ncec_ill, ncec, NULL);
2741 nce = nce_fastpath(ncec, B_TRUE, NULL);
2745 mutex_enter(&ncec->ncec_lock);
2749 nce_queue_mp_common(ncec_t *ncec, mblk_t *mp, boolean_t head_insert)
2754 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
2756 for (mpp = &ncec->ncec_qd_mp; *mpp != NULL; mpp = &(*mpp)->b_next) {
2757 if (++count > ncec->ncec_ill->ill_max_buf) {
2758 tmp = ncec->ncec_qd_mp->b_next;
2759 ncec->ncec_qd_mp->b_next = NULL;
2764 BUMP_MIB(ncec->ncec_ill->ill_ip_mib,
2766 ip_drop_output("ipIfStatsOutDiscards", ncec->ncec_qd_mp,
2767 ncec->ncec_ill);
2768 freemsg(ncec->ncec_qd_mp);
2769 ncec->ncec_qd_mp = tmp;
2774 ncec->ncec_nprobes++;
2775 mp->b_next = ncec->ncec_qd_mp;
2776 ncec->ncec_qd_mp = mp;
2803 * The ncec for the probe target is created with ncec_ill set to the ipmp_ill,
2807 nce_queue_mp(ncec_t *ncec, mblk_t *mp, boolean_t head_insert)
2809 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
2810 nce_queue_mp_common(ncec, mp, head_insert);
2818 ndp_resolv_failed(ncec_t *ncec)
2822 ill_t *ill = ncec->ncec_ill;
2838 inet_ntop(AF_INET6, (char *)&ncec->ncec_addr, buf, sizeof (buf))));
2839 mutex_enter(&ncec->ncec_lock);
2840 mp = ncec->ncec_qd_mp;
2841 ncec->ncec_qd_mp = NULL;
2842 ncec->ncec_nprobes = 0;
2843 mutex_exit(&ncec->ncec_lock);
2856 ncec_cb_dispatch(ncec); /* finish off waiting callbacks */
2863 nce_resolv_ok(ncec_t *ncec)
2869 ill_t *ill = ncec->ncec_ill;
2870 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
2873 if (IS_IPMP(ncec->ncec_ill)) {
2874 nce_resolv_ipmp_ok(ncec);
2879 mutex_enter(&ncec->ncec_lock);
2880 ASSERT(ncec->ncec_nprobes == 0);
2881 mp = ncec->ncec_qd_mp;
2882 ncec->ncec_qd_mp = NULL;
2883 mutex_exit(&ncec->ncec_lock);
2907 nce = nce_lookup(ill, &ncec->ncec_addr);
2935 ncec_cb_dispatch(ncec); /* complete callbacks */
2939 * Called by SIOCSNDP* ioctl to add/change an ncec entry
2948 ncec_t *ncec;
3017 ncec = nce->nce_common;
3018 old_flags = ncec->ncec_flags;
3020 ncec_router_to_host(ncec);
3037 mutex_enter(&ncec->ncec_lock);
3038 ncec->ncec_flags = new_flags;
3039 mutex_exit(&ncec->ncec_lock);
3046 nce_process(ncec, (uchar_t *)lnr->lnr_hdw_addr, 0, B_FALSE);
3052 * Create an nce_t structure for ill using the ncec->ncec_lladdr to set up
3053 * the nce_dlur_mp. If ill != ncec->ncec_ill, then the ips_ill_g_lock must
3057 nce_fastpath_create(ill_t *ill, ncec_t *ncec)
3062 nce = nce_ill_lookup_then_add(ill, ncec);
3070 * consistent with ncec->ncec_lladdr, even though some intermediate
3074 mutex_enter(&ncec->ncec_lock);
3075 if (ncec->ncec_lladdr != NULL) {
3076 bcopy(ncec->ncec_lladdr, nce->nce_dlur_mp->b_rptr +
3082 mutex_exit(&ncec->ncec_lock);
3088 * The caller ensures there is hold on ncec for this function.
3090 * no need to hold the nce or ncec beyond this function.
3093 * ncec_nce must correspond to the nce for ncec with nce_ill == ncec->ncec_ill
3100 nce_fastpath(ncec_t *ncec, boolean_t trigger_fp_req, nce_t *ncec_nce)
3103 ill_t *ill = ncec->ncec_ill;
3109 ipmp_ncec_refresh_nce(ncec);
3119 nce = nce_fastpath_create(ill, ncec);
3139 ncec_t *ncec = nce->nce_common;
3144 * i.e. allocation failure etc. leave the ncec in the list it
3150 nce_fastpath_list_delete(ill, ncec, NULL);
3154 * Add ncec to the nce fastpath list on ill.
3157 nce_ill_lookup_then_add_locked(ill_t *ill, ncec_t *ncec)
3168 mutex_enter(&ncec->ncec_lock);
3170 * if ncec has not been deleted and
3173 if (!NCE_ISCONDEMNED(ncec)) {
3174 nce = nce_lookup(ill, &ncec->ncec_addr);
3177 nce = nce_add(ill, ncec);
3180 mutex_exit(&ncec->ncec_lock);
3185 nce_ill_lookup_then_add(ill_t *ill, ncec_t *ncec)
3190 nce = nce_ill_lookup_then_add_locked(ill, ncec);
3197 * remove ncec from the ill_nce list. If 'dead' is non-null, the deleted
3202 nce_fastpath_list_delete(ill_t *ill, ncec_t *ncec, list_t *dead)
3208 /* delete any nces referencing the ncec from underlying ills */
3210 ipmp_ncec_delete_nce(ncec);
3216 if (nce->nce_common == ncec) {
3249 * Make sure that ncec is not condemned before adding. We hold the
3271 ncec_t *ncec = nce->nce_common;
3291 * The ncec is locked here to prevent any other threads from accessing
3298 mutex_enter(&ncec->ncec_lock);
3302 mutex_exit(&ncec->ncec_lock);
3306 mutex_exit(&ncec->ncec_lock);
3404 * computation as we walk through the ncec's (e.g., track ncec entries by
3408 ncec_cache_reclaim(ncec_t *ncec, char *arg)
3410 ip_stack_t *ipst = ncec->ncec_ipst;
3414 if ((ncec->ncec_flags &
3420 NCE_ADDR_HASH_V6(ncec->ncec_addr, NCE_TABLE_SIZE);
3423 ncec_delete(ncec);
3442 * Walk all CONNs that can have a reference on an ire, ncec or dce.
3479 ncec_trace_ref(ncec_t *ncec)
3481 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
3483 if (ncec->ncec_trace_disable)
3486 if (!th_trace_ref(ncec, ncec->ncec_ipst)) {
3487 ncec->ncec_trace_disable = B_TRUE;
3488 ncec_trace_cleanup(ncec);
3493 ncec_untrace_ref(ncec_t *ncec)
3495 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
3497 if (!ncec->ncec_trace_disable)
3498 th_trace_unref(ncec);
3502 ncec_trace_cleanup(const ncec_t *ncec)
3504 th_trace_cleanup(ncec, ncec->ncec_trace_disable);
3513 arp_resolv_failed(ncec_t *ncec)
3518 ill_t *ill = ncec->ncec_ill;
3519 ip_stack_t *ipst = ncec->ncec_ipst;
3534 IN6_V4MAPPED_TO_INADDR(&ncec->ncec_addr, &ipv4addr);
3537 mutex_enter(&ncec->ncec_lock);
3538 mp = ncec->ncec_qd_mp;
3539 ncec->ncec_qd_mp = NULL;
3540 ncec->ncec_nprobes = 0;
3541 mutex_exit(&ncec->ncec_lock);
3559 ncec_cb_dispatch(ncec); /* finish off waiting callbacks */
3598 * IPv4 broadcast ncec: compute the hwaddr.
3684 * IPMP notes: the ncec for non-local (i.e., !NCE_MYADDR(ncec) addresses
3724 ncec_t *ncec = nce->nce_common;
3725 uint16_t flags = ncec->ncec_flags;
3729 ip_stack_t *ipst = ncec->ncec_ill->ill_ipst;
3730 uchar_t *hw_addr = ncec->ncec_lladdr;
3735 * we call nce_fastpath as soon as the ncec is resolved in nce_process.
3739 if (NCE_PUBLISH(ncec) || !NCE_ISREACHABLE(ncec) || (hw_addr == NULL &&
3740 ncec->ncec_ill->ill_net_type != IRE_IF_NORESOLVER))
3746 if (NCE_PUBLISH(ncec) && ncec->ncec_state == ND_PROBE) {
3760 mutex_enter(&ncec->ncec_lock);
3761 ncec->ncec_unsolicit_count =
3763 mutex_exit(&ncec->ncec_lock);
3764 dropped = arp_announce(ncec);
3765 mutex_enter(&ncec->ncec_lock);
3767 ncec->ncec_unsolicit_count++;
3769 ncec->ncec_last_time_defended = ddi_get_lbolt();
3770 if (ncec->ncec_unsolicit_count != 0) {
3771 nce_start_timer(ncec,
3774 mutex_exit(&ncec->ncec_lock);
3782 mutex_enter(&ncec->ncec_lock);
3783 if (ncec->ncec_pcnt == 0) {
3790 ncec->ncec_unsolicit_count = 0;
3791 mutex_exit(&ncec->ncec_lock);
3792 nce_restart_timer(ncec, 0);
3794 mutex_exit(&ncec->ncec_lock);
3795 delay = ((ncec->ncec_flags & NCE_F_FAST) ?
3798 nce_dad(ncec, NULL, (delay == 0 ? B_TRUE : B_FALSE));
3810 nce_update_hw_changed(ncec_t *ncec, void *arg)
3815 if (ncec->ncec_state != ND_REACHABLE)
3818 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, ncec_addr);
3822 mutex_enter(&ncec->ncec_lock);
3824 ncec->ncec_flags = hwm->hwm_flags;
3825 nce_update(ncec, ND_STALE, hwm->hwm_hwaddr);
3826 mutex_exit(&ncec->ncec_lock);
3830 ncec_refhold(ncec_t *ncec)
3832 mutex_enter(&(ncec)->ncec_lock);
3833 (ncec)->ncec_refcnt++;
3834 ASSERT((ncec)->ncec_refcnt != 0);
3836 ncec_trace_ref(ncec);
3838 mutex_exit(&(ncec)->ncec_lock);
3842 ncec_refhold_notr(ncec_t *ncec)
3844 mutex_enter(&(ncec)->ncec_lock);
3845 (ncec)->ncec_refcnt++;
3846 ASSERT((ncec)->ncec_refcnt != 0);
3847 mutex_exit(&(ncec)->ncec_lock);
3851 ncec_refhold_locked(ncec_t *ncec)
3853 ASSERT(MUTEX_HELD(&(ncec)->ncec_lock));
3854 (ncec)->ncec_refcnt++;
3856 ncec_trace_ref(ncec);
3862 ncec_refrele(ncec_t *ncec)
3864 mutex_enter(&(ncec)->ncec_lock);
3866 ncec_untrace_ref(ncec);
3868 ASSERT((ncec)->ncec_refcnt != 0);
3869 if (--(ncec)->ncec_refcnt == 0) {
3870 ncec_inactive(ncec);
3872 mutex_exit(&(ncec)->ncec_lock);
3877 ncec_refrele_notr(ncec_t *ncec)
3879 mutex_enter(&(ncec)->ncec_lock);
3880 ASSERT((ncec)->ncec_refcnt != 0);
3881 if (--(ncec)->ncec_refcnt == 0) {
3882 ncec_inactive(ncec);
3884 mutex_exit(&(ncec)->ncec_lock);
3892 nce_restart_timer(ncec_t *ncec, uint_t ms)
3896 ASSERT(!MUTEX_HELD(&(ncec)->ncec_lock));
3899 mutex_enter(&ncec->ncec_lock);
3900 tid = ncec->ncec_timeout_id;
3901 ncec->ncec_timeout_id = 0;
3903 mutex_exit(&ncec->ncec_lock);
3905 mutex_enter(&ncec->ncec_lock);
3909 nce_start_timer(ncec, ms);
3910 mutex_exit(&ncec->ncec_lock);
3914 nce_start_timer(ncec_t *ncec, uint_t ms)
3916 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
3918 * Don't start the timer if the ncec has been deleted, or if the timer
3921 if (!NCE_ISCONDEMNED(ncec) && ncec->ncec_timeout_id == 0) {
3922 ncec->ncec_timeout_id = timeout(nce_timer, ncec,
4010 ncec_t *ncec = nce->nce_common;
4012 ASSERT(ncec->ncec_ill == ncert->ncert_ill);
4016 if (!NCE_MYADDR(ncec) || ncec->ncec_state != ND_REACHABLE)
4019 ncec_refhold(ncec);
4020 ncert->ncert_nces[ncert->ncert_num++] = ncec;
4024 ncec_refhold(ncec);
4026 ASSERT(ncec != NULL);
4028 ncec->ncec_last_time_defended) {
4030 *ncecs = ncec;
4031 ncec = ncec_temp;
4034 ncec_refrele(ncec);
4048 ncec_t *ncec;
4068 ncec = ncert->ncert_nces[i];
4069 mutex_enter(&ncec->ncec_lock);
4070 ncec->ncec_flags |= NCE_F_DELAYED;
4071 mutex_exit(&ncec->ncec_lock);
4073 * we plan to schedule this ncec, so incr the
4093 ill_defend_rate_limit(ill_t *ill, ncec_t *ncec)
4130 mutex_enter(&ncec->ncec_lock);
4131 if (ncec->ncec_flags & NCE_F_DELAYED) {
4133 * This ncec was rescheduled as one of the really old
4138 ncec->ncec_flags &= ~NCE_F_DELAYED;
4139 mutex_exit(&ncec->ncec_lock);
4143 mutex_exit(&ncec->ncec_lock);
4175 ndp_announce(ncec_t *ncec)
4177 return (ndp_xmit(ncec->ncec_ill, ND_NEIGHBOR_ADVERT, ncec->ncec_lladdr,
4178 ncec->ncec_lladdr_length, &ncec->ncec_addr, &ipv6_all_hosts_mcast,
4179 nce_advert_flags(ncec)));
4183 nce_resolve_src(ncec_t *ncec, in6_addr_t *src)
4188 ill_t *ill = ncec->ncec_ill;
4191 boolean_t is_myaddr = NCE_MYADDR(ncec);
4192 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
4198 src6 = ncec->ncec_addr;
4200 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, src4);
4205 mutex_enter(&ncec->ncec_lock);
4206 mp = ncec->ncec_qd_mp;
4219 mutex_exit(&ncec->ncec_lock);
4255 ncec_t *, ncec, ipif_t *, ipif);
4271 ipif = ipif_select_source_v6(ill, &ncec->ncec_addr,
4277 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, nce_addr);
4287 &ncec->ncec_addr, B_TRUE,
4291 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr,
4305 (char *)&ncec->ncec_addr, buf, sizeof (buf))));
4306 DTRACE_PROBE1(nce__resolve__no__ipif, ncec_t *, ncec);
4319 DTRACE_PROBE2(nce__resolve__src__ill, ncec_t *, ncec,
4330 ncec_t *ncec;
4337 * only one ncec is possible
4341 ncec = nce->nce_common;
4342 mutex_enter(&ncec->ncec_lock);
4343 if (NCE_ISREACHABLE(ncec))
4347 ncec->ncec_flags = flags;
4348 nce_update(ncec, new_state, hwaddr);
4349 mutex_exit(&ncec->ncec_lock);
4355 * ill is wildcard; clean up all ncec's and ire's
4371 * Common function to add ncec entries.
4372 * we always add the ncec with ncec_ill == ill, and always create
4374 * ncec is !reachable.
4388 ncec_t *ncec;
4435 ncec = *ncep;
4436 for (; ncec != NULL; ncec = ncec->ncec_next) {
4437 if (ncec->ncec_ill == ill) {
4438 if (IN6_ARE_ADDR_EQUAL(&ncec->ncec_addr, addr)) {
4453 if (NCE_MYADDR(ncec))
4455 *retnce = nce_ill_lookup_then_add(ill, ncec);
4464 ncec = kmem_cache_alloc(ncec_cache, KM_NOSLEEP);
4465 if (ncec == NULL)
4467 *ncec = nce_nil;
4468 ncec->ncec_ill = ill;
4469 ncec->ncec_ipversion = (ill->ill_isv6 ? IPV6_VERSION : IPV4_VERSION);
4470 ncec->ncec_flags = flags;
4471 ncec->ncec_ipst = ipst; /* No netstack_hold */
4487 } else if (IS_IPMP(ill) && NCE_PUBLISH(ncec) &&
4497 ncec->ncec_xmit_interval =
4499 ncec->ncec_pcnt =
4501 ncec->ncec_flags |= NCE_F_FAST;
4503 ncec->ncec_xmit_interval =
4505 ncec->ncec_pcnt =
4508 if (NCE_PUBLISH(ncec)) {
4509 ncec->ncec_unsolicit_count =
4517 ncec->ncec_pcnt = ND_MAX_UNICAST_SOLICIT;
4518 if (NCE_PUBLISH(ncec)) {
4519 ncec->ncec_unsolicit_count =
4523 ncec->ncec_rcnt = ill->ill_xmit_count;
4524 ncec->ncec_addr = *addr;
4525 ncec->ncec_qd_mp = NULL;
4526 ncec->ncec_refcnt = 1; /* for ncec getting created */
4527 mutex_init(&ncec->ncec_lock, NULL, MUTEX_DEFAULT, NULL);
4528 ncec->ncec_trace_disable = B_FALSE;
4539 ncec->ncec_lladdr = template;
4540 ncec->ncec_lladdr_length = hw_addr_len;
4541 bzero(ncec->ncec_lladdr, hw_addr_len);
4565 ncec->ncec_lladdr, ill->ill_phys_addr_length);
4577 ncec->ncec_lladdr, ill->ill_phys_addr_length);
4585 ncec->ncec_flags |= NCE_F_NONUD;
4592 * We are adding an ncec with a deterministic hw_addr,
4595 * if we are adding a unicast ncec for the local address
4603 else if (!NCE_PUBLISH(ncec))
4608 nce_set_ll(ncec, hw_addr);
4615 ncec->ncec_flags |= NCE_F_UNVERIFIED;
4617 ncec->ncec_state = state;
4620 ncec->ncec_last = ncec->ncec_init_time =
4623 ncec->ncec_last = 0;
4625 ncec->ncec_init_time = TICK_TO_MSEC(ddi_get_lbolt64());
4627 list_create(&ncec->ncec_cb, sizeof (ncec_cb_t),
4638 if (ncec->ncec_lladdr != NULL ||
4640 dlur_mp = ill_dlur_gen(ncec->ncec_lladdr,
4659 if (!NCE_MYADDR(ncec) &&
4662 DTRACE_PROBE1(nce__add__on__down__ill, ncec_t *, ncec);
4667 * Acquire the ncec_lock even before adding the ncec to the list
4668 * so that it cannot get deleted after the ncec is added, but
4671 mutex_enter(&ncec->ncec_lock);
4672 if ((ncec->ncec_next = *ncep) != NULL)
4673 ncec->ncec_next->ncec_ptpn = &ncec->ncec_next;
4674 *ncep = ncec;
4675 ncec->ncec_ptpn = ncep;
4677 /* Bump up the number of ncec's referencing this ill */
4679 (char *), "ncec", (void *), ncec);
4682 * Since we hold the ncec_lock at this time, the ncec cannot be
4685 *retnce = nce_add_impl(ill, ncec, nce, dlur_mp);
4686 mutex_exit(&ncec->ncec_lock);
4693 if (ncec != NULL)
4694 kmem_cache_free(ncec_cache, ncec);
4756 * If the number of ncec's associated with this ill have dropped
4775 nce_add_impl(ill_t *ill, ncec_t *ncec, nce_t *nce, mblk_t *dlur_mp)
4779 nce->nce_common = ncec;
4780 nce->nce_addr = ncec->ncec_addr;
4787 ncec->ncec_refcnt++; /* want ncec_refhold_locked_notr(ncec) */
4797 nce_add(ill_t *ill, ncec_t *ncec)
4803 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
4808 if (ncec->ncec_lladdr != NULL ||
4810 dlur_mp = ill_dlur_gen(ncec->ncec_lladdr,
4818 return (nce_add_impl(ill, ncec, nce, dlur_mp));
4964 nce_resolv_ipmp_ok(ncec_t *ncec)
4970 ill_t *ill = ncec->ncec_ill;
4971 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
4979 mutex_enter(&ncec->ncec_lock);
4980 nprobes = ncec->ncec_nprobes;
4981 mp = ncec->ncec_qd_mp;
4982 ncec->ncec_qd_mp = NULL;
4983 ncec->ncec_nprobes = 0;
4984 mutex_exit(&ncec->ncec_lock);
5026 send_ill = ipmp_ill_hold_xmit_ill(ncec->ncec_ill,
5034 (ncec_t *), ncec, (ipif_t *),
5044 if (IS_IN_SAME_ILLGRP(send_ill, ncec->ncec_ill))
5045 under_nce = nce_fastpath_create(send_ill, ncec);
5049 if (under_nce != NULL && NCE_ISREACHABLE(ncec))
5077 ncec_cb_dispatch(ncec); /* complete callbacks */