Home | History | Annotate | Line # | Download | only in netinet
tcp_vtw.c revision 1.4.2.2
      1  1.4.2.2  rmind /*
      2  1.4.2.2  rmind  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      3  1.4.2.2  rmind  * All rights reserved.
      4  1.4.2.2  rmind  *
      5  1.4.2.2  rmind  * This code is derived from software contributed to The NetBSD Foundation
      6  1.4.2.2  rmind  * by Coyote Point Systems, Inc.
      7  1.4.2.2  rmind  *
      8  1.4.2.2  rmind  * Redistribution and use in source and binary forms, with or without
      9  1.4.2.2  rmind  * modification, are permitted provided that the following conditions
     10  1.4.2.2  rmind  * are met:
     11  1.4.2.2  rmind  * 1. Redistributions of source code must retain the above copyright
     12  1.4.2.2  rmind  *    notice, this list of conditions and the following disclaimer.
     13  1.4.2.2  rmind  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.4.2.2  rmind  *    notice, this list of conditions and the following disclaimer in the
     15  1.4.2.2  rmind  *    documentation and/or other materials provided with the distribution.
     16  1.4.2.2  rmind  *
     17  1.4.2.2  rmind  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     18  1.4.2.2  rmind  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     19  1.4.2.2  rmind  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     20  1.4.2.2  rmind  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     21  1.4.2.2  rmind  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  1.4.2.2  rmind  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  1.4.2.2  rmind  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  1.4.2.2  rmind  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  1.4.2.2  rmind  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  1.4.2.2  rmind  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  1.4.2.2  rmind  * POSSIBILITY OF SUCH DAMAGE.
     28  1.4.2.2  rmind  */
     29  1.4.2.2  rmind #include <sys/cdefs.h>
     30  1.4.2.2  rmind 
     31  1.4.2.2  rmind #include "opt_ddb.h"
     32  1.4.2.2  rmind #include "opt_inet.h"
     33  1.4.2.2  rmind #include "opt_ipsec.h"
     34  1.4.2.2  rmind #include "opt_inet_csum.h"
     35  1.4.2.2  rmind #include "opt_tcp_debug.h"
     36  1.4.2.2  rmind 
     37  1.4.2.2  rmind #include <sys/param.h>
     38  1.4.2.2  rmind #include <sys/systm.h>
     39  1.4.2.2  rmind #include <sys/malloc.h>
     40  1.4.2.2  rmind #include <sys/kmem.h>
     41  1.4.2.2  rmind #include <sys/mbuf.h>
     42  1.4.2.2  rmind #include <sys/protosw.h>
     43  1.4.2.2  rmind #include <sys/socket.h>
     44  1.4.2.2  rmind #include <sys/socketvar.h>
     45  1.4.2.2  rmind #include <sys/errno.h>
     46  1.4.2.2  rmind #include <sys/syslog.h>
     47  1.4.2.2  rmind #include <sys/pool.h>
     48  1.4.2.2  rmind #include <sys/domain.h>
     49  1.4.2.2  rmind #include <sys/kernel.h>
     50  1.4.2.2  rmind #include <net/if.h>
     51  1.4.2.2  rmind #include <net/route.h>
     52  1.4.2.2  rmind #include <net/if_types.h>
     53  1.4.2.2  rmind 
     54  1.4.2.2  rmind #include <netinet/in.h>
     55  1.4.2.2  rmind #include <netinet/in_systm.h>
     56  1.4.2.2  rmind #include <netinet/ip.h>
     57  1.4.2.2  rmind #include <netinet/in_pcb.h>
     58  1.4.2.2  rmind #include <netinet/in_var.h>
     59  1.4.2.2  rmind #include <netinet/ip_var.h>
     60  1.4.2.2  rmind #include <netinet/in_offload.h>
     61  1.4.2.2  rmind #include <netinet/ip6.h>
     62  1.4.2.2  rmind #include <netinet6/ip6_var.h>
     63  1.4.2.2  rmind #include <netinet6/in6_pcb.h>
     64  1.4.2.2  rmind #include <netinet6/ip6_var.h>
     65  1.4.2.2  rmind #include <netinet6/in6_var.h>
     66  1.4.2.2  rmind #include <netinet/icmp6.h>
     67  1.4.2.2  rmind #include <netinet6/nd6.h>
     68  1.4.2.2  rmind 
     69  1.4.2.2  rmind #include <netinet/tcp.h>
     70  1.4.2.2  rmind #include <netinet/tcp_fsm.h>
     71  1.4.2.2  rmind #include <netinet/tcp_seq.h>
     72  1.4.2.2  rmind #include <netinet/tcp_timer.h>
     73  1.4.2.2  rmind #include <netinet/tcp_var.h>
     74  1.4.2.2  rmind #include <netinet/tcp_private.h>
     75  1.4.2.2  rmind #include <netinet/tcpip.h>
     76  1.4.2.2  rmind 
     77  1.4.2.2  rmind #include <machine/stdarg.h>
     78  1.4.2.2  rmind #include <netinet/tcp_vtw.h>
     79  1.4.2.2  rmind 
     80  1.4.2.2  rmind __KERNEL_RCSID(0, "$NetBSD: tcp_vtw.c,v 1.4.2.2 2011/05/31 03:05:08 rmind Exp $");
     81  1.4.2.2  rmind 
     82  1.4.2.2  rmind #define db_trace(__a, __b)	do { } while (/*CONSTCOND*/0)
     83  1.4.2.2  rmind 
     84  1.4.2.2  rmind static void vtw_debug_init(void);
     85  1.4.2.2  rmind 
     86  1.4.2.2  rmind fatp_ctl_t fat_tcpv4;
     87  1.4.2.2  rmind fatp_ctl_t fat_tcpv6;
     88  1.4.2.2  rmind vtw_ctl_t  vtw_tcpv4[VTW_NCLASS];
     89  1.4.2.2  rmind vtw_ctl_t  vtw_tcpv6[VTW_NCLASS];
     90  1.4.2.2  rmind vtw_stats_t vtw_stats;
     91  1.4.2.2  rmind 
     92  1.4.2.2  rmind /* We provide state for the lookup_ports iterator.
     93  1.4.2.2  rmind  * As currently we are netlock-protected, there is one.
     94  1.4.2.2  rmind  * If we were finer-grain, we would have one per CPU.
     95  1.4.2.2  rmind  * I do not want to be in the business of alloc/free.
     96  1.4.2.2  rmind  * The best alternate would be allocate on the caller's
     97  1.4.2.2  rmind  * stack, but that would require them to know the struct,
     98  1.4.2.2  rmind  * or at least the size.
     99  1.4.2.2  rmind  * See how she goes.
    100  1.4.2.2  rmind  */
    101  1.4.2.2  rmind struct tcp_ports_iterator {
    102  1.4.2.2  rmind 	union {
    103  1.4.2.2  rmind 		struct in_addr	v4;
    104  1.4.2.2  rmind 		struct in6_addr	v6;
    105  1.4.2.2  rmind 	}		addr;
    106  1.4.2.2  rmind 	u_int		port;
    107  1.4.2.2  rmind 
    108  1.4.2.2  rmind 	uint32_t	wild	: 1;
    109  1.4.2.2  rmind 
    110  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
    111  1.4.2.2  rmind 	fatp_t		*fp;
    112  1.4.2.2  rmind 
    113  1.4.2.2  rmind 	uint16_t	slot_idx;
    114  1.4.2.2  rmind 	uint16_t	ctl_idx;
    115  1.4.2.2  rmind };
    116  1.4.2.2  rmind 
    117  1.4.2.2  rmind static struct tcp_ports_iterator tcp_ports_iterator_v4;
    118  1.4.2.2  rmind static struct tcp_ports_iterator tcp_ports_iterator_v6;
    119  1.4.2.2  rmind 
    120  1.4.2.2  rmind static int vtw_age(vtw_ctl_t *, struct timeval *);
    121  1.4.2.2  rmind 
    122  1.4.2.2  rmind /*!\brief allocate a fat pointer from a collection.
    123  1.4.2.2  rmind  */
    124  1.4.2.2  rmind static fatp_t *
    125  1.4.2.2  rmind fatp_alloc(fatp_ctl_t *fat)
    126  1.4.2.2  rmind {
    127  1.4.2.2  rmind 	fatp_t	*fp	= 0;
    128  1.4.2.2  rmind 
    129  1.4.2.2  rmind 	if (fat->nfree) {
    130  1.4.2.2  rmind 		fp = fat->free;
    131  1.4.2.2  rmind 		if (fp) {
    132  1.4.2.2  rmind 			fat->free = fatp_next(fat, fp);
    133  1.4.2.2  rmind 			--fat->nfree;
    134  1.4.2.2  rmind 			++fat->nalloc;
    135  1.4.2.2  rmind 			fp->nxt = 0;
    136  1.4.2.2  rmind 
    137  1.4.2.2  rmind 			KASSERT(!fp->inuse);
    138  1.4.2.2  rmind 		}
    139  1.4.2.2  rmind 	}
    140  1.4.2.2  rmind 
    141  1.4.2.2  rmind 	return fp;
    142  1.4.2.2  rmind }
    143  1.4.2.2  rmind 
    144  1.4.2.2  rmind /*!\brief free a fat pointer.
    145  1.4.2.2  rmind  */
    146  1.4.2.2  rmind static void
    147  1.4.2.2  rmind fatp_free(fatp_ctl_t *fat, fatp_t *fp)
    148  1.4.2.2  rmind {
    149  1.4.2.2  rmind 	if (fp) {
    150  1.4.2.2  rmind 		KASSERT(!fp->inuse);
    151  1.4.2.2  rmind 		KASSERT(!fp->nxt);
    152  1.4.2.2  rmind 
    153  1.4.2.2  rmind 		fp->nxt = fatp_index(fat, fat->free);
    154  1.4.2.2  rmind 		fat->free = fp;
    155  1.4.2.2  rmind 
    156  1.4.2.2  rmind 		++fat->nfree;
    157  1.4.2.2  rmind 		--fat->nalloc;
    158  1.4.2.2  rmind 	}
    159  1.4.2.2  rmind }
    160  1.4.2.2  rmind 
    161  1.4.2.2  rmind /*!\brief initialise a collection of fat pointers.
    162  1.4.2.2  rmind  *
    163  1.4.2.2  rmind  *\param n	# hash buckets
    164  1.4.2.2  rmind  *\param m	total # fat pointers to allocate
    165  1.4.2.2  rmind  *
    166  1.4.2.2  rmind  * We allocate 2x as much, as we have two hashes: full and lport only.
    167  1.4.2.2  rmind  */
    168  1.4.2.2  rmind static void
    169  1.4.2.2  rmind fatp_init(fatp_ctl_t *fat, uint32_t n, uint32_t m)
    170  1.4.2.2  rmind {
    171  1.4.2.2  rmind 	fatp_t	*fp;
    172  1.4.2.2  rmind 
    173  1.4.2.2  rmind 	KASSERT(n <= FATP_MAX / 2);
    174  1.4.2.2  rmind 
    175  1.4.2.2  rmind 	fat->hash   = kmem_alloc(2*m * sizeof (fatp_t *), KM_SLEEP);
    176  1.4.2.2  rmind 	fat->base   = kmem_alloc(2*n * sizeof (fatp_t), KM_SLEEP);
    177  1.4.2.2  rmind 
    178  1.4.2.2  rmind 	if (!fat->base) {
    179  1.4.2.2  rmind 		if (fat->hash)
    180  1.4.2.2  rmind 			kmem_free(fat->hash, 2*m * sizeof (fatp_t *));
    181  1.4.2.2  rmind 
    182  1.4.2.2  rmind 		bzero(fat, sizeof (*fat));
    183  1.4.2.2  rmind 		return;
    184  1.4.2.2  rmind 	}
    185  1.4.2.2  rmind 
    186  1.4.2.2  rmind 	fat->port = &fat->hash[m];
    187  1.4.2.2  rmind 
    188  1.4.2.2  rmind 	fat->mask   = m - 1;	// ASSERT is power of 2 (m)
    189  1.4.2.2  rmind 	fat->lim    = fat->base + 2*n - 1;
    190  1.4.2.2  rmind 	fat->nfree  = 0;
    191  1.4.2.2  rmind 	fat->nalloc = 2*n;
    192  1.4.2.2  rmind 
    193  1.4.2.2  rmind 	bzero(fat->hash, 2*m * sizeof (fatp_t *));
    194  1.4.2.2  rmind 	bzero(fat->base, 2*n * sizeof (fatp_t));
    195  1.4.2.2  rmind 
    196  1.4.2.2  rmind 	/* Initialise the free list.
    197  1.4.2.2  rmind 	 */
    198  1.4.2.2  rmind 	for (fp = fat->lim; fp >= fat->base; --fp) {
    199  1.4.2.2  rmind 		fatp_free(fat, fp);
    200  1.4.2.2  rmind 	}
    201  1.4.2.2  rmind }
    202  1.4.2.2  rmind 
    203  1.4.2.2  rmind /*
    204  1.4.2.2  rmind  * The `xtra' is XORed into the tag stored.
    205  1.4.2.2  rmind  */
    206  1.4.2.2  rmind static uint32_t fatp_xtra[] = {
    207  1.4.2.2  rmind 	0x11111111,0x22222222,0x33333333,0x44444444,
    208  1.4.2.2  rmind 	0x55555555,0x66666666,0x77777777,0x88888888,
    209  1.4.2.2  rmind 	0x12121212,0x21212121,0x34343434,0x43434343,
    210  1.4.2.2  rmind 	0x56565656,0x65656565,0x78787878,0x87878787,
    211  1.4.2.2  rmind 	0x11221122,0x22112211,0x33443344,0x44334433,
    212  1.4.2.2  rmind 	0x55665566,0x66556655,0x77887788,0x88778877,
    213  1.4.2.2  rmind 	0x11112222,0x22221111,0x33334444,0x44443333,
    214  1.4.2.2  rmind 	0x55556666,0x66665555,0x77778888,0x88887777,
    215  1.4.2.2  rmind };
    216  1.4.2.2  rmind 
    217  1.4.2.2  rmind /*!\brief turn a {fatp_t*,slot} into an integral key.
    218  1.4.2.2  rmind  *
    219  1.4.2.2  rmind  * The key can be used to obtain the fatp_t, and the slot,
    220  1.4.2.2  rmind  * as it directly encodes them.
    221  1.4.2.2  rmind  */
    222  1.4.2.2  rmind static inline uint32_t
    223  1.4.2.2  rmind fatp_key(fatp_ctl_t *fat, fatp_t *fp, uint32_t slot)
    224  1.4.2.2  rmind {
    225  1.4.2.2  rmind 	CTASSERT(CACHE_LINE_SIZE == 32 ||
    226  1.4.2.2  rmind 	         CACHE_LINE_SIZE == 64 ||
    227  1.4.2.2  rmind 		 CACHE_LINE_SIZE == 128);
    228  1.4.2.2  rmind 
    229  1.4.2.2  rmind 	switch (fatp_ntags()) {
    230  1.4.2.2  rmind 	case 7:
    231  1.4.2.2  rmind 		return (fatp_index(fat, fp) << 3) | slot;
    232  1.4.2.2  rmind 	case 15:
    233  1.4.2.2  rmind 		return (fatp_index(fat, fp) << 4) | slot;
    234  1.4.2.2  rmind 	case 31:
    235  1.4.2.2  rmind 		return (fatp_index(fat, fp) << 5) | slot;
    236  1.4.2.2  rmind 	default:
    237  1.4.2.2  rmind 		KASSERT(0 && "no support, for no good reason");
    238  1.4.2.2  rmind 		return ~0;
    239  1.4.2.2  rmind 	}
    240  1.4.2.2  rmind }
    241  1.4.2.2  rmind 
    242  1.4.2.2  rmind static inline uint32_t
    243  1.4.2.2  rmind fatp_slot_from_key(fatp_ctl_t *fat, uint32_t key)
    244  1.4.2.2  rmind {
    245  1.4.2.2  rmind 	CTASSERT(CACHE_LINE_SIZE == 32 ||
    246  1.4.2.2  rmind 	         CACHE_LINE_SIZE == 64 ||
    247  1.4.2.2  rmind 		 CACHE_LINE_SIZE == 128);
    248  1.4.2.2  rmind 
    249  1.4.2.2  rmind 	switch (fatp_ntags()) {
    250  1.4.2.2  rmind 	case 7:
    251  1.4.2.2  rmind 		return key & 7;
    252  1.4.2.2  rmind 	case 15:
    253  1.4.2.2  rmind 		return key & 15;
    254  1.4.2.2  rmind 	case 31:
    255  1.4.2.2  rmind 		return key & 31;
    256  1.4.2.2  rmind 	default:
    257  1.4.2.2  rmind 		KASSERT(0 && "no support, for no good reason");
    258  1.4.2.2  rmind 		return ~0;
    259  1.4.2.2  rmind 	}
    260  1.4.2.2  rmind }
    261  1.4.2.2  rmind 
    262  1.4.2.2  rmind static inline fatp_t *
    263  1.4.2.2  rmind fatp_from_key(fatp_ctl_t *fat, uint32_t key)
    264  1.4.2.2  rmind {
    265  1.4.2.2  rmind 	CTASSERT(CACHE_LINE_SIZE == 32 ||
    266  1.4.2.2  rmind 	         CACHE_LINE_SIZE == 64 ||
    267  1.4.2.2  rmind 		 CACHE_LINE_SIZE == 128);
    268  1.4.2.2  rmind 
    269  1.4.2.2  rmind 	switch (fatp_ntags()) {
    270  1.4.2.2  rmind 	case 7:
    271  1.4.2.2  rmind 		key >>= 3;
    272  1.4.2.2  rmind 		break;
    273  1.4.2.2  rmind 	case 15:
    274  1.4.2.2  rmind 		key >>= 4;
    275  1.4.2.2  rmind 		break;
    276  1.4.2.2  rmind 	case 31:
    277  1.4.2.2  rmind 		key >>= 5;
    278  1.4.2.2  rmind 		break;
    279  1.4.2.2  rmind 	default:
    280  1.4.2.2  rmind 		KASSERT(0 && "no support, for no good reason");
    281  1.4.2.2  rmind 		return 0;
    282  1.4.2.2  rmind 	}
    283  1.4.2.2  rmind 
    284  1.4.2.2  rmind 	return key ? fat->base + key - 1 : 0;
    285  1.4.2.2  rmind }
    286  1.4.2.2  rmind 
    287  1.4.2.2  rmind static inline uint32_t
    288  1.4.2.2  rmind idx_encode(vtw_ctl_t *ctl, uint32_t idx)
    289  1.4.2.2  rmind {
    290  1.4.2.2  rmind 	return (idx << ctl->idx_bits) | idx;
    291  1.4.2.2  rmind }
    292  1.4.2.2  rmind 
    293  1.4.2.2  rmind static inline uint32_t
    294  1.4.2.2  rmind idx_decode(vtw_ctl_t *ctl, uint32_t bits)
    295  1.4.2.2  rmind {
    296  1.4.2.2  rmind 	uint32_t	idx	= bits & ctl->idx_mask;
    297  1.4.2.2  rmind 
    298  1.4.2.2  rmind 	if (idx_encode(ctl, idx) == bits)
    299  1.4.2.2  rmind 		return idx;
    300  1.4.2.2  rmind 	else
    301  1.4.2.2  rmind 		return ~0;
    302  1.4.2.2  rmind }
    303  1.4.2.2  rmind 
    304  1.4.2.2  rmind /*!\brief	insert index into fatp hash
    305  1.4.2.2  rmind  *
    306  1.4.2.2  rmind  *\param	idx	-	index of element being placed in hash chain
    307  1.4.2.2  rmind  *\param	tag	-	32-bit tag identifier
    308  1.4.2.2  rmind  *
    309  1.4.2.2  rmind  *\returns
    310  1.4.2.2  rmind  *	value which can be used to locate entry.
    311  1.4.2.2  rmind  *
    312  1.4.2.2  rmind  *\note
    313  1.4.2.2  rmind  *	we rely on the fact that there are unused high bits in the index
    314  1.4.2.2  rmind  *	for verification purposes on lookup.
    315  1.4.2.2  rmind  */
    316  1.4.2.2  rmind 
    317  1.4.2.2  rmind static inline uint32_t
    318  1.4.2.2  rmind fatp_vtw_inshash(fatp_ctl_t *fat, uint32_t idx, uint32_t tag, int which,
    319  1.4.2.2  rmind     void *dbg)
    320  1.4.2.2  rmind {
    321  1.4.2.2  rmind 	fatp_t	*fp;
    322  1.4.2.2  rmind 	fatp_t	**hash = (which ? fat->port : fat->hash);
    323  1.4.2.2  rmind 	int	i;
    324  1.4.2.2  rmind 
    325  1.4.2.2  rmind 	fp = hash[tag & fat->mask];
    326  1.4.2.2  rmind 
    327  1.4.2.2  rmind 	while (!fp || fatp_full(fp)) {
    328  1.4.2.2  rmind 		fatp_t	*fq;
    329  1.4.2.2  rmind 
    330  1.4.2.2  rmind 		/* All entries are inuse at the top level.
    331  1.4.2.2  rmind 		 * We allocate a spare, and push the top level
    332  1.4.2.2  rmind 		 * down one.  All entries in the fp we push down
    333  1.4.2.2  rmind 		 * (think of a tape worm here) will be expelled sooner than
    334  1.4.2.2  rmind 		 * any entries added subsequently to this hash bucket.
    335  1.4.2.2  rmind 		 * This is a property of the time waits we are exploiting.
    336  1.4.2.2  rmind 		 */
    337  1.4.2.2  rmind 
    338  1.4.2.2  rmind 		fq = fatp_alloc(fat);
    339  1.4.2.2  rmind 		if (!fq) {
    340  1.4.2.2  rmind 			vtw_age(fat->vtw, 0);
    341  1.4.2.2  rmind 			fp = hash[tag & fat->mask];
    342  1.4.2.2  rmind 			continue;
    343  1.4.2.2  rmind 		}
    344  1.4.2.2  rmind 
    345  1.4.2.2  rmind 		fq->inuse = 0;
    346  1.4.2.2  rmind 		fq->nxt   = fatp_index(fat, fp);
    347  1.4.2.2  rmind 
    348  1.4.2.2  rmind 		hash[tag & fat->mask] = fq;
    349  1.4.2.2  rmind 
    350  1.4.2.2  rmind 		fp = fq;
    351  1.4.2.2  rmind 	}
    352  1.4.2.2  rmind 
    353  1.4.2.2  rmind 	KASSERT(!fatp_full(fp));
    354  1.4.2.2  rmind 
    355  1.4.2.2  rmind 	/* Fill highest index first.  Lookup is lowest first.
    356  1.4.2.2  rmind 	 */
    357  1.4.2.2  rmind 	for (i = fatp_ntags(); --i >= 0; ) {
    358  1.4.2.2  rmind 		if (!((1 << i) & fp->inuse)) {
    359  1.4.2.2  rmind 			break;
    360  1.4.2.2  rmind 		}
    361  1.4.2.2  rmind 	}
    362  1.4.2.2  rmind 
    363  1.4.2.2  rmind 	fp->inuse |= 1 << i;
    364  1.4.2.2  rmind 	fp->tag[i] = tag ^ idx_encode(fat->vtw, idx) ^ fatp_xtra[i];
    365  1.4.2.2  rmind 
    366  1.4.2.2  rmind 	db_trace(KTR_VTW
    367  1.4.2.2  rmind 		 , (fp, "fat: inuse %5.5x tag[%x] %8.8x"
    368  1.4.2.2  rmind 		    , fp->inuse
    369  1.4.2.2  rmind 		    , i, fp->tag[i]));
    370  1.4.2.2  rmind 
    371  1.4.2.2  rmind 	return fatp_key(fat, fp, i);
    372  1.4.2.2  rmind }
    373  1.4.2.2  rmind 
    374  1.4.2.2  rmind static inline int
    375  1.4.2.2  rmind vtw_alive(const vtw_t *vtw)
    376  1.4.2.2  rmind {
    377  1.4.2.2  rmind 	return vtw->hashed && vtw->expire.tv_sec;
    378  1.4.2.2  rmind }
    379  1.4.2.2  rmind 
    380  1.4.2.2  rmind static inline uint32_t
    381  1.4.2.2  rmind vtw_index_v4(vtw_ctl_t *ctl, vtw_v4_t *v4)
    382  1.4.2.2  rmind {
    383  1.4.2.2  rmind 	if (ctl->base.v4 <= v4 && v4 <= ctl->lim.v4)
    384  1.4.2.2  rmind 		return v4 - ctl->base.v4;
    385  1.4.2.2  rmind 
    386  1.4.2.2  rmind 	KASSERT(0 && "vtw out of bounds");
    387  1.4.2.2  rmind 
    388  1.4.2.2  rmind 	return ~0;
    389  1.4.2.2  rmind }
    390  1.4.2.2  rmind 
    391  1.4.2.2  rmind static inline uint32_t
    392  1.4.2.2  rmind vtw_index_v6(vtw_ctl_t *ctl, vtw_v6_t *v6)
    393  1.4.2.2  rmind {
    394  1.4.2.2  rmind 	if (ctl->base.v6 <= v6 && v6 <= ctl->lim.v6)
    395  1.4.2.2  rmind 		return v6 - ctl->base.v6;
    396  1.4.2.2  rmind 
    397  1.4.2.2  rmind 	KASSERT(0 && "vtw out of bounds");
    398  1.4.2.2  rmind 
    399  1.4.2.2  rmind 	return ~0;
    400  1.4.2.2  rmind }
    401  1.4.2.2  rmind 
    402  1.4.2.2  rmind static inline uint32_t
    403  1.4.2.2  rmind vtw_index(vtw_ctl_t *ctl, vtw_t *vtw)
    404  1.4.2.2  rmind {
    405  1.4.2.2  rmind 	if (ctl->clidx)
    406  1.4.2.2  rmind 		ctl = ctl->ctl;
    407  1.4.2.2  rmind 
    408  1.4.2.2  rmind 	if (ctl->is_v4)
    409  1.4.2.2  rmind 		return vtw_index_v4(ctl, (vtw_v4_t *)vtw);
    410  1.4.2.2  rmind 
    411  1.4.2.2  rmind 	if (ctl->is_v6)
    412  1.4.2.2  rmind 		return vtw_index_v6(ctl, (vtw_v6_t *)vtw);
    413  1.4.2.2  rmind 
    414  1.4.2.2  rmind 	KASSERT(0 && "neither 4 nor 6.  most curious.");
    415  1.4.2.2  rmind 
    416  1.4.2.2  rmind 	return ~0;
    417  1.4.2.2  rmind }
    418  1.4.2.2  rmind 
    419  1.4.2.2  rmind static inline vtw_t *
    420  1.4.2.2  rmind vtw_from_index(vtw_ctl_t *ctl, uint32_t idx)
    421  1.4.2.2  rmind {
    422  1.4.2.2  rmind 	if (ctl->clidx)
    423  1.4.2.2  rmind 		ctl = ctl->ctl;
    424  1.4.2.2  rmind 
    425  1.4.2.2  rmind 	/* See if the index looks like it might be an index.
    426  1.4.2.2  rmind 	 * Bits on outside of the valid index bits is a give away.
    427  1.4.2.2  rmind 	 */
    428  1.4.2.2  rmind 	idx = idx_decode(ctl, idx);
    429  1.4.2.2  rmind 
    430  1.4.2.2  rmind 	if (idx == ~0) {
    431  1.4.2.2  rmind 		return 0;
    432  1.4.2.2  rmind 	} else if (ctl->is_v4) {
    433  1.4.2.2  rmind 		vtw_v4_t	*vtw = ctl->base.v4 + idx;
    434  1.4.2.2  rmind 
    435  1.4.2.2  rmind 		return (ctl->base.v4 <= vtw && vtw <= ctl->lim.v4)
    436  1.4.2.2  rmind 			? &vtw->common : 0;
    437  1.4.2.2  rmind 	} else if (ctl->is_v6) {
    438  1.4.2.2  rmind 		vtw_v6_t	*vtw = ctl->base.v6 + idx;
    439  1.4.2.2  rmind 
    440  1.4.2.2  rmind 		return (ctl->base.v6 <= vtw && vtw <= ctl->lim.v6)
    441  1.4.2.2  rmind 			? &vtw->common : 0;
    442  1.4.2.2  rmind 	} else {
    443  1.4.2.2  rmind 		KASSERT(0 && "badness");
    444  1.4.2.2  rmind 		return 0;
    445  1.4.2.2  rmind 	}
    446  1.4.2.2  rmind }
    447  1.4.2.2  rmind 
    448  1.4.2.2  rmind /*!\brief return the next vtw after this one.
    449  1.4.2.2  rmind  *
    450  1.4.2.2  rmind  * Due to the differing sizes of the entries in differing
    451  1.4.2.2  rmind  * arenas, we have to ensure we ++ the correct pointer type.
    452  1.4.2.2  rmind  *
    453  1.4.2.2  rmind  * Also handles wrap.
    454  1.4.2.2  rmind  */
    455  1.4.2.2  rmind static inline vtw_t *
    456  1.4.2.2  rmind vtw_next(vtw_ctl_t *ctl, vtw_t *vtw)
    457  1.4.2.2  rmind {
    458  1.4.2.2  rmind 	if (ctl->is_v4) {
    459  1.4.2.2  rmind 		vtw_v4_t	*v4 = (void*)vtw;
    460  1.4.2.2  rmind 
    461  1.4.2.2  rmind 		vtw = &(++v4)->common;
    462  1.4.2.2  rmind 	} else {
    463  1.4.2.2  rmind 		vtw_v6_t	*v6 = (void*)vtw;
    464  1.4.2.2  rmind 
    465  1.4.2.2  rmind 		vtw = &(++v6)->common;
    466  1.4.2.2  rmind 	}
    467  1.4.2.2  rmind 
    468  1.4.2.2  rmind 	if (vtw > ctl->lim.v)
    469  1.4.2.2  rmind 		vtw = ctl->base.v;
    470  1.4.2.2  rmind 
    471  1.4.2.2  rmind 	return vtw;
    472  1.4.2.2  rmind }
    473  1.4.2.2  rmind 
    474  1.4.2.2  rmind /*!\brief	remove entry from FATP hash chains
    475  1.4.2.2  rmind  */
    476  1.4.2.2  rmind static inline void
    477  1.4.2.2  rmind vtw_unhash(vtw_ctl_t *ctl, vtw_t *vtw)
    478  1.4.2.2  rmind {
    479  1.4.2.2  rmind 	fatp_ctl_t	*fat	= ctl->fat;
    480  1.4.2.2  rmind 	fatp_t		*fp;
    481  1.4.2.2  rmind 	uint32_t	key = vtw->key;
    482  1.4.2.2  rmind 	uint32_t	tag, slot, idx;
    483  1.4.2.2  rmind 	vtw_v4_t	*v4 = (void*)vtw;
    484  1.4.2.2  rmind 	vtw_v6_t	*v6 = (void*)vtw;
    485  1.4.2.2  rmind 
    486  1.4.2.2  rmind 	if (!vtw->hashed) {
    487  1.4.2.2  rmind 		KASSERT(0 && "unhashed");
    488  1.4.2.2  rmind 		return;
    489  1.4.2.2  rmind 	}
    490  1.4.2.2  rmind 
    491  1.4.2.2  rmind 	if (fat->vtw->is_v4) {
    492  1.4.2.2  rmind 		tag = v4_tag(v4->faddr, v4->fport, v4->laddr, v4->lport);
    493  1.4.2.2  rmind 	} else if (fat->vtw->is_v6) {
    494  1.4.2.2  rmind 		tag = v6_tag(&v6->faddr, v6->fport, &v6->laddr, v6->lport);
    495  1.4.2.2  rmind 	} else {
    496  1.4.2.2  rmind 		tag = 0;
    497  1.4.2.2  rmind 		KASSERT(0 && "not reached");
    498  1.4.2.2  rmind 	}
    499  1.4.2.2  rmind 
    500  1.4.2.2  rmind 	/* Remove from fat->hash[]
    501  1.4.2.2  rmind 	 */
    502  1.4.2.2  rmind 	slot = fatp_slot_from_key(fat, key);
    503  1.4.2.2  rmind 	fp   = fatp_from_key(fat, key);
    504  1.4.2.2  rmind 	idx  = vtw_index(ctl, vtw);
    505  1.4.2.2  rmind 
    506  1.4.2.2  rmind 	db_trace(KTR_VTW
    507  1.4.2.2  rmind 		 , (fp, "fat: del inuse %5.5x slot %x idx %x key %x tag %x"
    508  1.4.2.2  rmind 		    , fp->inuse, slot, idx, key, tag));
    509  1.4.2.2  rmind 
    510  1.4.2.2  rmind 	KASSERT(fp->inuse & (1 << slot));
    511  1.4.2.2  rmind 	KASSERT(fp->tag[slot] == (tag ^ idx_encode(ctl, idx)
    512  1.4.2.2  rmind 				  ^ fatp_xtra[slot]));
    513  1.4.2.2  rmind 
    514  1.4.2.2  rmind 	if ((fp->inuse & (1 << slot))
    515  1.4.2.2  rmind 	    && fp->tag[slot] == (tag ^ idx_encode(ctl, idx)
    516  1.4.2.2  rmind 				 ^ fatp_xtra[slot])) {
    517  1.4.2.2  rmind 		fp->inuse ^= 1 << slot;
    518  1.4.2.2  rmind 		fp->tag[slot] = 0;
    519  1.4.2.2  rmind 
    520  1.4.2.2  rmind 		/* When we delete entries, we do not compact.  This is
    521  1.4.2.2  rmind 		 * due to temporality.  We add entries, and they
    522  1.4.2.2  rmind 		 * (eventually) expire. Older entries will be further
    523  1.4.2.2  rmind 		 * down the chain.
    524  1.4.2.2  rmind 		 */
    525  1.4.2.2  rmind 		if (!fp->inuse) {
    526  1.4.2.2  rmind 			uint32_t hi = tag & fat->mask;
    527  1.4.2.2  rmind 			fatp_t	*fq = 0;
    528  1.4.2.2  rmind 			fatp_t	*fr = fat->hash[hi];
    529  1.4.2.2  rmind 
    530  1.4.2.2  rmind 			while (fr && fr != fp) {
    531  1.4.2.2  rmind 				fr = fatp_next(fat, fq = fr);
    532  1.4.2.2  rmind 			}
    533  1.4.2.2  rmind 
    534  1.4.2.2  rmind 			if (fr == fp) {
    535  1.4.2.2  rmind 				if (fq) {
    536  1.4.2.2  rmind 					fq->nxt = fp->nxt;
    537  1.4.2.2  rmind 					fp->nxt = 0;
    538  1.4.2.2  rmind 					fatp_free(fat, fp);
    539  1.4.2.2  rmind 				} else {
    540  1.4.2.2  rmind 					KASSERT(fat->hash[hi] == fp);
    541  1.4.2.2  rmind 
    542  1.4.2.2  rmind 					if (fp->nxt) {
    543  1.4.2.2  rmind 						fat->hash[hi]
    544  1.4.2.2  rmind 							= fatp_next(fat, fp);
    545  1.4.2.2  rmind 						fp->nxt = 0;
    546  1.4.2.2  rmind 						fatp_free(fat, fp);
    547  1.4.2.2  rmind 					} else {
    548  1.4.2.2  rmind 						/* retain for next use.
    549  1.4.2.2  rmind 						 */
    550  1.4.2.2  rmind 						;
    551  1.4.2.2  rmind 					}
    552  1.4.2.2  rmind 				}
    553  1.4.2.2  rmind 			} else {
    554  1.4.2.2  rmind 				fr = fat->hash[hi];
    555  1.4.2.2  rmind 
    556  1.4.2.2  rmind 				do {
    557  1.4.2.2  rmind 					db_trace(KTR_VTW
    558  1.4.2.2  rmind 						 , (fr
    559  1.4.2.2  rmind 						    , "fat:*del inuse %5.5x"
    560  1.4.2.2  rmind 						    " nxt %x"
    561  1.4.2.2  rmind 						    , fr->inuse, fr->nxt));
    562  1.4.2.2  rmind 
    563  1.4.2.2  rmind 					fr = fatp_next(fat, fq = fr);
    564  1.4.2.2  rmind 				} while (fr && fr != fp);
    565  1.4.2.2  rmind 
    566  1.4.2.2  rmind 				KASSERT(0 && "oops");
    567  1.4.2.2  rmind 			}
    568  1.4.2.2  rmind 		}
    569  1.4.2.2  rmind 		vtw->key ^= ~0;
    570  1.4.2.2  rmind 	}
    571  1.4.2.2  rmind 
    572  1.4.2.2  rmind 	if (fat->vtw->is_v4) {
    573  1.4.2.2  rmind 		tag = v4_port_tag(v4->lport);
    574  1.4.2.2  rmind 	} else if (fat->vtw->is_v6) {
    575  1.4.2.2  rmind 		tag = v6_port_tag(v6->lport);
    576  1.4.2.2  rmind 	}
    577  1.4.2.2  rmind 
    578  1.4.2.2  rmind 	/* Remove from fat->port[]
    579  1.4.2.2  rmind 	 */
    580  1.4.2.2  rmind 	key  = vtw->port_key;
    581  1.4.2.2  rmind 	slot = fatp_slot_from_key(fat, key);
    582  1.4.2.2  rmind 	fp   = fatp_from_key(fat, key);
    583  1.4.2.2  rmind 	idx  = vtw_index(ctl, vtw);
    584  1.4.2.2  rmind 
    585  1.4.2.2  rmind 	db_trace(KTR_VTW
    586  1.4.2.2  rmind 		 , (fp, "fatport: del inuse %5.5x"
    587  1.4.2.2  rmind 		    " slot %x idx %x key %x tag %x"
    588  1.4.2.2  rmind 		    , fp->inuse, slot, idx, key, tag));
    589  1.4.2.2  rmind 
    590  1.4.2.2  rmind 	KASSERT(fp->inuse & (1 << slot));
    591  1.4.2.2  rmind 	KASSERT(fp->tag[slot] == (tag ^ idx_encode(ctl, idx)
    592  1.4.2.2  rmind 				  ^ fatp_xtra[slot]));
    593  1.4.2.2  rmind 
    594  1.4.2.2  rmind 	if ((fp->inuse & (1 << slot))
    595  1.4.2.2  rmind 	    && fp->tag[slot] == (tag ^ idx_encode(ctl, idx)
    596  1.4.2.2  rmind 				 ^ fatp_xtra[slot])) {
    597  1.4.2.2  rmind 		fp->inuse ^= 1 << slot;
    598  1.4.2.2  rmind 		fp->tag[slot] = 0;
    599  1.4.2.2  rmind 
    600  1.4.2.2  rmind 		if (!fp->inuse) {
    601  1.4.2.2  rmind 			uint32_t hi = tag & fat->mask;
    602  1.4.2.2  rmind 			fatp_t	*fq = 0;
    603  1.4.2.2  rmind 			fatp_t	*fr = fat->port[hi];
    604  1.4.2.2  rmind 
    605  1.4.2.2  rmind 			while (fr && fr != fp) {
    606  1.4.2.2  rmind 				fr = fatp_next(fat, fq = fr);
    607  1.4.2.2  rmind 			}
    608  1.4.2.2  rmind 
    609  1.4.2.2  rmind 			if (fr == fp) {
    610  1.4.2.2  rmind 				if (fq) {
    611  1.4.2.2  rmind 					fq->nxt = fp->nxt;
    612  1.4.2.2  rmind 					fp->nxt = 0;
    613  1.4.2.2  rmind 					fatp_free(fat, fp);
    614  1.4.2.2  rmind 				} else {
    615  1.4.2.2  rmind 					KASSERT(fat->port[hi] == fp);
    616  1.4.2.2  rmind 
    617  1.4.2.2  rmind 					if (fp->nxt) {
    618  1.4.2.2  rmind 						fat->port[hi]
    619  1.4.2.2  rmind 							= fatp_next(fat, fp);
    620  1.4.2.2  rmind 						fp->nxt = 0;
    621  1.4.2.2  rmind 						fatp_free(fat, fp);
    622  1.4.2.2  rmind 					} else {
    623  1.4.2.2  rmind 						/* retain for next use.
    624  1.4.2.2  rmind 						 */
    625  1.4.2.2  rmind 						;
    626  1.4.2.2  rmind 					}
    627  1.4.2.2  rmind 				}
    628  1.4.2.2  rmind 			}
    629  1.4.2.2  rmind 		}
    630  1.4.2.2  rmind 		vtw->port_key ^= ~0;
    631  1.4.2.2  rmind 	}
    632  1.4.2.2  rmind 
    633  1.4.2.2  rmind 	vtw->hashed = 0;
    634  1.4.2.2  rmind }
    635  1.4.2.2  rmind 
    636  1.4.2.2  rmind /*!\brief	remove entry from hash, possibly free.
    637  1.4.2.2  rmind  */
    638  1.4.2.2  rmind void
    639  1.4.2.2  rmind vtw_del(vtw_ctl_t *ctl, vtw_t *vtw)
    640  1.4.2.2  rmind {
    641  1.4.2.2  rmind 	KASSERT(mutex_owned(softnet_lock));
    642  1.4.2.2  rmind 
    643  1.4.2.2  rmind 	if (vtw->hashed) {
    644  1.4.2.2  rmind 		++vtw_stats.del;
    645  1.4.2.2  rmind 		vtw_unhash(ctl, vtw);
    646  1.4.2.2  rmind 	}
    647  1.4.2.2  rmind 
    648  1.4.2.2  rmind 	/* We only delete the oldest entry.
    649  1.4.2.2  rmind 	 */
    650  1.4.2.2  rmind 	if (vtw != ctl->oldest.v)
    651  1.4.2.2  rmind 		return;
    652  1.4.2.2  rmind 
    653  1.4.2.2  rmind 	--ctl->nalloc;
    654  1.4.2.2  rmind 	++ctl->nfree;
    655  1.4.2.2  rmind 
    656  1.4.2.2  rmind 	vtw->expire.tv_sec  = 0;
    657  1.4.2.2  rmind 	vtw->expire.tv_usec = ~0;
    658  1.4.2.2  rmind 
    659  1.4.2.2  rmind 	if (!ctl->nalloc)
    660  1.4.2.2  rmind 		ctl->oldest.v = 0;
    661  1.4.2.2  rmind 
    662  1.4.2.2  rmind 	ctl->oldest.v = vtw_next(ctl, vtw);
    663  1.4.2.2  rmind }
    664  1.4.2.2  rmind 
    665  1.4.2.2  rmind /*!\brief	insert vestigial timewait in hash chain
    666  1.4.2.2  rmind  */
    667  1.4.2.2  rmind static void
    668  1.4.2.2  rmind vtw_inshash_v4(vtw_ctl_t *ctl, vtw_t *vtw)
    669  1.4.2.2  rmind {
    670  1.4.2.2  rmind 	uint32_t	idx	= vtw_index(ctl, vtw);
    671  1.4.2.2  rmind 	uint32_t	tag;
    672  1.4.2.2  rmind 	vtw_v4_t	*v4 = (void*)vtw;
    673  1.4.2.2  rmind 
    674  1.4.2.2  rmind 	KASSERT(mutex_owned(softnet_lock));
    675  1.4.2.2  rmind 	KASSERT(!vtw->hashed);
    676  1.4.2.2  rmind 	KASSERT(ctl->clidx == vtw->msl_class);
    677  1.4.2.2  rmind 
    678  1.4.2.2  rmind 	++vtw_stats.ins;
    679  1.4.2.2  rmind 
    680  1.4.2.2  rmind 	tag = v4_tag(v4->faddr, v4->fport,
    681  1.4.2.2  rmind 		     v4->laddr, v4->lport);
    682  1.4.2.2  rmind 
    683  1.4.2.2  rmind 	vtw->key = fatp_vtw_inshash(ctl->fat, idx, tag, 0, vtw);
    684  1.4.2.2  rmind 
    685  1.4.2.2  rmind 	db_trace(KTR_VTW, (ctl
    686  1.4.2.2  rmind 			   , "vtw: ins %8.8x:%4.4x %8.8x:%4.4x"
    687  1.4.2.2  rmind 			   " tag %8.8x key %8.8x"
    688  1.4.2.2  rmind 			   , v4->faddr, v4->fport
    689  1.4.2.2  rmind 			   , v4->laddr, v4->lport
    690  1.4.2.2  rmind 			   , tag
    691  1.4.2.2  rmind 			   , vtw->key));
    692  1.4.2.2  rmind 
    693  1.4.2.2  rmind 	tag = v4_port_tag(v4->lport);
    694  1.4.2.2  rmind 	vtw->port_key = fatp_vtw_inshash(ctl->fat, idx, tag, 1, vtw);
    695  1.4.2.2  rmind 
    696  1.4.2.2  rmind 	db_trace(KTR_VTW, (ctl, "vtw: ins %P - %4.4x tag %8.8x key %8.8x"
    697  1.4.2.2  rmind 			   , v4->lport, v4->lport
    698  1.4.2.2  rmind 			   , tag
    699  1.4.2.2  rmind 			   , vtw->key));
    700  1.4.2.2  rmind 
    701  1.4.2.2  rmind 	vtw->hashed = 1;
    702  1.4.2.2  rmind }
    703  1.4.2.2  rmind 
    704  1.4.2.2  rmind /*!\brief	insert vestigial timewait in hash chain
    705  1.4.2.2  rmind  */
    706  1.4.2.2  rmind static void
    707  1.4.2.2  rmind vtw_inshash_v6(vtw_ctl_t *ctl, vtw_t *vtw)
    708  1.4.2.2  rmind {
    709  1.4.2.2  rmind 	uint32_t	idx	= vtw_index(ctl, vtw);
    710  1.4.2.2  rmind 	uint32_t	tag;
    711  1.4.2.2  rmind 	vtw_v6_t	*v6	= (void*)vtw;
    712  1.4.2.2  rmind 
    713  1.4.2.2  rmind 	KASSERT(mutex_owned(softnet_lock));
    714  1.4.2.2  rmind 	KASSERT(!vtw->hashed);
    715  1.4.2.2  rmind 	KASSERT(ctl->clidx == vtw->msl_class);
    716  1.4.2.2  rmind 
    717  1.4.2.2  rmind 	++vtw_stats.ins;
    718  1.4.2.2  rmind 
    719  1.4.2.2  rmind 	tag = v6_tag(&v6->faddr, v6->fport,
    720  1.4.2.2  rmind 		     &v6->laddr, v6->lport);
    721  1.4.2.2  rmind 
    722  1.4.2.2  rmind 	vtw->key = fatp_vtw_inshash(ctl->fat, idx, tag, 0, vtw);
    723  1.4.2.2  rmind 
    724  1.4.2.2  rmind 	tag = v6_port_tag(v6->lport);
    725  1.4.2.2  rmind 	vtw->port_key = fatp_vtw_inshash(ctl->fat, idx, tag, 1, vtw);
    726  1.4.2.2  rmind 
    727  1.4.2.2  rmind 	db_trace(KTR_VTW, (ctl, "vtw: ins %P - %4.4x tag %8.8x key %8.8x"
    728  1.4.2.2  rmind 			   , v6->lport, v6->lport
    729  1.4.2.2  rmind 			   , tag
    730  1.4.2.2  rmind 			   , vtw->key));
    731  1.4.2.2  rmind 
    732  1.4.2.2  rmind 	vtw->hashed = 1;
    733  1.4.2.2  rmind }
    734  1.4.2.2  rmind 
    735  1.4.2.2  rmind static vtw_t *
    736  1.4.2.2  rmind vtw_lookup_hash_v4(vtw_ctl_t *ctl, uint32_t faddr, uint16_t fport
    737  1.4.2.2  rmind 				 , uint32_t laddr, uint16_t lport
    738  1.4.2.2  rmind 				 , int which)
    739  1.4.2.2  rmind {
    740  1.4.2.2  rmind 	vtw_v4_t	*v4;
    741  1.4.2.2  rmind 	vtw_t		*vtw;
    742  1.4.2.2  rmind 	uint32_t	tag;
    743  1.4.2.2  rmind 	fatp_t		*fp;
    744  1.4.2.2  rmind 	int		i;
    745  1.4.2.2  rmind 	uint32_t	fatps = 0, probes = 0, losings = 0;
    746  1.4.2.2  rmind 
    747  1.4.2.2  rmind 	if (!ctl || !ctl->fat)
    748  1.4.2.2  rmind 		return 0;
    749  1.4.2.2  rmind 
    750  1.4.2.2  rmind 	++vtw_stats.look[which];
    751  1.4.2.2  rmind 
    752  1.4.2.2  rmind 	if (which) {
    753  1.4.2.2  rmind 		tag = v4_port_tag(lport);
    754  1.4.2.2  rmind 		fp  = ctl->fat->port[tag & ctl->fat->mask];
    755  1.4.2.2  rmind 	} else {
    756  1.4.2.2  rmind 		tag = v4_tag(faddr, fport, laddr, lport);
    757  1.4.2.2  rmind 		fp  = ctl->fat->hash[tag & ctl->fat->mask];
    758  1.4.2.2  rmind 	}
    759  1.4.2.2  rmind 
    760  1.4.2.2  rmind 	while (fp && fp->inuse) {
    761  1.4.2.2  rmind 		uint32_t	inuse = fp->inuse;
    762  1.4.2.2  rmind 
    763  1.4.2.2  rmind 		++fatps;
    764  1.4.2.2  rmind 
    765  1.4.2.2  rmind 		for (i = 0; inuse && i < fatp_ntags(); ++i) {
    766  1.4.2.2  rmind 			uint32_t	idx;
    767  1.4.2.2  rmind 
    768  1.4.2.2  rmind 			if (!(inuse & (1 << i)))
    769  1.4.2.2  rmind 				continue;
    770  1.4.2.2  rmind 
    771  1.4.2.2  rmind 			inuse ^= 1 << i;
    772  1.4.2.2  rmind 
    773  1.4.2.2  rmind 			++probes;
    774  1.4.2.2  rmind 			++vtw_stats.probe[which];
    775  1.4.2.2  rmind 
    776  1.4.2.2  rmind 			idx = fp->tag[i] ^ tag ^ fatp_xtra[i];
    777  1.4.2.2  rmind 			vtw = vtw_from_index(ctl, idx);
    778  1.4.2.2  rmind 
    779  1.4.2.2  rmind 			if (!vtw) {
    780  1.4.2.2  rmind 				/* Hopefully fast path.
    781  1.4.2.2  rmind 				 */
    782  1.4.2.2  rmind 				db_trace(KTR_VTW
    783  1.4.2.2  rmind 					 , (fp, "vtw: fast %A:%P %A:%P"
    784  1.4.2.2  rmind 					    " idx %x tag %x"
    785  1.4.2.2  rmind 					    , faddr, fport
    786  1.4.2.2  rmind 					    , laddr, lport
    787  1.4.2.2  rmind 					    , idx, tag));
    788  1.4.2.2  rmind 				continue;
    789  1.4.2.2  rmind 			}
    790  1.4.2.2  rmind 
    791  1.4.2.2  rmind 			v4 = (void*)vtw;
    792  1.4.2.2  rmind 
    793  1.4.2.2  rmind 			/* The de-referencing of vtw is what we want to avoid.
    794  1.4.2.2  rmind 			 * Losing.
    795  1.4.2.2  rmind 			 */
    796  1.4.2.2  rmind 			if (vtw_alive(vtw)
    797  1.4.2.2  rmind 			    && ((which ? vtw->port_key : vtw->key)
    798  1.4.2.2  rmind 				== fatp_key(ctl->fat, fp, i))
    799  1.4.2.2  rmind 			    && (which
    800  1.4.2.2  rmind 				|| (v4->faddr == faddr && v4->laddr == laddr
    801  1.4.2.2  rmind 				    && v4->fport == fport))
    802  1.4.2.2  rmind 			    && v4->lport == lport) {
    803  1.4.2.2  rmind 				++vtw_stats.hit[which];
    804  1.4.2.2  rmind 
    805  1.4.2.2  rmind 				db_trace(KTR_VTW
    806  1.4.2.2  rmind 					 , (fp, "vtw: hit %8.8x:%4.4x"
    807  1.4.2.2  rmind 					    " %8.8x:%4.4x idx %x key %x"
    808  1.4.2.2  rmind 					    , faddr, fport
    809  1.4.2.2  rmind 					    , laddr, lport
    810  1.4.2.2  rmind 					    , idx_decode(ctl, idx), vtw->key));
    811  1.4.2.2  rmind 
    812  1.4.2.2  rmind 				KASSERT(vtw->hashed);
    813  1.4.2.2  rmind 
    814  1.4.2.2  rmind 				goto out;
    815  1.4.2.2  rmind 			}
    816  1.4.2.2  rmind 			++vtw_stats.losing[which];
    817  1.4.2.2  rmind 			++losings;
    818  1.4.2.2  rmind 
    819  1.4.2.2  rmind 			if (vtw_alive(vtw)) {
    820  1.4.2.2  rmind 				db_trace(KTR_VTW
    821  1.4.2.2  rmind 					 , (fp, "vtw:!mis %8.8x:%4.4x"
    822  1.4.2.2  rmind 					    " %8.8x:%4.4x key %x tag %x"
    823  1.4.2.2  rmind 					    , faddr, fport
    824  1.4.2.2  rmind 					    , laddr, lport
    825  1.4.2.2  rmind 					    , fatp_key(ctl->fat, fp, i)
    826  1.4.2.2  rmind 					    , v4_tag(faddr, fport
    827  1.4.2.2  rmind 						     , laddr, lport)));
    828  1.4.2.2  rmind 				db_trace(KTR_VTW
    829  1.4.2.2  rmind 					 , (vtw, "vtw:!mis %8.8x:%4.4x"
    830  1.4.2.2  rmind 					    " %8.8x:%4.4x key %x tag %x"
    831  1.4.2.2  rmind 					    , v4->faddr, v4->fport
    832  1.4.2.2  rmind 					    , v4->laddr, v4->lport
    833  1.4.2.2  rmind 					    , vtw->key
    834  1.4.2.2  rmind 					    , v4_tag(v4->faddr, v4->fport
    835  1.4.2.2  rmind 						     , v4->laddr, v4->lport)));
    836  1.4.2.2  rmind 
    837  1.4.2.2  rmind 				if (vtw->key == fatp_key(ctl->fat, fp, i)) {
    838  1.4.2.2  rmind 					db_trace(KTR_VTW
    839  1.4.2.2  rmind 						 , (vtw, "vtw:!mis %8.8x:%4.4x"
    840  1.4.2.2  rmind 						    " %8.8x:%4.4x key %x"
    841  1.4.2.2  rmind 						    " which %x"
    842  1.4.2.2  rmind 						    , v4->faddr, v4->fport
    843  1.4.2.2  rmind 						    , v4->laddr, v4->lport
    844  1.4.2.2  rmind 						    , vtw->key
    845  1.4.2.2  rmind 						    , which));
    846  1.4.2.2  rmind 
    847  1.4.2.2  rmind 				} else {
    848  1.4.2.2  rmind 					db_trace(KTR_VTW
    849  1.4.2.2  rmind 						 , (vtw
    850  1.4.2.2  rmind 						    , "vtw:!mis"
    851  1.4.2.2  rmind 						    " key %8.8x != %8.8x"
    852  1.4.2.2  rmind 						    " idx %x i %x which %x"
    853  1.4.2.2  rmind 						    , vtw->key
    854  1.4.2.2  rmind 						    , fatp_key(ctl->fat, fp, i)
    855  1.4.2.2  rmind 						    , idx_decode(ctl, idx)
    856  1.4.2.2  rmind 						    , i
    857  1.4.2.2  rmind 						    , which));
    858  1.4.2.2  rmind 				}
    859  1.4.2.2  rmind 			} else {
    860  1.4.2.2  rmind 				db_trace(KTR_VTW
    861  1.4.2.2  rmind 					 , (fp
    862  1.4.2.2  rmind 					    , "vtw:!mis free entry"
    863  1.4.2.2  rmind 					    " idx %x vtw %p which %x"
    864  1.4.2.2  rmind 					    , idx_decode(ctl, idx)
    865  1.4.2.2  rmind 					    , vtw, which));
    866  1.4.2.2  rmind 			}
    867  1.4.2.2  rmind 		}
    868  1.4.2.2  rmind 
    869  1.4.2.2  rmind 		if (fp->nxt) {
    870  1.4.2.2  rmind 			fp = fatp_next(ctl->fat, fp);
    871  1.4.2.2  rmind 		} else {
    872  1.4.2.2  rmind 			break;
    873  1.4.2.2  rmind 		}
    874  1.4.2.2  rmind 	}
    875  1.4.2.2  rmind 	++vtw_stats.miss[which];
    876  1.4.2.2  rmind 	vtw = 0;
    877  1.4.2.2  rmind out:
    878  1.4.2.2  rmind 	if (fatps > vtw_stats.max_chain[which])
    879  1.4.2.2  rmind 		vtw_stats.max_chain[which] = fatps;
    880  1.4.2.2  rmind 	if (probes > vtw_stats.max_probe[which])
    881  1.4.2.2  rmind 		vtw_stats.max_probe[which] = probes;
    882  1.4.2.2  rmind 	if (losings > vtw_stats.max_loss[which])
    883  1.4.2.2  rmind 		vtw_stats.max_loss[which] = losings;
    884  1.4.2.2  rmind 
    885  1.4.2.2  rmind 	return vtw;
    886  1.4.2.2  rmind }
    887  1.4.2.2  rmind 
    888  1.4.2.2  rmind static vtw_t *
    889  1.4.2.2  rmind vtw_lookup_hash_v6(vtw_ctl_t *ctl, const struct in6_addr *faddr, uint16_t fport
    890  1.4.2.2  rmind 				 , const struct in6_addr *laddr, uint16_t lport
    891  1.4.2.2  rmind 				 , int which)
    892  1.4.2.2  rmind {
    893  1.4.2.2  rmind 	vtw_v6_t	*v6;
    894  1.4.2.2  rmind 	vtw_t		*vtw;
    895  1.4.2.2  rmind 	uint32_t	tag;
    896  1.4.2.2  rmind 	fatp_t		*fp;
    897  1.4.2.2  rmind 	int		i;
    898  1.4.2.2  rmind 	uint32_t	fatps = 0, probes = 0, losings = 0;
    899  1.4.2.2  rmind 
    900  1.4.2.2  rmind 	++vtw_stats.look[which];
    901  1.4.2.2  rmind 
    902  1.4.2.2  rmind 	if (!ctl || !ctl->fat)
    903  1.4.2.2  rmind 		return 0;
    904  1.4.2.2  rmind 
    905  1.4.2.2  rmind 	if (which) {
    906  1.4.2.2  rmind 		tag = v6_port_tag(lport);
    907  1.4.2.2  rmind 		fp  = ctl->fat->port[tag & ctl->fat->mask];
    908  1.4.2.2  rmind 	} else {
    909  1.4.2.2  rmind 		tag = v6_tag(faddr, fport, laddr, lport);
    910  1.4.2.2  rmind 		fp  = ctl->fat->hash[tag & ctl->fat->mask];
    911  1.4.2.2  rmind 	}
    912  1.4.2.2  rmind 
    913  1.4.2.2  rmind 	while (fp && fp->inuse) {
    914  1.4.2.2  rmind 		uint32_t	inuse = fp->inuse;
    915  1.4.2.2  rmind 
    916  1.4.2.2  rmind 		++fatps;
    917  1.4.2.2  rmind 
    918  1.4.2.2  rmind 		for (i = 0; inuse && i < fatp_ntags(); ++i) {
    919  1.4.2.2  rmind 			uint32_t	idx;
    920  1.4.2.2  rmind 
    921  1.4.2.2  rmind 			if (!(inuse & (1 << i)))
    922  1.4.2.2  rmind 				continue;
    923  1.4.2.2  rmind 
    924  1.4.2.2  rmind 			inuse ^= 1 << i;
    925  1.4.2.2  rmind 
    926  1.4.2.2  rmind 			++probes;
    927  1.4.2.2  rmind 			++vtw_stats.probe[which];
    928  1.4.2.2  rmind 
    929  1.4.2.2  rmind 			idx = fp->tag[i] ^ tag ^ fatp_xtra[i];
    930  1.4.2.2  rmind 			vtw = vtw_from_index(ctl, idx);
    931  1.4.2.2  rmind 
    932  1.4.2.2  rmind 			db_trace(KTR_VTW
    933  1.4.2.2  rmind 				 , (fp, "probe: %2d %6A:%4.4x %6A:%4.4x idx %x"
    934  1.4.2.2  rmind 				    , i
    935  1.4.2.2  rmind 				    , db_store(faddr, sizeof (*faddr)), fport
    936  1.4.2.2  rmind 				    , db_store(laddr, sizeof (*laddr)), lport
    937  1.4.2.2  rmind 				    , idx_decode(ctl, idx)));
    938  1.4.2.2  rmind 
    939  1.4.2.2  rmind 			if (!vtw) {
    940  1.4.2.2  rmind 				/* Hopefully fast path.
    941  1.4.2.2  rmind 				 */
    942  1.4.2.2  rmind 				continue;
    943  1.4.2.2  rmind 			}
    944  1.4.2.2  rmind 
    945  1.4.2.2  rmind 			v6 = (void*)vtw;
    946  1.4.2.2  rmind 
    947  1.4.2.2  rmind 			if (vtw_alive(vtw)
    948  1.4.2.2  rmind 			    && ((which ? vtw->port_key : vtw->key)
    949  1.4.2.2  rmind 				== fatp_key(ctl->fat, fp, i))
    950  1.4.2.2  rmind 			    && v6->lport == lport
    951  1.4.2.2  rmind 			    && (which
    952  1.4.2.2  rmind 				|| (v6->fport == fport
    953  1.4.2.2  rmind 				    && !bcmp(&v6->faddr, faddr, sizeof (*faddr))
    954  1.4.2.2  rmind 				    && !bcmp(&v6->laddr, laddr
    955  1.4.2.2  rmind 					     , sizeof (*laddr))))) {
    956  1.4.2.2  rmind 				++vtw_stats.hit[which];
    957  1.4.2.2  rmind 
    958  1.4.2.2  rmind 				KASSERT(vtw->hashed);
    959  1.4.2.2  rmind 				goto out;
    960  1.4.2.2  rmind 			} else {
    961  1.4.2.2  rmind 				++vtw_stats.losing[which];
    962  1.4.2.2  rmind 				++losings;
    963  1.4.2.2  rmind 			}
    964  1.4.2.2  rmind 		}
    965  1.4.2.2  rmind 
    966  1.4.2.2  rmind 		if (fp->nxt) {
    967  1.4.2.2  rmind 			fp = fatp_next(ctl->fat, fp);
    968  1.4.2.2  rmind 		} else {
    969  1.4.2.2  rmind 			break;
    970  1.4.2.2  rmind 		}
    971  1.4.2.2  rmind 	}
    972  1.4.2.2  rmind 	++vtw_stats.miss[which];
    973  1.4.2.2  rmind 	vtw = 0;
    974  1.4.2.2  rmind out:
    975  1.4.2.2  rmind 	if (fatps > vtw_stats.max_chain[which])
    976  1.4.2.2  rmind 		vtw_stats.max_chain[which] = fatps;
    977  1.4.2.2  rmind 	if (probes > vtw_stats.max_probe[which])
    978  1.4.2.2  rmind 		vtw_stats.max_probe[which] = probes;
    979  1.4.2.2  rmind 	if (losings > vtw_stats.max_loss[which])
    980  1.4.2.2  rmind 		vtw_stats.max_loss[which] = losings;
    981  1.4.2.2  rmind 
    982  1.4.2.2  rmind 	return vtw;
    983  1.4.2.2  rmind }
    984  1.4.2.2  rmind 
    985  1.4.2.2  rmind /*!\brief port iterator
    986  1.4.2.2  rmind  */
    987  1.4.2.2  rmind static vtw_t *
    988  1.4.2.2  rmind vtw_next_port_v4(struct tcp_ports_iterator *it)
    989  1.4.2.2  rmind {
    990  1.4.2.2  rmind 	vtw_ctl_t	*ctl = it->ctl;
    991  1.4.2.2  rmind 	vtw_v4_t	*v4;
    992  1.4.2.2  rmind 	vtw_t		*vtw;
    993  1.4.2.2  rmind 	uint32_t	tag;
    994  1.4.2.2  rmind 	uint16_t	lport = it->port;
    995  1.4.2.2  rmind 	fatp_t		*fp;
    996  1.4.2.2  rmind 	int		i;
    997  1.4.2.2  rmind 	uint32_t	fatps = 0, probes = 0, losings = 0;
    998  1.4.2.2  rmind 
    999  1.4.2.2  rmind 	tag = v4_port_tag(lport);
   1000  1.4.2.2  rmind 	if (!it->fp) {
   1001  1.4.2.2  rmind 		it->fp = ctl->fat->port[tag & ctl->fat->mask];
   1002  1.4.2.2  rmind 		it->slot_idx = 0;
   1003  1.4.2.2  rmind 	}
   1004  1.4.2.2  rmind 	fp  = it->fp;
   1005  1.4.2.2  rmind 
   1006  1.4.2.2  rmind 	while (fp) {
   1007  1.4.2.2  rmind 		uint32_t	inuse = fp->inuse;
   1008  1.4.2.2  rmind 
   1009  1.4.2.2  rmind 		++fatps;
   1010  1.4.2.2  rmind 
   1011  1.4.2.2  rmind 		for (i = it->slot_idx; inuse && i < fatp_ntags(); ++i) {
   1012  1.4.2.2  rmind 			uint32_t	idx;
   1013  1.4.2.2  rmind 
   1014  1.4.2.2  rmind 			if (!(inuse & (1 << i)))
   1015  1.4.2.2  rmind 				continue;
   1016  1.4.2.2  rmind 
   1017  1.4.2.2  rmind 			inuse &= ~0 << i;
   1018  1.4.2.2  rmind 
   1019  1.4.2.2  rmind 			if (i < it->slot_idx)
   1020  1.4.2.2  rmind 				continue;
   1021  1.4.2.2  rmind 
   1022  1.4.2.2  rmind 			++vtw_stats.probe[1];
   1023  1.4.2.2  rmind 			++probes;
   1024  1.4.2.2  rmind 
   1025  1.4.2.2  rmind 			idx = fp->tag[i] ^ tag ^ fatp_xtra[i];
   1026  1.4.2.2  rmind 			vtw = vtw_from_index(ctl, idx);
   1027  1.4.2.2  rmind 
   1028  1.4.2.2  rmind 			if (!vtw) {
   1029  1.4.2.2  rmind 				/* Hopefully fast path.
   1030  1.4.2.2  rmind 				 */
   1031  1.4.2.2  rmind 				continue;
   1032  1.4.2.2  rmind 			}
   1033  1.4.2.2  rmind 
   1034  1.4.2.2  rmind 			v4 = (void*)vtw;
   1035  1.4.2.2  rmind 
   1036  1.4.2.2  rmind 			if (vtw_alive(vtw)
   1037  1.4.2.2  rmind 			    && vtw->port_key == fatp_key(ctl->fat, fp, i)
   1038  1.4.2.2  rmind 			    && v4->lport == lport) {
   1039  1.4.2.2  rmind 				++vtw_stats.hit[1];
   1040  1.4.2.2  rmind 
   1041  1.4.2.2  rmind 				it->slot_idx = i + 1;
   1042  1.4.2.2  rmind 
   1043  1.4.2.2  rmind 				goto out;
   1044  1.4.2.2  rmind 			} else if (vtw_alive(vtw)) {
   1045  1.4.2.2  rmind 				++vtw_stats.losing[1];
   1046  1.4.2.2  rmind 				++losings;
   1047  1.4.2.2  rmind 
   1048  1.4.2.2  rmind 				db_trace(KTR_VTW
   1049  1.4.2.2  rmind 					 , (vtw, "vtw:!mis"
   1050  1.4.2.2  rmind 					    " port %8.8x:%4.4x %8.8x:%4.4x"
   1051  1.4.2.2  rmind 					    " key %x port %x"
   1052  1.4.2.2  rmind 					    , v4->faddr, v4->fport
   1053  1.4.2.2  rmind 					    , v4->laddr, v4->lport
   1054  1.4.2.2  rmind 					    , vtw->key
   1055  1.4.2.2  rmind 					    , lport));
   1056  1.4.2.2  rmind 			} else {
   1057  1.4.2.2  rmind 				/* Really losing here.  We are coming
   1058  1.4.2.2  rmind 				 * up with references to free entries.
   1059  1.4.2.2  rmind 				 * Might find it better to use
   1060  1.4.2.2  rmind 				 * traditional, or need another
   1061  1.4.2.2  rmind 				 * add-hockery.  The other add-hockery
   1062  1.4.2.2  rmind 				 * would be to pul more into into the
   1063  1.4.2.2  rmind 				 * cache line to reject the false
   1064  1.4.2.2  rmind 				 * hits.
   1065  1.4.2.2  rmind 				 */
   1066  1.4.2.2  rmind 				++vtw_stats.losing[1];
   1067  1.4.2.2  rmind 				++losings;
   1068  1.4.2.2  rmind 				db_trace(KTR_VTW
   1069  1.4.2.2  rmind 					 , (fp, "vtw:!mis port %x"
   1070  1.4.2.2  rmind 					    " - free entry idx %x vtw %p"
   1071  1.4.2.2  rmind 					    , lport
   1072  1.4.2.2  rmind 					    , idx_decode(ctl, idx)
   1073  1.4.2.2  rmind 					    , vtw));
   1074  1.4.2.2  rmind 			}
   1075  1.4.2.2  rmind 		}
   1076  1.4.2.2  rmind 
   1077  1.4.2.2  rmind 		if (fp->nxt) {
   1078  1.4.2.2  rmind 			it->fp = fp = fatp_next(ctl->fat, fp);
   1079  1.4.2.2  rmind 			it->slot_idx = 0;
   1080  1.4.2.2  rmind 		} else {
   1081  1.4.2.2  rmind 			it->fp = 0;
   1082  1.4.2.2  rmind 			break;
   1083  1.4.2.2  rmind 		}
   1084  1.4.2.2  rmind 	}
   1085  1.4.2.2  rmind 	++vtw_stats.miss[1];
   1086  1.4.2.2  rmind 
   1087  1.4.2.2  rmind 	vtw = 0;
   1088  1.4.2.2  rmind out:
   1089  1.4.2.2  rmind 	if (fatps > vtw_stats.max_chain[1])
   1090  1.4.2.2  rmind 		vtw_stats.max_chain[1] = fatps;
   1091  1.4.2.2  rmind 	if (probes > vtw_stats.max_probe[1])
   1092  1.4.2.2  rmind 		vtw_stats.max_probe[1] = probes;
   1093  1.4.2.2  rmind 	if (losings > vtw_stats.max_loss[1])
   1094  1.4.2.2  rmind 		vtw_stats.max_loss[1] = losings;
   1095  1.4.2.2  rmind 
   1096  1.4.2.2  rmind 	return vtw;
   1097  1.4.2.2  rmind }
   1098  1.4.2.2  rmind 
   1099  1.4.2.2  rmind /*!\brief port iterator
   1100  1.4.2.2  rmind  */
   1101  1.4.2.2  rmind static vtw_t *
   1102  1.4.2.2  rmind vtw_next_port_v6(struct tcp_ports_iterator *it)
   1103  1.4.2.2  rmind {
   1104  1.4.2.2  rmind 	vtw_ctl_t	*ctl = it->ctl;
   1105  1.4.2.2  rmind 	vtw_v6_t	*v6;
   1106  1.4.2.2  rmind 	vtw_t		*vtw;
   1107  1.4.2.2  rmind 	uint32_t	tag;
   1108  1.4.2.2  rmind 	uint16_t	lport = it->port;
   1109  1.4.2.2  rmind 	fatp_t		*fp;
   1110  1.4.2.2  rmind 	int		i;
   1111  1.4.2.2  rmind 	uint32_t	fatps = 0, probes = 0, losings = 0;
   1112  1.4.2.2  rmind 
   1113  1.4.2.2  rmind 	tag = v6_port_tag(lport);
   1114  1.4.2.2  rmind 	if (!it->fp) {
   1115  1.4.2.2  rmind 		it->fp = ctl->fat->port[tag & ctl->fat->mask];
   1116  1.4.2.2  rmind 		it->slot_idx = 0;
   1117  1.4.2.2  rmind 	}
   1118  1.4.2.2  rmind 	fp  = it->fp;
   1119  1.4.2.2  rmind 
   1120  1.4.2.2  rmind 	while (fp) {
   1121  1.4.2.2  rmind 		uint32_t	inuse = fp->inuse;
   1122  1.4.2.2  rmind 
   1123  1.4.2.2  rmind 		++fatps;
   1124  1.4.2.2  rmind 
   1125  1.4.2.2  rmind 		for (i = it->slot_idx; inuse && i < fatp_ntags(); ++i) {
   1126  1.4.2.2  rmind 			uint32_t	idx;
   1127  1.4.2.2  rmind 
   1128  1.4.2.2  rmind 			if (!(inuse & (1 << i)))
   1129  1.4.2.2  rmind 				continue;
   1130  1.4.2.2  rmind 
   1131  1.4.2.2  rmind 			inuse &= ~0 << i;
   1132  1.4.2.2  rmind 
   1133  1.4.2.2  rmind 			if (i < it->slot_idx)
   1134  1.4.2.2  rmind 				continue;
   1135  1.4.2.2  rmind 
   1136  1.4.2.2  rmind 			++vtw_stats.probe[1];
   1137  1.4.2.2  rmind 			++probes;
   1138  1.4.2.2  rmind 
   1139  1.4.2.2  rmind 			idx = fp->tag[i] ^ tag ^ fatp_xtra[i];
   1140  1.4.2.2  rmind 			vtw = vtw_from_index(ctl, idx);
   1141  1.4.2.2  rmind 
   1142  1.4.2.2  rmind 			if (!vtw) {
   1143  1.4.2.2  rmind 				/* Hopefully fast path.
   1144  1.4.2.2  rmind 				 */
   1145  1.4.2.2  rmind 				continue;
   1146  1.4.2.2  rmind 			}
   1147  1.4.2.2  rmind 
   1148  1.4.2.2  rmind 			v6 = (void*)vtw;
   1149  1.4.2.2  rmind 
   1150  1.4.2.2  rmind 			db_trace(KTR_VTW
   1151  1.4.2.2  rmind 				 , (vtw, "vtw: i %x idx %x fp->tag %x"
   1152  1.4.2.2  rmind 				    " tag %x xtra %x"
   1153  1.4.2.2  rmind 				    , i, idx_decode(ctl, idx)
   1154  1.4.2.2  rmind 				    , fp->tag[i], tag, fatp_xtra[i]));
   1155  1.4.2.2  rmind 
   1156  1.4.2.2  rmind 			if (vtw_alive(vtw)
   1157  1.4.2.2  rmind 			    && vtw->port_key == fatp_key(ctl->fat, fp, i)
   1158  1.4.2.2  rmind 			    && v6->lport == lport) {
   1159  1.4.2.2  rmind 				++vtw_stats.hit[1];
   1160  1.4.2.2  rmind 
   1161  1.4.2.2  rmind 				db_trace(KTR_VTW
   1162  1.4.2.2  rmind 					 , (fp, "vtw: nxt port %P - %4.4x"
   1163  1.4.2.2  rmind 					    " idx %x key %x"
   1164  1.4.2.2  rmind 					    , lport, lport
   1165  1.4.2.2  rmind 					    , idx_decode(ctl, idx), vtw->key));
   1166  1.4.2.2  rmind 
   1167  1.4.2.2  rmind 				it->slot_idx = i + 1;
   1168  1.4.2.2  rmind 				goto out;
   1169  1.4.2.2  rmind 			} else if (vtw_alive(vtw)) {
   1170  1.4.2.2  rmind 				++vtw_stats.losing[1];
   1171  1.4.2.2  rmind 
   1172  1.4.2.2  rmind 				db_trace(KTR_VTW
   1173  1.4.2.2  rmind 					 , (vtw, "vtw:!mis port %6A:%4.4x"
   1174  1.4.2.2  rmind 					    " %6A:%4.4x key %x port %x"
   1175  1.4.2.2  rmind 					    , db_store(&v6->faddr
   1176  1.4.2.2  rmind 						       , sizeof (v6->faddr))
   1177  1.4.2.2  rmind 					    , v6->fport
   1178  1.4.2.2  rmind 					    , db_store(&v6->laddr
   1179  1.4.2.2  rmind 						       , sizeof (v6->faddr))
   1180  1.4.2.2  rmind 					    , v6->lport
   1181  1.4.2.2  rmind 					    , vtw->key
   1182  1.4.2.2  rmind 					    , lport));
   1183  1.4.2.2  rmind 			} else {
   1184  1.4.2.2  rmind 				/* Really losing here.  We are coming
   1185  1.4.2.2  rmind 				 * up with references to free entries.
   1186  1.4.2.2  rmind 				 * Might find it better to use
   1187  1.4.2.2  rmind 				 * traditional, or need another
   1188  1.4.2.2  rmind 				 * add-hockery.  The other add-hockery
   1189  1.4.2.2  rmind 				 * would be to pul more into into the
   1190  1.4.2.2  rmind 				 * cache line to reject the false
   1191  1.4.2.2  rmind 				 * hits.
   1192  1.4.2.2  rmind 				 */
   1193  1.4.2.2  rmind 				++vtw_stats.losing[1];
   1194  1.4.2.2  rmind 				++losings;
   1195  1.4.2.2  rmind 
   1196  1.4.2.2  rmind 				db_trace(KTR_VTW
   1197  1.4.2.2  rmind 					 , (fp
   1198  1.4.2.2  rmind 					    , "vtw:!mis port %x"
   1199  1.4.2.2  rmind 					    " - free entry idx %x vtw %p"
   1200  1.4.2.2  rmind 					    , lport, idx_decode(ctl, idx)
   1201  1.4.2.2  rmind 					    , vtw));
   1202  1.4.2.2  rmind 			}
   1203  1.4.2.2  rmind 		}
   1204  1.4.2.2  rmind 
   1205  1.4.2.2  rmind 		if (fp->nxt) {
   1206  1.4.2.2  rmind 			it->fp = fp = fatp_next(ctl->fat, fp);
   1207  1.4.2.2  rmind 			it->slot_idx = 0;
   1208  1.4.2.2  rmind 		} else {
   1209  1.4.2.2  rmind 			it->fp = 0;
   1210  1.4.2.2  rmind 			break;
   1211  1.4.2.2  rmind 		}
   1212  1.4.2.2  rmind 	}
   1213  1.4.2.2  rmind 	++vtw_stats.miss[1];
   1214  1.4.2.2  rmind 
   1215  1.4.2.2  rmind 	vtw = 0;
   1216  1.4.2.2  rmind out:
   1217  1.4.2.2  rmind 	if (fatps > vtw_stats.max_chain[1])
   1218  1.4.2.2  rmind 		vtw_stats.max_chain[1] = fatps;
   1219  1.4.2.2  rmind 	if (probes > vtw_stats.max_probe[1])
   1220  1.4.2.2  rmind 		vtw_stats.max_probe[1] = probes;
   1221  1.4.2.2  rmind 	if (losings > vtw_stats.max_loss[1])
   1222  1.4.2.2  rmind 		vtw_stats.max_loss[1] = losings;
   1223  1.4.2.2  rmind 
   1224  1.4.2.2  rmind 	return vtw;
   1225  1.4.2.2  rmind }
   1226  1.4.2.2  rmind 
   1227  1.4.2.2  rmind /*!\brief initialise the VTW allocation arena
   1228  1.4.2.2  rmind  *
   1229  1.4.2.2  rmind  * There are 1+3 allocation classes:
   1230  1.4.2.2  rmind  *	0	classless
   1231  1.4.2.2  rmind  *	{1,2,3}	MSL-class based allocation
   1232  1.4.2.2  rmind  *
   1233  1.4.2.2  rmind  * The allocation arenas are all initialised.  Classless gets all the
   1234  1.4.2.2  rmind  * space.  MSL-class based divides the arena, so that allocation
   1235  1.4.2.2  rmind  * within a class can proceed without having to consider entries
   1236  1.4.2.2  rmind  * (aka: cache lines) from different classes.
   1237  1.4.2.2  rmind  *
   1238  1.4.2.2  rmind  * Usually, we are completely classless or class-based, but there can be
   1239  1.4.2.2  rmind  * transition periods, corresponding to dynamic adjustments in the config
   1240  1.4.2.2  rmind  * by the operator.
   1241  1.4.2.2  rmind  */
   1242  1.4.2.2  rmind static void
   1243  1.4.2.2  rmind vtw_init(fatp_ctl_t *fat, vtw_ctl_t *ctl, uint32_t n)
   1244  1.4.2.2  rmind {
   1245  1.4.2.2  rmind 	int i;
   1246  1.4.2.2  rmind 	int sz = (ctl->is_v4 ? sizeof (vtw_v4_t) : sizeof (vtw_v6_t));
   1247  1.4.2.2  rmind 
   1248  1.4.2.2  rmind 	ctl->base.v4 = kmem_alloc(n * sz, KM_SLEEP);
   1249  1.4.2.2  rmind 	if (ctl->base.v4) {
   1250  1.4.2.2  rmind 		vtw_t	*base;
   1251  1.4.2.2  rmind 		int	class_n;
   1252  1.4.2.2  rmind 
   1253  1.4.2.2  rmind 		bzero(ctl->base.v4, n * sz);
   1254  1.4.2.2  rmind 
   1255  1.4.2.2  rmind 		if (ctl->is_v4) {
   1256  1.4.2.2  rmind 			ctl->lim.v4    = ctl->base.v4 + n - 1;
   1257  1.4.2.2  rmind 			ctl->alloc.v4  = ctl->base.v4;
   1258  1.4.2.2  rmind 		} else {
   1259  1.4.2.2  rmind 			ctl->lim.v6    = ctl->base.v6 + n - 1;
   1260  1.4.2.2  rmind 			ctl->alloc.v6  = ctl->base.v6;
   1261  1.4.2.2  rmind 		}
   1262  1.4.2.2  rmind 
   1263  1.4.2.2  rmind 		ctl->nfree  = n;
   1264  1.4.2.2  rmind 		ctl->ctl    = ctl;
   1265  1.4.2.2  rmind 
   1266  1.4.2.2  rmind 		ctl->idx_bits = 32;
   1267  1.4.2.2  rmind 		for (ctl->idx_mask = ~0; (ctl->idx_mask & (n-1)) == n-1; ) {
   1268  1.4.2.2  rmind 			ctl->idx_mask >>= 1;
   1269  1.4.2.2  rmind 			ctl->idx_bits  -= 1;
   1270  1.4.2.2  rmind 		}
   1271  1.4.2.2  rmind 
   1272  1.4.2.2  rmind 		ctl->idx_mask <<= 1;
   1273  1.4.2.2  rmind 		ctl->idx_mask  |= 1;
   1274  1.4.2.2  rmind 		ctl->idx_bits  += 1;
   1275  1.4.2.2  rmind 
   1276  1.4.2.2  rmind 		ctl->fat = fat;
   1277  1.4.2.2  rmind 		fat->vtw = ctl;
   1278  1.4.2.2  rmind 
   1279  1.4.2.2  rmind 		/* Divide the resources equally amongst the classes.
   1280  1.4.2.2  rmind 		 * This is not optimal, as the different classes
   1281  1.4.2.2  rmind 		 * arrive and leave at different rates, but it is
   1282  1.4.2.2  rmind 		 * the best I can do for now.
   1283  1.4.2.2  rmind 		 */
   1284  1.4.2.2  rmind 		class_n = n / (VTW_NCLASS-1);
   1285  1.4.2.2  rmind 		base    = ctl->base.v;
   1286  1.4.2.2  rmind 
   1287  1.4.2.2  rmind 		for (i = 1; i < VTW_NCLASS; ++i) {
   1288  1.4.2.2  rmind 			int j;
   1289  1.4.2.2  rmind 
   1290  1.4.2.2  rmind 			ctl[i] = ctl[0];
   1291  1.4.2.2  rmind 			ctl[i].clidx = i;
   1292  1.4.2.2  rmind 
   1293  1.4.2.2  rmind 			ctl[i].base.v = base;
   1294  1.4.2.2  rmind 			ctl[i].alloc  = ctl[i].base;
   1295  1.4.2.2  rmind 
   1296  1.4.2.2  rmind 			for (j = 0; j < class_n - 1; ++j) {
   1297  1.4.2.2  rmind 				if (tcp_msl_enable)
   1298  1.4.2.2  rmind 					base->msl_class = i;
   1299  1.4.2.2  rmind 				base = vtw_next(ctl, base);
   1300  1.4.2.2  rmind 			}
   1301  1.4.2.2  rmind 
   1302  1.4.2.2  rmind 			ctl[i].lim.v = base;
   1303  1.4.2.2  rmind 			base = vtw_next(ctl, base);
   1304  1.4.2.2  rmind 			ctl[i].nfree = class_n;
   1305  1.4.2.2  rmind 		}
   1306  1.4.2.2  rmind 	}
   1307  1.4.2.2  rmind 
   1308  1.4.2.2  rmind 	vtw_debug_init();
   1309  1.4.2.2  rmind }
   1310  1.4.2.2  rmind 
   1311  1.4.2.2  rmind /*!\brief	map class to TCP MSL
   1312  1.4.2.2  rmind  */
   1313  1.4.2.2  rmind static inline uint32_t
   1314  1.4.2.2  rmind class_to_msl(int class)
   1315  1.4.2.2  rmind {
   1316  1.4.2.2  rmind 	switch (class) {
   1317  1.4.2.2  rmind 	case 0:
   1318  1.4.2.2  rmind 	case 1:
   1319  1.4.2.2  rmind 		return tcp_msl_remote ? tcp_msl_remote : (TCPTV_MSL >> 0);
   1320  1.4.2.2  rmind 	case 2:
   1321  1.4.2.2  rmind 		return tcp_msl_local ? tcp_msl_local : (TCPTV_MSL >> 1);
   1322  1.4.2.2  rmind 	default:
   1323  1.4.2.2  rmind 		return tcp_msl_loop ? tcp_msl_loop : (TCPTV_MSL >> 2);
   1324  1.4.2.2  rmind 	}
   1325  1.4.2.2  rmind }
   1326  1.4.2.2  rmind 
   1327  1.4.2.2  rmind /*!\brief	map TCP MSL to class
   1328  1.4.2.2  rmind  */
   1329  1.4.2.2  rmind static inline uint32_t
   1330  1.4.2.2  rmind msl_to_class(int msl)
   1331  1.4.2.2  rmind {
   1332  1.4.2.2  rmind 	if (tcp_msl_enable) {
   1333  1.4.2.2  rmind 		if (msl <= (tcp_msl_loop ? tcp_msl_loop : (TCPTV_MSL >> 2)))
   1334  1.4.2.2  rmind 			return 1+2;
   1335  1.4.2.2  rmind 		if (msl <= (tcp_msl_local ? tcp_msl_local : (TCPTV_MSL >> 1)))
   1336  1.4.2.2  rmind 			return 1+1;
   1337  1.4.2.2  rmind 		return 1;
   1338  1.4.2.2  rmind 	}
   1339  1.4.2.2  rmind 	return 0;
   1340  1.4.2.2  rmind }
   1341  1.4.2.2  rmind 
   1342  1.4.2.2  rmind /*!\brief allocate a vtw entry
   1343  1.4.2.2  rmind  */
   1344  1.4.2.2  rmind static inline vtw_t *
   1345  1.4.2.2  rmind vtw_alloc(vtw_ctl_t *ctl)
   1346  1.4.2.2  rmind {
   1347  1.4.2.2  rmind 	vtw_t	*vtw	= 0;
   1348  1.4.2.2  rmind 	int	stuck	= 0;
   1349  1.4.2.2  rmind 	int	avail	= ctl ? (ctl->nalloc + ctl->nfree) : 0;
   1350  1.4.2.2  rmind 	int	msl;
   1351  1.4.2.2  rmind 
   1352  1.4.2.2  rmind 	KASSERT(mutex_owned(softnet_lock));
   1353  1.4.2.2  rmind 
   1354  1.4.2.2  rmind 	/* If no resources, we will not get far.
   1355  1.4.2.2  rmind 	 */
   1356  1.4.2.2  rmind 	if (!ctl || !ctl->base.v4 || avail <= 0)
   1357  1.4.2.2  rmind 		return 0;
   1358  1.4.2.2  rmind 
   1359  1.4.2.2  rmind 	/* Obtain a free one.
   1360  1.4.2.2  rmind 	 */
   1361  1.4.2.2  rmind 	while (!ctl->nfree) {
   1362  1.4.2.2  rmind 		vtw_age(ctl, 0);
   1363  1.4.2.2  rmind 
   1364  1.4.2.2  rmind 		if (++stuck > avail) {
   1365  1.4.2.2  rmind 			/* When in transition between
   1366  1.4.2.2  rmind 			 * schemes (classless, classed) we
   1367  1.4.2.2  rmind 			 * can be stuck having to await the
   1368  1.4.2.2  rmind 			 * expiration of cross-allocated entries.
   1369  1.4.2.2  rmind 			 *
   1370  1.4.2.2  rmind 			 * Returning zero means we will fall back to the
   1371  1.4.2.2  rmind 			 * traditional TIME_WAIT handling, except in the
   1372  1.4.2.2  rmind 			 * case of a re-shed, in which case we cannot
   1373  1.4.2.2  rmind 			 * perform the reshecd, but will retain the extant
   1374  1.4.2.2  rmind 			 * entry.
   1375  1.4.2.2  rmind 			 */
   1376  1.4.2.2  rmind 			db_trace(KTR_VTW
   1377  1.4.2.2  rmind 				 , (ctl, "vtw:!none free in class %x %x/%x"
   1378  1.4.2.2  rmind 				    , ctl->clidx
   1379  1.4.2.2  rmind 				    , ctl->nalloc, ctl->nfree));
   1380  1.4.2.2  rmind 
   1381  1.4.2.2  rmind 			return 0;
   1382  1.4.2.2  rmind 		}
   1383  1.4.2.2  rmind 	}
   1384  1.4.2.2  rmind 
   1385  1.4.2.2  rmind 	vtw = ctl->alloc.v;
   1386  1.4.2.2  rmind 
   1387  1.4.2.2  rmind 	if (vtw->msl_class != ctl->clidx) {
   1388  1.4.2.2  rmind 		/* Usurping rules:
   1389  1.4.2.2  rmind 		 * 	0 -> {1,2,3} or {1,2,3} -> 0
   1390  1.4.2.2  rmind 		 */
   1391  1.4.2.2  rmind 		KASSERT(!vtw->msl_class || !ctl->clidx);
   1392  1.4.2.2  rmind 
   1393  1.4.2.2  rmind 		if (vtw->hashed || vtw->expire.tv_sec) {
   1394  1.4.2.2  rmind 		    /* As this is owned by some other class,
   1395  1.4.2.2  rmind 		     * we must wait for it to expire it.
   1396  1.4.2.2  rmind 		     * This will only happen on class/classless
   1397  1.4.2.2  rmind 		     * transitions, which are guaranteed to progress
   1398  1.4.2.2  rmind 		     * to completion in small finite time, barring bugs.
   1399  1.4.2.2  rmind 		     */
   1400  1.4.2.2  rmind 		    db_trace(KTR_VTW
   1401  1.4.2.2  rmind 			     , (ctl, "vtw:!%p class %x!=%x %x:%x%s"
   1402  1.4.2.2  rmind 				, vtw, vtw->msl_class, ctl->clidx
   1403  1.4.2.2  rmind 				, vtw->expire.tv_sec
   1404  1.4.2.2  rmind 				, vtw->expire.tv_usec
   1405  1.4.2.2  rmind 				, vtw->hashed ? " hashed" : ""));
   1406  1.4.2.2  rmind 
   1407  1.4.2.2  rmind 		    return 0;
   1408  1.4.2.2  rmind 		}
   1409  1.4.2.2  rmind 
   1410  1.4.2.2  rmind 		db_trace(KTR_VTW
   1411  1.4.2.2  rmind 			 , (ctl, "vtw:!%p usurped from %x to %x"
   1412  1.4.2.2  rmind 			    , vtw, vtw->msl_class, ctl->clidx));
   1413  1.4.2.2  rmind 
   1414  1.4.2.2  rmind 		vtw->msl_class = ctl->clidx;
   1415  1.4.2.2  rmind 	}
   1416  1.4.2.2  rmind 
   1417  1.4.2.2  rmind 	if (vtw_alive(vtw)) {
   1418  1.4.2.2  rmind 		KASSERT(0 && "next free not free");
   1419  1.4.2.2  rmind 		return 0;
   1420  1.4.2.2  rmind 	}
   1421  1.4.2.2  rmind 
   1422  1.4.2.2  rmind 	/* Advance allocation poiter.
   1423  1.4.2.2  rmind 	 */
   1424  1.4.2.2  rmind 	ctl->alloc.v = vtw_next(ctl, vtw);
   1425  1.4.2.2  rmind 
   1426  1.4.2.2  rmind 	--ctl->nfree;
   1427  1.4.2.2  rmind 	++ctl->nalloc;
   1428  1.4.2.2  rmind 
   1429  1.4.2.2  rmind 	msl = (2 * class_to_msl(ctl->clidx) * 1000) / PR_SLOWHZ;	// msec
   1430  1.4.2.2  rmind 
   1431  1.4.2.2  rmind 	/* mark expiration
   1432  1.4.2.2  rmind 	 */
   1433  1.4.2.2  rmind 	getmicrouptime(&vtw->expire);
   1434  1.4.2.2  rmind 
   1435  1.4.2.2  rmind 	/* Move expiration into the future.
   1436  1.4.2.2  rmind 	 */
   1437  1.4.2.2  rmind 	vtw->expire.tv_sec  += msl / 1000;
   1438  1.4.2.2  rmind 	vtw->expire.tv_usec += 1000 * (msl % 1000);
   1439  1.4.2.2  rmind 
   1440  1.4.2.2  rmind 	while (vtw->expire.tv_usec >= 1000*1000) {
   1441  1.4.2.2  rmind 		vtw->expire.tv_usec -= 1000*1000;
   1442  1.4.2.2  rmind 		vtw->expire.tv_sec  += 1;
   1443  1.4.2.2  rmind 	}
   1444  1.4.2.2  rmind 
   1445  1.4.2.2  rmind 	if (!ctl->oldest.v)
   1446  1.4.2.2  rmind 		ctl->oldest.v = vtw;
   1447  1.4.2.2  rmind 
   1448  1.4.2.2  rmind 	return vtw;
   1449  1.4.2.2  rmind }
   1450  1.4.2.2  rmind 
   1451  1.4.2.2  rmind /*!\brief expiration
   1452  1.4.2.2  rmind  */
   1453  1.4.2.2  rmind static int
   1454  1.4.2.2  rmind vtw_age(vtw_ctl_t *ctl, struct timeval *_when)
   1455  1.4.2.2  rmind {
   1456  1.4.2.2  rmind 	vtw_t	*vtw;
   1457  1.4.2.2  rmind 	struct timeval then, *when = _when;
   1458  1.4.2.2  rmind 	int	maxtries = 0;
   1459  1.4.2.2  rmind 
   1460  1.4.2.2  rmind 	if (!ctl->oldest.v) {
   1461  1.4.2.2  rmind 		KASSERT(!ctl->nalloc);
   1462  1.4.2.2  rmind 		return 0;
   1463  1.4.2.2  rmind 	}
   1464  1.4.2.2  rmind 
   1465  1.4.2.2  rmind 	for (vtw = ctl->oldest.v; vtw && ctl->nalloc; ) {
   1466  1.4.2.2  rmind 		if (++maxtries > ctl->nalloc)
   1467  1.4.2.2  rmind 			break;
   1468  1.4.2.2  rmind 
   1469  1.4.2.2  rmind 		if (vtw->msl_class != ctl->clidx) {
   1470  1.4.2.2  rmind 			db_trace(KTR_VTW
   1471  1.4.2.2  rmind 				 , (vtw, "vtw:!age class mismatch %x != %x"
   1472  1.4.2.2  rmind 				    , vtw->msl_class, ctl->clidx));
   1473  1.4.2.2  rmind 			/* XXXX
   1474  1.4.2.2  rmind 			 * See if the appropriate action is to skip to the next.
   1475  1.4.2.2  rmind 			 * XXXX
   1476  1.4.2.2  rmind 			 */
   1477  1.4.2.2  rmind 			ctl->oldest.v = vtw = vtw_next(ctl, vtw);
   1478  1.4.2.2  rmind 			continue;
   1479  1.4.2.2  rmind 		}
   1480  1.4.2.2  rmind 		if (!when) {
   1481  1.4.2.2  rmind 			/* Latch oldest timeval if none specified.
   1482  1.4.2.2  rmind 			 */
   1483  1.4.2.2  rmind 			then = vtw->expire;
   1484  1.4.2.2  rmind 			when = &then;
   1485  1.4.2.2  rmind 		}
   1486  1.4.2.2  rmind 
   1487  1.4.2.2  rmind 		if (!timercmp(&vtw->expire, when, <=))
   1488  1.4.2.2  rmind 			break;
   1489  1.4.2.2  rmind 
   1490  1.4.2.2  rmind 		db_trace(KTR_VTW
   1491  1.4.2.2  rmind 			 , (vtw, "vtw: expire %x %8.8x:%8.8x %x/%x"
   1492  1.4.2.2  rmind 			    , ctl->clidx
   1493  1.4.2.2  rmind 			    , vtw->expire.tv_sec
   1494  1.4.2.2  rmind 			    , vtw->expire.tv_usec
   1495  1.4.2.2  rmind 			    , ctl->nalloc
   1496  1.4.2.2  rmind 			    , ctl->nfree));
   1497  1.4.2.2  rmind 
   1498  1.4.2.2  rmind 		if (!_when)
   1499  1.4.2.2  rmind 			++vtw_stats.kill;
   1500  1.4.2.2  rmind 
   1501  1.4.2.2  rmind 		vtw_del(ctl, vtw);
   1502  1.4.2.2  rmind 		vtw = ctl->oldest.v;
   1503  1.4.2.2  rmind 	}
   1504  1.4.2.2  rmind 
   1505  1.4.2.2  rmind 	return ctl->nalloc;	// # remaining allocated
   1506  1.4.2.2  rmind }
   1507  1.4.2.2  rmind 
   1508  1.4.2.2  rmind static callout_t vtw_cs;
   1509  1.4.2.2  rmind 
   1510  1.4.2.2  rmind /*!\brief notice the passage of time.
   1511  1.4.2.2  rmind  * It seems to be getting faster.  What happened to the year?
   1512  1.4.2.2  rmind  */
   1513  1.4.2.2  rmind static void
   1514  1.4.2.2  rmind vtw_tick(void *arg)
   1515  1.4.2.2  rmind {
   1516  1.4.2.2  rmind 	struct timeval now;
   1517  1.4.2.2  rmind 	int i, cnt = 0;
   1518  1.4.2.2  rmind 
   1519  1.4.2.2  rmind 	getmicrouptime(&now);
   1520  1.4.2.2  rmind 
   1521  1.4.2.2  rmind 	db_trace(KTR_VTW, (arg, "vtk: tick - now %8.8x:%8.8x"
   1522  1.4.2.2  rmind 			   , now.tv_sec, now.tv_usec));
   1523  1.4.2.2  rmind 
   1524  1.4.2.2  rmind 	mutex_enter(softnet_lock);
   1525  1.4.2.2  rmind 
   1526  1.4.2.2  rmind 	for (i = 0; i < VTW_NCLASS; ++i) {
   1527  1.4.2.2  rmind 		cnt += vtw_age(&vtw_tcpv4[i], &now);
   1528  1.4.2.2  rmind 		cnt += vtw_age(&vtw_tcpv6[i], &now);
   1529  1.4.2.2  rmind 	}
   1530  1.4.2.2  rmind 
   1531  1.4.2.2  rmind 	/* Keep ticks coming while we need them.
   1532  1.4.2.2  rmind 	 */
   1533  1.4.2.2  rmind 	if (cnt)
   1534  1.4.2.2  rmind 		callout_schedule(&vtw_cs, hz / 5);
   1535  1.4.2.2  rmind 	else {
   1536  1.4.2.2  rmind 		tcp_vtw_was_enabled = 0;
   1537  1.4.2.2  rmind 		tcbtable.vestige    = 0;
   1538  1.4.2.2  rmind 	}
   1539  1.4.2.2  rmind 	mutex_exit(softnet_lock);
   1540  1.4.2.2  rmind }
   1541  1.4.2.2  rmind 
   1542  1.4.2.2  rmind /* in_pcblookup_ports assist for handling vestigial entries.
   1543  1.4.2.2  rmind  */
   1544  1.4.2.2  rmind static void *
   1545  1.4.2.2  rmind tcp_init_ports_v4(struct in_addr addr, u_int port, int wild)
   1546  1.4.2.2  rmind {
   1547  1.4.2.2  rmind 	struct tcp_ports_iterator *it = &tcp_ports_iterator_v4;
   1548  1.4.2.2  rmind 
   1549  1.4.2.2  rmind 	bzero(it, sizeof (*it));
   1550  1.4.2.2  rmind 
   1551  1.4.2.2  rmind 	/* Note: the reference to vtw_tcpv4[0] is fine.
   1552  1.4.2.2  rmind 	 * We do not need per-class iteration.  We just
   1553  1.4.2.2  rmind 	 * need to get to the fat, and there is one
   1554  1.4.2.2  rmind 	 * shared fat.
   1555  1.4.2.2  rmind 	 */
   1556  1.4.2.2  rmind 	if (vtw_tcpv4[0].fat) {
   1557  1.4.2.2  rmind 		it->addr.v4 = addr;
   1558  1.4.2.2  rmind 		it->port = port;
   1559  1.4.2.2  rmind 		it->wild = !!wild;
   1560  1.4.2.2  rmind 		it->ctl  = &vtw_tcpv4[0];
   1561  1.4.2.2  rmind 
   1562  1.4.2.2  rmind 		++vtw_stats.look[1];
   1563  1.4.2.2  rmind 	}
   1564  1.4.2.2  rmind 
   1565  1.4.2.2  rmind 	return it;
   1566  1.4.2.2  rmind }
   1567  1.4.2.2  rmind 
   1568  1.4.2.2  rmind /*!\brief export an IPv4 vtw.
   1569  1.4.2.2  rmind  */
   1570  1.4.2.2  rmind static int
   1571  1.4.2.2  rmind vtw_export_v4(vtw_ctl_t *ctl, vtw_t *vtw, vestigial_inpcb_t *res)
   1572  1.4.2.2  rmind {
   1573  1.4.2.2  rmind 	vtw_v4_t	*v4 = (void*)vtw;
   1574  1.4.2.2  rmind 
   1575  1.4.2.2  rmind 	bzero(res, sizeof (*res));
   1576  1.4.2.2  rmind 
   1577  1.4.2.2  rmind 	if (ctl && vtw) {
   1578  1.4.2.2  rmind 		if (!ctl->clidx && vtw->msl_class)
   1579  1.4.2.2  rmind 			ctl += vtw->msl_class;
   1580  1.4.2.2  rmind 		else
   1581  1.4.2.2  rmind 			KASSERT(ctl->clidx == vtw->msl_class);
   1582  1.4.2.2  rmind 
   1583  1.4.2.2  rmind 		res->valid = 1;
   1584  1.4.2.2  rmind 		res->v4    = 1;
   1585  1.4.2.2  rmind 
   1586  1.4.2.2  rmind 		res->faddr.v4.s_addr = v4->faddr;
   1587  1.4.2.2  rmind 		res->laddr.v4.s_addr = v4->laddr;
   1588  1.4.2.2  rmind 		res->fport	= v4->fport;
   1589  1.4.2.2  rmind 		res->lport	= v4->lport;
   1590  1.4.2.2  rmind 		res->vtw	= vtw;		// netlock held over call(s)
   1591  1.4.2.2  rmind 		res->ctl	= ctl;
   1592  1.4.2.2  rmind 		res->reuse_addr = vtw->reuse_addr;
   1593  1.4.2.2  rmind 		res->reuse_port = vtw->reuse_port;
   1594  1.4.2.2  rmind 		res->snd_nxt    = vtw->snd_nxt;
   1595  1.4.2.2  rmind 		res->rcv_nxt	= vtw->rcv_nxt;
   1596  1.4.2.2  rmind 		res->rcv_wnd	= vtw->rcv_wnd;
   1597  1.4.2.2  rmind 		res->uid	= vtw->uid;
   1598  1.4.2.2  rmind 	}
   1599  1.4.2.2  rmind 
   1600  1.4.2.2  rmind 	return res->valid;
   1601  1.4.2.2  rmind }
   1602  1.4.2.2  rmind 
   1603  1.4.2.2  rmind /*!\brief return next port in the port iterator.  yowza.
   1604  1.4.2.2  rmind  */
   1605  1.4.2.2  rmind static int
   1606  1.4.2.2  rmind tcp_next_port_v4(void *arg, struct vestigial_inpcb *res)
   1607  1.4.2.2  rmind {
   1608  1.4.2.2  rmind 	struct tcp_ports_iterator *it = arg;
   1609  1.4.2.2  rmind 	vtw_t		*vtw = 0;
   1610  1.4.2.2  rmind 
   1611  1.4.2.2  rmind 	if (it->ctl)
   1612  1.4.2.2  rmind 		vtw = vtw_next_port_v4(it);
   1613  1.4.2.2  rmind 
   1614  1.4.2.2  rmind 	if (!vtw)
   1615  1.4.2.2  rmind 		it->ctl = 0;
   1616  1.4.2.2  rmind 
   1617  1.4.2.2  rmind 	return vtw_export_v4(it->ctl, vtw, res);
   1618  1.4.2.2  rmind }
   1619  1.4.2.2  rmind 
   1620  1.4.2.2  rmind static int
   1621  1.4.2.2  rmind tcp_lookup_v4(struct in_addr faddr, uint16_t fport,
   1622  1.4.2.2  rmind               struct in_addr laddr, uint16_t lport,
   1623  1.4.2.2  rmind 	      struct vestigial_inpcb *res)
   1624  1.4.2.2  rmind {
   1625  1.4.2.2  rmind 	vtw_t		*vtw;
   1626  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   1627  1.4.2.2  rmind 
   1628  1.4.2.2  rmind 
   1629  1.4.2.2  rmind 	db_trace(KTR_VTW
   1630  1.4.2.2  rmind 		 , (res, "vtw: lookup %A:%P %A:%P"
   1631  1.4.2.2  rmind 		    , faddr, fport
   1632  1.4.2.2  rmind 		    , laddr, lport));
   1633  1.4.2.2  rmind 
   1634  1.4.2.2  rmind 	vtw = vtw_lookup_hash_v4((ctl = &vtw_tcpv4[0])
   1635  1.4.2.2  rmind 				 , faddr.s_addr, fport
   1636  1.4.2.2  rmind 				 , laddr.s_addr, lport, 0);
   1637  1.4.2.2  rmind 
   1638  1.4.2.2  rmind 	return vtw_export_v4(ctl, vtw, res);
   1639  1.4.2.2  rmind }
   1640  1.4.2.2  rmind 
   1641  1.4.2.2  rmind /* in_pcblookup_ports assist for handling vestigial entries.
   1642  1.4.2.2  rmind  */
   1643  1.4.2.2  rmind static void *
   1644  1.4.2.2  rmind tcp_init_ports_v6(const struct in6_addr *addr, u_int port, int wild)
   1645  1.4.2.2  rmind {
   1646  1.4.2.2  rmind 	struct tcp_ports_iterator *it = &tcp_ports_iterator_v6;
   1647  1.4.2.2  rmind 
   1648  1.4.2.2  rmind 	bzero(it, sizeof (*it));
   1649  1.4.2.2  rmind 
   1650  1.4.2.2  rmind 	/* Note: the reference to vtw_tcpv6[0] is fine.
   1651  1.4.2.2  rmind 	 * We do not need per-class iteration.  We just
   1652  1.4.2.2  rmind 	 * need to get to the fat, and there is one
   1653  1.4.2.2  rmind 	 * shared fat.
   1654  1.4.2.2  rmind 	 */
   1655  1.4.2.2  rmind 	if (vtw_tcpv6[0].fat) {
   1656  1.4.2.2  rmind 		it->addr.v6 = *addr;
   1657  1.4.2.2  rmind 		it->port = port;
   1658  1.4.2.2  rmind 		it->wild = !!wild;
   1659  1.4.2.2  rmind 		it->ctl  = &vtw_tcpv6[0];
   1660  1.4.2.2  rmind 
   1661  1.4.2.2  rmind 		++vtw_stats.look[1];
   1662  1.4.2.2  rmind 	}
   1663  1.4.2.2  rmind 
   1664  1.4.2.2  rmind 	return it;
   1665  1.4.2.2  rmind }
   1666  1.4.2.2  rmind 
   1667  1.4.2.2  rmind /*!\brief export an IPv6 vtw.
   1668  1.4.2.2  rmind  */
   1669  1.4.2.2  rmind static int
   1670  1.4.2.2  rmind vtw_export_v6(vtw_ctl_t *ctl, vtw_t *vtw, vestigial_inpcb_t *res)
   1671  1.4.2.2  rmind {
   1672  1.4.2.2  rmind 	vtw_v6_t	*v6 = (void*)vtw;
   1673  1.4.2.2  rmind 
   1674  1.4.2.2  rmind 	bzero(res, sizeof (*res));
   1675  1.4.2.2  rmind 
   1676  1.4.2.2  rmind 	if (ctl && vtw) {
   1677  1.4.2.2  rmind 		if (!ctl->clidx && vtw->msl_class)
   1678  1.4.2.2  rmind 			ctl += vtw->msl_class;
   1679  1.4.2.2  rmind 		else
   1680  1.4.2.2  rmind 			KASSERT(ctl->clidx == vtw->msl_class);
   1681  1.4.2.2  rmind 
   1682  1.4.2.2  rmind 		res->valid = 1;
   1683  1.4.2.2  rmind 		res->v4    = 0;
   1684  1.4.2.2  rmind 
   1685  1.4.2.2  rmind 		res->faddr.v6	= v6->faddr;
   1686  1.4.2.2  rmind 		res->laddr.v6	= v6->laddr;
   1687  1.4.2.2  rmind 		res->fport	= v6->fport;
   1688  1.4.2.2  rmind 		res->lport	= v6->lport;
   1689  1.4.2.2  rmind 		res->vtw	= vtw;		// netlock held over call(s)
   1690  1.4.2.2  rmind 		res->ctl	= ctl;
   1691  1.4.2.2  rmind 
   1692  1.4.2.2  rmind 		res->v6only	= vtw->v6only;
   1693  1.4.2.2  rmind 		res->reuse_addr = vtw->reuse_addr;
   1694  1.4.2.2  rmind 		res->reuse_port = vtw->reuse_port;
   1695  1.4.2.2  rmind 
   1696  1.4.2.2  rmind 		res->snd_nxt    = vtw->snd_nxt;
   1697  1.4.2.2  rmind 		res->rcv_nxt	= vtw->rcv_nxt;
   1698  1.4.2.2  rmind 		res->rcv_wnd	= vtw->rcv_wnd;
   1699  1.4.2.2  rmind 		res->uid	= vtw->uid;
   1700  1.4.2.2  rmind 	}
   1701  1.4.2.2  rmind 
   1702  1.4.2.2  rmind 	return res->valid;
   1703  1.4.2.2  rmind }
   1704  1.4.2.2  rmind 
   1705  1.4.2.2  rmind static int
   1706  1.4.2.2  rmind tcp_next_port_v6(void *arg, struct vestigial_inpcb *res)
   1707  1.4.2.2  rmind {
   1708  1.4.2.2  rmind 	struct tcp_ports_iterator *it = arg;
   1709  1.4.2.2  rmind 	vtw_t		*vtw = 0;
   1710  1.4.2.2  rmind 
   1711  1.4.2.2  rmind 	if (it->ctl)
   1712  1.4.2.2  rmind 		vtw = vtw_next_port_v6(it);
   1713  1.4.2.2  rmind 
   1714  1.4.2.2  rmind 	if (!vtw)
   1715  1.4.2.2  rmind 		it->ctl = 0;
   1716  1.4.2.2  rmind 
   1717  1.4.2.2  rmind 	return vtw_export_v6(it->ctl, vtw, res);
   1718  1.4.2.2  rmind }
   1719  1.4.2.2  rmind 
   1720  1.4.2.2  rmind static int
   1721  1.4.2.2  rmind tcp_lookup_v6(const struct in6_addr *faddr, uint16_t fport,
   1722  1.4.2.2  rmind               const struct in6_addr *laddr, uint16_t lport,
   1723  1.4.2.2  rmind 	      struct vestigial_inpcb *res)
   1724  1.4.2.2  rmind {
   1725  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   1726  1.4.2.2  rmind 	vtw_t		*vtw;
   1727  1.4.2.2  rmind 
   1728  1.4.2.2  rmind 	db_trace(KTR_VTW
   1729  1.4.2.2  rmind 		 , (res, "vtw: lookup %6A:%P %6A:%P"
   1730  1.4.2.2  rmind 		    , db_store(faddr, sizeof (*faddr)), fport
   1731  1.4.2.2  rmind 		    , db_store(laddr, sizeof (*laddr)), lport));
   1732  1.4.2.2  rmind 
   1733  1.4.2.2  rmind 	vtw = vtw_lookup_hash_v6((ctl = &vtw_tcpv6[0])
   1734  1.4.2.2  rmind 				 , faddr, fport
   1735  1.4.2.2  rmind 				 , laddr, lport, 0);
   1736  1.4.2.2  rmind 
   1737  1.4.2.2  rmind 	return vtw_export_v6(ctl, vtw, res);
   1738  1.4.2.2  rmind }
   1739  1.4.2.2  rmind 
   1740  1.4.2.2  rmind static vestigial_hooks_t tcp_hooks = {
   1741  1.4.2.2  rmind 	.init_ports4	= tcp_init_ports_v4,
   1742  1.4.2.2  rmind 	.next_port4	= tcp_next_port_v4,
   1743  1.4.2.2  rmind 	.lookup4	= tcp_lookup_v4,
   1744  1.4.2.2  rmind 	.init_ports6	= tcp_init_ports_v6,
   1745  1.4.2.2  rmind 	.next_port6	= tcp_next_port_v6,
   1746  1.4.2.2  rmind 	.lookup6	= tcp_lookup_v6,
   1747  1.4.2.2  rmind };
   1748  1.4.2.2  rmind 
   1749  1.4.2.2  rmind static bool
   1750  1.4.2.2  rmind vtw_select(int af, fatp_ctl_t **fatp, vtw_ctl_t **ctlp)
   1751  1.4.2.2  rmind {
   1752  1.4.2.2  rmind 	fatp_ctl_t	*fat;
   1753  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   1754  1.4.2.2  rmind 
   1755  1.4.2.2  rmind 	switch (af) {
   1756  1.4.2.2  rmind 	case AF_INET:
   1757  1.4.2.2  rmind 		fat = &fat_tcpv4;
   1758  1.4.2.2  rmind 		ctl = &vtw_tcpv4[0];
   1759  1.4.2.2  rmind 		break;
   1760  1.4.2.2  rmind 	case AF_INET6:
   1761  1.4.2.2  rmind 		fat = &fat_tcpv6;
   1762  1.4.2.2  rmind 		ctl = &vtw_tcpv6[0];
   1763  1.4.2.2  rmind 		break;
   1764  1.4.2.2  rmind 	default:
   1765  1.4.2.2  rmind 		return false;
   1766  1.4.2.2  rmind 	}
   1767  1.4.2.2  rmind 	if (fatp != NULL)
   1768  1.4.2.2  rmind 		*fatp = fat;
   1769  1.4.2.2  rmind 	if (ctlp != NULL)
   1770  1.4.2.2  rmind 		*ctlp = ctl;
   1771  1.4.2.2  rmind 	return true;
   1772  1.4.2.2  rmind }
   1773  1.4.2.2  rmind 
   1774  1.4.2.2  rmind /*!\brief	initialize controlling instance
   1775  1.4.2.2  rmind  */
   1776  1.4.2.2  rmind static int
   1777  1.4.2.2  rmind vtw_control_init(int af)
   1778  1.4.2.2  rmind {
   1779  1.4.2.2  rmind 	fatp_ctl_t	*fat;
   1780  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   1781  1.4.2.2  rmind 
   1782  1.4.2.2  rmind 	if (!vtw_select(af, &fat, &ctl))
   1783  1.4.2.2  rmind 		return EAFNOSUPPORT;
   1784  1.4.2.2  rmind 
   1785  1.4.2.2  rmind 	if (!fat->base) {
   1786  1.4.2.2  rmind 		uint32_t	n, m;
   1787  1.4.2.2  rmind 
   1788  1.4.2.2  rmind 		KASSERT(powerof2(tcp_vtw_entries));
   1789  1.4.2.2  rmind 
   1790  1.4.2.2  rmind 		/* Allocate 10% more capacity in the fat pointers.
   1791  1.4.2.2  rmind 		 * We should only need ~#hash additional based on
   1792  1.4.2.2  rmind 		 * how they age, but TIME_WAIT assassination could cause
   1793  1.4.2.2  rmind 		 * sparse fat pointer utilisation.
   1794  1.4.2.2  rmind 		 */
   1795  1.4.2.2  rmind 		m = 512;
   1796  1.4.2.2  rmind 		n = 2*m + (11 * (tcp_vtw_entries / fatp_ntags())) / 10;
   1797  1.4.2.2  rmind 
   1798  1.4.2.2  rmind 		fatp_init(fat, n, m);
   1799  1.4.2.2  rmind 
   1800  1.4.2.2  rmind 		if (!fat->base)
   1801  1.4.2.2  rmind 			return ENOMEM;
   1802  1.4.2.2  rmind 	}
   1803  1.4.2.2  rmind 
   1804  1.4.2.2  rmind 	if (!ctl->base.v) {
   1805  1.4.2.2  rmind 
   1806  1.4.2.2  rmind 		vtw_init(fat, ctl, tcp_vtw_entries);
   1807  1.4.2.2  rmind 		if (!ctl->base.v)
   1808  1.4.2.2  rmind 			return ENOMEM;
   1809  1.4.2.2  rmind 	}
   1810  1.4.2.2  rmind 
   1811  1.4.2.2  rmind 	return 0;
   1812  1.4.2.2  rmind }
   1813  1.4.2.2  rmind 
   1814  1.4.2.2  rmind /*!\brief	select controlling instance
   1815  1.4.2.2  rmind  */
   1816  1.4.2.2  rmind static vtw_ctl_t *
   1817  1.4.2.2  rmind vtw_control(int af, uint32_t msl)
   1818  1.4.2.2  rmind {
   1819  1.4.2.2  rmind 	fatp_ctl_t	*fat;
   1820  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   1821  1.4.2.2  rmind 	int		class	= msl_to_class(msl);
   1822  1.4.2.2  rmind 
   1823  1.4.2.2  rmind 	if (!vtw_select(af, &fat, &ctl))
   1824  1.4.2.2  rmind 		return NULL;
   1825  1.4.2.2  rmind 
   1826  1.4.2.2  rmind 	if (!fat->base || !ctl->base.v)
   1827  1.4.2.2  rmind 		return NULL;
   1828  1.4.2.2  rmind 
   1829  1.4.2.2  rmind 	return ctl + class;
   1830  1.4.2.2  rmind }
   1831  1.4.2.2  rmind 
   1832  1.4.2.2  rmind /*!\brief	add TCP pcb to vestigial timewait
   1833  1.4.2.2  rmind  */
   1834  1.4.2.2  rmind int
   1835  1.4.2.2  rmind vtw_add(int af, struct tcpcb *tp)
   1836  1.4.2.2  rmind {
   1837  1.4.2.2  rmind 	int		enable;
   1838  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   1839  1.4.2.2  rmind 	vtw_t		*vtw;
   1840  1.4.2.2  rmind 
   1841  1.4.2.2  rmind 	KASSERT(mutex_owned(softnet_lock));
   1842  1.4.2.2  rmind 
   1843  1.4.2.2  rmind 	ctl = vtw_control(af, tp->t_msl);
   1844  1.4.2.2  rmind 	if (!ctl)
   1845  1.4.2.2  rmind 		return 0;
   1846  1.4.2.2  rmind 
   1847  1.4.2.2  rmind 	enable = (af == AF_INET) ? tcp4_vtw_enable : tcp6_vtw_enable;
   1848  1.4.2.2  rmind 
   1849  1.4.2.2  rmind 	vtw = vtw_alloc(ctl);
   1850  1.4.2.2  rmind 
   1851  1.4.2.2  rmind 	if (vtw) {
   1852  1.4.2.2  rmind 		vtw->snd_nxt = tp->snd_nxt;
   1853  1.4.2.2  rmind 		vtw->rcv_nxt = tp->rcv_nxt;
   1854  1.4.2.2  rmind 
   1855  1.4.2.2  rmind 		switch (af) {
   1856  1.4.2.2  rmind 		case AF_INET: {
   1857  1.4.2.2  rmind 			struct inpcb	*inp = tp->t_inpcb;
   1858  1.4.2.2  rmind 			vtw_v4_t	*v4  = (void*)vtw;
   1859  1.4.2.2  rmind 
   1860  1.4.2.2  rmind 			v4->faddr = inp->inp_faddr.s_addr;
   1861  1.4.2.2  rmind 			v4->laddr = inp->inp_laddr.s_addr;
   1862  1.4.2.2  rmind 			v4->fport = inp->inp_fport;
   1863  1.4.2.2  rmind 			v4->lport = inp->inp_lport;
   1864  1.4.2.2  rmind 
   1865  1.4.2.2  rmind 			vtw->reuse_port = !!(inp->inp_socket->so_options
   1866  1.4.2.2  rmind 					     & SO_REUSEPORT);
   1867  1.4.2.2  rmind 			vtw->reuse_addr = !!(inp->inp_socket->so_options
   1868  1.4.2.2  rmind 					     & SO_REUSEADDR);
   1869  1.4.2.2  rmind 			vtw->v6only	= 0;
   1870  1.4.2.2  rmind 			vtw->uid	= inp->inp_socket->so_uidinfo->ui_uid;
   1871  1.4.2.2  rmind 
   1872  1.4.2.2  rmind 			vtw_inshash_v4(ctl, vtw);
   1873  1.4.2.2  rmind 
   1874  1.4.2.2  rmind 
   1875  1.4.2.2  rmind #ifdef VTW_DEBUG
   1876  1.4.2.2  rmind 			/* Immediate lookup (connected and port) to
   1877  1.4.2.2  rmind 			 * ensure at least that works!
   1878  1.4.2.2  rmind 			 */
   1879  1.4.2.2  rmind 			if (enable & 4) {
   1880  1.4.2.2  rmind 				KASSERT(vtw_lookup_hash_v4
   1881  1.4.2.2  rmind 					(ctl
   1882  1.4.2.2  rmind 					 , inp->inp_faddr.s_addr, inp->inp_fport
   1883  1.4.2.2  rmind 					 , inp->inp_laddr.s_addr, inp->inp_lport
   1884  1.4.2.2  rmind 					 , 0)
   1885  1.4.2.2  rmind 					== vtw);
   1886  1.4.2.2  rmind 				KASSERT(vtw_lookup_hash_v4
   1887  1.4.2.2  rmind 					(ctl
   1888  1.4.2.2  rmind 					 , inp->inp_faddr.s_addr, inp->inp_fport
   1889  1.4.2.2  rmind 					 , inp->inp_laddr.s_addr, inp->inp_lport
   1890  1.4.2.2  rmind 					 , 1));
   1891  1.4.2.2  rmind 			}
   1892  1.4.2.2  rmind 			/* Immediate port iterator functionality check: not wild
   1893  1.4.2.2  rmind 			 */
   1894  1.4.2.2  rmind 			if (enable & 8) {
   1895  1.4.2.2  rmind 				struct tcp_ports_iterator *it;
   1896  1.4.2.2  rmind 				struct vestigial_inpcb res;
   1897  1.4.2.2  rmind 				int cnt = 0;
   1898  1.4.2.2  rmind 
   1899  1.4.2.2  rmind 				it = tcp_init_ports_v4(inp->inp_laddr
   1900  1.4.2.2  rmind 						       , inp->inp_lport, 0);
   1901  1.4.2.2  rmind 
   1902  1.4.2.2  rmind 				while (tcp_next_port_v4(it, &res)) {
   1903  1.4.2.2  rmind 					++cnt;
   1904  1.4.2.2  rmind 				}
   1905  1.4.2.2  rmind 				KASSERT(cnt);
   1906  1.4.2.2  rmind 			}
   1907  1.4.2.2  rmind 			/* Immediate port iterator functionality check: wild
   1908  1.4.2.2  rmind 			 */
   1909  1.4.2.2  rmind 			if (enable & 16) {
   1910  1.4.2.2  rmind 				struct tcp_ports_iterator *it;
   1911  1.4.2.2  rmind 				struct vestigial_inpcb res;
   1912  1.4.2.2  rmind 				struct in_addr any;
   1913  1.4.2.2  rmind 				int cnt = 0;
   1914  1.4.2.2  rmind 
   1915  1.4.2.2  rmind 				any.s_addr = htonl(INADDR_ANY);
   1916  1.4.2.2  rmind 
   1917  1.4.2.2  rmind 				it = tcp_init_ports_v4(any, inp->inp_lport, 1);
   1918  1.4.2.2  rmind 
   1919  1.4.2.2  rmind 				while (tcp_next_port_v4(it, &res)) {
   1920  1.4.2.2  rmind 					++cnt;
   1921  1.4.2.2  rmind 				}
   1922  1.4.2.2  rmind 				KASSERT(cnt);
   1923  1.4.2.2  rmind 			}
   1924  1.4.2.2  rmind #endif /* VTW_DEBUG */
   1925  1.4.2.2  rmind 			break;
   1926  1.4.2.2  rmind 		}
   1927  1.4.2.2  rmind 
   1928  1.4.2.2  rmind 		case AF_INET6: {
   1929  1.4.2.2  rmind 			struct in6pcb	*inp = tp->t_in6pcb;
   1930  1.4.2.2  rmind 			vtw_v6_t	*v6  = (void*)vtw;
   1931  1.4.2.2  rmind 
   1932  1.4.2.2  rmind 			v6->faddr = inp->in6p_faddr;
   1933  1.4.2.2  rmind 			v6->laddr = inp->in6p_laddr;
   1934  1.4.2.2  rmind 			v6->fport = inp->in6p_fport;
   1935  1.4.2.2  rmind 			v6->lport = inp->in6p_lport;
   1936  1.4.2.2  rmind 
   1937  1.4.2.2  rmind 			vtw->reuse_port = !!(inp->in6p_socket->so_options
   1938  1.4.2.2  rmind 					     & SO_REUSEPORT);
   1939  1.4.2.2  rmind 			vtw->reuse_addr = !!(inp->in6p_socket->so_options
   1940  1.4.2.2  rmind 					     & SO_REUSEADDR);
   1941  1.4.2.2  rmind 			vtw->v6only	= !!(inp->in6p_flags
   1942  1.4.2.2  rmind 					     & IN6P_IPV6_V6ONLY);
   1943  1.4.2.2  rmind 			vtw->uid	= inp->in6p_socket->so_uidinfo->ui_uid;
   1944  1.4.2.2  rmind 
   1945  1.4.2.2  rmind 			vtw_inshash_v6(ctl, vtw);
   1946  1.4.2.2  rmind #ifdef VTW_DEBUG
   1947  1.4.2.2  rmind 			/* Immediate lookup (connected and port) to
   1948  1.4.2.2  rmind 			 * ensure at least that works!
   1949  1.4.2.2  rmind 			 */
   1950  1.4.2.2  rmind 			if (enable & 4) {
   1951  1.4.2.2  rmind 				KASSERT(vtw_lookup_hash_v6(ctl
   1952  1.4.2.2  rmind 					 , &inp->in6p_faddr, inp->in6p_fport
   1953  1.4.2.2  rmind 					 , &inp->in6p_laddr, inp->in6p_lport
   1954  1.4.2.2  rmind 					 , 0)
   1955  1.4.2.2  rmind 					== vtw);
   1956  1.4.2.2  rmind 				KASSERT(vtw_lookup_hash_v6
   1957  1.4.2.2  rmind 					(ctl
   1958  1.4.2.2  rmind 					 , &inp->in6p_faddr, inp->in6p_fport
   1959  1.4.2.2  rmind 					 , &inp->in6p_laddr, inp->in6p_lport
   1960  1.4.2.2  rmind 					 , 1));
   1961  1.4.2.2  rmind 			}
   1962  1.4.2.2  rmind 			/* Immediate port iterator functionality check: not wild
   1963  1.4.2.2  rmind 			 */
   1964  1.4.2.2  rmind 			if (enable & 8) {
   1965  1.4.2.2  rmind 				struct tcp_ports_iterator *it;
   1966  1.4.2.2  rmind 				struct vestigial_inpcb res;
   1967  1.4.2.2  rmind 				int cnt = 0;
   1968  1.4.2.2  rmind 
   1969  1.4.2.2  rmind 				it = tcp_init_ports_v6(&inp->in6p_laddr
   1970  1.4.2.2  rmind 						       , inp->in6p_lport, 0);
   1971  1.4.2.2  rmind 
   1972  1.4.2.2  rmind 				while (tcp_next_port_v6(it, &res)) {
   1973  1.4.2.2  rmind 					++cnt;
   1974  1.4.2.2  rmind 				}
   1975  1.4.2.2  rmind 				KASSERT(cnt);
   1976  1.4.2.2  rmind 			}
   1977  1.4.2.2  rmind 			/* Immediate port iterator functionality check: wild
   1978  1.4.2.2  rmind 			 */
   1979  1.4.2.2  rmind 			if (enable & 16) {
   1980  1.4.2.2  rmind 				struct tcp_ports_iterator *it;
   1981  1.4.2.2  rmind 				struct vestigial_inpcb res;
   1982  1.4.2.2  rmind 				static struct in6_addr any = IN6ADDR_ANY_INIT;
   1983  1.4.2.2  rmind 				int cnt = 0;
   1984  1.4.2.2  rmind 
   1985  1.4.2.2  rmind 				it = tcp_init_ports_v6(&any
   1986  1.4.2.2  rmind 						       , inp->in6p_lport, 1);
   1987  1.4.2.2  rmind 
   1988  1.4.2.2  rmind 				while (tcp_next_port_v6(it, &res)) {
   1989  1.4.2.2  rmind 					++cnt;
   1990  1.4.2.2  rmind 				}
   1991  1.4.2.2  rmind 				KASSERT(cnt);
   1992  1.4.2.2  rmind 			}
   1993  1.4.2.2  rmind #endif /* VTW_DEBUG */
   1994  1.4.2.2  rmind 			break;
   1995  1.4.2.2  rmind 		}
   1996  1.4.2.2  rmind 		}
   1997  1.4.2.2  rmind 
   1998  1.4.2.2  rmind 		tcp_canceltimers(tp);
   1999  1.4.2.2  rmind 		tp = tcp_close(tp);
   2000  1.4.2.2  rmind 		KASSERT(!tp);
   2001  1.4.2.2  rmind 
   2002  1.4.2.2  rmind 		return 1;
   2003  1.4.2.2  rmind 	}
   2004  1.4.2.2  rmind 
   2005  1.4.2.2  rmind 	return 0;
   2006  1.4.2.2  rmind }
   2007  1.4.2.2  rmind 
   2008  1.4.2.2  rmind /*!\brief	restart timer for vestigial time-wait entry
   2009  1.4.2.2  rmind  */
   2010  1.4.2.2  rmind static void
   2011  1.4.2.2  rmind vtw_restart_v4(vestigial_inpcb_t *vp)
   2012  1.4.2.2  rmind {
   2013  1.4.2.2  rmind 	vtw_v4_t	copy = *(vtw_v4_t*)vp->vtw;
   2014  1.4.2.2  rmind 	vtw_t		*vtw;
   2015  1.4.2.2  rmind 	vtw_t		*cp  = &copy.common;
   2016  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   2017  1.4.2.2  rmind 
   2018  1.4.2.2  rmind 	KASSERT(mutex_owned(softnet_lock));
   2019  1.4.2.2  rmind 
   2020  1.4.2.2  rmind 	db_trace(KTR_VTW
   2021  1.4.2.2  rmind 		 , (vp->vtw, "vtw: restart %A:%P %A:%P"
   2022  1.4.2.2  rmind 		    , vp->faddr.v4.s_addr, vp->fport
   2023  1.4.2.2  rmind 		    , vp->laddr.v4.s_addr, vp->lport));
   2024  1.4.2.2  rmind 
   2025  1.4.2.2  rmind 	/* Class might have changed, so have a squiz.
   2026  1.4.2.2  rmind 	 */
   2027  1.4.2.2  rmind 	ctl = vtw_control(AF_INET, class_to_msl(cp->msl_class));
   2028  1.4.2.2  rmind 	vtw = vtw_alloc(ctl);
   2029  1.4.2.2  rmind 
   2030  1.4.2.2  rmind 	if (vtw) {
   2031  1.4.2.2  rmind 		vtw_v4_t	*v4  = (void*)vtw;
   2032  1.4.2.2  rmind 
   2033  1.4.2.2  rmind 		/* Safe now to unhash the old entry
   2034  1.4.2.2  rmind 		 */
   2035  1.4.2.2  rmind 		vtw_del(vp->ctl, vp->vtw);
   2036  1.4.2.2  rmind 
   2037  1.4.2.2  rmind 		vtw->snd_nxt = cp->snd_nxt;
   2038  1.4.2.2  rmind 		vtw->rcv_nxt = cp->rcv_nxt;
   2039  1.4.2.2  rmind 
   2040  1.4.2.2  rmind 		v4->faddr = copy.faddr;
   2041  1.4.2.2  rmind 		v4->laddr = copy.laddr;
   2042  1.4.2.2  rmind 		v4->fport = copy.fport;
   2043  1.4.2.2  rmind 		v4->lport = copy.lport;
   2044  1.4.2.2  rmind 
   2045  1.4.2.2  rmind 		vtw->reuse_port = cp->reuse_port;
   2046  1.4.2.2  rmind 		vtw->reuse_addr = cp->reuse_addr;
   2047  1.4.2.2  rmind 		vtw->v6only	= 0;
   2048  1.4.2.2  rmind 		vtw->uid	= cp->uid;
   2049  1.4.2.2  rmind 
   2050  1.4.2.2  rmind 		vtw_inshash_v4(ctl, vtw);
   2051  1.4.2.2  rmind 	}
   2052  1.4.2.2  rmind 
   2053  1.4.2.2  rmind 	vp->valid = 0;
   2054  1.4.2.2  rmind }
   2055  1.4.2.2  rmind 
   2056  1.4.2.2  rmind /*!\brief	restart timer for vestigial time-wait entry
   2057  1.4.2.2  rmind  */
   2058  1.4.2.2  rmind static void
   2059  1.4.2.2  rmind vtw_restart_v6(vestigial_inpcb_t *vp)
   2060  1.4.2.2  rmind {
   2061  1.4.2.2  rmind 	vtw_v6_t	copy = *(vtw_v6_t*)vp->vtw;
   2062  1.4.2.2  rmind 	vtw_t		*vtw;
   2063  1.4.2.2  rmind 	vtw_t		*cp  = &copy.common;
   2064  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   2065  1.4.2.2  rmind 
   2066  1.4.2.2  rmind 	KASSERT(mutex_owned(softnet_lock));
   2067  1.4.2.2  rmind 
   2068  1.4.2.2  rmind 	db_trace(KTR_VTW
   2069  1.4.2.2  rmind 		 , (vp->vtw, "vtw: restart %6A:%P %6A:%P"
   2070  1.4.2.2  rmind 		    , db_store(&vp->faddr.v6, sizeof (vp->faddr.v6))
   2071  1.4.2.2  rmind 		    , vp->fport
   2072  1.4.2.2  rmind 		    , db_store(&vp->laddr.v6, sizeof (vp->laddr.v6))
   2073  1.4.2.2  rmind 		    , vp->lport));
   2074  1.4.2.2  rmind 
   2075  1.4.2.2  rmind 	/* Class might have changed, so have a squiz.
   2076  1.4.2.2  rmind 	 */
   2077  1.4.2.2  rmind 	ctl = vtw_control(AF_INET6, class_to_msl(cp->msl_class));
   2078  1.4.2.2  rmind 	vtw = vtw_alloc(ctl);
   2079  1.4.2.2  rmind 
   2080  1.4.2.2  rmind 	if (vtw) {
   2081  1.4.2.2  rmind 		vtw_v6_t	*v6  = (void*)vtw;
   2082  1.4.2.2  rmind 
   2083  1.4.2.2  rmind 		/* Safe now to unhash the old entry
   2084  1.4.2.2  rmind 		 */
   2085  1.4.2.2  rmind 		vtw_del(vp->ctl, vp->vtw);
   2086  1.4.2.2  rmind 
   2087  1.4.2.2  rmind 		vtw->snd_nxt = cp->snd_nxt;
   2088  1.4.2.2  rmind 		vtw->rcv_nxt = cp->rcv_nxt;
   2089  1.4.2.2  rmind 
   2090  1.4.2.2  rmind 		v6->faddr = copy.faddr;
   2091  1.4.2.2  rmind 		v6->laddr = copy.laddr;
   2092  1.4.2.2  rmind 		v6->fport = copy.fport;
   2093  1.4.2.2  rmind 		v6->lport = copy.lport;
   2094  1.4.2.2  rmind 
   2095  1.4.2.2  rmind 		vtw->reuse_port = cp->reuse_port;
   2096  1.4.2.2  rmind 		vtw->reuse_addr = cp->reuse_addr;
   2097  1.4.2.2  rmind 		vtw->v6only	= cp->v6only;
   2098  1.4.2.2  rmind 		vtw->uid	= cp->uid;
   2099  1.4.2.2  rmind 
   2100  1.4.2.2  rmind 		vtw_inshash_v6(ctl, vtw);
   2101  1.4.2.2  rmind 	}
   2102  1.4.2.2  rmind 
   2103  1.4.2.2  rmind 	vp->valid = 0;
   2104  1.4.2.2  rmind }
   2105  1.4.2.2  rmind 
   2106  1.4.2.2  rmind /*!\brief	restart timer for vestigial time-wait entry
   2107  1.4.2.2  rmind  */
   2108  1.4.2.2  rmind void
   2109  1.4.2.2  rmind vtw_restart(vestigial_inpcb_t *vp)
   2110  1.4.2.2  rmind {
   2111  1.4.2.2  rmind 	if (!vp || !vp->valid)
   2112  1.4.2.2  rmind 		return;
   2113  1.4.2.2  rmind 
   2114  1.4.2.2  rmind 	if (vp->v4)
   2115  1.4.2.2  rmind 		vtw_restart_v4(vp);
   2116  1.4.2.2  rmind 	else
   2117  1.4.2.2  rmind 		vtw_restart_v6(vp);
   2118  1.4.2.2  rmind }
   2119  1.4.2.2  rmind 
   2120  1.4.2.2  rmind int
   2121  1.4.2.2  rmind vtw_earlyinit(void)
   2122  1.4.2.2  rmind {
   2123  1.4.2.2  rmind 	int rc;
   2124  1.4.2.2  rmind 
   2125  1.4.2.2  rmind 	if (!tcp_vtw_was_enabled) {
   2126  1.4.2.2  rmind 		int i;
   2127  1.4.2.2  rmind 
   2128  1.4.2.2  rmind 		/* This guarantees is timer ticks until we no longer need them.
   2129  1.4.2.2  rmind 		 */
   2130  1.4.2.2  rmind 		tcp_vtw_was_enabled = 1;
   2131  1.4.2.2  rmind 
   2132  1.4.2.2  rmind 		callout_init(&vtw_cs, 0);
   2133  1.4.2.2  rmind 		callout_setfunc(&vtw_cs, vtw_tick, 0);
   2134  1.4.2.2  rmind 		callout_schedule(&vtw_cs, hz / 5);
   2135  1.4.2.2  rmind 
   2136  1.4.2.2  rmind 		for (i = 0; i < VTW_NCLASS; ++i) {
   2137  1.4.2.2  rmind 			vtw_tcpv4[i].is_v4 = 1;
   2138  1.4.2.2  rmind 			vtw_tcpv6[i].is_v6 = 1;
   2139  1.4.2.2  rmind 		}
   2140  1.4.2.2  rmind 
   2141  1.4.2.2  rmind 		tcbtable.vestige = &tcp_hooks;
   2142  1.4.2.2  rmind 	}
   2143  1.4.2.2  rmind 
   2144  1.4.2.2  rmind 	if ((rc = vtw_control_init(AF_INET)) != 0 ||
   2145  1.4.2.2  rmind 	    (rc = vtw_control_init(AF_INET6)) != 0)
   2146  1.4.2.2  rmind 		return rc;
   2147  1.4.2.2  rmind 
   2148  1.4.2.2  rmind 	return 0;
   2149  1.4.2.2  rmind }
   2150  1.4.2.2  rmind 
   2151  1.4.2.2  rmind #ifdef VTW_DEBUG
   2152  1.4.2.2  rmind #include <sys/syscallargs.h>
   2153  1.4.2.2  rmind #include <sys/sysctl.h>
   2154  1.4.2.2  rmind 
   2155  1.4.2.2  rmind /*!\brief	add lalp, fafp entries for debug
   2156  1.4.2.2  rmind  */
   2157  1.4.2.2  rmind int
   2158  1.4.2.2  rmind vtw_debug_add(int af, sin_either_t *la, sin_either_t *fa, int msl, int class)
   2159  1.4.2.2  rmind {
   2160  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   2161  1.4.2.2  rmind 	vtw_t		*vtw;
   2162  1.4.2.2  rmind 
   2163  1.4.2.2  rmind 	ctl = vtw_control(af, msl ? msl : class_to_msl(class));
   2164  1.4.2.2  rmind 	if (!ctl)
   2165  1.4.2.2  rmind 		return 0;
   2166  1.4.2.2  rmind 
   2167  1.4.2.2  rmind 	vtw = vtw_alloc(ctl);
   2168  1.4.2.2  rmind 
   2169  1.4.2.2  rmind 	if (vtw) {
   2170  1.4.2.2  rmind 		vtw->snd_nxt = 0;
   2171  1.4.2.2  rmind 		vtw->rcv_nxt = 0;
   2172  1.4.2.2  rmind 
   2173  1.4.2.2  rmind 		switch (af) {
   2174  1.4.2.2  rmind 		case AF_INET: {
   2175  1.4.2.2  rmind 			vtw_v4_t	*v4  = (void*)vtw;
   2176  1.4.2.2  rmind 
   2177  1.4.2.2  rmind 			v4->faddr = fa->sin_addr.v4.s_addr;
   2178  1.4.2.2  rmind 			v4->laddr = la->sin_addr.v4.s_addr;
   2179  1.4.2.2  rmind 			v4->fport = fa->sin_port;
   2180  1.4.2.2  rmind 			v4->lport = la->sin_port;
   2181  1.4.2.2  rmind 
   2182  1.4.2.2  rmind 			vtw->reuse_port = 1;
   2183  1.4.2.2  rmind 			vtw->reuse_addr = 1;
   2184  1.4.2.2  rmind 			vtw->v6only	= 0;
   2185  1.4.2.2  rmind 			vtw->uid	= 0;
   2186  1.4.2.2  rmind 
   2187  1.4.2.2  rmind 			vtw_inshash_v4(ctl, vtw);
   2188  1.4.2.2  rmind 			break;
   2189  1.4.2.2  rmind 		}
   2190  1.4.2.2  rmind 
   2191  1.4.2.2  rmind 		case AF_INET6: {
   2192  1.4.2.2  rmind 			vtw_v6_t	*v6  = (void*)vtw;
   2193  1.4.2.2  rmind 
   2194  1.4.2.2  rmind 			v6->faddr = fa->sin_addr.v6;
   2195  1.4.2.2  rmind 			v6->laddr = la->sin_addr.v6;
   2196  1.4.2.2  rmind 
   2197  1.4.2.2  rmind 			v6->fport = fa->sin_port;
   2198  1.4.2.2  rmind 			v6->lport = la->sin_port;
   2199  1.4.2.2  rmind 
   2200  1.4.2.2  rmind 			vtw->reuse_port = 1;
   2201  1.4.2.2  rmind 			vtw->reuse_addr = 1;
   2202  1.4.2.2  rmind 			vtw->v6only	= 0;
   2203  1.4.2.2  rmind 			vtw->uid	= 0;
   2204  1.4.2.2  rmind 
   2205  1.4.2.2  rmind 			vtw_inshash_v6(ctl, vtw);
   2206  1.4.2.2  rmind 			break;
   2207  1.4.2.2  rmind 		}
   2208  1.4.2.2  rmind 
   2209  1.4.2.2  rmind 		default:
   2210  1.4.2.2  rmind 			break;
   2211  1.4.2.2  rmind 		}
   2212  1.4.2.2  rmind 
   2213  1.4.2.2  rmind 		return 1;
   2214  1.4.2.2  rmind 	}
   2215  1.4.2.2  rmind 
   2216  1.4.2.2  rmind 	return 0;
   2217  1.4.2.2  rmind }
   2218  1.4.2.2  rmind 
   2219  1.4.2.2  rmind static int vtw_syscall = 0;
   2220  1.4.2.2  rmind 
   2221  1.4.2.2  rmind static int
   2222  1.4.2.2  rmind vtw_debug_process(vtw_sysargs_t *ap)
   2223  1.4.2.2  rmind {
   2224  1.4.2.2  rmind 	struct vestigial_inpcb vestige;
   2225  1.4.2.2  rmind 	int	rc = 0;
   2226  1.4.2.2  rmind 
   2227  1.4.2.2  rmind 	mutex_enter(softnet_lock);
   2228  1.4.2.2  rmind 
   2229  1.4.2.2  rmind 	switch (ap->op) {
   2230  1.4.2.2  rmind 	case 0:		// insert
   2231  1.4.2.2  rmind 		vtw_debug_add(ap->la.sin_family
   2232  1.4.2.2  rmind 			      , &ap->la
   2233  1.4.2.2  rmind 			      , &ap->fa
   2234  1.4.2.2  rmind 			      , TCPTV_MSL
   2235  1.4.2.2  rmind 			      , 0);
   2236  1.4.2.2  rmind 		break;
   2237  1.4.2.2  rmind 
   2238  1.4.2.2  rmind 	case 1:		// lookup
   2239  1.4.2.2  rmind 	case 2:		// restart
   2240  1.4.2.2  rmind 		switch (ap->la.sin_family) {
   2241  1.4.2.2  rmind 		case AF_INET:
   2242  1.4.2.2  rmind 			if (tcp_lookup_v4(ap->fa.sin_addr.v4, ap->fa.sin_port,
   2243  1.4.2.2  rmind 					  ap->la.sin_addr.v4, ap->la.sin_port,
   2244  1.4.2.2  rmind 					  &vestige)) {
   2245  1.4.2.2  rmind 				if (ap->op == 2) {
   2246  1.4.2.2  rmind 					vtw_restart(&vestige);
   2247  1.4.2.2  rmind 				}
   2248  1.4.2.2  rmind 				rc = 0;
   2249  1.4.2.2  rmind 			} else
   2250  1.4.2.2  rmind 				rc = ESRCH;
   2251  1.4.2.2  rmind 			break;
   2252  1.4.2.2  rmind 
   2253  1.4.2.2  rmind 		case AF_INET6:
   2254  1.4.2.2  rmind 			if (tcp_lookup_v6(&ap->fa.sin_addr.v6, ap->fa.sin_port,
   2255  1.4.2.2  rmind 					  &ap->la.sin_addr.v6, ap->la.sin_port,
   2256  1.4.2.2  rmind 					  &vestige)) {
   2257  1.4.2.2  rmind 				if (ap->op == 2) {
   2258  1.4.2.2  rmind 					vtw_restart(&vestige);
   2259  1.4.2.2  rmind 				}
   2260  1.4.2.2  rmind 				rc = 0;
   2261  1.4.2.2  rmind 			} else
   2262  1.4.2.2  rmind 				rc = ESRCH;
   2263  1.4.2.2  rmind 			break;
   2264  1.4.2.2  rmind 		default:
   2265  1.4.2.2  rmind 			rc = EINVAL;
   2266  1.4.2.2  rmind 		}
   2267  1.4.2.2  rmind 		break;
   2268  1.4.2.2  rmind 
   2269  1.4.2.2  rmind 	default:
   2270  1.4.2.2  rmind 		rc = EINVAL;
   2271  1.4.2.2  rmind 	}
   2272  1.4.2.2  rmind 
   2273  1.4.2.2  rmind 	mutex_exit(softnet_lock);
   2274  1.4.2.2  rmind 	return rc;
   2275  1.4.2.2  rmind }
   2276  1.4.2.2  rmind 
   2277  1.4.2.2  rmind struct sys_vtw_args {
   2278  1.4.2.2  rmind 	syscallarg(const vtw_sysargs_t *) req;
   2279  1.4.2.2  rmind 	syscallarg(size_t) len;
   2280  1.4.2.2  rmind };
   2281  1.4.2.2  rmind 
   2282  1.4.2.2  rmind static int
   2283  1.4.2.2  rmind vtw_sys(struct lwp *l, const void *_, register_t *retval)
   2284  1.4.2.2  rmind {
   2285  1.4.2.2  rmind 	const struct sys_vtw_args *uap = _;
   2286  1.4.2.2  rmind 	void	*buf;
   2287  1.4.2.2  rmind 	int	rc;
   2288  1.4.2.2  rmind 	size_t	len	= SCARG(uap, len);
   2289  1.4.2.2  rmind 
   2290  1.4.2.2  rmind 	if (len != sizeof (vtw_sysargs_t))
   2291  1.4.2.2  rmind 		return EINVAL;
   2292  1.4.2.2  rmind 
   2293  1.4.2.2  rmind 	buf = kmem_alloc(len, KM_SLEEP);
   2294  1.4.2.2  rmind 	if (!buf)
   2295  1.4.2.2  rmind 		return ENOMEM;
   2296  1.4.2.2  rmind 
   2297  1.4.2.2  rmind 	rc = copyin(SCARG(uap, req), buf, len);
   2298  1.4.2.2  rmind 	if (!rc) {
   2299  1.4.2.2  rmind 		rc = vtw_debug_process(buf);
   2300  1.4.2.2  rmind 	}
   2301  1.4.2.2  rmind 	kmem_free(buf, len);
   2302  1.4.2.2  rmind 
   2303  1.4.2.2  rmind 	return rc;
   2304  1.4.2.2  rmind }
   2305  1.4.2.2  rmind 
   2306  1.4.2.2  rmind static void
   2307  1.4.2.2  rmind vtw_sanity_check(void)
   2308  1.4.2.2  rmind {
   2309  1.4.2.2  rmind 	vtw_ctl_t	*ctl;
   2310  1.4.2.2  rmind 	vtw_t		*vtw;
   2311  1.4.2.2  rmind 	int		i;
   2312  1.4.2.2  rmind 	int		n;
   2313  1.4.2.2  rmind 
   2314  1.4.2.2  rmind 	for (i = 0; i < VTW_NCLASS; ++i) {
   2315  1.4.2.2  rmind 		ctl = &vtw_tcpv4[i];
   2316  1.4.2.2  rmind 
   2317  1.4.2.2  rmind 		if (!ctl->base.v || ctl->nalloc)
   2318  1.4.2.2  rmind 			continue;
   2319  1.4.2.2  rmind 
   2320  1.4.2.2  rmind 		for (n = 0, vtw = ctl->base.v; ; ) {
   2321  1.4.2.2  rmind 			++n;
   2322  1.4.2.2  rmind 			vtw = vtw_next(ctl, vtw);
   2323  1.4.2.2  rmind 			if (vtw == ctl->base.v)
   2324  1.4.2.2  rmind 				break;
   2325  1.4.2.2  rmind 		}
   2326  1.4.2.2  rmind 		db_trace(KTR_VTW
   2327  1.4.2.2  rmind 			 , (ctl, "sanity: class %x n %x nfree %x"
   2328  1.4.2.2  rmind 			    , i, n, ctl->nfree));
   2329  1.4.2.2  rmind 
   2330  1.4.2.2  rmind 		KASSERT(n == ctl->nfree);
   2331  1.4.2.2  rmind 	}
   2332  1.4.2.2  rmind 
   2333  1.4.2.2  rmind 	for (i = 0; i < VTW_NCLASS; ++i) {
   2334  1.4.2.2  rmind 		ctl = &vtw_tcpv6[i];
   2335  1.4.2.2  rmind 
   2336  1.4.2.2  rmind 		if (!ctl->base.v || ctl->nalloc)
   2337  1.4.2.2  rmind 			continue;
   2338  1.4.2.2  rmind 
   2339  1.4.2.2  rmind 		for (n = 0, vtw = ctl->base.v; ; ) {
   2340  1.4.2.2  rmind 			++n;
   2341  1.4.2.2  rmind 			vtw = vtw_next(ctl, vtw);
   2342  1.4.2.2  rmind 			if (vtw == ctl->base.v)
   2343  1.4.2.2  rmind 				break;
   2344  1.4.2.2  rmind 		}
   2345  1.4.2.2  rmind 		db_trace(KTR_VTW
   2346  1.4.2.2  rmind 			 , (ctl, "sanity: class %x n %x nfree %x"
   2347  1.4.2.2  rmind 			    , i, n, ctl->nfree));
   2348  1.4.2.2  rmind 		KASSERT(n == ctl->nfree);
   2349  1.4.2.2  rmind 	}
   2350  1.4.2.2  rmind }
   2351  1.4.2.2  rmind 
   2352  1.4.2.2  rmind /*!\brief	Initialise debug support.
   2353  1.4.2.2  rmind  */
   2354  1.4.2.2  rmind static void
   2355  1.4.2.2  rmind vtw_debug_init(void)
   2356  1.4.2.2  rmind {
   2357  1.4.2.2  rmind 	int	i;
   2358  1.4.2.2  rmind 
   2359  1.4.2.2  rmind 	vtw_sanity_check();
   2360  1.4.2.2  rmind 
   2361  1.4.2.2  rmind 	if (vtw_syscall)
   2362  1.4.2.2  rmind 		return;
   2363  1.4.2.2  rmind 
   2364  1.4.2.2  rmind 	for (i = 511; i; --i) {
   2365  1.4.2.2  rmind 		if (sysent[i].sy_call == sys_nosys) {
   2366  1.4.2.2  rmind 			sysent[i].sy_call    = vtw_sys;
   2367  1.4.2.2  rmind 			sysent[i].sy_narg    = 2;
   2368  1.4.2.2  rmind 			sysent[i].sy_argsize = sizeof (struct sys_vtw_args);
   2369  1.4.2.2  rmind 			sysent[i].sy_flags   = 0;
   2370  1.4.2.2  rmind 
   2371  1.4.2.2  rmind 			vtw_syscall = i;
   2372  1.4.2.2  rmind 			break;
   2373  1.4.2.2  rmind 		}
   2374  1.4.2.2  rmind 	}
   2375  1.4.2.2  rmind 	if (i) {
   2376  1.4.2.2  rmind 		const struct sysctlnode *node;
   2377  1.4.2.2  rmind 		uint32_t	flags;
   2378  1.4.2.2  rmind 
   2379  1.4.2.2  rmind 		flags = sysctl_root.sysctl_flags;
   2380  1.4.2.2  rmind 
   2381  1.4.2.2  rmind 		sysctl_root.sysctl_flags |= CTLFLAG_READWRITE;
   2382  1.4.2.2  rmind 		sysctl_root.sysctl_flags &= ~CTLFLAG_PERMANENT;
   2383  1.4.2.2  rmind 
   2384  1.4.2.2  rmind 		sysctl_createv(0, 0, 0, &node,
   2385  1.4.2.2  rmind 			       CTLFLAG_PERMANENT, CTLTYPE_NODE,
   2386  1.4.2.2  rmind 			       "koff",
   2387  1.4.2.2  rmind 			       SYSCTL_DESCR("Kernel Obscure Feature Finder"),
   2388  1.4.2.2  rmind 			       0, 0, 0, 0, CTL_CREATE, CTL_EOL);
   2389  1.4.2.2  rmind 
   2390  1.4.2.2  rmind 		if (!node) {
   2391  1.4.2.2  rmind 			sysctl_createv(0, 0, 0, &node,
   2392  1.4.2.2  rmind 				       CTLFLAG_PERMANENT, CTLTYPE_NODE,
   2393  1.4.2.2  rmind 				       "koffka",
   2394  1.4.2.2  rmind 				       SYSCTL_DESCR("The Real(tm) Kernel"
   2395  1.4.2.2  rmind 						    " Obscure Feature Finder"),
   2396  1.4.2.2  rmind 				       0, 0, 0, 0, CTL_CREATE, CTL_EOL);
   2397  1.4.2.2  rmind 		}
   2398  1.4.2.2  rmind 		if (node) {
   2399  1.4.2.2  rmind 			sysctl_createv(0, 0, 0, 0,
   2400  1.4.2.2  rmind 				       CTLFLAG_PERMANENT|CTLFLAG_READONLY,
   2401  1.4.2.2  rmind 				       CTLTYPE_INT, "vtw_debug_syscall",
   2402  1.4.2.2  rmind 				       SYSCTL_DESCR("vtw debug"
   2403  1.4.2.2  rmind 						    " system call number"),
   2404  1.4.2.2  rmind 				       0, 0, &vtw_syscall, 0, node->sysctl_num,
   2405  1.4.2.2  rmind 				       CTL_CREATE, CTL_EOL);
   2406  1.4.2.2  rmind 		}
   2407  1.4.2.2  rmind 		sysctl_root.sysctl_flags = flags;
   2408  1.4.2.2  rmind 	}
   2409  1.4.2.2  rmind }
   2410  1.4.2.2  rmind #else /* !VTW_DEBUG */
   2411  1.4.2.2  rmind static void
   2412  1.4.2.2  rmind vtw_debug_init(void)
   2413  1.4.2.2  rmind {
   2414  1.4.2.2  rmind 	return;
   2415  1.4.2.2  rmind }
   2416  1.4.2.2  rmind #endif /* !VTW_DEBUG */
   2417