Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet/udp_usrreq.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet/udp_usrreq.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.165 retrieving revision 1.167 diff -u -p -r1.165 -r1.167 --- src/sys/netinet/udp_usrreq.c 2008/04/08 23:37:43 1.165 +++ src/sys/netinet/udp_usrreq.c 2008/04/15 03:57:04 1.167 @@ -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.167 2008/04/15 03:57:04 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include -__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.167 2008/04/15 03:57:04 thorpej Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -94,11 +94,13 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c #include #include #include +#include #ifdef INET6 #include #include #include +#include #include #include #include @@ -144,7 +146,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 +233,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 +329,7 @@ udp4_input_checksum(struct mbuf *m, cons return 0; badcsum: - udpstat[UDP_STAT_BADSUM]++; + UDP_STATINC(UDP_STAT_BADSUM); return -1; } @@ -347,7 +351,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 +359,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 +376,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 +393,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 +421,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), @@ -525,7 +529,7 @@ udp6_input(struct mbuf **mp, int *offp, plen = m->m_pkthdr.len - off; IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr)); if (uh == NULL) { - ip6stat[IP6_STAT_TOOSHORT]++; + IP6_STATINC(IP6_STAT_TOOSHORT); return IPPROTO_DONE; } KASSERT(UDP_HDR_ALIGNED_P(uh)); @@ -639,7 +643,7 @@ udp4_sendup(struct mbuf *m, int off /* o if (opts) m_freem(opts); so->so_rcv.sb_overflowed++; - udpstat[UDP_STAT_FULLSOCK]++; + UDP_STATINC(UDP_STAT_FULLSOCK); } else sorwakeup(so); } @@ -779,7 +783,7 @@ udp4_realinput(struct sockaddr_in *src, */ 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 +931,7 @@ udp6_realinput(int af, struct sockaddr_i 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 +1147,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 +1334,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 +1428,20 @@ SYSCTL_SETUP(sysctl_net_inet_udp_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: