Make CARP status per-cpu.
This commit is contained in:
parent
0e499be12d
commit
1121526b25
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/ucred.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/acct.h>
|
||||
#include <sys/percpu.h>
|
||||
|
||||
#include <sys/cpu.h>
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user