Make IP, TCP, UDP, and ICMP statistics per-CPU. The stats are collated

when the user requests them via sysctl.
This commit is contained in:
thorpej 2008-04-12 05:58:22 +00:00
parent bdd6dadf75
commit 7ff8d08aae
25 changed files with 777 additions and 283 deletions

16
sys/dist/pf/net/pf.c vendored
View File

@ -1,4 +1,4 @@
/* $NetBSD: pf.c,v 1.49 2008/04/08 15:04:35 thorpej Exp $ */
/* $NetBSD: pf.c,v 1.50 2008/04/12 05:58:22 thorpej Exp $ */
/* $OpenBSD: pf.c,v 1.487 2005/04/22 09:53:18 dhartmei Exp $ */
/*
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pf.c,v 1.49 2008/04/08 15:04:35 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: pf.c,v 1.50 2008/04/12 05:58:22 thorpej Exp $");
#include "bpfilter.h"
#include "pflog.h"
@ -5442,7 +5442,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
rt = rtcache_init(ro);
if (rt == NULL) {
ipstat[IP_STAT_NOROUTE]++;
ip_statinc(IP_STAT_NOROUTE);
goto bad;
}
@ -5555,7 +5555,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
* Must be able to put at least 8 bytes per fragment.
*/
if (ip->ip_off & htons(IP_DF)) {
ipstat[IP_STAT_CANTFRAG]++;
ip_statinc(IP_STAT_CANTFRAG);
if (r->rt != PF_DUPTO) {
icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
ifp->if_mtu);
@ -5585,7 +5585,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
}
if (error == 0)
ipstat[IP_STAT_FRAGMENTED]++;
ip_statinc(IP_STAT_FRAGMENTED);
done:
if (r->rt != PF_DUPTO)
@ -5829,13 +5829,13 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
#endif
switch (p) {
case IPPROTO_TCP:
tcpstat[TCP_STAT_RCVBADSUM]++;
tcp_statinc(TCP_STAT_RCVBADSUM);
break;
case IPPROTO_UDP:
udpstat[UDP_STAT_BADSUM]++;
udp_statinc(UDP_STAT_BADSUM);
break;
case IPPROTO_ICMP:
icmpstat[ICMP_STAT_CHECKSUM]++;
icmp_statinc(ICMP_STAT_CHECKSUM);
break;
#ifdef INET6
case IPPROTO_ICMPV6:

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bridge.c,v 1.58 2008/04/08 23:37:43 thorpej Exp $ */
/* $NetBSD: if_bridge.c,v 1.59 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.58 2008/04/08 23:37:43 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.59 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_bridge_ipf.h"
#include "opt_inet.h"
@ -2078,12 +2078,12 @@ bridge_ip_checkbasic(struct mbuf **mp)
if ((m = m_copyup(m, sizeof(struct ip),
(max_linkhdr + 3) & ~3)) == NULL) {
/* XXXJRT new stat, please */
ipstat[IP_STAT_TOOSMALL]++;
ip_statinc(IP_STAT_TOOSMALL);
goto bad;
}
} else if (__predict_false(m->m_len < sizeof (struct ip))) {
if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
ipstat[IP_STAT_TOOSMALL]++;
ip_statinc(IP_STAT_TOOSMALL);
goto bad;
}
}
@ -2091,17 +2091,17 @@ bridge_ip_checkbasic(struct mbuf **mp)
if (ip == NULL) goto bad;
if (ip->ip_v != IPVERSION) {
ipstat[IP_STAT_BADVERS]++;
ip_statinc(IP_STAT_BADVERS);
goto bad;
}
hlen = ip->ip_hl << 2;
if (hlen < sizeof(struct ip)) { /* minimum header length */
ipstat[IP_STAT_BADHLEN]++;
ip_statinc(IP_STAT_BADHLEN);
goto bad;
}
if (hlen > m->m_len) {
if ((m = m_pullup(m, hlen)) == 0) {
ipstat[IP_STAT_BADHLEN]++;
ip_statinc(IP_STAT_BADHLEN);
goto bad;
}
ip = mtod(m, struct ip *);
@ -2135,7 +2135,7 @@ bridge_ip_checkbasic(struct mbuf **mp)
* Check for additional length bogosity
*/
if (len < hlen) {
ipstat[IP_STAT_BADLEN]++;
ip_statinc(IP_STAT_BADLEN);
goto bad;
}
@ -2145,7 +2145,7 @@ bridge_ip_checkbasic(struct mbuf **mp)
* Drop packet if shorter than we expect.
*/
if (m->m_pkthdr.len < len) {
ipstat[IP_STAT_TOOSHORT]++;
ip_statinc(IP_STAT_TOOSHORT);
goto bad;
}

View File

@ -0,0 +1,69 @@
/* $NetBSD: icmp_private.h,v 1.1 2008/04/12 05:58:22 thorpej Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NETINET_ICMP_PRIVATE_H_
#define _NETINET_ICMP_PRIVATE_H_
/*
* Private definitions related to this implementation
* of the internet control message protocol.
*/
#ifdef _KERNEL
#include <sys/percpu.h>
extern percpu_t *icmpstat_percpu;
/*
* Most ICMP statistics are exceptional conditions, so this is good enough.
*/
#define ICMP_STATINC(x) \
do { \
uint64_t *_icps_ = percpu_getref(icmpstat_percpu); \
_icps_[x]++; \
percpu_putref(icmpstat_percpu); \
} while (/*CONSTCOND*/0)
#ifdef __NO_STRICT_ALIGNMENT
#define ICMP_HDR_ALIGNED_P(ic) 1
#else
#define ICMP_HDR_ALIGNED_P(ic) ((((vaddr_t) (ic)) & 3) == 0)
#endif
#endif /* _KERNEL_ */
#endif /* !_NETINET_ICMP_PRIVATE_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: icmp_var.h,v 1.26 2008/04/06 19:04:50 thorpej Exp $ */
/* $NetBSD: icmp_var.h,v 1.27 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@ -89,13 +89,9 @@
}
#ifdef _KERNEL
extern uint64_t icmpstat[ICMP_NSTATS];
#ifdef __NO_STRICT_ALIGNMENT
#define ICMP_HDR_ALIGNED_P(ic) 1
#else
#define ICMP_HDR_ALIGNED_P(ic) ((((vaddr_t) (ic)) & 3) == 0)
#endif
void icmp_statinc(u_int stat);
#endif /* _KERNEL_ */
#endif /* !_NETINET_ICMP_VAR_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_gif.c,v 1.58 2008/04/07 06:31:28 thorpej Exp $ */
/* $NetBSD: in_gif.c,v 1.59 2008/04/12 05:58:22 thorpej Exp $ */
/* $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.58 2008/04/07 06:31:28 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.59 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_iso.h"
@ -221,13 +221,13 @@ in_gif_input(struct mbuf *m, ...)
if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
m_freem(m);
ipstat[IP_STAT_NOGIF]++;
ip_statinc(IP_STAT_NOGIF);
return;
}
#ifndef GIF_ENCAPCHECK
if (!gif_validate4(ip, (struct gif_softc *)gifp, m->m_pkthdr.rcvif)) {
m_freem(m);
ipstat[IP_STAT_NOGIF]++;
ip_statinc(IP_STAT_NOGIF);
return;
}
#endif
@ -280,7 +280,7 @@ in_gif_input(struct mbuf *m, ...)
break;
#endif
default:
ipstat[IP_STAT_NOGIF]++;
ip_statinc(IP_STAT_NOGIF);
m_freem(m);
return;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_etherip.c,v 1.8 2008/04/07 06:31:28 thorpej Exp $ */
/* $NetBSD: ip_etherip.c,v 1.9 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_etherip.c,v 1.8 2008/04/07 06:31:28 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_etherip.c,v 1.9 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
@ -193,7 +193,7 @@ ip_etherip_input(struct mbuf *m, ...)
if (proto != IPPROTO_ETHERIP) {
m_freem(m);
ipstat[IP_STAT_NOPROTO]++;
ip_statinc(IP_STAT_NOPROTO);
return;
}
@ -222,7 +222,7 @@ ip_etherip_input(struct mbuf *m, ...)
/* no matching device found */
if (!ifp) {
m_freem(m);
ipstat[IP_STAT_ODROPPED]++;
ip_statinc(IP_STAT_ODROPPED);
return;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_flow.c,v 1.53 2008/04/09 05:14:20 thorpej Exp $ */
/* $NetBSD: ip_flow.c,v 1.54 2008/04/12 05:58:22 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.53 2008/04/09 05:14:20 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.54 2008/04/12 05:58:22 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -64,6 +64,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.53 2008/04/09 05:14:20 thorpej Exp $")
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
#include <netinet/ip_private.h>
/*
* Similar code is very well commented in netinet6/ip6_flow.c
@ -313,13 +314,17 @@ static void
ipflow_addstats(struct ipflow *ipf)
{
struct rtentry *rt;
uint64_t *ips;
if ((rt = rtcache_validate(&ipf->ipf_ro)) != NULL)
rt->rt_use += ipf->ipf_uses;
ipstat[IP_STAT_CANTFORWARD] += ipf->ipf_errors + ipf->ipf_dropped;
ipstat[IP_STAT_TOTAL] += ipf->ipf_uses;
ipstat[IP_STAT_FORWARD] += ipf->ipf_uses;
ipstat[IP_STAT_FASTFORWARD] += ipf->ipf_uses;
ips = IP_STAT_GETREF();
ips[IP_STAT_CANTFORWARD] += ipf->ipf_errors + ipf->ipf_dropped;
ips[IP_STAT_TOTAL] += ipf->ipf_uses;
ips[IP_STAT_FORWARD] += ipf->ipf_uses;
ips[IP_STAT_FASTFORWARD] += ipf->ipf_uses;
IP_STAT_PUTREF();
}
static void
@ -401,6 +406,7 @@ ipflow_slowtimo(void)
{
struct rtentry *rt;
struct ipflow *ipf, *next_ipf;
uint64_t *ips;
for (ipf = LIST_FIRST(&ipflowlist); ipf != NULL; ipf = next_ipf) {
next_ipf = LIST_NEXT(ipf, ipf_list);
@ -410,9 +416,11 @@ ipflow_slowtimo(void)
} else {
ipf->ipf_last_uses = ipf->ipf_uses;
rt->rt_use += ipf->ipf_uses;
ipstat[IP_STAT_TOTAL] += ipf->ipf_uses;
ipstat[IP_STAT_FORWARD] += ipf->ipf_uses;
ipstat[IP_STAT_FASTFORWARD] += ipf->ipf_uses;
ips = IP_STAT_GETREF();
ips[IP_STAT_TOTAL] += ipf->ipf_uses;
ips[IP_STAT_FORWARD] += ipf->ipf_uses;
ips[IP_STAT_FASTFORWARD] += ipf->ipf_uses;
IP_STAT_PUTREF();
ipf->ipf_uses = 0;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_icmp.c,v 1.115 2008/04/06 19:04:50 thorpej Exp $ */
/* $NetBSD: ip_icmp.c,v 1.116 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -101,7 +101,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.115 2008/04/06 19:04:50 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.116 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_ipsec.h"
@ -128,6 +128,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.115 2008/04/06 19:04:50 thorpej Exp $"
#include <netinet/in_pcb.h>
#include <netinet/in_proto.h>
#include <netinet/icmp_var.h>
#include <netinet/icmp_private.h>
#ifdef IPSEC
#include <netinet6/ipsec.h>
@ -153,7 +154,7 @@ int icmpprintfs = 0;
#endif
int icmpreturndatabytes = 8;
uint64_t icmpstat[ICMP_NSTATS];
percpu_t *icmpstat_percpu;
/*
* List of callbacks to notify when Path MTU changes are made.
@ -196,6 +197,8 @@ icmp_init(void)
icmp_redirect_timeout_q =
rt_timer_queue_create(icmp_redirtimeout);
}
icmpstat_percpu = percpu_alloc(sizeof(uint64_t) * ICMP_NSTATS);
}
/*
@ -240,7 +243,7 @@ icmp_error(struct mbuf *n, int type, int code, n_long dest,
printf("icmp_error(%p, type:%d, code:%d)\n", oip, type, code);
#endif
if (type != ICMP_REDIRECT)
icmpstat[ICMP_STAT_ERROR]++;
ICMP_STATINC(ICMP_STAT_ERROR);
/*
* Don't send error if the original packet was encrypted.
* Don't send error if not the first fragment of message.
@ -254,7 +257,7 @@ icmp_error(struct mbuf *n, int type, int code, n_long dest,
if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
n->m_len >= oiplen + ICMP_MINLEN &&
!ICMP_INFOTYPE(((struct icmp *)((char *)oip + oiplen))->icmp_type)) {
icmpstat[ICMP_STAT_OLDICMP]++;
ICMP_STATINC(ICMP_STAT_OLDICMP);
goto freeit;
}
/* Don't send error in response to a multicast or broadcast packet */
@ -313,7 +316,7 @@ icmp_error(struct mbuf *n, int type, int code, n_long dest,
icp = mtod(m, struct icmp *);
if ((u_int)type > ICMP_MAXTYPE)
panic("icmp_error");
icmpstat[ICMP_STAT_OUTHIST + type]++;
ICMP_STATINC(ICMP_STAT_OUTHIST + type);
icp->icmp_type = type;
if (type == ICMP_REDIRECT)
icp->icmp_gwaddr.s_addr = dest;
@ -419,12 +422,12 @@ icmp_input(struct mbuf *m, ...)
}
#endif
if (icmplen < ICMP_MINLEN) {
icmpstat[ICMP_STAT_TOOSHORT]++;
ICMP_STATINC(ICMP_STAT_TOOSHORT);
goto freeit;
}
i = hlen + min(icmplen, ICMP_ADVLENMIN);
if ((m->m_len < i || M_READONLY(m)) && (m = m_pullup(m, i)) == 0) {
icmpstat[ICMP_STAT_TOOSHORT]++;
ICMP_STATINC(ICMP_STAT_TOOSHORT);
return;
}
ip = mtod(m, struct ip *);
@ -433,7 +436,7 @@ icmp_input(struct mbuf *m, ...)
icp = mtod(m, struct icmp *);
/* Don't need to assert alignment, here. */
if (in_cksum(m, icmplen)) {
icmpstat[ICMP_STAT_CHECKSUM]++;
ICMP_STATINC(ICMP_STAT_CHECKSUM);
goto freeit;
}
m->m_len += hlen;
@ -449,7 +452,7 @@ icmp_input(struct mbuf *m, ...)
#endif
if (icp->icmp_type > ICMP_MAXTYPE)
goto raw;
icmpstat[ICMP_STAT_INHIST + icp->icmp_type]++;
ICMP_STATINC(ICMP_STAT_INHIST + icp->icmp_type);
code = icp->icmp_code;
switch (icp->icmp_type) {
@ -521,7 +524,7 @@ icmp_input(struct mbuf *m, ...)
*/
if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
icmpstat[ICMP_STAT_BADLEN]++;
ICMP_STATINC(ICMP_STAT_BADLEN);
goto freeit;
}
if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr))
@ -538,7 +541,7 @@ icmp_input(struct mbuf *m, ...)
break;
badcode:
icmpstat[ICMP_STAT_BADCODE]++;
ICMP_STATINC(ICMP_STAT_BADCODE);
break;
case ICMP_ECHO:
@ -547,7 +550,7 @@ icmp_input(struct mbuf *m, ...)
case ICMP_TSTAMP:
if (icmplen < ICMP_TSLEN) {
icmpstat[ICMP_STAT_BADLEN]++;
ICMP_STATINC(ICMP_STAT_BADLEN);
break;
}
icp->icmp_type = ICMP_TSTAMPREPLY;
@ -563,7 +566,7 @@ icmp_input(struct mbuf *m, ...)
* unless we receive it over a point-to-point interface.
*/
if (icmplen < ICMP_MASKLEN) {
icmpstat[ICMP_STAT_BADLEN]++;
ICMP_STATINC(ICMP_STAT_BADLEN);
break;
}
if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
@ -584,8 +587,12 @@ icmp_input(struct mbuf *m, ...)
ip->ip_src = ia->ia_dstaddr.sin_addr;
}
reflect:
icmpstat[ICMP_STAT_REFLECT]++;
icmpstat[ICMP_STAT_OUTHIST + icp->icmp_type]++;
{
uint64_t *icps = percpu_getref(icmpstat_percpu);
icps[ICMP_STAT_REFLECT]++;
icps[ICMP_STAT_OUTHIST + icp->icmp_type]++;
percpu_putref(icmpstat_percpu);
}
icmp_reflect(m);
return;
@ -596,7 +603,7 @@ reflect:
goto freeit;
if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
icmpstat[ICMP_STAT_BADLEN]++;
ICMP_STATINC(ICMP_STAT_BADLEN);
break;
}
/*
@ -976,6 +983,38 @@ sysctl_net_inet_icmp_redirtimeout(SYSCTLFN_ARGS)
return (0);
}
static void
icmpstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci)
{
uint64_t *icpsc = v1;
uint64_t *icps = v2;
u_int i;
for (i = 0; i < ICMP_NSTATS; i++)
icps[i] += icpsc[i];
}
static void
icmpstat_convert_to_user(uint64_t *icps)
{
memset(icps, 0, sizeof(uint64_t) * ICMP_NSTATS);
percpu_foreach(icmpstat_percpu, icmpstat_convert_to_user_cb, icps);
}
static int
sysctl_net_inet_icmp_stats(SYSCTLFN_ARGS)
{
struct sysctlnode node;
uint64_t icps[ICMP_NSTATS];
icmpstat_convert_to_user(icps);
node = *rnode;
node.sysctl_data = icps;
node.sysctl_size = sizeof(icps);
return (sysctl_lookup(SYSCTLFN_CALL(&node)));
}
SYSCTL_SETUP(sysctl_net_inet_icmp_setup, "sysctl net.inet.icmp subtree setup")
{
@ -1040,11 +1079,19 @@ SYSCTL_SETUP(sysctl_net_inet_icmp_setup, "sysctl net.inet.icmp subtree setup")
CTLFLAG_PERMANENT,
CTLTYPE_STRUCT, "stats",
SYSCTL_DESCR("ICMP statistics"),
NULL, 0, icmpstat, sizeof(icmpstat),
sysctl_net_inet_icmp_stats, 0, NULL, 0,
CTL_NET, PF_INET, IPPROTO_ICMP, ICMPCTL_STATS,
CTL_EOL);
}
void
icmp_statinc(u_int stat)
{
KASSERT(stat < ICMP_NSTATS);
ICMP_STATINC(stat);
}
/* Table of common MTUs: */
static const u_int mtu_table[] = {
@ -1127,7 +1174,7 @@ icmp_mtudisc(struct icmp *icp, struct in_addr faddr)
rt->rt_rmx.rmx_locks |= RTV_MTU;
else if (rt->rt_rmx.rmx_mtu > mtu ||
rt->rt_rmx.rmx_mtu == 0) {
icmpstat[ICMP_STAT_PMTUCHG]++;
ICMP_STATINC(ICMP_STAT_PMTUCHG);
rt->rt_rmx.rmx_mtu = mtu;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_input.c,v 1.265 2008/04/09 05:14:20 thorpej Exp $ */
/* $NetBSD: ip_input.c,v 1.266 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.265 2008/04/09 05:14:20 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.266 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_gateway.h"
@ -135,6 +135,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.265 2008/04/09 05:14:20 thorpej Exp $
#include <netinet/in_proto.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
#include <netinet/ip_private.h>
#include <netinet/ip_icmp.h>
/* just for gif_ttl */
#include <netinet/in_gif.h>
@ -230,9 +231,10 @@ u_long in_multihash; /* size of hash table - 1 */
int in_multientries; /* total number of addrs */
struct in_multihashhead *in_multihashtbl;
struct ifqueue ipintrq;
uint64_t ipstat[IP_NSTATS];
uint16_t ip_id;
percpu_t *ipstat_percpu;
#ifdef PFIL_HOOKS
struct pfil_head inet_pfil_hook;
#endif
@ -447,6 +449,8 @@ ip_init(void)
MOWNER_ATTACH(&ip_tx_mowner);
MOWNER_ATTACH(&ip_rx_mowner);
#endif /* MBUFTRACE */
ipstat_percpu = percpu_alloc(sizeof(uint64_t) * IP_NSTATS);
}
struct sockaddr_in ipaddr = {
@ -511,7 +515,7 @@ ip_input(struct mbuf *m)
*/
if (TAILQ_FIRST(&in_ifaddrhead) == 0)
goto bad;
ipstat[IP_STAT_TOTAL]++;
IP_STATINC(IP_STAT_TOTAL);
/*
* If the IP header is not aligned, slurp it up into a new
* mbuf with space for link headers, in the event we forward
@ -522,28 +526,28 @@ ip_input(struct mbuf *m)
if ((m = m_copyup(m, sizeof(struct ip),
(max_linkhdr + 3) & ~3)) == NULL) {
/* XXXJRT new stat, please */
ipstat[IP_STAT_TOOSMALL]++;
IP_STATINC(IP_STAT_TOOSMALL);
return;
}
} else if (__predict_false(m->m_len < sizeof (struct ip))) {
if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
ipstat[IP_STAT_TOOSMALL]++;
IP_STATINC(IP_STAT_TOOSMALL);
return;
}
}
ip = mtod(m, struct ip *);
if (ip->ip_v != IPVERSION) {
ipstat[IP_STAT_BADVERS]++;
IP_STATINC(IP_STAT_BADVERS);
goto bad;
}
hlen = ip->ip_hl << 2;
if (hlen < sizeof(struct ip)) { /* minimum header length */
ipstat[IP_STAT_BADHLEN]++;
IP_STATINC(IP_STAT_BADHLEN);
goto bad;
}
if (hlen > m->m_len) {
if ((m = m_pullup(m, hlen)) == 0) {
ipstat[IP_STAT_BADHLEN]++;
IP_STATINC(IP_STAT_BADHLEN);
return;
}
ip = mtod(m, struct ip *);
@ -554,7 +558,7 @@ ip_input(struct mbuf *m)
* not allowed.
*/
if (IN_MULTICAST(ip->ip_src.s_addr)) {
ipstat[IP_STAT_BADADDR]++;
IP_STATINC(IP_STAT_BADADDR);
goto bad;
}
@ -562,7 +566,7 @@ ip_input(struct mbuf *m)
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
(ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
ipstat[IP_STAT_BADADDR]++;
IP_STATINC(IP_STAT_BADADDR);
goto bad;
}
}
@ -600,7 +604,7 @@ ip_input(struct mbuf *m)
* Check for additional length bogosity
*/
if (len < hlen) {
ipstat[IP_STAT_BADLEN]++;
IP_STATINC(IP_STAT_BADLEN);
goto bad;
}
@ -611,7 +615,7 @@ ip_input(struct mbuf *m)
* Drop packet if shorter than we expect.
*/
if (m->m_pkthdr.len < len) {
ipstat[IP_STAT_TOOSHORT]++;
IP_STATINC(IP_STAT_TOOSHORT);
goto bad;
}
if (m->m_pkthdr.len > len) {
@ -780,7 +784,7 @@ ip_input(struct mbuf *m)
* ip_output().)
*/
if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
m_freem(m);
return;
}
@ -792,7 +796,7 @@ ip_input(struct mbuf *m)
*/
if (ip->ip_p == IPPROTO_IGMP)
goto ours;
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
}
#endif
/*
@ -801,7 +805,7 @@ ip_input(struct mbuf *m)
*/
IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
if (inm == NULL) {
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
m_freem(m);
return;
}
@ -815,7 +819,7 @@ ip_input(struct mbuf *m)
* Not for us; forward if possible and desirable.
*/
if (ipforwarding == 0) {
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
m_freem(m);
} else {
/*
@ -826,7 +830,7 @@ ip_input(struct mbuf *m)
*/
if (downmatch) {
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
return;
}
#ifdef IPSEC
@ -859,7 +863,7 @@ ip_input(struct mbuf *m)
KEY_FREESP(&sp);
splx(s);
if (error) {
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
goto bad;
}
@ -906,7 +910,7 @@ ours:
*/
off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
if ((off > 0 ? off + hlen : len) < IP_MINFRAGSIZE - 1) {
ipstat[IP_STAT_BADFRAGS]++;
IP_STATINC(IP_STAT_BADFRAGS);
goto bad;
}
/*
@ -925,7 +929,7 @@ ours:
* fragments.
*/
if (ip->ip_tos != fp->ipq_tos) {
ipstat[IP_STAT_BADFRAGS]++;
IP_STATINC(IP_STAT_BADFRAGS);
goto bad;
}
goto found;
@ -948,7 +952,7 @@ found:
*/
if (ntohs(ip->ip_len) == 0 ||
(ntohs(ip->ip_len) & 0x7) != 0) {
ipstat[IP_STAT_BADFRAGS]++;
IP_STATINC(IP_STAT_BADFRAGS);
IPQ_UNLOCK();
goto bad;
}
@ -961,12 +965,12 @@ found:
* attempt reassembly; if it succeeds, proceed.
*/
if (mff || ip->ip_off != htons(0)) {
ipstat[IP_STAT_FRAGMENTS]++;
IP_STATINC(IP_STAT_FRAGMENTS);
s = splvm();
ipqe = pool_get(&ipqent_pool, PR_NOWAIT);
splx(s);
if (ipqe == NULL) {
ipstat[IP_STAT_RCVMEMDROP]++;
IP_STATINC(IP_STAT_RCVMEMDROP);
IPQ_UNLOCK();
goto bad;
}
@ -978,7 +982,7 @@ found:
IPQ_UNLOCK();
return;
}
ipstat[IP_STAT_REASSEMBLED]++;
IP_STATINC(IP_STAT_REASSEMBLED);
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
ip->ip_len = htons(ntohs(ip->ip_len) + hlen);
@ -1046,7 +1050,7 @@ DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
if (ia && ip)
ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len);
#endif
ipstat[IP_STAT_DELIVERED]++;
IP_STATINC(IP_STAT_DELIVERED);
{
int off = hlen, nh = ip->ip_p;
@ -1058,7 +1062,7 @@ bad:
return;
badcsum:
ipstat[IP_STAT_BADSUM]++;
IP_STATINC(IP_STAT_BADSUM);
m_freem(m);
}
@ -1216,7 +1220,7 @@ insert:
q = TAILQ_FIRST(&fp->ipq_fragq);
ip = q->ipqe_ip;
if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
ipstat[IP_STAT_TOOLONG]++;
IP_STATINC(IP_STAT_TOOLONG);
ip_freef(fp);
return (0);
}
@ -1266,7 +1270,7 @@ dropfrag:
if (fp != 0)
fp->ipq_nfrags--;
ip_nfrags--;
ipstat[IP_STAT_FRAGDROPPED]++;
IP_STATINC(IP_STAT_FRAGDROPPED);
m_freem(m);
s = splvm();
pool_put(&ipqent_pool, ipqe);
@ -1333,7 +1337,7 @@ ip_reass_ttl_decr(u_int ticks)
0 : fp->ipq_ttl - ticks);
nfp = LIST_NEXT(fp, ipq_q);
if (fp->ipq_ttl == 0) {
ipstat[IP_STAT_FRAGTIMEOUT]++;
IP_STATINC(IP_STAT_FRAGTIMEOUT);
ip_freef(fp);
} else {
nfrags += fp->ipq_nfrags;
@ -1680,7 +1684,7 @@ ip_dooptions(struct mbuf *m)
return (0);
bad:
icmp_error(m, type, code, 0, 0);
ipstat[IP_STAT_BADOPTIONS]++;
IP_STATINC(IP_STAT_BADOPTIONS);
return (1);
}
@ -1853,7 +1857,7 @@ ip_forward(struct mbuf *m, int srcrt)
}
#endif
if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
m_freem(m);
return;
}
@ -1917,12 +1921,15 @@ ip_forward(struct mbuf *m, int srcrt)
(struct ip_moptions *)NULL, (struct socket *)NULL);
if (error)
ipstat[IP_STAT_CANTFORWARD]++;
IP_STATINC(IP_STAT_CANTFORWARD);
else {
ipstat[IP_STAT_FORWARD]++;
if (type)
ipstat[IP_STAT_REDIRECTSENT]++;
else {
uint64_t *ips = IP_STAT_GETREF();
ips[IP_STAT_FORWARD]++;
if (type) {
ips[IP_STAT_REDIRECTSENT]++;
IP_STAT_PUTREF();
} else {
IP_STAT_PUTREF();
if (mcopy) {
#ifdef GATEWAY
if (mcopy->m_flags & M_CANFASTFWD)
@ -2008,7 +2015,7 @@ ip_forward(struct mbuf *m, int srcrt)
}
#endif /*defined(IPSEC) || defined(FAST_IPSEC)*/
}
ipstat[IP_STAT_CANTFRAG]++;
IP_STATINC(IP_STAT_CANTFRAG);
break;
case ENOBUFS:
@ -2187,6 +2194,37 @@ sysctl_net_inet_ip_hashsize(SYSCTLFN_ARGS)
}
#endif /* GATEWAY */
static void
ipstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci)
{
uint64_t *ipsc = v1;
uint64_t *ips = v2;
u_int i;
for (i = 0; i < IP_NSTATS; i++)
ips[i] += ipsc[i];
}
static void
ipstat_convert_to_user(uint64_t *ips)
{
memset(ips, 0, sizeof(uint64_t) * IP_NSTATS);
percpu_foreach(ipstat_percpu, ipstat_convert_to_user_cb, ips);
}
static int
sysctl_net_inet_ip_stats(SYSCTLFN_ARGS)
{
struct sysctlnode node;
uint64_t ips[IP_NSTATS];
ipstat_convert_to_user(ips);
node = *rnode;
node.sysctl_data = ips;
node.sysctl_size = sizeof(ips);
return (sysctl_lookup(SYSCTLFN_CALL(&node)));
}
SYSCTL_SETUP(sysctl_net_inet_ip_setup, "sysctl net.inet.ip subtree setup")
{
@ -2391,7 +2429,15 @@ SYSCTL_SETUP(sysctl_net_inet_ip_setup, "sysctl net.inet.ip subtree setup")
CTLFLAG_PERMANENT,
CTLTYPE_STRUCT, "stats",
SYSCTL_DESCR("IP statistics"),
NULL, 0, ipstat, sizeof(ipstat),
sysctl_net_inet_ip_stats, 0, NULL, 0,
CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS,
CTL_EOL);
}
void
ip_statinc(u_int stat)
{
KASSERT(stat < IP_NSTATS);
IP_STATINC(stat);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_output.c,v 1.193 2008/04/07 06:31:28 thorpej Exp $ */
/* $NetBSD: ip_output.c,v 1.194 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.193 2008/04/07 06:31:28 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.194 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_pfil_hooks.h"
#include "opt_inet.h"
@ -129,6 +129,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.193 2008/04/07 06:31:28 thorpej Exp
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
#include <netinet/ip_private.h>
#include <netinet/in_offload.h>
#ifdef MROUTING
@ -262,7 +263,7 @@ ip_output(struct mbuf *m0, ...)
ip->ip_off = htons(0);
/* ip->ip_id filled in after we find out source ia */
ip->ip_hl = hlen >> 2;
ipstat[IP_STAT_LOCALOUT]++;
IP_STATINC(IP_STAT_LOCALOUT);
} else {
hlen = ip->ip_hl << 2;
}
@ -298,7 +299,7 @@ ip_output(struct mbuf *m0, ...)
*/
if (flags & IP_ROUTETOIF) {
if ((ia = ifatoia(ifa_ifwithladdr(sintocsa(dst)))) == NULL) {
ipstat[IP_STAT_NOROUTE]++;
IP_STATINC(IP_STAT_NOROUTE);
error = ENETUNREACH;
goto bad;
}
@ -315,7 +316,7 @@ ip_output(struct mbuf *m0, ...)
if (rt == NULL)
rt = rtcache_init(ro);
if (rt == NULL) {
ipstat[IP_STAT_NOROUTE]++;
IP_STATINC(IP_STAT_NOROUTE);
error = EHOSTUNREACH;
goto bad;
}
@ -346,7 +347,7 @@ ip_output(struct mbuf *m0, ...)
* output
*/
if (!ifp) {
ipstat[IP_STAT_NOROUTE]++;
IP_STATINC(IP_STAT_NOROUTE);
error = ENETUNREACH;
goto bad;
}
@ -359,7 +360,7 @@ ip_output(struct mbuf *m0, ...)
(ifp->if_flags & IFF_MULTICAST) == 0) ||
((m->m_flags & M_BCAST) &&
(ifp->if_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0)) {
ipstat[IP_STAT_NOROUTE]++;
IP_STATINC(IP_STAT_NOROUTE);
error = ENETUNREACH;
goto bad;
}
@ -447,7 +448,7 @@ ip_output(struct mbuf *m0, ...)
* RFC 1112
*/
if (IN_MULTICAST(ip->ip_src.s_addr)) {
ipstat[IP_STAT_ODROPPED]++;
IP_STATINC(IP_STAT_ODROPPED);
error = EADDRNOTAVAIL;
goto bad;
}
@ -867,7 +868,7 @@ spd_done:
if (flags & IP_RETURNMTU)
*mtu_p = mtu;
error = EMSGSIZE;
ipstat[IP_STAT_CANTFRAG]++;
IP_STATINC(IP_STAT_CANTFRAG);
goto bad;
}
@ -916,7 +917,7 @@ spd_done:
}
if (error == 0)
ipstat[IP_STAT_FRAGMENTED]++;
IP_STATINC(IP_STAT_FRAGMENTED);
done:
rtcache_free(&iproute);
@ -975,7 +976,7 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m == 0) {
error = ENOBUFS;
ipstat[IP_STAT_ODROPPED]++;
IP_STATINC(IP_STAT_ODROPPED);
goto sendorfree;
}
MCLAIM(m, m0->m_owner);
@ -1004,7 +1005,7 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
m->m_next = m_copym(m0, off, len, M_DONTWAIT);
if (m->m_next == 0) {
error = ENOBUFS; /* ??? */
ipstat[IP_STAT_ODROPPED]++;
IP_STATINC(IP_STAT_ODROPPED);
goto sendorfree;
}
m->m_pkthdr.len = mhlen + len;
@ -1017,7 +1018,7 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
m->m_pkthdr.csum_data |= mhlen << 16;
}
ipstat[IP_STAT_OFRAGMENTS]++;
IP_STATINC(IP_STAT_OFRAGMENTS);
fragments++;
}
/*
@ -1048,7 +1049,7 @@ sendorfree:
if (ifp->if_snd.ifq_maxlen - ifp->if_snd.ifq_len < fragments &&
error == 0) {
error = ENOBUFS;
ipstat[IP_STAT_ODROPPED]++;
IP_STATINC(IP_STAT_ODROPPED);
IFQ_INC_DROPS(&ifp->if_snd);
}
splx(s);

71
sys/netinet/ip_private.h Normal file
View File

@ -0,0 +1,71 @@
/* $NetBSD: ip_private.h,v 1.1 2008/04/12 05:58:22 thorpej Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NETINET_IP_PRIVATE_H_
#define _NETINET_IP_PRIVATE_H_
#ifdef _KERNEL
#include <sys/percpu.h>
extern percpu_t *ipstat_percpu;
#define IP_STAT_GETREF() percpu_getref(ipstat_percpu)
#define IP_STAT_PUTREF() percpu_putref(ipstat_percpu)
#define IP_STATINC(x) \
do { \
uint64_t *_ips_ = IP_STAT_GETREF(); \
_ips_[x]++; \
IP_STAT_PUTREF(); \
} while (/*CONSTCOND*/0)
#define IP_STATDEC(x) \
do { \
uint64_t *_ips_ = IP_STAT_GETREF(); \
_ips_[x]--; \
IP_STAT_PUTREF(); \
} while (/*CONSTCOND*/0)
#ifdef __NO_STRICT_ALIGNMENT
#define IP_HDR_ALIGNED_P(ip) 1
#else
#define IP_HDR_ALIGNED_P(ip) ((((vaddr_t) (ip)) & 3) == 0)
#endif
#endif /* _KERNEL */
#endif /* !_NETINET_IP_PRIVATE_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_var.h,v 1.86 2008/04/09 05:14:20 thorpej Exp $ */
/* $NetBSD: ip_var.h,v 1.87 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@ -176,15 +176,8 @@ struct ip_moptions {
#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
#define IP_MTUDISC 0x0400 /* Path MTU Discovery; set DF */
#ifdef __NO_STRICT_ALIGNMENT
#define IP_HDR_ALIGNED_P(ip) 1
#else
#define IP_HDR_ALIGNED_P(ip) ((((vaddr_t) (ip)) & 3) == 0)
#endif
extern struct domain inetdomain;
extern uint64_t ipstat[IP_NSTATS]; /* ip statistics */
extern LIST_HEAD(ipqhead, ipq) ipq[]; /* ip reass. queue */
extern int ip_defttl; /* default IP ttl */
extern int ipforwarding; /* ip forwarding */
@ -232,6 +225,7 @@ void ip_slowtimo(void);
struct mbuf *
ip_srcroute(void);
int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
void ip_statinc(u_int);
void ipintr(void);
void * rip_ctlinput(int, const struct sockaddr *, void *);
int rip_ctloutput(int, struct socket *, int, int, struct mbuf **);

