diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 8098be3be786..b6a946b5df0f 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_carp.c,v 1.23 2008/03/15 16:44:03 ws Exp $ */ +/* $NetBSD: ip_carp.c,v 1.24 2008/04/15 06:03:28 thorpej Exp $ */ /* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */ /* @@ -28,7 +28,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.23 2008/03/15 16:44:03 ws Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.24 2008/04/15 06:03:28 thorpej Exp $"); /* * TODO: @@ -53,6 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.23 2008/03/15 16:44:03 ws Exp $"); #include #include #include +#include #include @@ -155,7 +156,15 @@ struct carp_softc { int carp_suppress_preempt = 0; int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 0, 0 }; /* XXX for now */ -struct carpstats carpstats; + +static percpu_t *carpstat_percpu; + +#define CARP_STATINC(x) \ +do { \ + uint64_t *_carps_ = percpu_getref(carpstat_percpu); \ + _carps_[x]++; \ + percpu_putref(carpstat_percpu); \ +} while (/*CONSTCOND*/0) struct carp_if { TAILQ_HEAD(, carp_softc) vhif_vrs; @@ -460,7 +469,7 @@ carp_proto_input(struct mbuf *m, ...) hlen = va_arg(ap, int); va_end(ap); - carpstats.carps_ipackets++; + CARP_STATINC(CARP_STAT_IPACKETS); if (!carp_opts[CARPCTL_ALLOW]) { m_freem(m); @@ -469,7 +478,7 @@ carp_proto_input(struct mbuf *m, ...) /* check if received on a valid carp interface */ if (m->m_pkthdr.rcvif->if_type != IFT_CARP) { - carpstats.carps_badif++; + CARP_STATINC(CARP_STAT_BADIF); CARP_LOG(sc, ("packet received on non-carp interface: %s", m->m_pkthdr.rcvif->if_xname)); m_freem(m); @@ -478,7 +487,7 @@ carp_proto_input(struct mbuf *m, ...) /* verify that the IP TTL is 255. */ if (ip->ip_ttl != CARP_DFLTTL) { - carpstats.carps_badttl++; + CARP_STATINC(CARP_STAT_BADTTL); CARP_LOG(sc, ("received ttl %d != %d on %s", ip->ip_ttl, CARP_DFLTTL, m->m_pkthdr.rcvif->if_xname)); m_freem(m); @@ -492,7 +501,7 @@ carp_proto_input(struct mbuf *m, ...) iplen = ip->ip_hl << 2; len = iplen + sizeof(*ch); if (len > m->m_pkthdr.len) { - carpstats.carps_badlen++; + CARP_STATINC(CARP_STAT_BADLEN); CARP_LOG(sc, ("packet too short %d on %s", m->m_pkthdr.len, m->m_pkthdr.rcvif->if_xname)); m_freem(m); @@ -500,7 +509,7 @@ carp_proto_input(struct mbuf *m, ...) } if ((m = m_pullup(m, len)) == NULL) { - carpstats.carps_hdrops++; + CARP_STATINC(CARP_STAT_HDROPS); return; } ip = mtod(m, struct ip *); @@ -508,7 +517,7 @@ carp_proto_input(struct mbuf *m, ...) /* verify the CARP checksum */ m->m_data += iplen; if (carp_cksum(m, len - iplen)) { - carpstats.carps_badsum++; + CARP_STATINC(CARP_STAT_BADSUM); CARP_LOG(sc, ("checksum failed on %s", m->m_pkthdr.rcvif->if_xname)); m_freem(m); @@ -529,7 +538,7 @@ carp6_proto_input(struct mbuf **mp, int *offp, int proto) struct carp_header *ch; u_int len; - carpstats.carps_ipackets6++; + CARP_STATINC(CARP_STAT_IPACKETS6); if (!carp_opts[CARPCTL_ALLOW]) { m_freem(m); @@ -538,7 +547,7 @@ carp6_proto_input(struct mbuf **mp, int *offp, int proto) /* check if received on a valid carp interface */ if (m->m_pkthdr.rcvif->if_type != IFT_CARP) { - carpstats.carps_badif++; + CARP_STATINC(CARP_STAT_BADIF); CARP_LOG(sc, ("packet received on non-carp interface: %s", m->m_pkthdr.rcvif->if_xname)); m_freem(m); @@ -547,7 +556,7 @@ carp6_proto_input(struct mbuf **mp, int *offp, int proto) /* verify that the IP TTL is 255 */ if (ip6->ip6_hlim != CARP_DFLTTL) { - carpstats.carps_badttl++; + CARP_STATINC(CARP_STAT_BADTTL); CARP_LOG(sc, ("received ttl %d != %d on %s", ip6->ip6_hlim, CARP_DFLTTL, m->m_pkthdr.rcvif->if_xname)); m_freem(m); @@ -558,7 +567,7 @@ carp6_proto_input(struct mbuf **mp, int *offp, int proto) len = m->m_len; IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch)); if (ch == NULL) { - carpstats.carps_badlen++; + CARP_STATINC(CARP_STAT_BADLEN); CARP_LOG(sc, ("packet size %u too small", len)); return (IPPROTO_DONE); } @@ -567,7 +576,7 @@ carp6_proto_input(struct mbuf **mp, int *offp, int proto) /* verify the CARP checksum */ m->m_data += *offp; if (carp_cksum(m, sizeof(*ch))) { - carpstats.carps_badsum++; + CARP_STATINC(CARP_STAT_BADSUM); CARP_LOG(sc, ("checksum failed, on %s", m->m_pkthdr.rcvif->if_xname)); m_freem(m); @@ -594,7 +603,7 @@ carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) if (!sc || (sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - carpstats.carps_badvhid++; + CARP_STATINC(CARP_STAT_BADVHID); m_freem(m); return; } @@ -647,7 +656,7 @@ carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) /* verify the CARP version. */ if (ch->carp_version != CARP_VERSION) { - carpstats.carps_badver++; + CARP_STATINC(CARP_STAT_BADVER); sc->sc_if.if_ierrors++; CARP_LOG(sc, ("invalid version %d != %d", ch->carp_version, CARP_VERSION)); @@ -657,7 +666,7 @@ carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) /* verify the hash */ if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) { - carpstats.carps_badauth++; + CARP_STATINC(CARP_STAT_BADAUTH); sc->sc_if.if_ierrors++; CARP_LOG(sc, ("incorrect hash")); m_freem(m); @@ -740,6 +749,8 @@ void carpattach(int n) { if_clone_attach(&carp_cloner); + + carpstat_percpu = percpu_alloc(sizeof(uint64_t) * CARP_NSTATS); } int @@ -959,7 +970,7 @@ carp_send_ad(void *v) MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { sc->sc_if.if_oerrors++; - carpstats.carps_onomem++; + CARP_STATINC(CARP_STAT_ONOMEM); /* XXX maybe less ? */ goto retry_later; } @@ -1002,13 +1013,13 @@ carp_send_ad(void *v) microtime(&sc->sc_if.if_lastchange); sc->sc_if.if_opackets++; sc->sc_if.if_obytes += len; - carpstats.carps_opackets++; + CARP_STATINC(CARP_STAT_OPACKETS); error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL); if (error) { if (error == ENOBUFS) - carpstats.carps_onomem++; + CARP_STATINC(CARP_STAT_ONOMEM); else CARP_LOG(sc, ("ip_output failed: %d", error)); sc->sc_if.if_oerrors++; @@ -1039,7 +1050,7 @@ carp_send_ad(void *v) MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { sc->sc_if.if_oerrors++; - carpstats.carps_onomem++; + CARP_STATINC(CARP_STAT_ONOMEM); /* XXX maybe less ? */ goto retry_later; } @@ -1087,12 +1098,12 @@ carp_send_ad(void *v) microtime(&sc->sc_if.if_lastchange); sc->sc_if.if_opackets++; sc->sc_if.if_obytes += len; - carpstats.carps_opackets6++; + CARP_STATINC(CARP_STAT_OPACKETS6); error = ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL, NULL); if (error) { if (error == ENOBUFS) - carpstats.carps_onomem++; + CARP_STATINC(CARP_STAT_ONOMEM); else CARP_LOG(sc, ("ip6_output failed: %d", error)); sc->sc_if.if_oerrors++; @@ -2233,6 +2244,38 @@ carp_ether_purgemulti(struct carp_softc *sc) } } +static void +carpstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci) +{ + uint64_t *carpsc = v1; + uint64_t *carps = v2; + u_int i; + + for (i = 0; i < CARP_NSTATS; i++) + carps[i] += carpsc[i]; +} + +static void +carpstat_convert_to_user(uint64_t *carps) +{ + + memset(carps, 0, sizeof(uint64_t) * CARP_NSTATS); + percpu_foreach(carpstat_percpu, carpstat_convert_to_user_cb, carps); +} + +static int +sysctl_net_inet_carp_stats(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + uint64_t carps[CARP_NSTATS]; + + carpstat_convert_to_user(carps); + node = *rnode; + node.sysctl_data = carps; + node.sysctl_size = sizeof(carps); + return (sysctl_lookup(SYSCTLFN_CALL(&node))); +} + SYSCTL_SETUP(sysctl_net_inet_carp_setup, "sysctl net.inet.carp subtree setup") { @@ -2285,7 +2328,7 @@ SYSCTL_SETUP(sysctl_net_inet_carp_setup, "sysctl net.inet.carp subtree setup") CTLFLAG_PERMANENT, CTLTYPE_STRUCT, "stats", SYSCTL_DESCR("CARP statistics"), - NULL, 0, &carpstats, sizeof(carpstats), + sysctl_net_inet_carp_stats, 0, NULL, 0, CTL_NET, PF_INET, IPPROTO_CARP, CARPCTL_STATS, CTL_EOL); } diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h index e4df19640720..dfa858712194 100644 --- a/sys/netinet/ip_carp.h +++ b/sys/netinet/ip_carp.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_carp.h,v 1.3 2007/02/17 22:34:11 dyoung Exp $ */ +/* $NetBSD: ip_carp.h,v 1.4 2008/04/15 06:03:28 thorpej Exp $ */ /* $OpenBSD: ip_carp.h,v 1.18 2005/04/20 23:00:41 mpf Exp $ */ /* @@ -92,26 +92,24 @@ struct carp_header { /* * Statistics. */ -struct carpstats { - u_int64_t carps_ipackets; /* total input packets, IPv4 */ - u_int64_t carps_ipackets6; /* total input packets, IPv6 */ - u_int64_t carps_badif; /* wrong interface */ - u_int64_t carps_badttl; /* TTL is not CARP_DFLTTL */ - u_int64_t carps_hdrops; /* packets shorter than hdr */ - u_int64_t carps_badsum; /* bad checksum */ - u_int64_t carps_badver; /* bad (incl unsupp) version */ - u_int64_t carps_badlen; /* data length does not match */ - u_int64_t carps_badauth; /* bad authentication */ - u_int64_t carps_badvhid; /* bad VHID */ - u_int64_t carps_badaddrs; /* bad address list */ +#define CARP_STAT_IPACKETS 0 /* total input packets, IPv4 */ +#define CARP_STAT_IPACKETS6 1 /* total input packets, IPv6 */ +#define CARP_STAT_BADIF 2 /* wrong interface */ +#define CARP_STAT_BADTTL 3 /* TTL is not CARP_DFLTTL */ +#define CARP_STAT_HDROPS 4 /* packets shorter than hdr */ +#define CARP_STAT_BADSUM 5 /* bad checksum */ +#define CARP_STAT_BADVER 6 /* bad (incl unsupported) version */ +#define CARP_STAT_BADLEN 7 /* data length does not match */ +#define CARP_STAT_BADAUTH 8 /* bad authentication */ +#define CARP_STAT_BADVHID 9 /* bad VHID */ +#define CARP_STAT_BADADDRS 10 /* bad address list */ +#define CARP_STAT_OPACKETS 11 /* total output packets, IPv4 */ +#define CARP_STAT_OPACKETS6 12 /* total output packets, IPv6 */ +#define CARP_STAT_ONOMEM 13 /* no memory for an mbuf */ +#define CARP_STAT_OSTATES 14 /* total state updates sent */ +#define CARP_STAT_PREEMPT 15 /* in enabled, preemptions */ - u_int64_t carps_opackets; /* total output packets, IPv4 */ - u_int64_t carps_opackets6; /* total output packets, IPv6 */ - u_int64_t carps_onomem; /* no memory for an mbuf */ - u_int64_t carps_ostates; /* total state updates sent */ - - u_int64_t carps_preempt; /* if enabled, preemptions */ -}; +#define CARP_NSTATS 16 #define CARPDEVNAMSIZ 16 #ifdef IFNAMSIZ diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 721815bb75ae..259b3493ca94 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -1,4 +1,4 @@ -/* $NetBSD: inet.c,v 1.84 2008/04/15 04:50:05 thorpej Exp $ */ +/* $NetBSD: inet.c,v 1.85 2008/04/15 06:03:28 thorpej Exp $ */ /* * Copyright (c) 1983, 1988, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94"; #else -__RCSID("$NetBSD: inet.c,v 1.84 2008/04/15 04:50:05 thorpej Exp $"); +__RCSID("$NetBSD: inet.c,v 1.85 2008/04/15 06:03:28 thorpej Exp $"); #endif #endif /* not lint */ @@ -631,12 +631,12 @@ igmp_stats(u_long off, char *name) void carp_stats(u_long off, char *name) { - struct carpstats carpstat; + uint64_t carpstat[CARP_NSTATS]; if (use_sysctl) { size_t size = sizeof(carpstat); - if (sysctlbyname("net.inet.carp.stats", &carpstat, &size, + if (sysctlbyname("net.inet.carp.stats", carpstat, &size, NULL, 0) == -1) { /* most likely CARP is not compiled in the kernel */ return; @@ -644,37 +644,37 @@ carp_stats(u_long off, char *name) } else { if (off == 0) return; - kread(off, (char *)&carpstat, sizeof(carpstat)); + kread(off, (char *)carpstat, sizeof(carpstat)); } printf("%s:\n", name); -#define p(f, m) if (carpstat.f || sflag <= 1) \ - printf(m, carpstat.f, plural(carpstat.f)) -#define p2(f, m) if (carpstat.f || sflag <= 1) \ - printf(m, carpstat.f) +#define p(f, m) if (carpstat[f] || sflag <= 1) \ + printf(m, carpstat[f], plural(carpstat[f])) +#define p2(f, m) if (carpstat[f] || sflag <= 1) \ + printf(m, carpstat[f]) - p(carps_ipackets, "\t%" PRIu64 " packet%s received (IPv4)\n"); - p(carps_ipackets6, "\t%" PRIu64 " packet%s received (IPv6)\n"); - p(carps_badif, + p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n"); + p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n"); + p(CARP_STAT_BADIF, "\t\t%" PRIu64 " packet%s discarded for bad interface\n"); - p(carps_badttl, + p(CARP_STAT_BADTTL, "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n"); - p(carps_hdrops, "\t\t%" PRIu64 " packet%s shorter than header\n"); - p(carps_badsum, "\t\t%" PRIu64 + p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n"); + p(CARP_STAT_BADSUM, "\t\t%" PRIu64 " packet%s discarded for bad checksum\n"); - p(carps_badver, + p(CARP_STAT_BADVER, "\t\t%" PRIu64 " packet%s discarded with a bad version\n"); - p2(carps_badlen, + p2(CARP_STAT_BADLEN, "\t\t%" PRIu64 " discarded because packet was too short\n"); - p(carps_badauth, + p(CARP_STAT_BADAUTH, "\t\t%" PRIu64 " packet%s discarded for bad authentication\n"); - p(carps_badvhid, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n"); - p(carps_badaddrs, "\t\t%" PRIu64 + p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n"); + p(CARP_STAT_BADADDRS, "\t\t%" PRIu64 " packet%s discarded because of a bad address list\n"); - p(carps_opackets, "\t%" PRIu64 " packet%s sent (IPv4)\n"); - p(carps_opackets6, "\t%" PRIu64 " packet%s sent (IPv6)\n"); - p2(carps_onomem, + p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n"); + p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n"); + p2(CARP_STAT_ONOMEM, "\t\t%" PRIu64 " send failed due to mbuf memory error\n"); #undef p #undef p2