1 /* $NetBSD: vtw.c,v 1.8 2015/06/16 22:54:10 christos Exp $ */
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Coyote Point Systems, Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 * Copyright (c) 1983, 1988, 1993
33 * The Regents of the University of California. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 #include <sys/cdefs.h>
63 static char sccsid
[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
65 __RCSID("$NetBSD: vtw.c,v 1.8 2015/06/16 22:54:10 christos Exp $");
69 #define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
71 #include <sys/param.h>
72 #include <sys/queue.h>
73 #include <sys/socket.h>
74 #include <sys/socketvar.h>
76 #include <sys/protosw.h>
77 #include <sys/sysctl.h>
79 #include <net/if_arp.h>
80 #include <net/route.h>
81 #include <netinet/in.h>
82 #include <netinet/in_systm.h>
83 #include <netinet/ip.h>
84 #include <netinet/in_pcb.h>
85 #include <netinet/ip_icmp.h>
88 #include <netinet/ip6.h>
91 #include <netinet/icmp_var.h>
92 #include <netinet/igmp_var.h>
93 #include <netinet/ip_var.h>
94 #include <netinet/pim_var.h>
95 #include <netinet/tcp.h>
96 #include <netinet/tcpip.h>
97 #include <netinet/tcp_seq.h>
98 #include <netinet/tcp_fsm.h>
99 #include <netinet/tcp_timer.h>
100 #include <netinet/tcp_var.h>
101 #include <netinet/tcp_debug.h>
102 #include <netinet/udp.h>
103 #include <netinet/ip_carp.h>
104 #include <netinet/udp_var.h>
105 #include <netinet/tcp_vtw.h>
107 #include <arpa/inet.h>
117 #include "prog_ops.h"
119 static void snarf(const void *, void *, size_t);
120 static void *lookup(const char *);
121 static void process_vtw(const vtw_ctl_t
*, void (*)(const vtw_t
*));
124 snarf(const void *addr
, void *buf
, size_t len
)
130 cc
= kvm_read(get_kvmd(), (unsigned long) addr
, buf
, len
);
133 warnx("%s: short read at %p, len %zx cc %zx", __func__
, addr
,
139 lookup(const char *name
)
148 if ((k
= get_kvmd()) == NULL
) {
150 errx(EXIT_FAILURE
, "kvm not available");
153 switch (kvm_nlist(k
, &nl
[0])) {
155 err(EXIT_FAILURE
, "kvm_nlist");
159 return (void *)nl
[0].n_value
;
163 errx(EXIT_FAILURE
, "%s missing in symbol table", name
);
171 timebase(struct timeval
*tv
)
174 struct bintime timebasebin
;
176 p
= lookup("timebasebin");
179 snarf(p
, &timebasebin
, sizeof(timebasebin
));
180 bintime2timeval(&timebasebin
, tv
);
184 process_vtw(const vtw_ctl_t
* ctl
, void (*print
)(const vtw_t
*))
188 for (vp
= ctl
->base
.v
; vp
&& vp
<= ctl
->lim
.v
;) {
193 vtw_v4_t
*v4
= (vtw_v4_t
*)vp
;
195 vp
= &(++v4
)->common
;
196 } else if (ctl
->is_v6
) {
197 vtw_v6_t
*v6
= (vtw_v6_t
*)vp
;
199 vp
= &(++v6
)->common
;
213 if ((p
= lookup("vtw_stats")) == NULL
)
215 snarf(p
, &stats
, sizeof(stats
));
217 printf("\t\t%" PRIu64
" inserts\n", stats
.ins
);
218 printf("\t\t%" PRIu64
" deletes\n", stats
.del
);
219 printf("\t\t%" PRIu64
" assassinations\n", stats
.kill
);
220 printf("\tvestigial time-wait lookup_connect\n");
221 printf("\t\t%" PRIu64
" look\n", stats
.look
[0]);
222 printf("\t\t%" PRIu64
" hit\n", stats
.hit
[0]);
223 printf("\t\t%" PRIu64
" miss\n", stats
.miss
[0]);
224 printf("\t\t%" PRIu64
" probe\n", stats
.probe
[0]);
225 printf("\t\t%" PRIu64
" losing\n", stats
.losing
[0]);
226 printf("\t\t%" PRIu64
" max_chain\n", stats
.max_chain
[0]);
227 printf("\t\t%" PRIu64
" max_probe\n", stats
.max_probe
[0]);
228 printf("\t\t%" PRIu64
" max_loss\n", stats
.max_loss
[0]);
229 printf("\tvestigial time-wait lookup_port\n");
230 printf("\t\t%" PRIu64
" look\n", stats
.look
[1]);
231 printf("\t\t%" PRIu64
" hit\n", stats
.hit
[1]);
232 printf("\t\t%" PRIu64
" miss\n", stats
.miss
[1]);
233 printf("\t\t%" PRIu64
" probe\n", stats
.probe
[1]);
234 printf("\t\t%" PRIu64
" losing\n", stats
.losing
[1]);
235 printf("\t\t%" PRIu64
" max_chain\n", stats
.max_chain
[1]);
236 printf("\t\t%" PRIu64
" max_probe\n", stats
.max_probe
[1]);
237 printf("\t\t%" PRIu64
" max_loss\n", stats
.max_loss
[1]);
241 show_vtw_v4(void (*print
)(const vtw_t
*))
244 fatp_t
**hash
, **port
;
246 fatp_ctl_t fat_tcpv4
;
247 vtw_ctl_t vtw_tcpv4
[VTW_NCLASS
];
252 if ((p
= lookup("fat_tcpv4")) == NULL
)
254 snarf(p
, &fat_tcpv4
, sizeof(fat_tcpv4
));
256 if ((p
= lookup("vtw_tcpv4")) == NULL
)
258 snarf(p
, &vtw_tcpv4
[0], sizeof(vtw_tcpv4
));
260 mem
+= sizeof(fat_tcpv4
);
261 mem
+= sizeof(vtw_tcpv4
);
263 /* snarf/adjust vtw_ctl */
264 for (i
= 0; i
< VTW_NCLASS
; ++i
) {
265 vtw_v4_t
*kbase
, *klim
;
269 kbase
= vtw_tcpv4
[i
].base
.v4
;
270 klim
= vtw_tcpv4
[i
].lim
.v4
;
275 n
= (klim
- kbase
+ 1);
278 if ((ubase
= malloc(n
* sizeof(*kbase
))) == NULL
)
279 err(EXIT_FAILURE
, NULL
);
280 snarf(kbase
, ubase
, n
* sizeof(*ubase
));
282 mem
+= n
* sizeof(*ubase
);
284 ubase
= vtw_tcpv4
[0].base
.v4
;
287 delta
= ubase
- kbase
;
289 vtw_tcpv4
[i
].base
.v4
+= delta
;
290 vtw_tcpv4
[i
].lim
.v4
+= delta
;
291 vtw_tcpv4
[i
].alloc
.v4
+= delta
;
292 vtw_tcpv4
[i
].fat
= &fat_tcpv4
;
294 if (vtw_tcpv4
[i
].oldest
.v4
)
295 vtw_tcpv4
[i
].oldest
.v4
+= delta
;
298 /* snarf/adjust fat_ctl */
300 base
= fat_tcpv4
.base
;
306 mem
+= (lim
- base
+ 1) * sizeof(*base
);
308 fat_tcpv4
.base
= malloc((lim
- base
+ 1) * sizeof(*base
));
309 if (fat_tcpv4
.base
== NULL
)
310 err(EXIT_FAILURE
, NULL
);
311 fat_tcpv4
.lim
= fat_tcpv4
.base
+ (lim
- base
);
313 snarf(base
, fat_tcpv4
.base
, sizeof(*base
) * (lim
- base
+ 1));
315 fat_tcpv4
.vtw
= &vtw_tcpv4
[0];
316 fat_tcpv4
.free
= fat_tcpv4
.base
+ (fat_tcpv4
.free
- base
);
318 n
= fat_tcpv4
.mask
+ 1;
319 hash
= fat_tcpv4
.hash
;
320 port
= fat_tcpv4
.port
;
322 fat_tcpv4
.hash
= malloc(n
* sizeof(*hash
));
323 fat_tcpv4
.port
= malloc(n
* sizeof(*port
));
324 if (fat_tcpv4
.hash
== NULL
|| fat_tcpv4
.port
== NULL
)
325 err(EXIT_FAILURE
, NULL
);
327 snarf(hash
, fat_tcpv4
.hash
, n
* sizeof(*hash
));
328 snarf(port
, fat_tcpv4
.port
, n
* sizeof(*port
));
331 process_vtw(&vtw_tcpv4
[0], print
);
334 if (Vflag
&& vflag
) {
335 printf("total memory for VTW in current config: %d bytes %f MB\n"
337 ,mem
/ (1024.0 * 1024));
343 show_vtw_v6(void (*print
)(const vtw_t
*))
346 fatp_t
**hash
, **port
;
348 fatp_ctl_t fat_tcpv6
;
349 vtw_ctl_t vtw_tcpv6
[VTW_NCLASS
];
354 if ((p
= lookup("fat_tcpv6")) == NULL
)
356 snarf(p
, &fat_tcpv6
, sizeof(fat_tcpv6
));
357 if ((p
= lookup("vtw_tcpv6")) == NULL
)
359 snarf(p
, &vtw_tcpv6
[0], sizeof(vtw_tcpv6
));
361 mem
+= sizeof(fat_tcpv6
);
362 mem
+= sizeof(vtw_tcpv6
);
364 for (i
= 0; i
< VTW_NCLASS
; ++i
) {
365 vtw_v6_t
*kbase
, *klim
;
369 kbase
= vtw_tcpv6
[i
].base
.v6
;
370 klim
= vtw_tcpv6
[i
].lim
.v6
;
375 n
= (klim
- kbase
+ 1);
378 if ((ubase
= malloc(n
* sizeof(*kbase
))) == NULL
)
379 err(EXIT_FAILURE
, NULL
);
381 snarf(kbase
, ubase
, n
* sizeof(*ubase
));
383 mem
+= n
* sizeof(*ubase
);
385 ubase
= vtw_tcpv6
[0].base
.v6
;
388 delta
= ubase
- kbase
;
390 vtw_tcpv6
[i
].base
.v6
+= delta
;
391 vtw_tcpv6
[i
].lim
.v6
+= delta
;
392 vtw_tcpv6
[i
].alloc
.v6
+= delta
;
393 vtw_tcpv6
[i
].fat
= &fat_tcpv6
;
395 if (vtw_tcpv6
[i
].oldest
.v6
)
396 vtw_tcpv6
[i
].oldest
.v6
+= delta
;
399 base
= fat_tcpv6
.base
;
405 mem
+= (lim
- base
+ 1) * sizeof(*base
);
407 fat_tcpv6
.base
= malloc((lim
- base
+ 1) * sizeof(*base
));
408 if (fat_tcpv6
.base
== NULL
)
409 err(EXIT_FAILURE
, NULL
);
410 fat_tcpv6
.lim
= fat_tcpv6
.base
+ (lim
- base
);
412 snarf(base
, fat_tcpv6
.base
, sizeof(*base
) * (lim
- base
+ 1));
414 fat_tcpv6
.vtw
= &vtw_tcpv6
[0];
415 fat_tcpv6
.free
= fat_tcpv6
.base
+ (fat_tcpv6
.free
- base
);
417 n
= fat_tcpv6
.mask
+ 1;
418 hash
= fat_tcpv6
.hash
;
419 port
= fat_tcpv6
.port
;
421 fat_tcpv6
.hash
= malloc(n
* sizeof(*hash
));
422 fat_tcpv6
.port
= malloc(n
* sizeof(*port
));
423 if (fat_tcpv6
.hash
== NULL
|| fat_tcpv6
.port
== NULL
)
424 err(EXIT_FAILURE
, NULL
);
426 snarf(hash
, fat_tcpv6
.hash
, n
* sizeof(*hash
));
427 snarf(port
, fat_tcpv6
.port
, n
* sizeof(*port
));
431 process_vtw(&vtw_tcpv6
[0], print
);
433 if (Vflag
&& vflag
) {
434 printf("total memory for VTW in current config: %d bytes %f MB\n"
436 ,mem
/ (1024.0 * 1024));