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