1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
--- 91 unchanged lines hidden (view full) ---
100uint64_t mibarpticks;
101
102/* info on system clocks */
103struct clockinfo clockinfo;
104
105/* list of all New if registrations */
106static struct newifreg_list newifreg_list = TAILQ_HEAD_INITIALIZER(newifreg_list);
107
108/* baud rate of fastest interface */
109uint64_t mibif_maxspeed;
110
111/* user-forced update interval */
112u_int mibif_force_hc_update_interval;
113
114/* current update interval */
115u_int mibif_hc_update_interval;
116
117/* HC update timer handle */
118static void *hc_update_timer;
119
120/*****************************/
121
122static const struct asn_oid oid_ifMIB = OIDX_ifMIB;
123static const struct asn_oid oid_ipMIB = OIDX_ipMIB;
124static const struct asn_oid oid_tcpMIB = OIDX_tcpMIB;
125static const struct asn_oid oid_udpMIB = OIDX_udpMIB;
126static const struct asn_oid oid_ipForward = OIDX_ipForward;
127static const struct asn_oid oid_linkDown = OIDX_linkDown;
--- 159 unchanged lines hidden (view full) ---
287 ifindex.var.subs[ifindex.var.len++] = ifp->index;
288 ifindex.syntax = SNMP_SYNTAX_INTEGER;
289 ifindex.v.integer = ifp->index;
290
291 snmp_send_trap(up ? &oid_linkUp : &oid_linkDown, &ifindex,
292 (struct snmp_value *)NULL);
293}
294
295/**
296 * Fetch the GENERIC IFMIB and update the HC counters
297 */
298static int
299fetch_generic_mib(struct mibif *ifp, const struct ifmibdata *old)
300{
301 int name[6];
302 size_t len;
303 struct mibif_private *p = ifp->private;
304
305 name[0] = CTL_NET;
306 name[1] = PF_LINK;
307 name[2] = NETLINK_GENERIC;
308 name[3] = IFMIB_IFDATA;
309 name[4] = ifp->sysindex;
310 name[5] = IFDATA_GENERAL;
311
312 len = sizeof(ifp->mib);
313 if (sysctl(name, 6, &ifp->mib, &len, NULL, 0) == -1) {
314 if (errno != ENOENT)
315 syslog(LOG_WARNING, "sysctl(ifmib, %s) failed %m",
316 ifp->name);
317 return (-1);
318 }
319
320 /*
321 * Assume that one of the two following compounds is optimized away
322 */
323 if (ULONG_MAX >= 0xffffffffffffffffULL) {
324 p->hc_inoctets = ifp->mib.ifmd_data.ifi_ibytes;
325 p->hc_outoctets = ifp->mib.ifmd_data.ifi_obytes;
326 p->hc_omcasts = ifp->mib.ifmd_data.ifi_omcasts;
327 p->hc_opackets = ifp->mib.ifmd_data.ifi_opackets;
328 p->hc_imcasts = ifp->mib.ifmd_data.ifi_imcasts;
329 p->hc_ipackets = ifp->mib.ifmd_data.ifi_ipackets;
330
331 } else if (ULONG_MAX >= 0xffffffff) {
332
333#define UPDATE(HC, MIB) \
334 if (old->ifmd_data.MIB > ifp->mib.ifmd_data.MIB) \
335 p->HC += (0x100000000ULL + \
336 ifp->mib.ifmd_data.MIB) - \
337 old->ifmd_data.MIB; \
338 else \
339 p->HC += ifp->mib.ifmd_data.MIB - \
340 old->ifmd_data.MIB;
341
342 UPDATE(hc_inoctets, ifi_ibytes)
343 UPDATE(hc_outoctets, ifi_obytes)
344 UPDATE(hc_omcasts, ifi_omcasts)
345 UPDATE(hc_opackets, ifi_opackets)
346 UPDATE(hc_imcasts, ifi_imcasts)
347 UPDATE(hc_ipackets, ifi_ipackets)
348
349#undef UPDATE
350 } else
351 abort();
352 return (0);
353}
354
355/**
356 * Update the 64-bit interface counters
357 */
358static void
359update_hc_counters(void *arg __unused)
360{
361 struct mibif *ifp;
362 struct ifmibdata oldmib;
363
364 TAILQ_FOREACH(ifp, &mibif_list, link) {
365 oldmib = ifp->mib;
366 (void)fetch_generic_mib(ifp, &oldmib);
367 }
368}
369
370/**
371 * Recompute the poll timer for the HC counters
372 */
373void
374mibif_reset_hc_timer(void)
375{
376 u_int ticks;
377
378 if ((ticks = mibif_force_hc_update_interval) == 0) {
379 if (mibif_maxspeed <= 10000000) {
380 /* at 10Mbps overflow needs 3436 seconds */
381 ticks = 3000 * 100; /* 50 minutes */
382 } else if (mibif_maxspeed <= 100000000) {
383 /* at 100Mbps overflow needs 343 seconds */
384 ticks = 300 * 100; /* 5 minutes */
385 } else if (mibif_maxspeed < 650000000) {
386 /* at 622Mbps overflow needs 53 seconds */
387 ticks = 40 * 100; /* 40 seconds */
388 } else if (mibif_maxspeed <= 1000000000) {
389 /* at 1Gbps overflow needs 34 seconds */
390 ticks = 20 * 100; /* 20 seconds */
391 } else {
392 /* at 10Gbps overflow needs 3.4 seconds */
393 ticks = 100; /* 1 seconds */
394 }
395 }
396
397 if (ticks == mibif_hc_update_interval)
398 return;
399
400 if (hc_update_timer != NULL) {
401 timer_stop(hc_update_timer);
402 hc_update_timer = NULL;
403 }
404 update_hc_counters(NULL);
405 if ((hc_update_timer = timer_start_repeat(ticks * 10, ticks * 10,
406 update_hc_counters, NULL, module)) == NULL) {
407 syslog(LOG_ERR, "timer_start(%u): %m", ticks);
408 return;
409 }
410 mibif_hc_update_interval = ticks;
411}
412
413/*
414 * Fetch new MIB data.
415 */
416int
417mib_fetch_ifmib(struct mibif *ifp)
418{
419 int name[6];
420 size_t len;
421 void *newmib;
422 struct ifmibdata oldmib = ifp->mib;
423
424 if (fetch_generic_mib(ifp, &oldmib) == -1)
425 return (-1);
426
427 /*
428 * Quoting RFC2863, 3.1.15: "... LinkUp and linkDown traps are
429 * generated just after ifOperStatus leaves, or just before it
430 * enters, the down state, respectively;"
431 */
432 if (ifp->trap_enable && ifp->mib.ifmd_data.ifi_link_state !=
433 oldmib.ifmd_data.ifi_link_state &&
434 (ifp->mib.ifmd_data.ifi_link_state == LINK_STATE_DOWN ||
435 oldmib.ifmd_data.ifi_link_state == LINK_STATE_DOWN))
436 link_trap(ifp, ifp->mib.ifmd_data.ifi_link_state ==
437 LINK_STATE_UP ? 1 : 0);
438
439 ifp->flags &= ~(MIBIF_HIGHSPEED | MIBIF_VERYHIGHSPEED);
440 if (ifp->mib.ifmd_data.ifi_baudrate > 20000000) {
441 ifp->flags |= MIBIF_HIGHSPEED;
442 if (ifp->mib.ifmd_data.ifi_baudrate > 650000000)
443 ifp->flags |= MIBIF_VERYHIGHSPEED;
444 }
445 if (ifp->mib.ifmd_data.ifi_baudrate > mibif_maxspeed) {
446 mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate;
447 mibif_reset_hc_timer();
448 }
449
450 /*
451 * linkspecific MIB
452 */
453 name[0] = CTL_NET;
454 name[1] = PF_LINK;
455 name[2] = NETLINK_GENERIC;
456 name[3] = IFMIB_IFDATA;
457 name[4] = ifp->sysindex;
458 name[5] = IFDATA_LINKSPECIFIC;
459 if (sysctl(name, 6, NULL, &len, NULL, 0) == -1) {
460 syslog(LOG_WARNING, "sysctl linkmib estimate (%s): %m",
461 ifp->name);
462 if (ifp->specmib != NULL) {
463 ifp->specmib = NULL;
464 ifp->specmiblen = 0;
465 }
--- 175 unchanged lines hidden (view full) ---
641}
642
643/*
644 * Free an interface
645 */
646static void
647mibif_free(struct mibif *ifp)
648{
649 struct mibif *ifp1;
650 struct mibindexmap *map;
651 struct mibifa *ifa, *ifa1;
652 struct mibrcvaddr *rcv, *rcv1;
653 struct mibarp *at, *at1;
654
655 if (ifp->xnotify != NULL)
656 (*ifp->xnotify)(ifp, MIBIF_NOTIFY_DESTROY, ifp->xnotify_data);
657
658 (void)mib_ifstack_delete(ifp, NULL);
659 (void)mib_ifstack_delete(NULL, ifp);
660
661 TAILQ_REMOVE(&mibif_list, ifp, link);
662
663 /* if this was the fastest interface - recompute this */
664 if (ifp->mib.ifmd_data.ifi_baudrate == mibif_maxspeed) {
665 mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate;
666 TAILQ_FOREACH(ifp1, &mibif_list, link)
667 if (ifp1->mib.ifmd_data.ifi_baudrate > mibif_maxspeed)
668 mibif_maxspeed =
669 ifp1->mib.ifmd_data.ifi_baudrate;
670 mibif_reset_hc_timer();
671 }
672
673 free(ifp->private);
674 if (ifp->physaddr != NULL)
675 free(ifp->physaddr);
676 if (ifp->specmib != NULL)
677 free(ifp->specmib);
678
679 STAILQ_FOREACH(map, &mibindexmap_list, link)
680 if (map->mibif == ifp) {
681 map->mibif = NULL;
--- 42 unchanged lines hidden (view full) ---
724 struct mibif *ifp;
725 struct mibindexmap *map;
726
727 if ((ifp = malloc(sizeof(*ifp))) == NULL) {
728 syslog(LOG_WARNING, "%s: %m", __func__);
729 return (NULL);
730 }
731 memset(ifp, 0, sizeof(*ifp));
732 if ((ifp->private = malloc(sizeof(struct mibif_private))) == NULL) {
733 syslog(LOG_WARNING, "%s: %m", __func__);
734 free(ifp);
735 return (NULL);
736 }
737 memset(ifp->private, 0, sizeof(struct mibif_private));
738
739 ifp->sysindex = sysindex;
740 strcpy(ifp->name, name);
741 strcpy(ifp->descr, name);
742 ifp->spec_oid = oid_zeroDotZero;
743
744 map = NULL;
745 if (!mib_if_is_dyn(ifp->name)) {
746 /* non-dynamic. look whether we know the interface */
--- 1043 unchanged lines hidden ---
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
--- 91 unchanged lines hidden (view full) ---
100uint64_t mibarpticks;
101
102/* info on system clocks */
103struct clockinfo clockinfo;
104
105/* list of all New if registrations */
106static struct newifreg_list newifreg_list = TAILQ_HEAD_INITIALIZER(newifreg_list);
107
108/* baud rate of fastest interface */
109uint64_t mibif_maxspeed;
110
111/* user-forced update interval */
112u_int mibif_force_hc_update_interval;
113
114/* current update interval */
115u_int mibif_hc_update_interval;
116
117/* HC update timer handle */
118static void *hc_update_timer;
119
120/*****************************/
121
122static const struct asn_oid oid_ifMIB = OIDX_ifMIB;
123static const struct asn_oid oid_ipMIB = OIDX_ipMIB;
124static const struct asn_oid oid_tcpMIB = OIDX_tcpMIB;
125static const struct asn_oid oid_udpMIB = OIDX_udpMIB;
126static const struct asn_oid oid_ipForward = OIDX_ipForward;
127static const struct asn_oid oid_linkDown = OIDX_linkDown;
--- 159 unchanged lines hidden (view full) ---
287 ifindex.var.subs[ifindex.var.len++] = ifp->index;
288 ifindex.syntax = SNMP_SYNTAX_INTEGER;
289 ifindex.v.integer = ifp->index;
290
291 snmp_send_trap(up ? &oid_linkUp : &oid_linkDown, &ifindex,
292 (struct snmp_value *)NULL);
293}
294
295/**
296 * Fetch the GENERIC IFMIB and update the HC counters
297 */
298static int
299fetch_generic_mib(struct mibif *ifp, const struct ifmibdata *old)
300{
301 int name[6];
302 size_t len;
303 struct mibif_private *p = ifp->private;
304
305 name[0] = CTL_NET;
306 name[1] = PF_LINK;
307 name[2] = NETLINK_GENERIC;
308 name[3] = IFMIB_IFDATA;
309 name[4] = ifp->sysindex;
310 name[5] = IFDATA_GENERAL;
311
312 len = sizeof(ifp->mib);
313 if (sysctl(name, 6, &ifp->mib, &len, NULL, 0) == -1) {
314 if (errno != ENOENT)
315 syslog(LOG_WARNING, "sysctl(ifmib, %s) failed %m",
316 ifp->name);
317 return (-1);
318 }
319
320 /*
321 * Assume that one of the two following compounds is optimized away
322 */
323 if (ULONG_MAX >= 0xffffffffffffffffULL) {
324 p->hc_inoctets = ifp->mib.ifmd_data.ifi_ibytes;
325 p->hc_outoctets = ifp->mib.ifmd_data.ifi_obytes;
326 p->hc_omcasts = ifp->mib.ifmd_data.ifi_omcasts;
327 p->hc_opackets = ifp->mib.ifmd_data.ifi_opackets;
328 p->hc_imcasts = ifp->mib.ifmd_data.ifi_imcasts;
329 p->hc_ipackets = ifp->mib.ifmd_data.ifi_ipackets;
330
331 } else if (ULONG_MAX >= 0xffffffff) {
332
333#define UPDATE(HC, MIB) \
334 if (old->ifmd_data.MIB > ifp->mib.ifmd_data.MIB) \
335 p->HC += (0x100000000ULL + \
336 ifp->mib.ifmd_data.MIB) - \
337 old->ifmd_data.MIB; \
338 else \
339 p->HC += ifp->mib.ifmd_data.MIB - \
340 old->ifmd_data.MIB;
341
342 UPDATE(hc_inoctets, ifi_ibytes)
343 UPDATE(hc_outoctets, ifi_obytes)
344 UPDATE(hc_omcasts, ifi_omcasts)
345 UPDATE(hc_opackets, ifi_opackets)
346 UPDATE(hc_imcasts, ifi_imcasts)
347 UPDATE(hc_ipackets, ifi_ipackets)
348
349#undef UPDATE
350 } else
351 abort();
352 return (0);
353}
354
355/**
356 * Update the 64-bit interface counters
357 */
358static void
359update_hc_counters(void *arg __unused)
360{
361 struct mibif *ifp;
362 struct ifmibdata oldmib;
363
364 TAILQ_FOREACH(ifp, &mibif_list, link) {
365 oldmib = ifp->mib;
366 (void)fetch_generic_mib(ifp, &oldmib);
367 }
368}
369
370/**
371 * Recompute the poll timer for the HC counters
372 */
373void
374mibif_reset_hc_timer(void)
375{
376 u_int ticks;
377
378 if ((ticks = mibif_force_hc_update_interval) == 0) {
379 if (mibif_maxspeed <= 10000000) {
380 /* at 10Mbps overflow needs 3436 seconds */
381 ticks = 3000 * 100; /* 50 minutes */
382 } else if (mibif_maxspeed <= 100000000) {
383 /* at 100Mbps overflow needs 343 seconds */
384 ticks = 300 * 100; /* 5 minutes */
385 } else if (mibif_maxspeed < 650000000) {
386 /* at 622Mbps overflow needs 53 seconds */
387 ticks = 40 * 100; /* 40 seconds */
388 } else if (mibif_maxspeed <= 1000000000) {
389 /* at 1Gbps overflow needs 34 seconds */
390 ticks = 20 * 100; /* 20 seconds */
391 } else {
392 /* at 10Gbps overflow needs 3.4 seconds */
393 ticks = 100; /* 1 seconds */
394 }
395 }
396
397 if (ticks == mibif_hc_update_interval)
398 return;
399
400 if (hc_update_timer != NULL) {
401 timer_stop(hc_update_timer);
402 hc_update_timer = NULL;
403 }
404 update_hc_counters(NULL);
405 if ((hc_update_timer = timer_start_repeat(ticks * 10, ticks * 10,
406 update_hc_counters, NULL, module)) == NULL) {
407 syslog(LOG_ERR, "timer_start(%u): %m", ticks);
408 return;
409 }
410 mibif_hc_update_interval = ticks;
411}
412
413/*
414 * Fetch new MIB data.
415 */
416int
417mib_fetch_ifmib(struct mibif *ifp)
418{
419 int name[6];
420 size_t len;
421 void *newmib;
422 struct ifmibdata oldmib = ifp->mib;
423
424 if (fetch_generic_mib(ifp, &oldmib) == -1)
425 return (-1);
426
427 /*
428 * Quoting RFC2863, 3.1.15: "... LinkUp and linkDown traps are
429 * generated just after ifOperStatus leaves, or just before it
430 * enters, the down state, respectively;"
431 */
432 if (ifp->trap_enable && ifp->mib.ifmd_data.ifi_link_state !=
433 oldmib.ifmd_data.ifi_link_state &&
434 (ifp->mib.ifmd_data.ifi_link_state == LINK_STATE_DOWN ||
435 oldmib.ifmd_data.ifi_link_state == LINK_STATE_DOWN))
436 link_trap(ifp, ifp->mib.ifmd_data.ifi_link_state ==
437 LINK_STATE_UP ? 1 : 0);
438
439 ifp->flags &= ~(MIBIF_HIGHSPEED | MIBIF_VERYHIGHSPEED);
440 if (ifp->mib.ifmd_data.ifi_baudrate > 20000000) {
441 ifp->flags |= MIBIF_HIGHSPEED;
442 if (ifp->mib.ifmd_data.ifi_baudrate > 650000000)
443 ifp->flags |= MIBIF_VERYHIGHSPEED;
444 }
445 if (ifp->mib.ifmd_data.ifi_baudrate > mibif_maxspeed) {
446 mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate;
447 mibif_reset_hc_timer();
448 }
449
450 /*
451 * linkspecific MIB
452 */
453 name[0] = CTL_NET;
454 name[1] = PF_LINK;
455 name[2] = NETLINK_GENERIC;
456 name[3] = IFMIB_IFDATA;
457 name[4] = ifp->sysindex;
458 name[5] = IFDATA_LINKSPECIFIC;
459 if (sysctl(name, 6, NULL, &len, NULL, 0) == -1) {
460 syslog(LOG_WARNING, "sysctl linkmib estimate (%s): %m",
461 ifp->name);
462 if (ifp->specmib != NULL) {
463 ifp->specmib = NULL;
464 ifp->specmiblen = 0;
465 }
--- 175 unchanged lines hidden (view full) ---
641}
642
643/*
644 * Free an interface
645 */
646static void
647mibif_free(struct mibif *ifp)
648{
649 struct mibif *ifp1;
650 struct mibindexmap *map;
651 struct mibifa *ifa, *ifa1;
652 struct mibrcvaddr *rcv, *rcv1;
653 struct mibarp *at, *at1;
654
655 if (ifp->xnotify != NULL)
656 (*ifp->xnotify)(ifp, MIBIF_NOTIFY_DESTROY, ifp->xnotify_data);
657
658 (void)mib_ifstack_delete(ifp, NULL);
659 (void)mib_ifstack_delete(NULL, ifp);
660
661 TAILQ_REMOVE(&mibif_list, ifp, link);
662
663 /* if this was the fastest interface - recompute this */
664 if (ifp->mib.ifmd_data.ifi_baudrate == mibif_maxspeed) {
665 mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate;
666 TAILQ_FOREACH(ifp1, &mibif_list, link)
667 if (ifp1->mib.ifmd_data.ifi_baudrate > mibif_maxspeed)
668 mibif_maxspeed =
669 ifp1->mib.ifmd_data.ifi_baudrate;
670 mibif_reset_hc_timer();
671 }
672
673 free(ifp->private);
674 if (ifp->physaddr != NULL)
675 free(ifp->physaddr);
676 if (ifp->specmib != NULL)
677 free(ifp->specmib);
678
679 STAILQ_FOREACH(map, &mibindexmap_list, link)
680 if (map->mibif == ifp) {
681 map->mibif = NULL;
--- 42 unchanged lines hidden (view full) ---
724 struct mibif *ifp;
725 struct mibindexmap *map;
726
727 if ((ifp = malloc(sizeof(*ifp))) == NULL) {
728 syslog(LOG_WARNING, "%s: %m", __func__);
729 return (NULL);
730 }
731 memset(ifp, 0, sizeof(*ifp));
732 if ((ifp->private = malloc(sizeof(struct mibif_private))) == NULL) {
733 syslog(LOG_WARNING, "%s: %m", __func__);
734 free(ifp);
735 return (NULL);
736 }
737 memset(ifp->private, 0, sizeof(struct mibif_private));
738
739 ifp->sysindex = sysindex;
740 strcpy(ifp->name, name);
741 strcpy(ifp->descr, name);
742 ifp->spec_oid = oid_zeroDotZero;
743
744 map = NULL;
745 if (!mib_if_is_dyn(ifp->name)) {
746 /* non-dynamic. look whether we know the interface */
--- 1043 unchanged lines hidden ---