summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2006-02-13 14:11:18 +0000
committerharti <harti@FreeBSD.org>2006-02-13 14:11:18 +0000
commita923e07ab3efd8202b4be3f02e729f61e7aef5af (patch)
tree58f53ab4a3f529c38f0fc2c5d695c82f16c80100 /contrib
parentaf0ed09791e779050efb210d9304ae1e7100c129 (diff)
downloadFreeBSD-src-a923e07ab3efd8202b4be3f02e729f61e7aef5af.zip
FreeBSD-src-a923e07ab3efd8202b4be3f02e729f61e7aef5af.tar.gz
Vendor fix: make mibII HC counters really 64-bit on 32-bit platforms by polling
the kernel periodically. Submitted by: glebius (partly)
Diffstat (limited to 'contrib')
-rw-r--r--contrib/bsnmp/oid-list1
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII.c159
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII.h32
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII_interfaces.c14
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII_tree.def17
-rw-r--r--contrib/bsnmp/snmp_mibII/snmp_mibII.h3
6 files changed, 207 insertions, 19 deletions
diff --git a/contrib/bsnmp/oid-list b/contrib/bsnmp/oid-list
index 32a1c0e..c831f15 100644
--- a/contrib/bsnmp/oid-list
+++ b/contrib/bsnmp/oid-list
@@ -11,6 +11,7 @@ enterprises
1 BEGEMOT
1 BEGEMOT-SNMPD
2 BEGEMOT-NETGRAPH snmpd netgraph module
+ 3 BEGEMOT-IP snmpd mibII module
100 BEGEMOT-ILMID snmpd ILMID module
101 BEGEMOT-ATM snmpd ATM module
200 BEGEMOT-PF snmpd PF module (phillip@freebsd.org)
diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c
index 98a16d4..9dbec01 100644
--- a/contrib/bsnmp/snmp_mibII/mibII.c
+++ b/contrib/bsnmp/snmp_mibII/mibII.c
@@ -105,6 +105,18 @@ struct clockinfo clockinfo;
/* list of all New if registrations */
static struct newifreg_list newifreg_list = TAILQ_HEAD_INITIALIZER(newifreg_list);
+/* baud rate of fastest interface */
+uint64_t mibif_maxspeed;
+
+/* user-forced update interval */
+u_int mibif_force_hc_update_interval;
+
+/* current update interval */
+u_int mibif_hc_update_interval;
+
+/* HC update timer handle */
+static void *hc_update_timer;
+
/*****************************/
static const struct asn_oid oid_ifMIB = OIDX_ifMIB;
@@ -280,16 +292,15 @@ link_trap(struct mibif *ifp, int up)
(struct snmp_value *)NULL);
}
-/*
- * Fetch new MIB data.
+/**
+ * Fetch the GENERIC IFMIB and update the HC counters
*/
-int
-mib_fetch_ifmib(struct mibif *ifp)
+static int
+fetch_generic_mib(struct mibif *ifp, const struct ifmibdata *old)
{
int name[6];
size_t len;
- void *newmib;
- struct ifmibdata oldmib = ifp->mib;
+ struct mibif_private *p = ifp->private;
name[0] = CTL_NET;
name[1] = PF_LINK;
@@ -307,6 +318,113 @@ mib_fetch_ifmib(struct mibif *ifp)
}
/*
+ * Assume that one of the two following compounds is optimized away
+ */
+ if (ULONG_MAX >= 0xffffffffffffffffULL) {
+ p->hc_inoctets = ifp->mib.ifmd_data.ifi_ibytes;
+ p->hc_outoctets = ifp->mib.ifmd_data.ifi_obytes;
+ p->hc_omcasts = ifp->mib.ifmd_data.ifi_omcasts;
+ p->hc_opackets = ifp->mib.ifmd_data.ifi_opackets;
+ p->hc_imcasts = ifp->mib.ifmd_data.ifi_imcasts;
+ p->hc_ipackets = ifp->mib.ifmd_data.ifi_ipackets;
+
+ } else if (ULONG_MAX >= 0xffffffff) {
+
+#define UPDATE(HC, MIB) \
+ if (old->ifmd_data.MIB > ifp->mib.ifmd_data.MIB) \
+ p->HC += (0x100000000ULL + \
+ ifp->mib.ifmd_data.MIB) - \
+ old->ifmd_data.MIB; \
+ else \
+ p->HC += ifp->mib.ifmd_data.MIB - \
+ old->ifmd_data.MIB;
+
+ UPDATE(hc_inoctets, ifi_ibytes)
+ UPDATE(hc_outoctets, ifi_obytes)
+ UPDATE(hc_omcasts, ifi_omcasts)
+ UPDATE(hc_opackets, ifi_opackets)
+ UPDATE(hc_imcasts, ifi_imcasts)
+ UPDATE(hc_ipackets, ifi_ipackets)
+
+#undef UPDATE
+ } else
+ abort();
+ return (0);
+}
+
+/**
+ * Update the 64-bit interface counters
+ */
+static void
+update_hc_counters(void *arg __unused)
+{
+ struct mibif *ifp;
+ struct ifmibdata oldmib;
+
+ TAILQ_FOREACH(ifp, &mibif_list, link) {
+ oldmib = ifp->mib;
+ (void)fetch_generic_mib(ifp, &oldmib);
+ }
+}
+
+/**
+ * Recompute the poll timer for the HC counters
+ */
+void
+mibif_reset_hc_timer(void)
+{
+ u_int ticks;
+
+ if ((ticks = mibif_force_hc_update_interval) == 0) {
+ if (mibif_maxspeed <= 10000000) {
+ /* at 10Mbps overflow needs 3436 seconds */
+ ticks = 3000 * 100; /* 50 minutes */
+ } else if (mibif_maxspeed <= 100000000) {
+ /* at 100Mbps overflow needs 343 seconds */
+ ticks = 300 * 100; /* 5 minutes */
+ } else if (mibif_maxspeed < 650000000) {
+ /* at 622Mbps overflow needs 53 seconds */
+ ticks = 40 * 100; /* 40 seconds */
+ } else if (mibif_maxspeed <= 1000000000) {
+ /* at 1Gbps overflow needs 34 seconds */
+ ticks = 20 * 100; /* 20 seconds */
+ } else {
+ /* at 10Gbps overflow needs 3.4 seconds */
+ ticks = 100; /* 1 seconds */
+ }
+ }
+
+ if (ticks == mibif_hc_update_interval)
+ return;
+
+ if (hc_update_timer != NULL) {
+ timer_stop(hc_update_timer);
+ hc_update_timer = NULL;
+ }
+ update_hc_counters(NULL);
+ if ((hc_update_timer = timer_start_repeat(ticks * 10, ticks * 10,
+ update_hc_counters, NULL, module)) == NULL) {
+ syslog(LOG_ERR, "timer_start(%u): %m", ticks);
+ return;
+ }
+ mibif_hc_update_interval = ticks;
+}
+
+/*
+ * Fetch new MIB data.
+ */
+int
+mib_fetch_ifmib(struct mibif *ifp)
+{
+ int name[6];
+ size_t len;
+ void *newmib;
+ struct ifmibdata oldmib = ifp->mib;
+
+ if (fetch_generic_mib(ifp, &oldmib) == -1)
+ return (-1);
+
+ /*
* Quoting RFC2863, 3.1.15: "... LinkUp and linkDown traps are
* generated just after ifOperStatus leaves, or just before it
* enters, the down state, respectively;"
@@ -324,10 +442,19 @@ mib_fetch_ifmib(struct mibif *ifp)
if (ifp->mib.ifmd_data.ifi_baudrate > 650000000)
ifp->flags |= MIBIF_VERYHIGHSPEED;
}
+ if (ifp->mib.ifmd_data.ifi_baudrate > mibif_maxspeed) {
+ mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate;
+ mibif_reset_hc_timer();
+ }
/*
* linkspecific MIB
*/
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_IFDATA;
+ name[4] = ifp->sysindex;
name[5] = IFDATA_LINKSPECIFIC;
if (sysctl(name, 6, NULL, &len, NULL, 0) == -1) {
syslog(LOG_WARNING, "sysctl linkmib estimate (%s): %m",
@@ -519,6 +646,7 @@ get_physaddr(struct mibif *ifp, struct sockaddr_dl *sdl, u_char *ptr)
static void
mibif_free(struct mibif *ifp)
{
+ struct mibif *ifp1;
struct mibindexmap *map;
struct mibifa *ifa, *ifa1;
struct mibrcvaddr *rcv, *rcv1;
@@ -531,6 +659,18 @@ mibif_free(struct mibif *ifp)
(void)mib_ifstack_delete(NULL, ifp);
TAILQ_REMOVE(&mibif_list, ifp, link);
+
+ /* if this was the fastest interface - recompute this */
+ if (ifp->mib.ifmd_data.ifi_baudrate == mibif_maxspeed) {
+ mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate;
+ TAILQ_FOREACH(ifp1, &mibif_list, link)
+ if (ifp1->mib.ifmd_data.ifi_baudrate > mibif_maxspeed)
+ mibif_maxspeed =
+ ifp1->mib.ifmd_data.ifi_baudrate;
+ mibif_reset_hc_timer();
+ }
+
+ free(ifp->private);
if (ifp->physaddr != NULL)
free(ifp->physaddr);
if (ifp->specmib != NULL)
@@ -589,6 +729,13 @@ mibif_create(u_int sysindex, const char *name)
return (NULL);
}
memset(ifp, 0, sizeof(*ifp));
+ if ((ifp->private = malloc(sizeof(struct mibif_private))) == NULL) {
+ syslog(LOG_WARNING, "%s: %m", __func__);
+ free(ifp);
+ return (NULL);
+ }
+ memset(ifp->private, 0, sizeof(struct mibif_private));
+
ifp->sysindex = sysindex;
strcpy(ifp->name, name);
strcpy(ifp->descr, name);
diff --git a/contrib/bsnmp/snmp_mibII/mibII.h b/contrib/bsnmp/snmp_mibII/mibII.h
index 4b0803d..65c14cc 100644
--- a/contrib/bsnmp/snmp_mibII/mibII.h
+++ b/contrib/bsnmp/snmp_mibII/mibII.h
@@ -56,7 +56,6 @@
#include "snmp_mibII.h"
#include "mibII_tree.h"
-
/*
* Interface list and flags.
*/
@@ -66,12 +65,19 @@ enum {
MIBIF_HIGHSPEED = 0x0002,
MIBIF_VERYHIGHSPEED = 0x0004,
};
-#define hc_inoctets mib.ifmd_data.ifi_ibytes
-#define hc_outoctets mib.ifmd_data.ifi_obytes
-#define hc_omcasts mib.ifmd_data.ifi_omcasts
-#define hc_opackets mib.ifmd_data.ifi_opackets
-#define hc_imcasts mib.ifmd_data.ifi_imcasts
-#define hc_ipackets mib.ifmd_data.ifi_ipackets
+
+/*
+ * Private mibif data - hang off from the mibif.
+ */
+struct mibif_private {
+ uint64_t hc_inoctets;
+ uint64_t hc_outoctets;
+ uint64_t hc_omcasts;
+ uint64_t hc_opackets;
+ uint64_t hc_imcasts;
+ uint64_t hc_ipackets;
+};
+#define MIBIF_PRIV(IFP) ((struct mibif_private *)((IFP)->private))
/*
* Interface addresses.
@@ -193,6 +199,18 @@ extern uint64_t mibarpticks;
/* info on system clocks */
extern struct clockinfo clockinfo;
+/* baud rate of fastest interface */
+extern uint64_t mibif_maxspeed;
+
+/* user-forced update interval */
+extern u_int mibif_force_hc_update_interval;
+
+/* current update interval */
+extern u_int mibif_hc_update_interval;
+
+/* re-compute update interval */
+void mibif_reset_hc_timer(void);
+
/* get interfaces and interface addresses. */
void mib_fetch_interfaces(void);
diff --git a/contrib/bsnmp/snmp_mibII/mibII_interfaces.c b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
index d3211d0..50ad630 100644
--- a/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
+++ b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
@@ -463,19 +463,20 @@ op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,
case LEAF_ifHCInOctets:
if (!(ifp->flags & MIBIF_HIGHSPEED))
goto again;
- value->v.counter64 = ifp->hc_inoctets;
+ value->v.counter64 = MIBIF_PRIV(ifp)->hc_inoctets;
break;
case LEAF_ifHCInUcastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
- value->v.counter64 = ifp->hc_ipackets - ifp->hc_imcasts;
+ value->v.counter64 = MIBIF_PRIV(ifp)->hc_ipackets -
+ MIBIF_PRIV(ifp)->hc_imcasts;
break;
case LEAF_ifHCInMulticastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
- value->v.counter64 = ifp->hc_imcasts;
+ value->v.counter64 = MIBIF_PRIV(ifp)->hc_imcasts;
break;
case LEAF_ifHCInBroadcastPkts:
@@ -487,19 +488,20 @@ op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,
case LEAF_ifHCOutOctets:
if (!(ifp->flags & MIBIF_HIGHSPEED))
goto again;
- value->v.counter64 = ifp->hc_outoctets;
+ value->v.counter64 = MIBIF_PRIV(ifp)->hc_outoctets;
break;
case LEAF_ifHCOutUcastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
- value->v.counter64 = ifp->hc_opackets - ifp->hc_omcasts;
+ value->v.counter64 = MIBIF_PRIV(ifp)->hc_opackets -
+ MIBIF_PRIV(ifp)->hc_omcasts;
break;
case LEAF_ifHCOutMulticastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
- value->v.counter64 = ifp->hc_omcasts;
+ value->v.counter64 = MIBIF_PRIV(ifp)->hc_omcasts;
break;
case LEAF_ifHCOutBroadcastPkts:
diff --git a/contrib/bsnmp/snmp_mibII/mibII_tree.def b/contrib/bsnmp/snmp_mibII/mibII_tree.def
index f8e250d..79e1345 100644
--- a/contrib/bsnmp/snmp_mibII/mibII_tree.def
+++ b/contrib/bsnmp/snmp_mibII/mibII_tree.def
@@ -230,6 +230,23 @@
(50 udpMIB
)
))
+ (4 private
+ (1 enterprises
+ (12325 fokus
+ (1 begemot
+ (3 begemotIp
+ (1 begemotIpObjects
+ (1 begemotMib2
+ (1 begemotIfMaxspeed COUNTER64 op_begemot_mibII GET)
+ (2 begemotIfPoll TIMETICKS op_begemot_mibII GET)
+ (3 begemotIfForcePoll TIMETICKS op_begemot_mibII GET SET)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
(6 snmpV2
(3 snmpModules
(1 snmpMIB
diff --git a/contrib/bsnmp/snmp_mibII/snmp_mibII.h b/contrib/bsnmp/snmp_mibII/snmp_mibII.h
index 98f2a72..9345184 100644
--- a/contrib/bsnmp/snmp_mibII/snmp_mibII.h
+++ b/contrib/bsnmp/snmp_mibII/snmp_mibII.h
@@ -79,6 +79,9 @@ struct mibif {
/* to be set by ifType specific modules. This is ifSpecific. */
struct asn_oid spec_oid;
+
+ /* private data - don't touch */
+ void *private;
};
/*
OpenPOWER on IntegriCloud