View File

@ -1,4 +1,4 @@
/* $NetBSD: raw_ip.c,v 1.104 2008/04/07 06:31:28 thorpej Exp $ */
/* $NetBSD: raw_ip.c,v 1.105 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.104 2008/04/07 06:31:28 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.105 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -86,6 +86,7 @@ __KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.104 2008/04/07 06:31:28 thorpej Exp $")
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_private.h>
#include <netinet/ip_mroute.h>
#include <netinet/ip_icmp.h>
#include <netinet/in_pcb.h>
@ -215,17 +216,21 @@ rip_input(struct mbuf *m, ...)
if (last != NULL && ipsec4_in_reject_so(m, last->inp_socket)) {
m_freem(m);
ipsecstat.in_polvio++;
ipstat[IP_STAT_DELIVERED]--;
IP_STATDEC(IP_STAT_DELIVERED);
/* do not inject data to pcb */
} else
#endif /*IPSEC*/
if (last != NULL)
rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, opts, m);
else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
uint64_t *ips;
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
0, 0);
ipstat[IP_STAT_NOPROTO]++;
ipstat[IP_STAT_DELIVERED]--;
ips = IP_STAT_GETREF();
ips[IP_STAT_NOPROTO]++;
ips[IP_STAT_DELIVERED]--;
IP_STAT_PUTREF();
} else
m_freem(m);
return;
@ -363,7 +368,7 @@ rip_output(struct mbuf *m, ...)
opts = NULL;
/* XXX prevent ip_output from overwriting header fields */
flags |= IP_RAWOUTPUT;
ipstat[IP_STAT_RAWOUT]++;
IP_STATINC(IP_STAT_RAWOUT);
}
return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions,
inp->inp_socket, &inp->inp_errormtu));

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_input.c,v 1.283 2008/04/08 01:03:58 thorpej Exp $ */
/* $NetBSD: tcp_input.c,v 1.284 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -152,7 +152,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.283 2008/04/08 01:03:58 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.284 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -214,6 +214,7 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.283 2008/04/08 01:03:58 thorpej Exp
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_private.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_congctl.h>
#include <netinet/tcp_debug.h>
@ -447,6 +448,7 @@ tcp_reass(struct tcpcb *tp, const struct tcphdr *th, struct mbuf *m, int *tlen)
#ifdef TCP_REASS_COUNTERS
u_int count = 0;
#endif
uint64_t *tcps;
if (tp->t_inpcb)
so = tp->t_inpcb->inp_socket;
@ -579,8 +581,10 @@ tcp_reass(struct tcpcb *tp, const struct tcphdr *th, struct mbuf *m, int *tlen)
*/
if (SEQ_LEQ(q->ipqe_seq, pkt_seq) &&
SEQ_GEQ(q->ipqe_seq + q->ipqe_len, pkt_seq + pkt_len)) {
tcpstat[TCP_STAT_RCVDUPPACK]++;
tcpstat[TCP_STAT_RCVDUPBYTE] += pkt_len;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVDUPPACK]++;
tcps[TCP_STAT_RCVDUPBYTE] += pkt_len;
TCP_STAT_PUTREF();
tcp_new_dsack(tp, pkt_seq, pkt_len);
m_freem(m);
if (tiqe != NULL) {
@ -723,7 +727,7 @@ tcp_reass(struct tcpcb *tp, const struct tcphdr *th, struct mbuf *m, int *tlen)
if (tiqe == NULL) {
tiqe = tcpipqent_alloc();
if (tiqe == NULL) {
tcpstat[TCP_STAT_RCVMEMDROP]++;
TCP_STATINC(TCP_STAT_RCVMEMDROP);
m_freem(m);
return (0);
}
@ -732,12 +736,14 @@ tcp_reass(struct tcpcb *tp, const struct tcphdr *th, struct mbuf *m, int *tlen)
/*
* Update the counters.
*/
tcpstat[TCP_STAT_RCVOOPACK]++;
tcpstat[TCP_STAT_RCVOOBYTE] += rcvoobyte;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVOOPACK]++;
tcps[TCP_STAT_RCVOOBYTE] += rcvoobyte;
if (rcvpartdupbyte) {
tcpstat[TCP_STAT_RCVPARTDUPPACK]++;
tcpstat[TCP_STAT_RCVPARTDUPBYTE] += rcvpartdupbyte;
tcps[TCP_STAT_RCVPARTDUPPACK]++;
tcps[TCP_STAT_RCVPARTDUPBYTE] += rcvpartdupbyte;
}
TCP_STAT_PUTREF();
/*
* Insert the new fragment queue entry into both queues.
@ -814,7 +820,7 @@ tcp6_input(struct mbuf **mp, int *offp, int proto)
struct ip6_hdr *ip6;
if (m->m_len < sizeof(struct ip6_hdr)) {
if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
tcpstat[TCP_STAT_RCVSHORT]++;
TCP_STATINC(TCP_STAT_RCVSHORT);
return IPPROTO_DONE;
}
}
@ -974,7 +980,7 @@ tcp_input_checksum(int af, struct mbuf *m, const struct tcphdr *th,
return 0;
badcsum:
tcpstat[TCP_STAT_RCVBADSUM]++;
TCP_STATINC(TCP_STAT_RCVBADSUM);
return -1;
}
@ -1009,6 +1015,7 @@ tcp_input(struct mbuf *m, ...)
struct mbuf *tcp_saveti = NULL;
uint32_t ts_rtt;
uint8_t iptos;
uint64_t *tcps;
MCLAIM(m, &tcp_rx_mowner);
va_start(ap, m);
@ -1016,7 +1023,7 @@ tcp_input(struct mbuf *m, ...)
(void)va_arg(ap, int); /* ignore value, advance ap */
va_end(ap);
tcpstat[TCP_STAT_RCVTOTAL]++;
TCP_STATINC(TCP_STAT_RCVTOTAL);
bzero(&opti, sizeof(opti));
opti.ts_present = 0;
@ -1059,7 +1066,7 @@ tcp_input(struct mbuf *m, ...)
IP6_EXTHDR_GET(th, struct tcphdr *, m, toff,
sizeof(struct tcphdr));
if (th == NULL) {
tcpstat[TCP_STAT_RCVSHORT]++;
TCP_STATINC(TCP_STAT_RCVSHORT);
return;
}
/* We do the checksum after PCB lookup... */
@ -1077,7 +1084,7 @@ tcp_input(struct mbuf *m, ...)
IP6_EXTHDR_GET(th, struct tcphdr *, m, toff,
sizeof(struct tcphdr));
if (th == NULL) {
tcpstat[TCP_STAT_RCVSHORT]++;
TCP_STATINC(TCP_STAT_RCVSHORT);
return;
}
@ -1129,7 +1136,7 @@ tcp_input(struct mbuf *m, ...)
*/
off = th->th_off << 2;
if (off < sizeof (struct tcphdr) || off > tlen) {
tcpstat[TCP_STAT_RCVBADOFF]++;
TCP_STATINC(TCP_STAT_RCVBADOFF);
goto drop;
}
tlen -= off;
@ -1144,7 +1151,7 @@ tcp_input(struct mbuf *m, ...)
if (off > sizeof (struct tcphdr)) {
IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, off);
if (th == NULL) {
tcpstat[TCP_STAT_RCVSHORT]++;
TCP_STATINC(TCP_STAT_RCVSHORT);
return;
}
/*
@ -1188,7 +1195,7 @@ findpcb:
inp = in_pcblookup_connect(&tcbtable, ip->ip_src, th->th_sport,
ip->ip_dst, th->th_dport);
if (inp == 0) {
tcpstat[TCP_STAT_PCBHASHMISS]++;
TCP_STATINC(TCP_STAT_PCBHASHMISS);
inp = in_pcblookup_bind(&tcbtable, ip->ip_dst, th->th_dport);
}
#ifdef INET6
@ -1205,7 +1212,7 @@ findpcb:
in6p = in6_pcblookup_connect(&tcbtable, &s,
th->th_sport, &d, th->th_dport, 0);
if (in6p == 0) {
tcpstat[TCP_STAT_PCBHASHMISS]++;
TCP_STATINC(TCP_STAT_PCBHASHMISS);
in6p = in6_pcblookup_bind(&tcbtable, &d,
th->th_dport, 0);
}
@ -1217,7 +1224,7 @@ findpcb:
if (inp == 0 && in6p == 0)
#endif
{
tcpstat[TCP_STAT_NOPORT]++;
TCP_STATINC(TCP_STAT_NOPORT);
if (tcp_log_refused &&
(tiflags & (TH_RST|TH_ACK|TH_SYN)) == TH_SYN) {
tcp4_log_refused(ip, th);
@ -1255,12 +1262,12 @@ findpcb:
in6p = in6_pcblookup_connect(&tcbtable, &ip6->ip6_src,
th->th_sport, &ip6->ip6_dst, th->th_dport, faith);
if (in6p == NULL) {
tcpstat[TCP_STAT_PCBHASHMISS]++;
TCP_STATINC(TCP_STAT_PCBHASHMISS);
in6p = in6_pcblookup_bind(&tcbtable, &ip6->ip6_dst,
th->th_dport, faith);
}
if (in6p == NULL) {
tcpstat[TCP_STAT_NOPORT]++;
TCP_STATINC(TCP_STAT_NOPORT);
if (tcp_log_refused &&
(tiflags & (TH_RST|TH_ACK|TH_SYN)) == TH_SYN) {
tcp6_log_refused(ip6, th);
@ -1588,7 +1595,7 @@ findpcb:
i = 1;
}
if (i) {
tcpstat[TCP_STAT_BADSYN]++;
TCP_STATINC(TCP_STAT_BADSYN);
goto drop;
}
}
@ -1643,10 +1650,10 @@ after_listen:
switch (iptos & IPTOS_ECN_MASK) {
case IPTOS_ECN_CE:
tp->t_flags |= TF_ECN_SND_ECE;
tcpstat[TCP_STAT_ECN_CE]++;
TCP_STATINC(TCP_STAT_ECN_CE);
break;
case IPTOS_ECN_ECT0:
tcpstat[TCP_STAT_ECN_ECT]++;
TCP_STATINC(TCP_STAT_ECN_ECT);
break;
case IPTOS_ECN_ECT1:
/* XXX: ignore for now -- rpaulo */
@ -1725,7 +1732,6 @@ after_listen:
/*
* this is a pure ack for outstanding data.
*/
tcpstat[TCP_STAT_PREDACK]++;
if (ts_rtt)
tcp_xmit_timer(tp, ts_rtt);
else if (tp->t_rtttime &&
@ -1733,8 +1739,11 @@ after_listen:
tcp_xmit_timer(tp,
tcp_now - tp->t_rtttime);
acked = th->th_ack - tp->snd_una;
tcpstat[TCP_STAT_RCVACKPACK]++;
tcpstat[TCP_STAT_RCVACKBYTE] += acked;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_PREDACK]++;
tcps[TCP_STAT_RCVACKPACK]++;
tcps[TCP_STAT_RCVACKBYTE] += acked;
TCP_STAT_PUTREF();
nd6_hint(tp);
if (acked > (tp->t_lastoff - tp->t_inoff))
@ -1783,10 +1792,12 @@ after_listen:
* with nothing on the reassembly queue and
* we have enough buffer space to take it.
*/
tcpstat[TCP_STAT_PREDDAT]++;
tp->rcv_nxt += tlen;
tcpstat[TCP_STAT_RCVPACK]++;
tcpstat[TCP_STAT_RCVBYTE] += tlen;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_PREDDAT]++;
tcps[TCP_STAT_RCVPACK]++;
tcps[TCP_STAT_RCVBYTE] += tlen;
TCP_STAT_PUTREF();
nd6_hint(tp);
/*
@ -1929,7 +1940,7 @@ after_listen:
if ((tiflags & TH_ECE) && tcp_do_ecn) {
tp->t_flags |= TF_ECN_PERMIT;
tcpstat[TCP_STAT_ECN_SHS]++;
TCP_STATINC(TCP_STAT_ECN_SHS);
}
}
@ -1960,7 +1971,7 @@ after_listen:
tcp_rmx_rtt(tp);
if (tiflags & TH_ACK) {
tcpstat[TCP_STAT_CONNECTS]++;
TCP_STATINC(TCP_STAT_CONNECTS);
soisconnected(so);
tcp_established(tp);
/* Do window scaling on this connection? */
@ -1992,8 +2003,10 @@ after_listen:
m_adj(m, -todrop);
tlen = tp->rcv_wnd;
tiflags &= ~TH_FIN;
tcpstat[TCP_STAT_RCVPACKAFTERWIN]++;
tcpstat[TCP_STAT_RCVBYTEAFTERWIN] += todrop;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVPACKAFTERWIN]++;
tcps[TCP_STAT_RCVBYTEAFTERWIN] += todrop;
TCP_STAT_PUTREF();
}
tp->snd_wl1 = th->th_seq - 1;
tp->rcv_up = th->th_seq;
@ -2040,9 +2053,11 @@ after_listen:
*/
tp->ts_recent = 0;
} else {
tcpstat[TCP_STAT_RCVDUPPACK]++;
tcpstat[TCP_STAT_RCVDUPBYTE] += tlen;
tcpstat[TCP_STAT_PAWSDROP]++;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVDUPPACK]++;
tcps[TCP_STAT_RCVDUPBYTE] += tlen;
tcps[TCP_STAT_PAWSDROP]++;
TCP_STAT_PUTREF();
tcp_new_dsack(tp, th->th_seq, tlen);
goto dropafterack;
}
@ -2079,8 +2094,10 @@ after_listen:
tp->t_flags |= TF_ACKNOW;
todrop = tlen;
dupseg = true;
tcpstat[TCP_STAT_RCVDUPPACK]++;
tcpstat[TCP_STAT_RCVDUPBYTE] += todrop;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVDUPPACK]++;
tcps[TCP_STAT_RCVDUPBYTE] += todrop;
TCP_STAT_PUTREF();
} else if ((tiflags & TH_RST) &&
th->th_seq != tp->last_ack_sent) {
/*
@ -2089,8 +2106,10 @@ after_listen:
*/
goto dropafterack_ratelim;
} else {
tcpstat[TCP_STAT_RCVPARTDUPPACK]++;
tcpstat[TCP_STAT_RCVPARTDUPBYTE] += todrop;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVPARTDUPPACK]++;
tcps[TCP_STAT_RCVPARTDUPBYTE] += todrop;
TCP_STAT_PUTREF();
}
tcp_new_dsack(tp, th->th_seq, todrop);
hdroptlen += todrop; /*drop from head afterwards*/
@ -2111,7 +2130,7 @@ after_listen:
if ((so->so_state & SS_NOFDREF) &&
tp->t_state > TCPS_CLOSE_WAIT && tlen) {
tp = tcp_close(tp);
tcpstat[TCP_STAT_RCVAFTERCLOSE]++;
TCP_STATINC(TCP_STAT_RCVAFTERCLOSE);
goto dropwithreset;
}
@ -2121,7 +2140,7 @@ after_listen:
*/
todrop = (th->th_seq + tlen) - (tp->rcv_nxt+tp->rcv_wnd);
if (todrop > 0) {
tcpstat[TCP_STAT_RCVPACKAFTERWIN]++;
TCP_STATINC(TCP_STAT_RCVPACKAFTERWIN);
if (todrop >= tlen) {
/*
* The segment actually starts after the window.
@ -2129,7 +2148,7 @@ after_listen:
* th->th_seq - tp->rcv_nxt - tp->rcv_wnd >= 0
* th->th_seq >= tp->rcv_nxt + tp->rcv_wnd
*/
tcpstat[TCP_STAT_RCVBYTEAFTERWIN] += tlen;
TCP_STATADD(TCP_STAT_RCVBYTEAFTERWIN, tlen);
/*
* If a new connection request is received
* while in TIME_WAIT, drop the old connection
@ -2159,11 +2178,11 @@ after_listen:
*/
if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) {
tp->t_flags |= TF_ACKNOW;
tcpstat[TCP_STAT_RCVWINPROBE]++;
TCP_STATINC(TCP_STAT_RCVWINPROBE);
} else
goto dropafterack;
} else
tcpstat[TCP_STAT_RCVBYTEAFTERWIN] += todrop;
TCP_STATADD(TCP_STAT_RCVBYTEAFTERWIN, todrop);
m_adj(m, -todrop);
tlen -= todrop;
tiflags &= ~(TH_PUSH|TH_FIN);
@ -2221,7 +2240,7 @@ after_listen:
so->so_error = ECONNRESET;
close:
tp->t_state = TCPS_CLOSED;
tcpstat[TCP_STAT_DROPS]++;
TCP_STATINC(TCP_STAT_DROPS);
tp = tcp_close(tp);
goto drop;
@ -2277,7 +2296,7 @@ after_listen:
if (SEQ_GT(tp->snd_una, th->th_ack) ||
SEQ_GT(th->th_ack, tp->snd_max))
goto dropwithreset;
tcpstat[TCP_STAT_CONNECTS]++;
TCP_STATINC(TCP_STAT_CONNECTS);
soisconnected(so);
tcp_established(tp);
/* Do window scaling? */
@ -2310,7 +2329,7 @@ after_listen:
if (SEQ_LEQ(th->th_ack, tp->snd_una)) {
if (tlen == 0 && !dupseg && tiwin == tp->snd_wnd) {
tcpstat[TCP_STAT_RCVDUPPACK]++;
TCP_STATINC(TCP_STAT_RCVDUPPACK);
/*
* If we have outstanding data (other than
* a window probe), this is a completely
@ -2370,12 +2389,14 @@ after_listen:
else
tp->t_congctl->fast_retransmit_newack(tp, th);
if (SEQ_GT(th->th_ack, tp->snd_max)) {
tcpstat[TCP_STAT_RCVACKTOOMUCH]++;
TCP_STATINC(TCP_STAT_RCVACKTOOMUCH);
goto dropafterack;
}
acked = th->th_ack - tp->snd_una;
tcpstat[TCP_STAT_RCVACKPACK]++;
tcpstat[TCP_STAT_RCVACKBYTE] += acked;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVACKPACK]++;
tcps[TCP_STAT_RCVACKBYTE] += acked;
TCP_STAT_PUTREF();
/*
* If we have a timestamp reply, update smoothed
@ -2509,7 +2530,7 @@ step6:
/* keep track of pure window updates */
if (tlen == 0 &&
tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd)
tcpstat[TCP_STAT_RCVWINUPD]++;
TCP_STATINC(TCP_STAT_RCVWINUPD);
tp->snd_wnd = tiwin;
tp->snd_wl1 = th->th_seq;
tp->snd_wl2 = th->th_ack;
@ -2609,8 +2630,10 @@ dodata: /* XXX */
tcp_setup_ack(tp, th);
tp->rcv_nxt += tlen;
tiflags = th->th_flags & TH_FIN;
tcpstat[TCP_STAT_RCVPACK]++;
tcpstat[TCP_STAT_RCVBYTE] += tlen;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_RCVPACK]++;
tcps[TCP_STAT_RCVBYTE] += tlen;
TCP_STAT_PUTREF();
nd6_hint(tp);
if (so->so_state & SS_CANTRCVMORE)
m_freem(m);
@ -2705,7 +2728,7 @@ badsyn:
/*
* Received a bad SYN. Increment counters and dropwithreset.
*/
tcpstat[TCP_STAT_BADSYN]++;
TCP_STATINC(TCP_STAT_BADSYN);
tp = NULL;
goto dropwithreset;
@ -3112,7 +3135,7 @@ tcp_dooptions(struct tcpcb *tp, const u_char *cp, int cnt,
tcp_fields_to_host(th);
if (bcmp(sig, sigp, TCP_SIGLEN)) {
tcpstat[TCP_STAT_BADSIG]++;
TCP_STATINC(TCP_STAT_BADSIG);
if (sav == NULL)
return (-1);
#ifdef FAST_IPSEC
@ -3122,7 +3145,7 @@ tcp_dooptions(struct tcpcb *tp, const u_char *cp, int cnt,
#endif
return (-1);
} else
tcpstat[TCP_STAT_GOODSIG]++;
TCP_STATINC(TCP_STAT_GOODSIG);
key_sa_recordxfer(sav, m);
#ifdef FAST_IPSEC
@ -3176,7 +3199,7 @@ tcp_xmit_timer(struct tcpcb *tp, uint32_t rtt)
{
int32_t delta;
tcpstat[TCP_STAT_RTTUPDATED]++;
TCP_STATINC(TCP_STAT_RTTUPDATED);
if (tp->t_srtt != 0) {
/*
* srtt is stored as fixed point with 3 bits after the
@ -3363,7 +3386,7 @@ syn_cache_insert(struct syn_cache *sc, struct tcpcb *tp)
*/
s = splsoftnet();
if (scp->sch_length >= tcp_syn_bucket_limit) {
tcpstat[TCP_STAT_SC_BUCKETOVERFLOW]++;
TCP_STATINC(TCP_STAT_SC_BUCKETOVERFLOW);
/*
* The bucket is full. Toss the oldest element in the
* bucket. This will be the first entry in the bucket.
@ -3382,7 +3405,7 @@ syn_cache_insert(struct syn_cache *sc, struct tcpcb *tp)
} else if (syn_cache_count >= tcp_syn_cache_limit) {
struct syn_cache_head *scp2, *sce;
tcpstat[TCP_STAT_SC_OVERFLOWED]++;
TCP_STATINC(TCP_STAT_SC_OVERFLOWED);
/*
* The cache is full. Toss the oldest entry in the
* first non-empty bucket we can find.
@ -3430,7 +3453,7 @@ syn_cache_insert(struct syn_cache *sc, struct tcpcb *tp)
scp->sch_length++;
syn_cache_count++;
tcpstat[TCP_STAT_SC_ADDED]++;
TCP_STATINC(TCP_STAT_SC_ADDED);
splx(s);
}
@ -3449,7 +3472,7 @@ syn_cache_timer(void *arg)
callout_ack(&sc->sc_timer);
if (__predict_false(sc->sc_flags & SCF_DEAD)) {
tcpstat[TCP_STAT_SC_DELAYED_FREE]++;
TCP_STATINC(TCP_STAT_SC_DELAYED_FREE);
callout_destroy(&sc->sc_timer);
pool_put(&syn_cache_pool, sc);
splx(s);
@ -3470,7 +3493,7 @@ syn_cache_timer(void *arg)
if (sc->sc_rxttot >= tcp_keepinit)
goto dropit;
tcpstat[TCP_STAT_SC_RETRANSMITTED]++;
TCP_STATINC(TCP_STAT_SC_RETRANSMITTED);
(void) syn_cache_respond(sc, NULL);
/* Advance the timer back-off. */
@ -3481,7 +3504,7 @@ syn_cache_timer(void *arg)
return;
dropit:
tcpstat[TCP_STAT_SC_TIMED_OUT]++;
TCP_STATINC(TCP_STAT_SC_TIMED_OUT);
syn_cache_rm(sc);
syn_cache_put(sc); /* calls pool_put but see spl above */
splx(s);
@ -3804,7 +3827,7 @@ syn_cache_get(struct sockaddr *src, struct sockaddr *dst,
tcp_rcvseqinit(tp);
tp->t_state = TCPS_SYN_RECEIVED;
TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepinit);
tcpstat[TCP_STAT_ACCEPTS]++;
TCP_STATINC(TCP_STAT_ACCEPTS);
if ((sc->sc_flags & SCF_SACK_PERMIT) && tcp_do_sack)
tp->t_flags |= TF_WILL_SACK;
@ -3858,7 +3881,7 @@ syn_cache_get(struct sockaddr *src, struct sockaddr *dst,
tp->t_partialacks = -1;
tp->t_dupacks = 0;
tcpstat[TCP_STAT_SC_COMPLETED]++;
TCP_STATINC(TCP_STAT_SC_COMPLETED);
s = splsoftnet();
syn_cache_put(sc);
splx(s);
@ -3872,7 +3895,7 @@ abort:
s = splsoftnet();
syn_cache_put(sc);
splx(s);
tcpstat[TCP_STAT_SC_ABORTED]++;
TCP_STATINC(TCP_STAT_SC_ABORTED);
return ((struct socket *)(-1));
}
@ -3899,7 +3922,7 @@ syn_cache_reset(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th)
return;
}
syn_cache_rm(sc);
tcpstat[TCP_STAT_SC_RESET]++;
TCP_STATINC(TCP_STAT_SC_RESET);
syn_cache_put(sc); /* calls pool_put but see spl above */
splx(s);
}
@ -3938,7 +3961,7 @@ syn_cache_unreach(const struct sockaddr *src, const struct sockaddr *dst,
}
syn_cache_rm(sc);
tcpstat[TCP_STAT_SC_UNREACH]++;
TCP_STATINC(TCP_STAT_SC_UNREACH);
syn_cache_put(sc); /* calls pool_put but see spl above */
splx(s);
}
@ -4023,7 +4046,7 @@ syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
* as a retransmission (XXX though maybe we should).
*/
if ((sc = syn_cache_lookup(src, dst, &scp)) != NULL) {
tcpstat[TCP_STAT_SC_DUPESYN]++;
TCP_STATINC(TCP_STAT_SC_DUPESYN);
if (ipopts) {
/*
* If we were remembering a previous source route,
@ -4035,8 +4058,10 @@ syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
}
sc->sc_timestamp = tb.ts_recent;
if (syn_cache_respond(sc, m) == 0) {
tcpstat[TCP_STAT_SNDACKS]++;
tcpstat[TCP_STAT_SNDTOTAL]++;
uint64_t *tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_SNDACKS]++;
tcps[TCP_STAT_SNDTOTAL]++;
TCP_STAT_PUTREF();
}
return (1);
}
@ -4143,14 +4168,16 @@ syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
#endif
sc->sc_tp = tp;
if (syn_cache_respond(sc, m) == 0) {
uint64_t *tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_SNDACKS]++;
tcps[TCP_STAT_SNDTOTAL]++;
TCP_STAT_PUTREF();
syn_cache_insert(sc, tp);
tcpstat[TCP_STAT_SNDACKS]++;
tcpstat[TCP_STAT_SNDTOTAL]++;
} else {
s = splsoftnet();
syn_cache_put(sc);
splx(s);
tcpstat[TCP_STAT_SC_DROPPED]++;
TCP_STATINC(TCP_STAT_SC_DROPPED);
}
return (1);
}
@ -4318,7 +4345,7 @@ syn_cache_respond(struct syn_cache *sc, struct mbuf *m)
if ((sc->sc_flags & SCF_ECN_PERMIT) && tp &&
SEQ_GEQ(tp->snd_nxt, tp->snd_max)) {
th->th_flags |= TH_ECE;
tcpstat[TCP_STAT_ECN_SHS]++;
TCP_STATINC(TCP_STAT_ECN_SHS);
/*
* draft-ietf-tcpm-ecnsyn-00.txt
@ -4355,7 +4382,7 @@ syn_cache_respond(struct syn_cache *sc, struct mbuf *m)
break;
#endif
}
tcpstat[TCP_STAT_ECN_ECT]++;
TCP_STATINC(TCP_STAT_ECN_ECT);
}
#ifdef TCP_SIGNATURE

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_output.c,v 1.165 2008/04/08 01:03:58 thorpej Exp $ */
/* $NetBSD: tcp_output.c,v 1.166 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -142,7 +142,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.165 2008/04/08 01:03:58 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.166 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -199,6 +199,7 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.165 2008/04/08 01:03:58 thorpej Exp
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_private.h>
#include <netinet/tcp_congctl.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_debug.h>
@ -444,16 +445,19 @@ tcp_build_datapkt(struct tcpcb *tp, struct socket *so, int off,
long len, int hdrlen, struct mbuf **mp)
{
struct mbuf *m, *m0;
uint64_t *tcps;
tcps = TCP_STAT_GETREF();
if (tp->t_force && len == 1)
tcpstat[TCP_STAT_SNDPROBE]++;
tcps[TCP_STAT_SNDPROBE]++;
else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
tcpstat[TCP_STAT_SNDREXMITPACK]++;
tcpstat[TCP_STAT_SNDREXMITBYTE] += len;
tcps[TCP_STAT_SNDREXMITPACK]++;
tcps[TCP_STAT_SNDREXMITBYTE] += len;
} else {
tcpstat[TCP_STAT_SNDPACK]++;
tcpstat[TCP_STAT_SNDBYTE] += len;
tcps[TCP_STAT_SNDPACK]++;
tcps[TCP_STAT_SNDBYTE] += len;
}
TCP_STAT_PUTREF();
#ifdef notyet
if ((m = m_copypack(so->so_snd.sb_mb, off,
(int)len, max_linkhdr + hdrlen)) == 0)
@ -580,6 +584,7 @@ tcp_output(struct tcpcb *tp)
#ifdef TCP_SIGNATURE
int sigoff = 0;
#endif
uint64_t *tcps;
#ifdef DIAGNOSTIC
if (tp->t_inpcb && tp->t_in6pcb)
@ -1263,14 +1268,16 @@ send:
if (off + len == so->so_snd.sb_cc)
flags |= TH_PUSH;
} else {
tcps = TCP_STAT_GETREF();
if (tp->t_flags & TF_ACKNOW)
tcpstat[TCP_STAT_SNDACKS]++;
tcps[TCP_STAT_SNDACKS]++;
else if (flags & (TH_SYN|TH_FIN|TH_RST))
tcpstat[TCP_STAT_SNDCTRL]++;
tcps[TCP_STAT_SNDCTRL]++;
else if (SEQ_GT(tp->snd_up, tp->snd_una))
tcpstat[TCP_STAT_SNDURG]++;
tcps[TCP_STAT_SNDURG]++;
else
tcpstat[TCP_STAT_SNDWINUP]++;
tcps[TCP_STAT_SNDWINUP]++;
TCP_STAT_PUTREF();
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m != NULL && max_linkhdr + hdrlen > MHLEN) {
@ -1356,7 +1363,7 @@ send:
break;
#endif
}
tcpstat[TCP_STAT_ECN_ECT]++;
TCP_STATINC(TCP_STAT_ECN_ECT);
}
/*
@ -1520,7 +1527,7 @@ send:
if (tp->t_rtttime == 0) {
tp->t_rtttime = tcp_now;
tp->t_rtseq = startseq;
tcpstat[TCP_STAT_SEGSTIMED]++;
TCP_STATINC(TCP_STAT_SEGSTIMED);
}
}
@ -1641,7 +1648,7 @@ timer:
if (error) {
out:
if (error == ENOBUFS) {
tcpstat[TCP_STAT_SELFQUENCH]++;
TCP_STATINC(TCP_STAT_SELFQUENCH);
#ifdef INET
if (tp->t_inpcb)
tcp_quench(tp->t_inpcb, 0);
@ -1671,9 +1678,11 @@ out:
if (packetlen > tp->t_pmtud_mtu_sent)
tp->t_pmtud_mtu_sent = packetlen;
tcpstat[TCP_STAT_SNDTOTAL]++;
tcps = TCP_STAT_GETREF();
tcps[TCP_STAT_SNDTOTAL]++;
if (tp->t_flags & TF_DELACK)
tcpstat[TCP_STAT_DELACK]++;
tcps[TCP_STAT_DELACK]++;
TCP_STAT_PUTREF();
/*
* Data sent (as far as we can tell).

71
sys/netinet/tcp_private.h Normal file
View File

@ -0,0 +1,71 @@
/* $NetBSD: tcp_private.h,v 1.1 2008/04/12 05:58:22 thorpej Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NETINET_TCP_PRIVATE_H_
#define _NETINET_TCP_PRIVATE_H_
#ifdef _KERNEL
#include <sys/percpu.h>
extern percpu_t *tcpstat_percpu;
#define TCP_STAT_GETREF() percpu_getref(tcpstat_percpu)
#define TCP_STAT_PUTREF() percpu_putref(tcpstat_percpu)
#define TCP_STATINC(x) \
do { \
uint64_t *_tcps_ = TCP_STAT_GETREF(); \
_tcps_[x]++; \
TCP_STAT_PUTREF(); \
} while (/*CONSTCOND*/0)
#define TCP_STATADD(x, v) \
do { \
uint64_t *_tcps_ = TCP_STAT_GETREF(); \
_tcps_[x] += (v); \
TCP_STAT_PUTREF(); \
} while (/*CONSTCOND*/0)
#ifdef __NO_STRICT_ALIGNMENT
#define TCP_HDR_ALIGNED_P(th) 1
#else
#define TCP_HDR_ALIGNED_P(th) ((((vaddr_t)(th)) & 3) == 0)
#endif /* __NO_STRICT_ALIGNMENT */
#endif /* _KERNEL */
#endif /* !_NETINET_TCP_PRIVATE_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_subr.c,v 1.226 2008/04/08 01:03:58 thorpej Exp $ */
/* $NetBSD: tcp_subr.c,v 1.227 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.226 2008/04/08 01:03:58 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.227 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -151,6 +151,7 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.226 2008/04/08 01:03:58 thorpej Exp $
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_private.h>
#include <netinet/tcp_congctl.h>
#include <netinet/tcpip.h>
@ -170,9 +171,10 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.226 2008/04/08 01:03:58 thorpej Exp $
struct inpcbtable tcbtable; /* head of queue of active tcpcb's */
uint64_t tcpstat[TCP_NSTATS]; /* tcp statistics */
u_int32_t tcp_now; /* for RFC 1323 timestamps */
percpu_t *tcpstat_percpu;
/* patchable/settable parameters for tcp */
int tcp_mssdflt = TCP_MSS;
int tcp_minmss = TCP_MINMSS;
@ -1094,9 +1096,9 @@ tcp_drop(struct tcpcb *tp, int errno)
if (TCPS_HAVERCVDSYN(tp->t_state)) {
tp->t_state = TCPS_CLOSED;
(void) tcp_output(tp);
tcpstat[TCP_STAT_DROPS]++;
TCP_STATINC(TCP_STAT_DROPS);
} else
tcpstat[TCP_STAT_CONNDROPS]++;
TCP_STATINC(TCP_STAT_CONNDROPS);
if (errno == ETIMEDOUT && tp->t_softerror)
errno = tp->t_softerror;
so->so_error = errno;
@ -1122,7 +1124,7 @@ tcp_isdead(struct tcpcb *tp)
if (tcp_timers_invoking(tp) > 0)
/* not quite there yet -- count separately? */
return dead;
tcpstat[TCP_STAT_DELAYED_FREE]++;
TCP_STATINC(TCP_STAT_DELAYED_FREE);
for (i = 0; i < TCPT_NTIMERS; i++)
callout_destroy(&tp->t_timer[i]);
callout_destroy(&tp->t_delack_ch);
@ -1275,7 +1277,7 @@ tcp_close(struct tcpcb *tp)
in6_pcbdetach(in6p);
}
#endif
tcpstat[TCP_STAT_CLOSED]++;
TCP_STATINC(TCP_STAT_CLOSED);
return ((struct tcpcb *)0);
}
@ -1342,7 +1344,7 @@ tcp_drain(void)
if (tcp_reass_lock_try(tp) == 0)
continue;
if (tcp_freeq(tp))
tcpstat[TCP_STAT_CONNSDRAINED]++;
TCP_STATINC(TCP_STAT_CONNSDRAINED);
TCP_REASS_UNLOCK(tp);
}
}
@ -2360,3 +2362,19 @@ tcp_hdrsz(struct tcpcb *tp)
#endif
return hlen;
}
void
tcp_statinc(u_int stat)
{
KASSERT(stat < TCP_NSTATS);
TCP_STATINC(stat);
}
void
tcp_statadd(u_int stat, uint64_t val)
{
KASSERT(stat < TCP_NSTATS);
TCP_STATADD(stat, val);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_timer.c,v 1.78 2008/04/08 01:03:58 thorpej Exp $ */
/* $NetBSD: tcp_timer.c,v 1.79 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -100,7 +100,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_timer.c,v 1.78 2008/04/08 01:03:58 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_timer.c,v 1.79 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_tcp_debug.h"
@ -138,6 +138,7 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_timer.c,v 1.78 2008/04/08 01:03:58 thorpej Exp $
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_private.h>
#include <netinet/tcp_congctl.h>
#include <netinet/tcpip.h>
#ifdef TCP_DEBUG
@ -349,12 +350,12 @@ tcp_timer_rexmt(void *arg)
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
tp->t_rxtshift = TCP_MAXRXTSHIFT;
tcpstat[TCP_STAT_TIMEOUTDROP]++;
TCP_STATINC(TCP_STAT_TIMEOUTDROP);
tp = tcp_drop(tp, tp->t_softerror ?
tp->t_softerror : ETIMEDOUT);
goto out;
}
tcpstat[TCP_STAT_REXMTTIMEO]++;
TCP_STATINC(TCP_STAT_REXMTTIMEO);
rto = TCP_REXMTVAL(tp);
if (rto < tp->t_rttmin)
rto = tp->t_rttmin;
@ -371,7 +372,7 @@ tcp_timer_rexmt(void *arg)
* value here...
*/
if (tp->t_mtudisc && tp->t_rxtshift > TCP_MAXRXTSHIFT / 6) {
tcpstat[TCP_STAT_PMTUBLACKHOLE]++;
TCP_STATINC(TCP_STAT_PMTUBLACKHOLE);
#ifdef INET
/* try turning PMTUD off */
@ -486,11 +487,11 @@ tcp_timer_persist(void *arg)
if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
((tcp_now - tp->t_rcvtime) >= tcp_maxpersistidle ||
(tcp_now - tp->t_rcvtime) >= rto * tcp_totbackoff)) {
tcpstat[TCP_STAT_PERSISTDROPS]++;
TCP_STATINC(TCP_STAT_PERSISTDROPS);
tp = tcp_drop(tp, ETIMEDOUT);
goto out;
}
tcpstat[TCP_STAT_PERSISTTIMEO]++;
TCP_STATINC(TCP_STAT_PERSISTTIMEO);
tcp_setpersist(tp);
tp->t_force = 1;
(void) tcp_output(tp);
@ -531,7 +532,7 @@ tcp_timer_keep(void *arg)
* or drop connection if idle for too long.
*/
tcpstat[TCP_STAT_KEEPTIMEO]++;
TCP_STATINC(TCP_STAT_KEEPTIMEO);
if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)
goto dropit;
#ifdef INET
@ -561,7 +562,7 @@ tcp_timer_keep(void *arg)
* by the protocol spec, this requires the
* correspondent TCP to respond.
*/
tcpstat[TCP_STAT_KEEPPROBE]++;
TCP_STATINC(TCP_STAT_KEEPPROBE);
if (tcp_compat_42) {
/*
* The keepalive packet must have nonzero
@ -588,7 +589,7 @@ tcp_timer_keep(void *arg)
return;
dropit:
tcpstat[TCP_STAT_KEEPDROPS]++;
TCP_STATINC(TCP_STAT_KEEPDROPS);
(void) tcp_drop(tp, ETIMEDOUT);
splx(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_usrreq.c,v 1.141 2008/04/08 01:03:58 thorpej Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.142 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.141 2008/04/08 01:03:58 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.142 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -151,6 +151,7 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.141 2008/04/08 01:03:58 thorpej Exp
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_private.h>
#include <netinet/tcp_congctl.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_debug.h>
@ -436,7 +437,7 @@ tcp_usrreq(struct socket *so, int req,
(TCP_MAXWIN << tp->request_r_scale) < sb_max)
tp->request_r_scale++;
soisconnecting(so);
tcpstat[TCP_STAT_CONNATTEMPT]++;
TCP_STATINC(TCP_STAT_CONNATTEMPT);
tp->t_state = TCPS_SYN_SENT;
TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepinit);
tp->iss = tcp_new_iss(tp, 0);
@ -1612,6 +1613,37 @@ sysctl_tcp_keep(SYSCTLFN_ARGS)
return 0;
}
static void
tcpstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci)
{
uint64_t *tcpsc = v1;
uint64_t *tcps = v2;
u_int i;
for (i = 0; i < TCP_NSTATS; i++)
tcps[i] += tcpsc[i];
}
static void
tcpstat_convert_to_user(uint64_t *tcps)
{
memset(tcps, 0, sizeof(uint64_t) * TCP_NSTATS);
percpu_foreach(tcpstat_percpu, tcpstat_convert_to_user_cb, tcps);
}
static int
sysctl_net_inet_tcp_stats(SYSCTLFN_ARGS)
{
struct sysctlnode node;
uint64_t tcps[TCP_NSTATS];
tcpstat_convert_to_user(tcps);
node = *rnode;
node.sysctl_data = tcps;
node.sysctl_size = sizeof(tcps);
return (sysctl_lookup(SYSCTLFN_CALL(&node)));
}
/*
* this (second stage) setup routine is a replacement for tcp_sysctl()
@ -1959,7 +1991,7 @@ sysctl_net_inet_tcp_setup2(struct sysctllog **clog, int pf, const char *pfname,
CTLFLAG_PERMANENT,
CTLTYPE_STRUCT, "stats",
SYSCTL_DESCR("TCP statistics"),
NULL, 0, tcpstat, sizeof(tcpstat),
sysctl_net_inet_tcp_stats, 0, NULL, 0,
CTL_NET, pf, IPPROTO_TCP, TCPCTL_STATS,
CTL_EOL);
#ifdef TCP_DEBUG

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_var.h,v 1.154 2008/04/08 01:03:58 thorpej Exp $ */
/* $NetBSD: tcp_var.h,v 1.155 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -734,7 +734,6 @@ struct syn_cache_head {
#ifdef _KERNEL
extern struct inpcbtable tcbtable; /* head of queue of active tcpcb's */
extern uint64_t tcpstat[TCP_NSTATS]; /* tcp statistics */
extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
extern int tcp_do_rfc1323; /* enabled/disabled? */
extern int tcp_do_sack; /* SACK enabled/disabled? */
@ -819,12 +818,6 @@ extern int tcp_autosndbuf_max;
{ 1, 0, &tcp_ackdrop_ppslim }, \
}
#ifdef __NO_STRICT_ALIGNMENT
#define TCP_HDR_ALIGNED_P(th) 1
#else
#define TCP_HDR_ALIGNED_P(th) ((((vaddr_t)(th)) & 3) == 0)
#endif
struct secasvar;
int tcp_attach(struct socket *);
@ -910,6 +903,9 @@ void tcp_sack_newack(struct tcpcb *, const struct tcphdr *);
int tcp_sack_numblks(const struct tcpcb *);
#define TCP_SACK_OPTLEN(nblks) ((nblks) * 8 + 2 + 2)
void tcp_statinc(u_int);
void tcp_statadd(u_int, uint64_t);
int syn_cache_add(struct sockaddr *, struct sockaddr *,
struct tcphdr *, unsigned int, struct socket *,
struct mbuf *, u_char *, int, struct tcp_opt_info *);

