bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * CDDL HEADER START
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The contents of this file are subject to the terms of the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Common Development and Distribution License (the "License").
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * You may not use this file except in compliance with the License.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * or http://www.opensolaris.org/os/licensing.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * See the License for the specific language governing permissions
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * and limitations under the License.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When distributing Covered Code, include this CDDL HEADER in each
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If applicable, add the following below this CDDL HEADER, with the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * fields enclosed by brackets "[]" replaced with your own identifying
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * information: Portions Copyright [yyyy] [name of copyright owner]
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * CDDL HEADER END
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
1eee170a5f6cf875d905524fea524c7c5c870aa0Erik Nordmark * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * Copyright (c) 2012, Joyent, Inc. All rights reserved.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/types.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/stream.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/strsun.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/zone.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/ddi.h>
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek#include <sys/disp.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/sunddi.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/cmn_err.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/debug.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/atomic.h>
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek#include <sys/callb.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#define _SUN_TPI_VERSION 2
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/tihdr.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/common.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/mi.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/mib2.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/snmpcom.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <netinet/ip6.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <netinet/icmp6.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_impl.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip6.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip6_asp.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_multi.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_if.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_ire.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_ftable.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_rts.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_ndp.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ipclassifier.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <inet/ip_listutils.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#include <sys/sunddi.h>
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Routines for handling destination cache entries.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * There is always one DCEF_DEFAULT for each ip_stack_t created at init time.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * That entry holds both the IP ident value and the dce generation number.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Any time a DCE is changed significantly (different path MTU, but NOT
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * different ULP info!), the dce_generation number is increased.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Also, when a new DCE is created, the dce_generation number in the default
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * DCE is bumped. That allows the dce_t information to be cached efficiently
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * as long as the entity caching the dce_t also caches the dce_generation,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * and compares the cached generation to detect any changes.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Furthermore, when a DCE is deleted, if there are any outstanding references
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * to the DCE it will be marked as condemned. The condemned mark is
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * a designated generation number which is never otherwise used, hence
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the single comparison with the generation number captures that as well.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * An example of code which caches is as follows:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * if (mystruct->my_dce_generation != mystruct->my_dce->dce_generation) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The DCE has changed
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * mystruct->my_dce = dce_lookup_pkt(mp, ixa,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * &mystruct->my_dce_generation);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Not needed in practice, since we have the default DCE:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * if (DCE_IS_CONDEMNED(mystruct->my_dce))
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * return failure;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that for IPv6 link-local addresses we record the ifindex since the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * link-locals are not globally unique.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Hash bucket structure for DCEs
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarktypedef struct dcb_s {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark krwlock_t dcb_lock;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint32_t dcb_cnt;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dcb_dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark} dcb_t;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void dce_delete_locked(dcb_t *, dce_t *);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void dce_make_condemned(dce_t *);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic kmem_cache_t *dce_cache;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekstatic kthread_t *dce_reclaim_thread;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekstatic kmutex_t dce_reclaim_lock;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekstatic kcondvar_t dce_reclaim_cv;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekstatic int dce_reclaim_shutdown;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek/* Global so it can be tuned in /etc/system. This must be a power of two. */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekuint_t ip_dce_hash_size = 1024;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek/* The time in seconds between executions of the IP DCE reclaim worker. */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekuint_t ip_dce_reclaim_interval = 60;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek/* The factor of the DCE threshold at which to start hard reclaims */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekuint_t ip_dce_reclaim_threshold_hard = 2;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* Operates on a uint64_t */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark#define RANDOM_HASH(p) ((p) ^ ((p)>>16) ^ ((p)>>32) ^ ((p)>>48))
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Reclaim a fraction of dce's in the dcb.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * For now we have a higher probability to delete DCEs without DCE_PMTU.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdcb_reclaim(dcb_t *dcb, ip_stack_t *ipst, uint_t fraction)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t fraction_pmtu = fraction*4;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t hash;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce, *nextdce;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek hrtime_t seed = gethrtime();
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek uint_t retained = 0;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek uint_t max = ipst->ips_ip_dce_reclaim_threshold;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek max *= ip_dce_reclaim_threshold_hard;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_WRITER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = nextdce) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark nextdce = dce->dce_next;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Clear DCEF_PMTU if the pmtu is too old */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if ((dce->dce_flags & DCEF_PMTU) &&
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni TICK_TO_SEC(ddi_get_lbolt64()) - dce->dce_last_change_time >
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_ip_pathmtu_interval) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_flags &= ~DCEF_PMTU;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_increment_generation(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (max == 0 || retained < max) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek hash = RANDOM_HASH((uint64_t)((uintptr_t)dce | seed));
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (dce->dce_flags & DCEF_PMTU) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (hash % fraction_pmtu != 0) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek retained++;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek continue;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek }
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek } else {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (hash % fraction != 0) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek retained++;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek continue;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek }
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IP_STAT(ipst, ip_dce_reclaim_deleted);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_delete_locked(dcb, dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refrele(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * kmem_cache callback to free up memory.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_dce_reclaim_stack(ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark int i;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IP_STAT(ipst, ip_dce_reclaim_calls);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (i = 0; i < ipst->ips_dce_hashsize; i++) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_reclaim(&ipst->ips_dce_hash_v4[i], ipst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_ip_dce_reclaim_fraction);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_reclaim(&ipst->ips_dce_hash_v6[i], ipst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_ip_dce_reclaim_fraction);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Walk all CONNs that can have a reference on an ire, nce or dce.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Get them to update any stale references to drop any refholds they
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * have.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipcl_walk(conn_ixa_cleanup, (void *)B_FALSE, ipst);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * Called by dce_reclaim_worker() below, and no one else. Typically this will
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * mean that the number of entries in the hash buckets has exceeded a tunable
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * threshold.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekstatic void
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekip_dce_reclaim(void)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark netstack_handle_t nh;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark netstack_t *ns;
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon ip_stack_t *ipst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ASSERT(curthread == dce_reclaim_thread);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark netstack_next_init(&nh);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark while ((ns = netstack_next(&nh)) != NULL) {
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon /*
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon * netstack_next() can return a netstack_t with a NULL
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon * netstack_ip at boot time.
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon */
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon if ((ipst = ns->netstack_ip) == NULL) {
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon netstack_rele(ns);
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon continue;
4ba231cedd10104ba0c43236736c7a3b1bbc1143Kacheong Poon }
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (atomic_swap_uint(&ipst->ips_dce_reclaim_needed, 0) != 0)
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ip_dce_reclaim_stack(ipst);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark netstack_rele(ns);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark netstack_next_fini(&nh);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek/* ARGSUSED */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekstatic void
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinekdce_reclaim_worker(void *arg)
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek{
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek callb_cpr_t cprinfo;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek CALLB_CPR_INIT(&cprinfo, &dce_reclaim_lock, callb_generic_cpr,
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek "dce_reclaim_worker");
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek mutex_enter(&dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek while (!dce_reclaim_shutdown) {
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek CALLB_CPR_SAFE_BEGIN(&cprinfo);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek (void) cv_timedwait(&dce_reclaim_cv, &dce_reclaim_lock,
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ddi_get_lbolt() + ip_dce_reclaim_interval * hz);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek CALLB_CPR_SAFE_END(&cprinfo, &dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (dce_reclaim_shutdown)
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek break;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek mutex_exit(&dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ip_dce_reclaim();
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek mutex_enter(&dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek }
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ASSERT(MUTEX_HELD(&dce_reclaim_lock));
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek dce_reclaim_thread = NULL;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek dce_reclaim_shutdown = 0;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek cv_broadcast(&dce_reclaim_cv);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek CALLB_CPR_EXIT(&cprinfo); /* drops the lock */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek thread_exit();
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek}
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_g_init(void)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_cache = kmem_cache_create("dce_cache",
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek sizeof (dce_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek mutex_init(&dce_reclaim_lock, NULL, MUTEX_DEFAULT, NULL);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek cv_init(&dce_reclaim_cv, NULL, CV_DEFAULT, NULL);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek dce_reclaim_thread = thread_create(NULL, 0, dce_reclaim_worker,
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek NULL, 0, &p0, TS_RUN, minclsyspri);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_g_destroy(void)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek mutex_enter(&dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek dce_reclaim_shutdown = 1;
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek cv_signal(&dce_reclaim_cv);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek while (dce_reclaim_thread != NULL)
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek cv_wait(&dce_reclaim_cv, &dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek mutex_exit(&dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek cv_destroy(&dce_reclaim_cv);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek mutex_destroy(&dce_reclaim_lock);
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark kmem_cache_destroy(dce_cache);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Allocate a default DCE and a hash table for per-IP address DCEs
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_stack_init(ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark int i;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_default = kmem_cache_alloc(dce_cache, KM_SLEEP);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark bzero(ipst->ips_dce_default, sizeof (dce_t));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_default->dce_flags = DCEF_DEFAULT;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_default->dce_generation = DCE_GENERATION_INITIAL;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ipst->ips_dce_default->dce_last_change_time =
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni TICK_TO_SEC(ddi_get_lbolt64());
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_default->dce_refcnt = 1; /* Should never go away */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_default->dce_ipst = ipst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* This must be a power of two since we are using IRE_ADDR_HASH macro */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek ipst->ips_dce_hashsize = ip_dce_hash_size;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_hash_v4 = kmem_zalloc(ipst->ips_dce_hashsize *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sizeof (dcb_t), KM_SLEEP);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_hash_v6 = kmem_zalloc(ipst->ips_dce_hashsize *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sizeof (dcb_t), KM_SLEEP);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (i = 0; i < ipst->ips_dce_hashsize; i++) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_init(&ipst->ips_dce_hash_v4[i].dcb_lock, NULL, RW_DEFAULT,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_init(&ipst->ips_dce_hash_v6[i].dcb_lock, NULL, RW_DEFAULT,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_stack_destroy(ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark int i;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (i = 0; i < ipst->ips_dce_hashsize; i++) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_destroy(&ipst->ips_dce_hash_v4[i].dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_destroy(&ipst->ips_dce_hash_v6[i].dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark kmem_free(ipst->ips_dce_hash_v4,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_hashsize * sizeof (dcb_t));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_hash_v4 = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark kmem_free(ipst->ips_dce_hash_v6,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_hashsize * sizeof (dcb_t));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_hash_v6 = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_hashsize = 0;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(ipst->ips_dce_default->dce_refcnt == 1);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark kmem_cache_free(dce_cache, ipst->ips_dce_default);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipst->ips_dce_default = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* When any DCE is good enough */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_get_default(ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = ipst->ips_dce_default;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Generic for IPv4 and IPv6.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Used by callers that need to cache e.g., the datapath
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns the generation number in the last argument.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_lookup_pkt(mblk_t *mp, ip_xmit_attr_t *ixa, uint_t *generationp)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (ixa->ixa_flags & IXAF_IS_IPV4) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If we have a source route we need to look for the final
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * destination in the source route option.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipaddr_t final_dst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipha_t *ipha = (ipha_t *)mp->b_rptr;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark final_dst = ip_get_dst(ipha);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce_lookup_v4(final_dst, ixa->ixa_ipst, generationp));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t ifindex;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If we have a routing header we need to look for the final
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * destination in the routing extension header.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark in6_addr_t final_dst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip6_t *ip6h = (ip6_t *)mp->b_rptr;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark final_dst = ip_get_dst_v6(ip6h, mp, NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ifindex = 0;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (IN6_IS_ADDR_LINKSCOPE(&final_dst) && ixa->ixa_nce != NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ifindex = ixa->ixa_nce->nce_common->ncec_ill->
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ill_phyint->phyint_ifindex;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce_lookup_v6(&final_dst, ifindex, ixa->ixa_ipst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark generationp));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Used by callers that need to cache e.g., the datapath
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns the generation number in the last argument.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_lookup_v4(ipaddr_t dst, ip_stack_t *ipst, uint_t *generationp)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t hash;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_t *dcb;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Set *generationp before dropping the lock(s) that allow additions */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (generationp != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *generationp = ipst->ips_dce_default->dce_generation;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark hash = IRE_ADDR_HASH(dst, ipst->ips_dce_hashsize);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v4[hash];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_READER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_v4addr == dst) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!DCE_IS_CONDEMNED(dce)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (generationp != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *generationp = dce->dce_generation;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Not found */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = ipst->ips_dce_default;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Used by callers that need to cache e.g., the datapath
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Returns the generation number in the last argument.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ifindex should only be set for link-locals
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_lookup_v6(const in6_addr_t *dst, uint_t ifindex, ip_stack_t *ipst,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t *generationp)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t hash;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_t *dcb;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Set *generationp before dropping the lock(s) that allow additions */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (generationp != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *generationp = ipst->ips_dce_default->dce_generation;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark hash = IRE_ADDR_HASH_V6(*dst, ipst->ips_dce_hashsize);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v6[hash];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_READER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (IN6_ARE_ADDR_EQUAL(&dce->dce_v6addr, dst) &&
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ifindex == ifindex) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!DCE_IS_CONDEMNED(dce)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (generationp != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *generationp = dce->dce_generation;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Not found */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = ipst->ips_dce_default;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Atomically looks for a non-default DCE, and if not found tries to create one.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If there is no memory it returns NULL.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When an entry is created we increase the generation number on
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the default DCE so that conn_ip_output will detect there is a new DCE.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_lookup_and_add_v4(ipaddr_t dst, ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t hash;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_t *dcb;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark hash = IRE_ADDR_HASH(dst, ipst->ips_dce_hashsize);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v4[hash];
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek /*
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * Assuming that we get fairly even distribution across all of the
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * buckets, once one bucket is overly full, prune the whole cache.
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (dcb->dcb_cnt > ipst->ips_ip_dce_reclaim_threshold)
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek atomic_or_uint(&ipst->ips_dce_reclaim_needed, 1);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_WRITER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_v4addr == dst) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!DCE_IS_CONDEMNED(dce)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = kmem_cache_alloc(dce_cache, KM_NOSLEEP);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce == NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark bzero(dce, sizeof (dce_t));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ipst = ipst; /* No netstack_hold */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_v4addr = dst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_generation = DCE_GENERATION_INITIAL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ipversion = IPV4_VERSION;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce); /* For the hash list */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Link into list */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dcb->dcb_dce != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb->dcb_dce->dce_ptpn = &dce->dce_next;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_next = dcb->dcb_dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ptpn = &dcb->dcb_dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb->dcb_dce = dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_bucket = dcb;
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&dcb->dcb_cnt);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce); /* For the caller */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Initialize dce_ident to be different than for the last packet */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ident = ipst->ips_dce_default->dce_ident + 1;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_increment_generation(ipst->ips_dce_default);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Atomically looks for a non-default DCE, and if not found tries to create one.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If there is no memory it returns NULL.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * When an entry is created we increase the generation number on
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * the default DCE so that conn_ip_output will detect there is a new DCE.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * ifindex should only be used with link-local addresses.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_lookup_and_add_v6(const in6_addr_t *dst, uint_t ifindex, ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t hash;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_t *dcb;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We should not create entries for link-locals w/o an ifindex */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(!(IN6_IS_ADDR_LINKSCOPE(dst)) || ifindex != 0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark hash = IRE_ADDR_HASH_V6(*dst, ipst->ips_dce_hashsize);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v6[hash];
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek /*
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * Assuming that we get fairly even distribution across all of the
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek * buckets, once one bucket is overly full, prune the whole cache.
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek */
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek if (dcb->dcb_cnt > ipst->ips_ip_dce_reclaim_threshold)
7c6d7024e51780d3aacf9063d2133c1e957d7eeaJerry Jelinek atomic_or_uint(&ipst->ips_dce_reclaim_needed, 1);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_WRITER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (IN6_ARE_ADDR_EQUAL(&dce->dce_v6addr, dst) &&
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ifindex == ifindex) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!DCE_IS_CONDEMNED(dce)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = kmem_cache_alloc(dce_cache, KM_NOSLEEP);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce == NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark bzero(dce, sizeof (dce_t));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ipst = ipst; /* No netstack_hold */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_v6addr = *dst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ifindex = ifindex;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_generation = DCE_GENERATION_INITIAL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ipversion = IPV6_VERSION;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce); /* For the hash list */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Link into list */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dcb->dcb_dce != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb->dcb_dce->dce_ptpn = &dce->dce_next;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_next = dcb->dcb_dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ptpn = &dcb->dcb_dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb->dcb_dce = dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_bucket = dcb;
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&dcb->dcb_cnt);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refhold(dce); /* For the caller */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Initialize dce_ident to be different than for the last packet */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ident = ipst->ips_dce_default->dce_ident + 1;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_increment_generation(ipst->ips_dce_default);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Set/update uinfo. Creates a per-destination dce if none exists.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Note that we do not bump the generation number here.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * New connections will find the new uinfo.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * The only use of this (tcp, sctp using iulp_t) is to set rtt+rtt_sd.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_setuinfo(dce_t *dce, iulp_t *uinfo)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Update the round trip time estimate and/or the max frag size
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * and/or the slow start threshold.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * We serialize multiple advises using dce_lock.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Gard against setting to zero */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (uinfo->iulp_rtt != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * If there is no old cached values, initialize them
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * conservatively. Set them to be (1.5 * new value).
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_uinfo.iulp_rtt != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_uinfo.iulp_rtt = (dce->dce_uinfo.iulp_rtt +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uinfo->iulp_rtt) >> 1;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_uinfo.iulp_rtt = uinfo->iulp_rtt +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (uinfo->iulp_rtt >> 1);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_uinfo.iulp_rtt_sd != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_uinfo.iulp_rtt_sd =
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (dce->dce_uinfo.iulp_rtt_sd +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uinfo->iulp_rtt_sd) >> 1;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_uinfo.iulp_rtt_sd = uinfo->iulp_rtt_sd +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (uinfo->iulp_rtt_sd >> 1);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (uinfo->iulp_mtu != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_flags & DCEF_PMTU) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_pmtu = MIN(uinfo->iulp_mtu, dce->dce_pmtu);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_pmtu = MIN(uinfo->iulp_mtu, IP_MAXPACKET);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_flags |= DCEF_PMTU;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (uinfo->iulp_ssthresh != 0) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_uinfo.iulp_ssthresh != 0)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_uinfo.iulp_ssthresh =
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (uinfo->iulp_ssthresh +
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_uinfo.iulp_ssthresh) >> 1;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_uinfo.iulp_ssthresh = uinfo->iulp_ssthresh;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* We have uinfo for sure */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_flags |= DCEF_UINFO;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_update_uinfo_v4(ipaddr_t dst, iulp_t *uinfo, ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = dce_lookup_and_add_v4(dst, ipst);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce == NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ENOMEM);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_setuinfo(dce, uinfo);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refrele(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_update_uinfo_v6(const in6_addr_t *dst, uint_t ifindex, iulp_t *uinfo,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce = dce_lookup_and_add_v6(dst, ifindex, ipst);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce == NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (ENOMEM);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_setuinfo(dce, uinfo);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refrele(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* Common routine for IPv4 and IPv6 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkint
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_update_uinfo(const in6_addr_t *dst, uint_t ifindex, iulp_t *uinfo,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ipaddr_t dst4;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (IN6_IS_ADDR_V4MAPPED_ANY(dst)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark IN6_V4MAPPED_TO_IPADDR(dst, dst4);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce_update_uinfo_v4(dst4, uinfo, ipst));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark } else {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (dce_update_uinfo_v6(dst, ifindex, uinfo, ipst));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_make_condemned(dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_stack_t *ipst = dce->dce_ipst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(!DCE_IS_CONDEMNED(dce));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_generation = DCE_GENERATION_CONDEMNED;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Count how many condemned dces for kmem_cache callback */
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&ipst->ips_num_dce_condemned);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Increment the generation avoiding the special condemned value
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_increment_generation(dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t generation;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_enter(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!DCE_IS_CONDEMNED(dce)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark generation = dce->dce_generation + 1;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (generation == DCE_GENERATION_CONDEMNED)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark generation = DCE_GENERATION_INITIAL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(generation != DCE_GENERATION_VERIFY);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_generation = generation;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mutex_exit(&dce->dce_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Increment the generation number on all dces that have a path MTU and
1eee170a5f6cf875d905524fea524c7c5c870aa0Erik Nordmark * the default DCE. Used when ill_mtu or ill_mc_mtu changes.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_increment_all_generations(boolean_t isv6, ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark int i;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_t *dcb;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (i = 0; i < ipst->ips_dce_hashsize; i++) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (isv6)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v6[i];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v4[i];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_WRITER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (DCE_IS_CONDEMNED(dce))
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark continue;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_increment_generation(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_increment_generation(ipst->ips_dce_default);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Caller needs to do a dce_refrele since we can't do the
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * dce_refrele under dcb_lock.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_delete_locked(dcb_t *dcb, dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_bucket = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark *dce->dce_ptpn = dce->dce_next;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_next != NULL)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_next->dce_ptpn = dce->dce_ptpn;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_ptpn = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_next = NULL;
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&dcb->dcb_cnt);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_make_condemned(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkstatic void
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_inactive(dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip_stack_t *ipst = dce->dce_ipst;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(!(dce->dce_flags & DCEF_DEFAULT));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(dce->dce_ptpn == NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(dce->dce_bucket == NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Count how many condemned dces for kmem_cache callback */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (DCE_IS_CONDEMNED(dce))
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&ipst->ips_num_dce_condemned);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark kmem_cache_free(dce_cache, dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_refrele(dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(dce->dce_refcnt != 0);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek if (atomic_dec_32_nv(&dce->dce_refcnt) == 0)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_inactive(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_refhold(dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&dce->dce_refcnt);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(dce->dce_refcnt != 0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* No tracing support yet hence the same as the above functions */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_refrele_notr(dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(dce->dce_refcnt != 0);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek if (atomic_dec_32_nv(&dce->dce_refcnt) == 0)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_inactive(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_refhold_notr(dce_t *dce)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&dce->dce_refcnt);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ASSERT(dce->dce_refcnt != 0);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/* Report both the IPv4 and IPv6 DCEs. */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkmblk_t *
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkip_snmp_get_mib2_ip_dce(queue_t *q, mblk_t *mpctl, ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark struct opthdr *optp;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mblk_t *mp2ctl;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache_entry_t dest_cache;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mblk_t *mp_tail = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_t *dcb;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark int i;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint64_t current_time;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni current_time = TICK_TO_SEC(ddi_get_lbolt64());
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * make a copy of the original message
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mp2ctl = copymsg(mpctl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* First we do IPv4 entries */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp = (struct opthdr *)&mpctl->b_rptr[
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sizeof (struct T_optmgmt_ack)];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp->level = MIB2_IP;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp->name = EXPER_IP_DCE;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (i = 0; i < ipst->ips_dce_hashsize; i++) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v4[i];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_READER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestIpv4Address = dce->dce_v4addr;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestFlags = dce->dce_flags;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_flags & DCEF_PMTU)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestPmtu = dce->dce_pmtu;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestPmtu = 0;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestIdent = dce->dce_ident;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestIfindex = 0;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestAge = current_time -
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_last_change_time;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!snmp_append_data2(mpctl->b_cont, &mp_tail,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (char *)&dest_cache, (int)sizeof (dest_cache))) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip1dbg(("ip_snmp_get_mib2_ip_dce: "
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark "failed to allocate %u bytes\n",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (uint_t)sizeof (dest_cache)));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp->len = (t_uscalar_t)msgdsize(mpctl->b_cont);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip3dbg(("ip_snmp_get: level %d, name %d, len %d\n",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (int)optp->level, (int)optp->name, (int)optp->len));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark qreply(q, mpctl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (mp2ctl == NULL) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Copymsg failed above */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (NULL);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* Now for IPv6 */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mpctl = mp2ctl;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mp_tail = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mp2ctl = copymsg(mpctl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp = (struct opthdr *)&mpctl->b_rptr[
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sizeof (struct T_optmgmt_ack)];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp->level = MIB2_IP6;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp->name = EXPER_IP_DCE;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (i = 0; i < ipst->ips_dce_hashsize; i++) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v6[i];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_READER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestIpv6Address = dce->dce_v6addr;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestFlags = dce->dce_flags;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_flags & DCEF_PMTU)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestPmtu = dce->dce_pmtu;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestPmtu = 0;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestIdent = dce->dce_ident;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (IN6_IS_ADDR_LINKSCOPE(&dce->dce_v6addr))
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestIfindex = dce->dce_ifindex;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark else
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestIfindex = 0;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dest_cache.DestAge = current_time -
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce->dce_last_change_time;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!snmp_append_data2(mpctl->b_cont, &mp_tail,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (char *)&dest_cache, (int)sizeof (dest_cache))) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip1dbg(("ip_snmp_get_mib2_ip_dce: "
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark "failed to allocate %u bytes\n",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (uint_t)sizeof (dest_cache)));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark optp->len = (t_uscalar_t)msgdsize(mpctl->b_cont);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark ip3dbg(("ip_snmp_get: level %d, name %d, len %d\n",
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark (int)optp->level, (int)optp->name, (int)optp->len));
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark qreply(q, mpctl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark return (mp2ctl);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark/*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Remove IPv6 DCEs which refer to an ifindex that is going away.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * This is not required for correctness, but it avoids netstat -d
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * showing stale stuff that will never be used.
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkvoid
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmarkdce_cleanup(uint_t ifindex, ip_stack_t *ipst)
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark{
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark uint_t i;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb_t *dcb;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_t *dce, *nextdce;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (i = 0; i < ipst->ips_dce_hashsize; i++) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dcb = &ipst->ips_dce_hash_v6[i];
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_enter(&dcb->dcb_lock, RW_WRITER);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark for (dce = dcb->dcb_dce; dce != NULL; dce = nextdce) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark nextdce = dce->dce_next;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (dce->dce_ifindex == ifindex) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_delete_locked(dcb, dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark dce_refrele(dce);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark rw_exit(&dcb->dcb_lock);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark}