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.156.4.3 retrieving revision 1.170 diff -u -p -r1.156.4.3 -r1.170 --- src/sys/netinet/udp_usrreq.c 2007/05/17 13:41:51 1.156.4.3 +++ src/sys/netinet/udp_usrreq.c 2008/04/24 11:38:38 1.170 @@ -1,4 +1,4 @@ -/* $NetBSD: udp_usrreq.c,v 1.156.4.3 2007/05/17 13:41:51 yamt Exp $ */ +/* $NetBSD: udp_usrreq.c,v 1.170 2008/04/24 11:38:38 ad Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.156.4.3 2007/05/17 13:41:51 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.170 2008/04/24 11:38:38 ad Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -94,13 +94,16 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c #include #include #include +#include #ifdef INET6 #include #include #include +#include #include #include +#include #include #endif @@ -118,18 +121,20 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c #ifdef FAST_IPSEC #include -#include /* XXX ipsecstat namespace */ +#include +#include #include #ifdef INET6 #include #endif -#endif /* FAST_IPSEC*/ +#endif /* FAST_IPSEC */ #ifdef IPSEC #include +#include #include #include -#endif /*IPSEC*/ +#endif /* IPSEC */ #ifdef IPKDB #include @@ -143,7 +148,8 @@ int udpcksum = 1; int udp_do_loopback_cksum = 0; struct inpcbtable udbtable; -struct udpstat udpstat; + +percpu_t *udpstat_percpu; #ifdef INET #ifdef IPSEC_NAT_T @@ -230,6 +236,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); } /* @@ -324,7 +332,7 @@ udp4_input_checksum(struct mbuf *m, cons return 0; badcsum: - udpstat.udps_badsum++; + UDP_STATINC(UDP_STAT_BADSUM); return -1; } @@ -346,7 +354,7 @@ udp_input(struct mbuf *m, ...) va_end(ap); MCLAIM(m, &udp_rx_mowner); - udpstat.udps_ipackets++; + UDP_STATINC(UDP_STAT_IPACKETS); /* * Get IP and UDP header together in first mbuf. @@ -354,7 +362,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.udps_hdrops++; + UDP_STATINC(UDP_STAT_HDROPS); return; } KASSERT(UDP_HDR_ALIGNED_P(uh)); @@ -371,7 +379,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.udps_badlen++; + UDP_STATINC(UDP_STAT_BADLEN); goto bad; } m_adj(m, iphlen + len - ip_len); @@ -388,7 +396,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.udps_hdrops++; + UDP_STATINC(UDP_STAT_HDROPS); return; } #ifdef INET6 @@ -416,10 +424,10 @@ udp_input(struct mbuf *m, ...) if (n == 0) { if (m->m_flags & (M_BCAST | M_MCAST)) { - udpstat.udps_noportbcast++; + UDP_STATINC(UDP_STAT_NOPORTBCAST); goto bad; } - udpstat.udps_noport++; + UDP_STATINC(UDP_STAT_NOPORT); #ifdef IPKDB if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport, m, iphlen + sizeof(struct udphdr), @@ -459,7 +467,7 @@ udp6_input_checksum(struct mbuf *m, cons goto good; } if (uh->uh_sum == 0) { - udp6stat.udp6s_nosum++; + UDP6_STATINC(UDP6_STAT_NOSUM); goto bad; } @@ -468,7 +476,7 @@ udp6_input_checksum(struct mbuf *m, cons M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) { case M_CSUM_UDPv6|M_CSUM_TCP_UDP_BAD: UDP_CSUM_COUNTER_INCR(&udp6_hwcsum_bad); - udp6stat.udp6s_badsum++; + UDP6_STATINC(UDP6_STAT_BADSUM); goto bad; #if 0 /* notyet */ @@ -487,7 +495,7 @@ udp6_input_checksum(struct mbuf *m, cons */ UDP_CSUM_COUNTER_INCR(&udp6_swcsum); if (in6_cksum(m, IPPROTO_UDP, off, len) != 0) { - udp6stat.udp6s_badsum++; + UDP6_STATINC(UDP6_STAT_BADSUM); goto bad; } } @@ -518,13 +526,13 @@ udp6_input(struct mbuf **mp, int *offp, } #endif - udp6stat.udp6s_ipackets++; + UDP6_STATINC(UDP6_STAT_IPACKETS); /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ plen = m->m_pkthdr.len - off; IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr)); if (uh == NULL) { - ip6stat.ip6s_tooshort++; + IP6_STATINC(IP6_STAT_TOOSHORT); return IPPROTO_DONE; } KASSERT(UDP_HDR_ALIGNED_P(uh)); @@ -537,7 +545,7 @@ udp6_input(struct mbuf **mp, int *offp, ulen = plen; if (plen != ulen) { - udp6stat.udp6s_badlen++; + UDP6_STATINC(UDP6_STAT_BADLEN); goto bad; } @@ -575,10 +583,10 @@ udp6_input(struct mbuf **mp, int *offp, if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) { if (m->m_flags & M_MCAST) { - udp6stat.udp6s_noportmcast++; + UDP6_STATINC(UDP6_STAT_NOPORTMCAST); goto bad; } - udp6stat.udp6s_noport++; + UDP6_STATINC(UDP6_STAT_NOPORT); icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); m = NULL; } @@ -616,15 +624,15 @@ udp4_sendup(struct mbuf *m, int off /* o #if defined(IPSEC) || defined(FAST_IPSEC) /* check AH/ESP integrity. */ if (so != NULL && ipsec4_in_reject_so(m, so)) { - ipsecstat.in_polvio++; - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) + IPSEC_STATINC(IPSEC_STAT_IN_POLVIO); + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT, 0, 0); return; } #endif /*IPSEC*/ - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { if (inp && (inp->inp_flags & INP_CONTROLOPTS || so->so_options & SO_TIMESTAMP)) { struct ip *ip = mtod(n, struct ip *); @@ -638,7 +646,7 @@ udp4_sendup(struct mbuf *m, int off /* o if (opts) m_freem(opts); so->so_rcv.sb_overflowed++; - udpstat.udps_fullsock++; + UDP_STATINC(UDP_STAT_FULLSOCK); } else sorwakeup(so); } @@ -663,15 +671,15 @@ udp6_sendup(struct mbuf *m, int off /* o #if defined(IPSEC) || defined(FAST_IPSEC) /* check AH/ESP integrity. */ if (so != NULL && ipsec6_in_reject_so(m, so)) { - ipsec6stat.in_polvio++; - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) + IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO); + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) icmp6_error(n, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN, 0); return; } #endif /*IPSEC*/ - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS || in6p->in6p_socket->so_options & SO_TIMESTAMP)) { struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *); @@ -684,7 +692,7 @@ udp6_sendup(struct mbuf *m, int off /* o if (opts) m_freem(opts); so->so_rcv.sb_overflowed++; - udp6stat.udp6s_fullsock++; + UDP6_STATINC(UDP6_STAT_FULLSOCK); } else sorwakeup(so); } @@ -778,7 +786,7 @@ udp4_realinput(struct sockaddr_in *src, */ inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport); if (inp == 0) { - ++udpstat.udps_pcbhashmiss; + UDP_STATINC(UDP_STAT_PCBHASHMISS); inp = in_pcblookup_bind(&udbtable, *dst4, *dport); if (inp == 0) return rcvcnt; @@ -926,7 +934,7 @@ udp6_realinput(int af, struct sockaddr_i in6p = in6_pcblookup_connect(&udbtable, &src6, sport, dst6, dport, 0); if (in6p == 0) { - ++udpstat.udps_pcbhashmiss; + UDP_STATINC(UDP_STAT_PCBHASHMISS); in6p = in6_pcblookup_bind(&udbtable, dst6, dport, 0); if (in6p == 0) return rcvcnt; @@ -1029,7 +1037,7 @@ udp_ctloutput(int op, struct socket *so, switch (optname) { case UDP_ENCAP: - if (m == NULL || m->m_len < sizeof (int)) { + if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; break; } @@ -1142,7 +1150,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.udps_opackets++; + UDP_STATINC(UDP_STAT_OPACKETS); return (ip_output(m, inp->inp_options, ro, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), @@ -1173,9 +1181,11 @@ udp_usrreq(struct socket *so, int req, s s = splsoftnet(); if (req == PRU_PURGEIF) { + mutex_enter(softnet_lock); in_pcbpurgeif0(&udbtable, (struct ifnet *)control); in_purgeif((struct ifnet *)control); in_pcbpurgeif(&udbtable, (struct ifnet *)control); + mutex_exit(softnet_lock); splx(s); return (0); } @@ -1185,7 +1195,9 @@ udp_usrreq(struct socket *so, int req, s if (req != PRU_SEND && req != PRU_SENDOOB && control) panic("udp_usrreq: unexpected control mbuf"); #endif - if (inp == 0 && req != PRU_ATTACH) { + if (req == PRU_ATTACH) { + sosetlock(so); + } else if (inp == 0) { error = EINVAL; goto release; } @@ -1329,6 +1341,18 @@ release: return (error); } +static int +sysctl_net_inet_udp_stats(SYSCTLFN_ARGS) +{ + netstat_sysctl_context ctx; + uint64_t udps[UDP_NSTATS]; + + ctx.ctx_stat = udpstat_percpu; + ctx.ctx_counters = udps; + ctx.ctx_ncounters = UDP_NSTATS; + return (NETSTAT_SYSCTL(&ctx)); +} + /* * Sysctl for udp variables. */ @@ -1391,12 +1415,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: @@ -1528,7 +1560,7 @@ udp4_espinudp(struct mbuf **mp, int off, m_tag_prepend(n, tag); #ifdef FAST_IPSEC - ipsec4_common_input(n, iphdrlen); + ipsec4_common_input(n, iphdrlen, IPPROTO_ESP); #else esp4_input(n, iphdrlen); #endif