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 ncec_refrele(ncec);
1141 ip_ndp_resolve(ncec_t *ncec)
1148 src_ill = nce_resolve_src(ncec, &sender6);
1151 ms = ncec->ncec_ill->ill_reachable_retrans_time;
1152 nce_restart_timer(ncec, (clock_t)ms);
1155 if (ncec->ncec_ipversion == IPV4_VERSION)
1157 mutex_enter(&ncec->ncec_lock);
1158 if (ncec->ncec_ipversion == IPV6_VERSION)
1159 ms = ndp_solicit(ncec, sender6, src_ill);
1161 ms = arp_request(ncec, sender4, src_ill);
1162 mutex_exit(&ncec->ncec_lock);
1164 if (ncec->ncec_state != ND_REACHABLE) {
1165 if (ncec->ncec_ipversion == IPV6_VERSION)
1166 ndp_resolv_failed(ncec);
1168 arp_resolv_failed(ncec);
1169 ASSERT((ncec->ncec_flags & NCE_F_STATIC) == 0);
1170 nce_make_unreachable(ncec);
1171 ncec_delete(ncec);
1174 nce_restart_timer(ncec, (clock_t)ms);
1192 ndp_solicit(ncec_t *ncec, in6_addr_t src, ill_t *ill)
1197 ASSERT(ncec->ncec_ipversion == IPV6_VERSION);
1198 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
1200 if (ncec->ncec_rcnt == 0)
1203 dst = ncec->ncec_addr;
1204 ncec->ncec_rcnt--;
1205 mutex_exit(&ncec->ncec_lock);
1208 mutex_enter(&ncec->ncec_lock);
1210 ncec->ncec_rcnt++;
1211 return (ncec->ncec_ill->ill_reachable_retrans_time);
1505 * that tearing down the ipif also means deleting the ncec through ipif_down, so
1506 * it's not possible to do recovery by just restarting the ncec timer. Instead,
1556 ip_nce_conflict(mblk_t *mp, ip_recv_attr_t *ira, ncec_t *ncec)
1569 ipif = ipif_lookup_addr_v6(&ncec->ncec_addr, ill, ALL_ZONES,
1579 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, ncec_addr);
1599 elapsed = (drv_hztousec(now - ncec->ncec_last_time_defended))/1000000;
1600 mutex_enter(&ncec->ncec_lock);
1601 if ((defs = ncec->ncec_defense_count) > 0 &&
1607 ncec->ncec_defense_count = defs = 0;
1609 ncec->ncec_defense_count++;
1610 ncec->ncec_last_time_defended = now;
1611 mutex_exit(&ncec->ncec_lock);
2298 nce_make_unreachable(ncec_t *ncec)
2300 mutex_enter(&ncec->ncec_lock);
2301 ncec->ncec_state = ND_UNREACHABLE;
2302 mutex_exit(&ncec->ncec_lock);
2314 ncec_t *ncec = arg;
2315 ill_t *ill = ncec->ncec_ill, *src_ill;
2318 ip_stack_t *ipst = ncec->ncec_ipst;
2319 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
2327 * bump up the refcnt so that we can continue to use the ncec
2329 ASSERT(ncec != NULL);
2330 mutex_enter(&ncec->ncec_lock);
2331 ncec_refhold_locked(ncec);
2332 ncec->ncec_timeout_id = 0;
2333 mutex_exit(&ncec->ncec_lock);
2335 src_ill = nce_resolve_src(ncec, &sender6);
2339 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, sender4);
2344 &ncec->ncec_addr, addrbuf, sizeof (addrbuf))));
2346 nce_restart_timer(ncec, ill->ill_reachable_retrans_time);
2347 ncec_refrele(ncec);
2353 mutex_enter(&ncec->ncec_lock);
2357 switch (ncec->ncec_state) {
2359 ASSERT(ncec->ncec_lladdr != NULL);
2360 ncec->ncec_state = ND_PROBE;
2361 ncec->ncec_pcnt = ND_MAX_UNICAST_SOLICIT;
2363 mutex_exit(&ncec->ncec_lock);
2367 &sender6, &ncec->ncec_addr,
2370 dropped = (arp_request(ncec, sender4, src_ill) == 0);
2371 mutex_exit(&ncec->ncec_lock);
2374 mutex_enter(&ncec->ncec_lock);
2375 ncec->ncec_pcnt--;
2376 mutex_exit(&ncec->ncec_lock);
2381 "to PROBE\n", AF_INET6, &ncec->ncec_addr);
2383 nce_restart_timer(ncec, ill->ill_reachable_retrans_time);
2387 ASSERT(ncec->ncec_pcnt >= -1);
2388 if (ncec->ncec_pcnt > 0) {
2390 * As per RFC2461, the ncec gets deleted after
2396 ncec->ncec_pcnt,
2398 &ncec->ncec_addr, addrbuf, sizeof (addrbuf))));
2399 if (NCE_PUBLISH(ncec)) {
2400 mutex_exit(&ncec->ncec_lock);
2407 nce_dad(ncec, src_ill, B_TRUE);
2411 mutex_exit(&ncec->ncec_lock);
2416 &sender6, &ncec->ncec_addr,
2424 dropped = (arp_request(ncec, sender4,
2426 mutex_exit(&ncec->ncec_lock);
2429 mutex_enter(&ncec->ncec_lock);
2430 ncec->ncec_pcnt--;
2431 mutex_exit(&ncec->ncec_lock);
2433 nce_restart_timer(ncec,
2436 } else if (ncec->ncec_pcnt < 0) {
2437 /* No hope, delete the ncec */
2439 ncec->ncec_state = ND_UNREACHABLE;
2440 mutex_exit(&ncec->ncec_lock);
2445 &ncec->ncec_addr);
2448 if ((ncec->ncec_flags & NCE_F_STATIC) == 0)
2449 ncec_delete(ncec);
2451 } else if (!NCE_PUBLISH(ncec)) {
2457 ASSERT((ncec->ncec_flags & NCE_F_NONUD) == 0);
2459 ncec->ncec_pcnt, inet_ntop(AF_INET6,
2460 &ncec->ncec_addr, addrbuf, sizeof (addrbuf))));
2461 ncec->ncec_pcnt--;
2462 mutex_exit(&ncec->ncec_lock);
2464 nce_restart_timer(ncec,
2475 ncec->ncec_state = ND_REACHABLE;
2476 ncec->ncec_flags &= ~NCE_F_UNVERIFIED;
2477 mutex_exit(&ncec->ncec_lock);
2480 &ncec->ncec_addr, ill, ipst);
2482 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr,
2510 if (ncec->ncec_unsolicit_count > 0) {
2511 ncec->ncec_unsolicit_count--;
2513 dropped = ndp_announce(ncec);
2515 dropped = arp_announce(ncec);
2519 ncec->ncec_unsolicit_count++;
2521 ncec->ncec_last_time_defended =
2524 if (ncec->ncec_unsolicit_count > 0) {
2525 nce_restart_timer(ncec,
2528 nce_restart_timer(ncec, DEFENSE_INTERVAL(isv6));
2537 ncec->ncec_state = ND_REACHABLE;
2538 mutex_exit(&ncec->ncec_lock);
2552 prevmpp = &ncec->ncec_qd_mp;
2553 for (mp = ncec->ncec_qd_mp; mp != NULL; mp = nextmp) {
2556 if (IS_UNDER_IPMP(ill) && ncec->ncec_nprobes > 0) {
2558 ncec->ncec_nprobes--;
2568 mutex_exit(&ncec->ncec_lock);
2569 ip_ndp_resolve(ncec);
2573 if (((ncec->ncec_flags & NCE_F_UNSOL_ADV) &&
2574 ncec->ncec_unsolicit_count != 0) ||
2575 (NCE_PUBLISH(ncec) && DEFENSE_INTERVAL(isv6) != 0)) {
2576 if (ncec->ncec_unsolicit_count > 0) {
2577 ncec->ncec_unsolicit_count--;
2578 mutex_exit(&ncec->ncec_lock);
2586 mutex_exit(&ncec->ncec_lock);
2587 rate_limit = ill_defend_rate_limit(ill, ncec);
2589 nce_restart_timer(ncec,
2595 dropped = ndp_announce(ncec);
2597 dropped = arp_announce(ncec);
2599 mutex_enter(&ncec->ncec_lock);
2601 ncec->ncec_unsolicit_count++;
2603 ncec->ncec_last_time_defended =
2606 mutex_exit(&ncec->ncec_lock);
2607 if (ncec->ncec_unsolicit_count != 0) {
2608 nce_restart_timer(ncec,
2611 nce_restart_timer(ncec, DEFENSE_INTERVAL(isv6));
2614 mutex_exit(&ncec->ncec_lock);
2618 mutex_exit(&ncec->ncec_lock);
2622 ncec_refrele(ncec);
2631 nce_set_ll(ncec_t *ncec, uchar_t *ll_addr)
2633 ill_t *ill = ncec->ncec_ill;
2654 bcopy(ll_addr, ncec->ncec_lladdr, ill->ill_nd_lla_len);
2659 nce_cmp_ll_addr(const ncec_t *ncec, const uchar_t *ll_addr,
2662 ASSERT(ncec->ncec_lladdr != NULL);
2665 if (bcmp(ll_addr, ncec->ncec_lladdr, ll_addr_len) != 0)
2675 nce_update(ncec_t *ncec, uint16_t new_state, uchar_t *new_ll_addr)
2677 ill_t *ill = ncec->ncec_ill;
2683 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
2693 if ((ncec->ncec_flags & NCE_F_NONUD) &&
2694 (ncec->ncec_state != ND_INCOMPLETE))
2700 ncec->ncec_last = TICK_TO_MSEC(ddi_get_lbolt64());
2703 ncec->ncec_last = 0;
2705 ncec->ncec_state = new_state;
2706 ncec->ncec_pcnt = ND_MAX_UNICAST_SOLICIT;
2707 ASSERT(ncec->ncec_lladdr != NULL || new_state == ND_INITIAL ||
2710 if (need_stop_timer || (ncec->ncec_flags & NCE_F_STATIC)) {
2711 tid = ncec->ncec_timeout_id;
2712 ncec->ncec_timeout_id = 0;
2720 bcopy(new_ll_addr, ncec->ncec_lladdr,
2724 mutex_exit(&ncec->ncec_lock);
2725 if (need_stop_timer || (ncec->ncec_flags & NCE_F_STATIC)) {
2735 nce_fastpath_list_delete(ncec->ncec_ill, ncec, NULL);
2739 nce = nce_fastpath(ncec, B_TRUE, NULL);
2743 mutex_enter(&ncec->ncec_lock);
2747 nce_queue_mp_common(ncec_t *ncec, mblk_t *mp, boolean_t head_insert)
2752 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
2754 for (mpp = &ncec->ncec_qd_mp; *mpp != NULL; mpp = &(*mpp)->b_next) {
2755 if (++count > ncec->ncec_ill->ill_max_buf) {
2756 tmp = ncec->ncec_qd_mp->b_next;
2757 ncec->ncec_qd_mp->b_next = NULL;
2762 BUMP_MIB(ncec->ncec_ill->ill_ip_mib,
2764 ip_drop_output("ipIfStatsOutDiscards", ncec->ncec_qd_mp,
2765 ncec->ncec_ill);
2766 freemsg(ncec->ncec_qd_mp);
2767 ncec->ncec_qd_mp = tmp;
2772 ncec->ncec_nprobes++;
2773 mp->b_next = ncec->ncec_qd_mp;
2774 ncec->ncec_qd_mp = mp;
2801 * The ncec for the probe target is created with ncec_ill set to the ipmp_ill,
2805 nce_queue_mp(ncec_t *ncec, mblk_t *mp, boolean_t head_insert)
2807 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
2808 nce_queue_mp_common(ncec, mp, head_insert);
2816 ndp_resolv_failed(ncec_t *ncec)
2820 ill_t *ill = ncec->ncec_ill;
2836 inet_ntop(AF_INET6, (char *)&ncec->ncec_addr, buf, sizeof (buf))));
2837 mutex_enter(&ncec->ncec_lock);
2838 mp = ncec->ncec_qd_mp;
2839 ncec->ncec_qd_mp = NULL;
2840 ncec->ncec_nprobes = 0;
2841 mutex_exit(&ncec->ncec_lock);
2854 ncec_cb_dispatch(ncec); /* finish off waiting callbacks */
2861 nce_resolv_ok(ncec_t *ncec)
2867 ill_t *ill = ncec->ncec_ill;
2868 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
2871 if (IS_IPMP(ncec->ncec_ill)) {
2872 nce_resolv_ipmp_ok(ncec);
2877 mutex_enter(&ncec->ncec_lock);
2878 ASSERT(ncec->ncec_nprobes == 0);
2879 mp = ncec->ncec_qd_mp;
2880 ncec->ncec_qd_mp = NULL;
2881 mutex_exit(&ncec->ncec_lock);
2905 nce = nce_lookup(ill, &ncec->ncec_addr);
2933 ncec_cb_dispatch(ncec); /* complete callbacks */
2937 * Called by SIOCSNDP* ioctl to add/change an ncec entry
2946 ncec_t *ncec;
3015 ncec = nce->nce_common;
3016 old_flags = ncec->ncec_flags;
3018 ncec_router_to_host(ncec);
3035 mutex_enter(&ncec->ncec_lock);
3036 ncec->ncec_flags = new_flags;
3037 mutex_exit(&ncec->ncec_lock);
3044 nce_process(ncec, (uchar_t *)lnr->lnr_hdw_addr, 0, B_FALSE);
3050 * Create an nce_t structure for ill using the ncec->ncec_lladdr to set up
3051 * the nce_dlur_mp. If ill != ncec->ncec_ill, then the ips_ill_g_lock must
3055 nce_fastpath_create(ill_t *ill, ncec_t *ncec)
3060 nce = nce_ill_lookup_then_add(ill, ncec);
3068 * consistent with ncec->ncec_lladdr, even though some intermediate
3072 mutex_enter(&ncec->ncec_lock);
3073 if (ncec->ncec_lladdr != NULL) {
3074 bcopy(ncec->ncec_lladdr, nce->nce_dlur_mp->b_rptr +
3080 mutex_exit(&ncec->ncec_lock);
3086 * The caller ensures there is hold on ncec for this function.
3088 * no need to hold the nce or ncec beyond this function.
3091 * ncec_nce must correspond to the nce for ncec with nce_ill == ncec->ncec_ill
3098 nce_fastpath(ncec_t *ncec, boolean_t trigger_fp_req, nce_t *ncec_nce)
3101 ill_t *ill = ncec->ncec_ill;
3107 ipmp_ncec_refresh_nce(ncec);
3117 nce = nce_fastpath_create(ill, ncec);
3137 ncec_t *ncec = nce->nce_common;
3142 * i.e. allocation failure etc. leave the ncec in the list it
3148 nce_fastpath_list_delete(ill, ncec, NULL);
3152 * Add ncec to the nce fastpath list on ill.
3155 nce_ill_lookup_then_add_locked(ill_t *ill, ncec_t *ncec)
3166 mutex_enter(&ncec->ncec_lock);
3168 * if ncec has not been deleted and
3171 if (!NCE_ISCONDEMNED(ncec)) {
3172 nce = nce_lookup(ill, &ncec->ncec_addr);
3175 nce = nce_add(ill, ncec);
3178 mutex_exit(&ncec->ncec_lock);
3183 nce_ill_lookup_then_add(ill_t *ill, ncec_t *ncec)
3188 nce = nce_ill_lookup_then_add_locked(ill, ncec);
3195 * remove ncec from the ill_nce list. If 'dead' is non-null, the deleted
3200 nce_fastpath_list_delete(ill_t *ill, ncec_t *ncec, list_t *dead)
3206 /* delete any nces referencing the ncec from underlying ills */
3208 ipmp_ncec_delete_nce(ncec);
3214 if (nce->nce_common == ncec) {
3247 * Make sure that ncec is not condemned before adding. We hold the
3269 ncec_t *ncec = nce->nce_common;
3289 * The ncec is locked here to prevent any other threads from accessing
3296 mutex_enter(&ncec->ncec_lock);
3300 mutex_exit(&ncec->ncec_lock);
3304 mutex_exit(&ncec->ncec_lock);
3402 * computation as we walk through the ncec's (e.g., track ncec entries by
3406 ncec_cache_reclaim(ncec_t *ncec, char *arg)
3408 ip_stack_t *ipst = ncec->ncec_ipst;
3412 if ((ncec->ncec_flags &
3418 NCE_ADDR_HASH_V6(ncec->ncec_addr, NCE_TABLE_SIZE);
3421 ncec_delete(ncec);
3440 * Walk all CONNs that can have a reference on an ire, ncec or dce.
3477 ncec_trace_ref(ncec_t *ncec)
3479 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
3481 if (ncec->ncec_trace_disable)
3484 if (!th_trace_ref(ncec, ncec->ncec_ipst)) {
3485 ncec->ncec_trace_disable = B_TRUE;
3486 ncec_trace_cleanup(ncec);
3491 ncec_untrace_ref(ncec_t *ncec)
3493 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
3495 if (!ncec->ncec_trace_disable)
3496 th_trace_unref(ncec);
3500 ncec_trace_cleanup(const ncec_t *ncec)
3502 th_trace_cleanup(ncec, ncec->ncec_trace_disable);
3511 arp_resolv_failed(ncec_t *ncec)
3516 ill_t *ill = ncec->ncec_ill;
3517 ip_stack_t *ipst = ncec->ncec_ipst;
3532 IN6_V4MAPPED_TO_INADDR(&ncec->ncec_addr, &ipv4addr);
3535 mutex_enter(&ncec->ncec_lock);
3536 mp = ncec->ncec_qd_mp;
3537 ncec->ncec_qd_mp = NULL;
3538 ncec->ncec_nprobes = 0;
3539 mutex_exit(&ncec->ncec_lock);
3557 ncec_cb_dispatch(ncec); /* finish off waiting callbacks */
3596 * IPv4 broadcast ncec: compute the hwaddr.
3682 * IPMP notes: the ncec for non-local (i.e., !NCE_MYADDR(ncec) addresses
3722 ncec_t *ncec = nce->nce_common;
3723 uint16_t flags = ncec->ncec_flags;
3727 ip_stack_t *ipst = ncec->ncec_ill->ill_ipst;
3728 uchar_t *hw_addr = ncec->ncec_lladdr;
3733 * we call nce_fastpath as soon as the ncec is resolved in nce_process.
3737 if (NCE_PUBLISH(ncec) || !NCE_ISREACHABLE(ncec) || (hw_addr == NULL &&
3738 ncec->ncec_ill->ill_net_type != IRE_IF_NORESOLVER))
3744 if (NCE_PUBLISH(ncec) && ncec->ncec_state == ND_PROBE) {
3758 mutex_enter(&ncec->ncec_lock);
3759 ncec->ncec_unsolicit_count =
3761 mutex_exit(&ncec->ncec_lock);
3762 dropped = arp_announce(ncec);
3763 mutex_enter(&ncec->ncec_lock);
3765 ncec->ncec_unsolicit_count++;
3767 ncec->ncec_last_time_defended = ddi_get_lbolt();
3768 if (ncec->ncec_unsolicit_count != 0) {
3769 nce_start_timer(ncec,
3772 mutex_exit(&ncec->ncec_lock);
3780 mutex_enter(&ncec->ncec_lock);
3781 if (ncec->ncec_pcnt == 0) {
3788 ncec->ncec_unsolicit_count = 0;
3789 mutex_exit(&ncec->ncec_lock);
3790 nce_restart_timer(ncec, 0);
3792 mutex_exit(&ncec->ncec_lock);
3793 delay = ((ncec->ncec_flags & NCE_F_FAST) ?
3796 nce_dad(ncec, NULL, (delay == 0 ? B_TRUE : B_FALSE));
3808 nce_update_hw_changed(ncec_t *ncec, void *arg)
3813 if (ncec->ncec_state != ND_REACHABLE)
3816 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, ncec_addr);
3820 mutex_enter(&ncec->ncec_lock);
3822 ncec->ncec_flags = hwm->hwm_flags;
3823 nce_update(ncec, ND_STALE, hwm->hwm_hwaddr);
3824 mutex_exit(&ncec->ncec_lock);
3828 ncec_refhold(ncec_t *ncec)
3830 mutex_enter(&(ncec)->ncec_lock);
3831 (ncec)->ncec_refcnt++;
3832 ASSERT((ncec)->ncec_refcnt != 0);
3834 ncec_trace_ref(ncec);
3836 mutex_exit(&(ncec)->ncec_lock);
3840 ncec_refhold_notr(ncec_t *ncec)
3842 mutex_enter(&(ncec)->ncec_lock);
3843 (ncec)->ncec_refcnt++;
3844 ASSERT((ncec)->ncec_refcnt != 0);
3845 mutex_exit(&(ncec)->ncec_lock);
3849 ncec_refhold_locked(ncec_t *ncec)
3851 ASSERT(MUTEX_HELD(&(ncec)->ncec_lock));
3852 (ncec)->ncec_refcnt++;
3854 ncec_trace_ref(ncec);
3860 ncec_refrele(ncec_t *ncec)
3862 mutex_enter(&(ncec)->ncec_lock);
3864 ncec_untrace_ref(ncec);
3866 ASSERT((ncec)->ncec_refcnt != 0);
3867 if (--(ncec)->ncec_refcnt == 0) {
3868 ncec_inactive(ncec);
3870 mutex_exit(&(ncec)->ncec_lock);
3875 ncec_refrele_notr(ncec_t *ncec)
3877 mutex_enter(&(ncec)->ncec_lock);
3878 ASSERT((ncec)->ncec_refcnt != 0);
3879 if (--(ncec)->ncec_refcnt == 0) {
3880 ncec_inactive(ncec);
3882 mutex_exit(&(ncec)->ncec_lock);
3890 nce_restart_timer(ncec_t *ncec, uint_t ms)
3894 ASSERT(!MUTEX_HELD(&(ncec)->ncec_lock));
3897 mutex_enter(&ncec->ncec_lock);
3898 tid = ncec->ncec_timeout_id;
3899 ncec->ncec_timeout_id = 0;
3901 mutex_exit(&ncec->ncec_lock);
3903 mutex_enter(&ncec->ncec_lock);
3907 nce_start_timer(ncec, ms);
3908 mutex_exit(&ncec->ncec_lock);
3912 nce_start_timer(ncec_t *ncec, uint_t ms)
3914 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
3916 * Don't start the timer if the ncec has been deleted, or if the timer
3919 if (!NCE_ISCONDEMNED(ncec) && ncec->ncec_timeout_id == 0) {
3920 ncec->ncec_timeout_id = timeout(nce_timer, ncec,
4008 ncec_t *ncec = nce->nce_common;
4010 ASSERT(ncec->ncec_ill == ncert->ncert_ill);
4014 if (!NCE_MYADDR(ncec) || ncec->ncec_state != ND_REACHABLE)
4017 ncec_refhold(ncec);
4018 ncert->ncert_nces[ncert->ncert_num++] = ncec;
4022 ncec_refhold(ncec);
4024 ASSERT(ncec != NULL);
4026 ncec->ncec_last_time_defended) {
4028 *ncecs = ncec;
4029 ncec = ncec_temp;
4032 ncec_refrele(ncec);
4046 ncec_t *ncec;
4066 ncec = ncert->ncert_nces[i];
4067 mutex_enter(&ncec->ncec_lock);
4068 ncec->ncec_flags |= NCE_F_DELAYED;
4069 mutex_exit(&ncec->ncec_lock);
4071 * we plan to schedule this ncec, so incr the
4091 ill_defend_rate_limit(ill_t *ill, ncec_t *ncec)
4128 mutex_enter(&ncec->ncec_lock);
4129 if (ncec->ncec_flags & NCE_F_DELAYED) {
4131 * This ncec was rescheduled as one of the really old
4136 ncec->ncec_flags &= ~NCE_F_DELAYED;
4137 mutex_exit(&ncec->ncec_lock);
4141 mutex_exit(&ncec->ncec_lock);
4173 ndp_announce(ncec_t *ncec)
4175 return (ndp_xmit(ncec->ncec_ill, ND_NEIGHBOR_ADVERT, ncec->ncec_lladdr,
4176 ncec->ncec_lladdr_length, &ncec->ncec_addr, &ipv6_all_hosts_mcast,
4177 nce_advert_flags(ncec)));
4181 nce_resolve_src(ncec_t *ncec, in6_addr_t *src)
4186 ill_t *ill = ncec->ncec_ill;
4189 boolean_t is_myaddr = NCE_MYADDR(ncec);
4190 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
4196 src6 = ncec->ncec_addr;
4198 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, src4);
4203 mutex_enter(&ncec->ncec_lock);
4204 mp = ncec->ncec_qd_mp;
4217 mutex_exit(&ncec->ncec_lock);
4253 ncec_t *, ncec, ipif_t *, ipif);
4269 ipif = ipif_select_source_v6(ill, &ncec->ncec_addr,
4275 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr, nce_addr);
4285 &ncec->ncec_addr, B_TRUE,
4289 IN6_V4MAPPED_TO_IPADDR(&ncec->ncec_addr,
4303 (char *)&ncec->ncec_addr, buf, sizeof (buf))));
4304 DTRACE_PROBE1(nce__resolve__no__ipif, ncec_t *, ncec);
4317 DTRACE_PROBE2(nce__resolve__src__ill, ncec_t *, ncec,
4328 ncec_t *ncec;
4335 * only one ncec is possible
4339 ncec = nce->nce_common;
4340 mutex_enter(&ncec->ncec_lock);
4341 if (NCE_ISREACHABLE(ncec))
4345 ncec->ncec_flags = flags;
4346 nce_update(ncec, new_state, hwaddr);
4347 mutex_exit(&ncec->ncec_lock);
4353 * ill is wildcard; clean up all ncec's and ire's
4369 * Common function to add ncec entries.
4370 * we always add the ncec with ncec_ill == ill, and always create
4372 * ncec is !reachable.
4386 ncec_t *ncec;
4433 ncec = *ncep;
4434 for (; ncec != NULL; ncec = ncec->ncec_next) {
4435 if (ncec->ncec_ill == ill) {
4436 if (IN6_ARE_ADDR_EQUAL(&ncec->ncec_addr, addr)) {
4451 if (NCE_MYADDR(ncec))
4453 *retnce = nce_ill_lookup_then_add(ill, ncec);
4462 ncec = kmem_cache_alloc(ncec_cache, KM_NOSLEEP);
4463 if (ncec == NULL)
4465 *ncec = nce_nil;
4466 ncec->ncec_ill = ill;
4467 ncec->ncec_ipversion = (ill->ill_isv6 ? IPV6_VERSION : IPV4_VERSION);
4468 ncec->ncec_flags = flags;
4469 ncec->ncec_ipst = ipst; /* No netstack_hold */
4485 } else if (IS_IPMP(ill) && NCE_PUBLISH(ncec) &&
4495 ncec->ncec_xmit_interval =
4497 ncec->ncec_pcnt =
4499 ncec->ncec_flags |= NCE_F_FAST;
4501 ncec->ncec_xmit_interval =
4503 ncec->ncec_pcnt =
4506 if (NCE_PUBLISH(ncec)) {
4507 ncec->ncec_unsolicit_count =
4515 ncec->ncec_pcnt = ND_MAX_UNICAST_SOLICIT;
4516 if (NCE_PUBLISH(ncec)) {
4517 ncec->ncec_unsolicit_count =
4521 ncec->ncec_rcnt = ill->ill_xmit_count;
4522 ncec->ncec_addr = *addr;
4523 ncec->ncec_qd_mp = NULL;
4524 ncec->ncec_refcnt = 1; /* for ncec getting created */
4525 mutex_init(&ncec->ncec_lock, NULL, MUTEX_DEFAULT, NULL);
4526 ncec->ncec_trace_disable = B_FALSE;
4537 ncec->ncec_lladdr = template;
4538 ncec->ncec_lladdr_length = hw_addr_len;
4539 bzero(ncec->ncec_lladdr, hw_addr_len);
4563 ncec->ncec_lladdr, ill->ill_phys_addr_length);
4575 ncec->ncec_lladdr, ill->ill_phys_addr_length);
4583 ncec->ncec_flags |= NCE_F_NONUD;
4590 * We are adding an ncec with a deterministic hw_addr,
4593 * if we are adding a unicast ncec for the local address
4601 else if (!NCE_PUBLISH(ncec))
4606 nce_set_ll(ncec, hw_addr);
4613 ncec->ncec_flags |= NCE_F_UNVERIFIED;
4615 ncec->ncec_state = state;
4618 ncec->ncec_last = ncec->ncec_init_time =
4621 ncec->ncec_last = 0;
4623 ncec->ncec_init_time = TICK_TO_MSEC(ddi_get_lbolt64());
4625 list_create(&ncec->ncec_cb, sizeof (ncec_cb_t),
4636 if (ncec->ncec_lladdr != NULL ||
4638 dlur_mp = ill_dlur_gen(ncec->ncec_lladdr,
4657 if (!NCE_MYADDR(ncec) &&
4660 DTRACE_PROBE1(nce__add__on__down__ill, ncec_t *, ncec);
4665 * Acquire the ncec_lock even before adding the ncec to the list
4666 * so that it cannot get deleted after the ncec is added, but
4669 mutex_enter(&ncec->ncec_lock);
4670 if ((ncec->ncec_next = *ncep) != NULL)
4671 ncec->ncec_next->ncec_ptpn = &ncec->ncec_next;
4672 *ncep = ncec;
4673 ncec->ncec_ptpn = ncep;
4675 /* Bump up the number of ncec's referencing this ill */
4677 (char *), "ncec", (void *), ncec);
4680 * Since we hold the ncec_lock at this time, the ncec cannot be
4683 *retnce = nce_add_impl(ill, ncec, nce, dlur_mp);
4684 mutex_exit(&ncec->ncec_lock);
4691 if (ncec != NULL)
4692 kmem_cache_free(ncec_cache, ncec);
4754 * If the number of ncec's associated with this ill have dropped
4773 nce_add_impl(ill_t *ill, ncec_t *ncec, nce_t *nce, mblk_t *dlur_mp)
4777 nce->nce_common = ncec;
4778 nce->nce_addr = ncec->ncec_addr;
4785 ncec->ncec_refcnt++; /* want ncec_refhold_locked_notr(ncec) */
4795 nce_add(ill_t *ill, ncec_t *ncec)
4801 ASSERT(MUTEX_HELD(&ncec->ncec_lock));
4806 if (ncec->ncec_lladdr != NULL ||
4808 dlur_mp = ill_dlur_gen(ncec->ncec_lladdr,
4816 return (nce_add_impl(ill, ncec, nce, dlur_mp));
4962 nce_resolv_ipmp_ok(ncec_t *ncec)
4968 ill_t *ill = ncec->ncec_ill;
4969 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION);
4977 mutex_enter(&ncec->ncec_lock);
4978 nprobes = ncec->ncec_nprobes;
4979 mp = ncec->ncec_qd_mp;
4980 ncec->ncec_qd_mp = NULL;
4981 ncec->ncec_nprobes = 0;
4982 mutex_exit(&ncec->ncec_lock);
5024 send_ill = ipmp_ill_hold_xmit_ill(ncec->ncec_ill,
5032 (ncec_t *), ncec, (ipif_t *),
5042 if (IS_IN_SAME_ILLGRP(send_ill, ncec->ncec_ill))
5043 under_nce = nce_fastpath_create(send_ill, ncec);
5047 if (under_nce != NULL && NCE_ISREACHABLE(ncec))
5075 ncec_cb_dispatch(ncec); /* complete callbacks */