64
sys/netinet/udp_private.h Normal file
View File

@ -0,0 +1,64 @@
/* $NetBSD: udp_private.h,v 1.1 2008/04/12 05:58:22 thorpej Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NETINET_UDP_PRIVATE_H_
#define _NETINET_UDP_PRIVATE_H_
#ifdef _KERNEL
#include <sys/percpu.h>
extern percpu_t *udpstat_percpu;
/*
* Most UDP statistics are exceptional conditions, so this is good enough.
*/
#define UDP_STATINC(x) \
do { \
uint64_t *_udps_ = percpu_getref(udpstat_percpu); \
_udps_[x]++; \
percpu_putref(udpstat_percpu); \
} while (/*CONSTCOND*/0)
#ifdef __NO_STRICT_ALIGNMENT
#define UDP_HDR_ALIGNED_P(uh) 1
#else
#define UDP_HDR_ALIGNED_P(uh) ((((vaddr_t) (uh)) & 3) == 0)
#endif
#endif /* _KERNEL */
#endif /* !_NETINET_UDP_PRIVATE_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp_usrreq.c,v 1.165 2008/04/08 23:37:43 thorpej Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.166 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.165 2008/04/08 23:37:43 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.166 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -94,6 +94,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.165 2008/04/08 23:37:43 thorpej Exp
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/udp_private.h>
#ifdef INET6
#include <netinet/ip6.h>
@ -144,7 +145,7 @@ int udp_do_loopback_cksum = 0;
struct inpcbtable udbtable;
uint64_t udpstat[UDP_NSTATS];
percpu_t *udpstat_percpu;
#ifdef INET
#ifdef IPSEC_NAT_T
@ -231,6 +232,8 @@ udp_init(void)
MOWNER_ATTACH(&udp_tx_mowner);
MOWNER_ATTACH(&udp_rx_mowner);
MOWNER_ATTACH(&udp_mowner);
udpstat_percpu = percpu_alloc(sizeof(uint64_t) * UDP_NSTATS);
}
/*
@ -325,7 +328,7 @@ udp4_input_checksum(struct mbuf *m, const struct udphdr *uh,
return 0;
badcsum:
udpstat[UDP_STAT_BADSUM]++;
UDP_STATINC(UDP_STAT_BADSUM);
return -1;
}
@ -347,7 +350,7 @@ udp_input(struct mbuf *m, ...)
va_end(ap);
MCLAIM(m, &udp_rx_mowner);
udpstat[UDP_STAT_IPACKETS]++;
UDP_STATINC(UDP_STAT_IPACKETS);
/*
* Get IP and UDP header together in first mbuf.
@ -355,7 +358,7 @@ udp_input(struct mbuf *m, ...)
ip = mtod(m, struct ip *);
IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
if (uh == NULL) {
udpstat[UDP_STAT_HDROPS]++;
UDP_STATINC(UDP_STAT_HDROPS);
return;
}
KASSERT(UDP_HDR_ALIGNED_P(uh));
@ -372,7 +375,7 @@ udp_input(struct mbuf *m, ...)
len = ntohs((u_int16_t)uh->uh_ulen);
if (ip_len != iphlen + len) {
if (ip_len < iphlen + len || len < sizeof(struct udphdr)) {
udpstat[UDP_STAT_BADLEN]++;
UDP_STATINC(UDP_STAT_BADLEN);
goto bad;
}
m_adj(m, iphlen + len - ip_len);
@ -389,7 +392,7 @@ udp_input(struct mbuf *m, ...)
sockaddr_in_init(&dst, &ip->ip_dst, uh->uh_dport);
if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) {
udpstat[UDP_STAT_HDROPS]++;
UDP_STATINC(UDP_STAT_HDROPS);
return;
}
#ifdef INET6
@ -417,10 +420,10 @@ udp_input(struct mbuf *m, ...)
if (n == 0) {
if (m->m_flags & (M_BCAST | M_MCAST)) {
udpstat[UDP_STAT_NOPORTBCAST]++;
UDP_STATINC(UDP_STAT_NOPORTBCAST);
goto bad;
}
udpstat[UDP_STAT_NOPORT]++;
UDP_STATINC(UDP_STAT_NOPORT);
#ifdef IPKDB
if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport,
m, iphlen + sizeof(struct udphdr),
@ -639,7 +642,7 @@ udp4_sendup(struct mbuf *m, int off /* offset of data portion */,
if (opts)
m_freem(opts);
so->so_rcv.sb_overflowed++;
udpstat[UDP_STAT_FULLSOCK]++;
UDP_STATINC(UDP_STAT_FULLSOCK);
} else
sorwakeup(so);
}
@ -779,7 +782,7 @@ udp4_realinput(struct sockaddr_in *src, struct sockaddr_in *dst,
*/
inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport);
if (inp == 0) {
udpstat[UDP_STAT_PCBHASHMISS]++;
UDP_STATINC(UDP_STAT_PCBHASHMISS);
inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
if (inp == 0)
return rcvcnt;
@ -927,7 +930,7 @@ udp6_realinput(int af, struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
in6p = in6_pcblookup_connect(&udbtable, &src6, sport, dst6,
dport, 0);
if (in6p == 0) {
udpstat[UDP_STAT_PCBHASHMISS]++;
UDP_STATINC(UDP_STAT_PCBHASHMISS);
in6p = in6_pcblookup_bind(&udbtable, dst6, dport, 0);
if (in6p == 0)
return rcvcnt;
@ -1143,7 +1146,7 @@ udp_output(struct mbuf *m, ...)
((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
udpstat[UDP_STAT_OPACKETS]++;
UDP_STATINC(UDP_STAT_OPACKETS);
return (ip_output(m, inp->inp_options, ro,
inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
@ -1330,6 +1333,38 @@ release:
return (error);
}
static void
udpstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci)
{
uint64_t *udpsc = v1;
uint64_t *udps = v2;
u_int i;
for (i = 0; i < UDP_NSTATS; i++)
udps[i] += udpsc[i];
}
static void
udpstat_convert_to_user(uint64_t *udps)
{
memset(udps, 0, sizeof(uint64_t) * UDP_NSTATS);
percpu_foreach(udpstat_percpu, udpstat_convert_to_user_cb, udps);
}
static int
sysctl_net_inet_udp_stats(SYSCTLFN_ARGS)
{
struct sysctlnode node;
uint64_t udps[UDP_NSTATS];
udpstat_convert_to_user(udps);
node = *rnode;
node.sysctl_data = udps;
node.sysctl_size = sizeof(udps);
return (sysctl_lookup(SYSCTLFN_CALL(&node)));
}
/*
* Sysctl for udp variables.
*/
@ -1392,12 +1427,20 @@ SYSCTL_SETUP(sysctl_net_inet_udp_setup, "sysctl net.inet.udp subtree setup")
CTLFLAG_PERMANENT,
CTLTYPE_STRUCT, "stats",
SYSCTL_DESCR("UDP statistics"),
NULL, 0, udpstat, sizeof(udpstat),
sysctl_net_inet_udp_stats, 0, NULL, 0,
CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS,
CTL_EOL);
}
#endif
void
udp_statinc(u_int stat)
{
KASSERT(stat < UDP_NSTATS);
UDP_STATINC(stat);
}
#if (defined INET && defined IPSEC_NAT_T)
/*
* Returns:

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp_var.h,v 1.34 2008/04/06 20:17:27 thorpej Exp $ */
/* $NetBSD: udp_var.h,v 1.35 2008/04/12 05:58:22 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -88,13 +88,6 @@ struct udpiphdr {
#ifdef _KERNEL
extern struct inpcbtable udbtable;
extern uint64_t udpstat[UDP_NSTATS];
#ifdef __NO_STRICT_ALIGNMENT
#define UDP_HDR_ALIGNED_P(uh) 1
#else
#define UDP_HDR_ALIGNED_P(uh) ((((vaddr_t) (uh)) & 3) == 0)
#endif
void *udp_ctlinput(int, const struct sockaddr *, void *);
int udp_ctloutput(int, struct socket *, int, int, struct mbuf **);
@ -105,8 +98,9 @@ int udp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
int udp_usrreq(struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *);
int udp_input_checksum(int af, struct mbuf *, const struct udphdr *, int,
int udp_input_checksum(int af, struct mbuf *, const struct udphdr *, int,
int);
#endif
void udp_statinc(u_int);
#endif /* _KERNEL */
#endif /* !_NETINET_UDP_VAR_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipsec.c,v 1.126 2008/04/08 23:37:43 thorpej Exp $ */
/* $NetBSD: ipsec.c,v 1.127 2008/04/12 05:58:22 thorpej Exp $ */
/* $KAME: ipsec.c,v 1.136 2002/05/19 00:36:39 itojun Exp $ */
/*
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.126 2008/04/08 23:37:43 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.127 2008/04/12 05:58:22 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -61,6 +61,7 @@ __KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.126 2008/04/08 23:37:43 thorpej Exp $");
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_private.h>
#include <netinet/in_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
@ -2641,7 +2642,7 @@ ipsec4_output(struct ipsec_output_state *state, struct secpolicy *sp, int flags)
sockaddr_in_init(&u.dst4, &ip->ip_dst, 0);
if ((rt = rtcache_lookup(state->ro, &u.dst)) == NULL) {
rtcache_free(state->ro);
ipstat[IP_STAT_NOROUTE]++;
IP_STATINC(IP_STAT_NOROUTE);
error = EHOSTUNREACH;
goto bad;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp6_output.c,v 1.33 2008/04/06 23:36:43 xtraeme Exp $ */
/* $NetBSD: udp6_output.c,v 1.34 2008/04/12 05:58:23 thorpej Exp $ */
/* $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $ */
/*
@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.33 2008/04/06 23:36:43 xtraeme Exp $");
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.34 2008/04/12 05:58:23 thorpej Exp $");
#include "opt_inet.h"
@ -91,6 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.33 2008/04/06 23:36:43 xtraeme Exp
#include <netinet/in_pcb.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/udp_private.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_pcb.h>
@ -392,7 +393,7 @@ udp6_output(struct in6pcb *in6p, struct mbuf *m, struct mbuf *addr6,
ip->ip_ttl = in6_selecthlim(in6p, NULL); /* XXX */
ip->ip_tos = 0; /* XXX */
udpstat[UDP_STAT_OPACKETS]++;
UDP_STATINC(UDP_STAT_OPACKETS);
error = ip_output(m, NULL, &in6p->in6p_route, flags /* XXX */,
(struct ip_moptions *)NULL,
(struct socket *)in6p->in6p_socket);