version 1.1.1.1, 2012/02/21 22:19:56
|
version 1.1.1.3, 2019/10/21 14:58:35
|
Line 1
|
Line 1
|
/* |
/* |
* in_sysctl.c sysctl (BSD) |
* in_sysctl.c sysctl (BSD) |
* |
* |
|
* $Id$ |
|
* |
* Copyright (c) 2001-2004 Thomas Graf <tgraf@suug.ch> |
* Copyright (c) 2001-2004 Thomas Graf <tgraf@suug.ch> |
|
* Copyright (c) 2014 Žilvinas Valinskas <zilvinas.valinskas@gmail.com> |
* |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* copy of this software and associated documentation files (the "Software"), |
Line 24
|
Line 27
|
|
|
#include <bmon/bmon.h> |
#include <bmon/bmon.h> |
#include <bmon/input.h> |
#include <bmon/input.h> |
#include <bmon/item.h> |
|
#include <bmon/conf.h> |
#include <bmon/conf.h> |
#include <bmon/node.h> | #include <bmon/group.h> |
| #include <bmon/element.h> |
#include <bmon/utils.h> |
#include <bmon/utils.h> |
|
|
#if defined SYS_BSD |
#if defined SYS_BSD |
Line 37
|
Line 40
|
#include <net/if_dl.h> |
#include <net/if_dl.h> |
#include <net/route.h> |
#include <net/route.h> |
|
|
static int c_debug; | static int c_debug = 0; |
| static struct element_group *grp; |
|
|
static void sysctl_read(void) | enum { |
| SYSCTL_RX_BYTES = 0x100, |
| SYSCTL_TX_BYTES, |
| SYSCTL_RX_PACKETS, |
| SYSCTL_TX_PACKETS, |
| SYSCTL_RX_ERRORS, |
| SYSCTL_TX_ERRORS, |
| SYSCTL_RX_DROPS, |
| SYSCTL_RX_MCAST, |
| SYSCTL_TX_MCAST, |
| SYSCTL_TX_COLLS, |
| }; |
| static struct attr_map link_attrs[] = { |
{ |
{ |
|
.name = "bytes", |
|
.type = ATTR_TYPE_COUNTER, |
|
.unit = UNIT_BYTE, |
|
.rxid = SYSCTL_RX_BYTES, |
|
.txid = SYSCTL_TX_BYTES, |
|
.description = "Bytes", |
|
}, |
|
{ |
|
.name = "packets", |
|
.type = ATTR_TYPE_COUNTER, |
|
.unit = UNIT_NUMBER, |
|
.rxid = SYSCTL_RX_PACKETS, |
|
.txid = SYSCTL_TX_PACKETS, |
|
.description = "Packets", |
|
}, |
|
{ |
|
.name = "errors", |
|
.type = ATTR_TYPE_COUNTER, |
|
.unit = UNIT_NUMBER, |
|
.rxid = SYSCTL_RX_ERRORS, |
|
.txid = SYSCTL_TX_ERRORS, |
|
.description = "Errors", |
|
}, |
|
{ |
|
.name = "drop", |
|
.type = ATTR_TYPE_COUNTER, |
|
.unit = UNIT_NUMBER, |
|
.rxid = SYSCTL_RX_DROPS, |
|
.description = "Dropped", |
|
}, |
|
{ |
|
.name = "coll", |
|
.type = ATTR_TYPE_COUNTER, |
|
.unit = UNIT_NUMBER, |
|
.txid = SYSCTL_TX_COLLS, |
|
.description = "Collisions", |
|
}, |
|
{ |
|
.name = "mcast", |
|
.type = ATTR_TYPE_COUNTER, |
|
.unit = UNIT_NUMBER, |
|
.rxid = SYSCTL_RX_MCAST, |
|
.txid = SYSCTL_TX_MCAST, |
|
.description = "Multicast", |
|
} |
|
}; |
|
|
|
uint64_t sysctl_get_stats(const struct if_msghdr *ifm, int what) |
|
{ |
|
switch(what) { |
|
case SYSCTL_RX_BYTES: |
|
return ifm->ifm_data.ifi_ibytes; |
|
case SYSCTL_TX_BYTES: |
|
return ifm->ifm_data.ifi_obytes; |
|
|
|
case SYSCTL_RX_PACKETS: |
|
return ifm->ifm_data.ifi_ipackets; |
|
case SYSCTL_TX_PACKETS: |
|
return ifm->ifm_data.ifi_opackets; |
|
|
|
case SYSCTL_RX_ERRORS: |
|
return ifm->ifm_data.ifi_ierrors; |
|
case SYSCTL_TX_ERRORS: |
|
return ifm->ifm_data.ifi_oerrors; |
|
|
|
case SYSCTL_RX_DROPS: |
|
return ifm->ifm_data.ifi_iqdrops; |
|
|
|
case SYSCTL_RX_MCAST: |
|
return ifm->ifm_data.ifi_imcasts; |
|
case SYSCTL_TX_MCAST: |
|
return ifm->ifm_data.ifi_omcasts; |
|
case SYSCTL_TX_COLLS: |
|
return ifm->ifm_data.ifi_collisions; |
|
|
|
default: |
|
return 0; |
|
}; |
|
} |
|
|
|
static void |
|
sysctl_read(void) |
|
{ |
int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; |
int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; |
size_t n; |
size_t n; |
char *buf, *next, *lim; |
char *buf, *next, *lim; |
Line 49 static void sysctl_read(void)
|
Line 148 static void sysctl_read(void)
|
quit("sysctl() failed"); |
quit("sysctl() failed"); |
|
|
if (c_debug) |
if (c_debug) |
fprintf(stderr, "sysctl 1-pass n=%d\n", (int) n); | fprintf(stderr, "sysctl 1-pass n=%zd\n", n); |
|
|
buf = xcalloc(1, n); |
buf = xcalloc(1, n); |
|
|
Line 57 static void sysctl_read(void)
|
Line 156 static void sysctl_read(void)
|
quit("sysctl() failed"); |
quit("sysctl() failed"); |
|
|
if (c_debug) |
if (c_debug) |
fprintf(stderr, "sysctl 2-pass n=%d\n", (int) n); | fprintf(stderr, "sysctl 2-pass n=%zd\n", n); |
|
|
lim = buf + n; | lim = (buf + n); |
next = buf; | for (next = buf; next < lim; ) { |
| struct element *e, *e_parent = NULL; |
while (next < lim) { | |
struct if_msghdr *ifm, *nextifm; |
struct if_msghdr *ifm, *nextifm; |
struct sockaddr_dl *sdl; |
struct sockaddr_dl *sdl; |
item_t *it; | char info_buf[64]; |
|
|
ifm = (struct if_msghdr *) next; |
ifm = (struct if_msghdr *) next; |
if (ifm->ifm_type != RTM_IFINFO) |
if (ifm->ifm_type != RTM_IFINFO) |
break; |
break; |
|
|
next += ifm->ifm_msglen; |
next += ifm->ifm_msglen; |
|
|
while (next < lim) { |
while (next < lim) { |
nextifm = (struct if_msghdr *) next; |
nextifm = (struct if_msghdr *) next; |
if (nextifm->ifm_type != RTM_NEWADDR) |
if (nextifm->ifm_type != RTM_NEWADDR) |
Line 81 static void sysctl_read(void)
|
Line 180 static void sysctl_read(void)
|
|
|
sdl = (struct sockaddr_dl *) (ifm + 1); |
sdl = (struct sockaddr_dl *) (ifm + 1); |
|
|
if (sdl->sdl_family != AF_LINK) | if (!cfg_show_all && !(ifm->ifm_flags & IFF_UP)) |
continue; |
continue; |
|
|
if (get_show_only_running() && !(ifm->ifm_flags & IFF_UP)) | if (sdl->sdl_family != AF_LINK) |
continue; |
continue; |
|
|
if (c_debug) |
if (c_debug) |
fprintf(stderr, "Processing %s\n", sdl->sdl_data); |
fprintf(stderr, "Processing %s\n", sdl->sdl_data); |
|
|
it = lookup_item(get_local_node(), sdl->sdl_data, 0, 0); | sdl->sdl_data[sdl->sdl_nlen] = '\0'; |
if (it == NULL) | e = element_lookup(grp, |
| sdl->sdl_data, sdl->sdl_index, |
| e_parent, ELEMENT_CREAT); |
| if (!e) |
continue; |
continue; |
|
|
it->i_major_attr = BYTES; | if (e->e_flags & ELEMENT_FLAG_CREATED) { |
it->i_minor_attr = PACKETS; | if (e->e_parent) |
| e->e_level = e->e_parent->e_level + 1; |
|
|
update_attr(it, PACKETS, | if (element_set_key_attr(e, "bytes", "packets") || |
ifm->ifm_data.ifi_ipackets, | element_set_usage_attr(e, "bytes")) |
ifm->ifm_data.ifi_opackets, | BUG(); |
RX_PROVIDED | TX_PROVIDED); | |
|
|
update_attr(it, BYTES, | e->e_flags &= ~ELEMENT_FLAG_CREATED; |
ifm->ifm_data.ifi_ibytes, | } |
ifm->ifm_data.ifi_obytes, | |
RX_PROVIDED | TX_PROVIDED); | |
|
|
update_attr(it, ERRORS, | int i; |
ifm->ifm_data.ifi_ierrors, | for (i = 0; i < ARRAY_SIZE(link_attrs); i++) { |
ifm->ifm_data.ifi_oerrors, | struct attr_map *m = &link_attrs[i]; |
RX_PROVIDED | TX_PROVIDED); | uint64_t rx = 0, tx = 0; |
| int flags = 0; |
|
|
update_attr(it, COLLISIONS, | if (m->rxid) { |
0, ifm->ifm_data.ifi_collisions, | rx = sysctl_get_stats(ifm, m->rxid); |
TX_PROVIDED); | flags |= UPDATE_FLAG_RX; |
| } |
|
|
update_attr(it, MULTICAST, | if (m->txid) { |
ifm->ifm_data.ifi_imcasts, | tx = sysctl_get_stats(ifm, m->txid); |
0, | flags |= UPDATE_FLAG_TX; |
RX_PROVIDED); | } |
|
|
update_attr(it, DROP, | attr_update(e, m->attrid, rx, tx, flags); |
0, | } |
ifm->ifm_data.ifi_iqdrops, | |
TX_PROVIDED); | |
|
|
notify_update(it, NULL); | snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_mtu); |
increase_lifetime(it, 1); | element_update_info(e, "MTU", info_buf); |
| |
| snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_metric); |
| element_update_info(e, "Metric", info_buf); |
| |
| #if !(defined(__NetBSD__) || defined(__FreeBSD__)) |
| snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_recvquota); |
| element_update_info(e, "RX-Quota", info_buf); |
| |
| snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_xmitquota); |
| element_update_info(e, "TX-Quota", info_buf); |
| #endif |
| |
| element_notify_update(e, NULL); |
| element_lifesign(e, 1); |
} |
} |
|
|
xfree(buf); |
xfree(buf); |
} |
} |
|
|
static void print_help(void) | static void |
| print_help(void) |
{ |
{ |
printf( |
printf( |
"sysctl - sysctl statistic collector for BSD and Darwin\n" \ | "sysctl - sysctl statistic collector for BSD and Darwin\n" \ |
"\n" \ | "\n" \ |
" BSD and Darwin statistic collector using sysctl()\n" \ | " BSD and Darwin statistic collector using sysctl()\n" \ |
" Author: Thomas Graf <tgraf@suug.ch>\n" \ | " Author: Thomas Graf <tgraf@suug.ch>\n" \ |
"\n"); | "\n"); |
} |
} |
|
|
static void sysctl_set_opts(tv_t *attrs) | static void |
| sysctl_set_opts(const char* type, const char* value) |
{ |
{ |
while (attrs) { | if (!strcasecmp(type, "debug")) |
if (!strcasecmp(attrs->type, "debug")) | c_debug = 1; |
c_debug = 1; | else if (!strcasecmp(type, "help")) { |
else if (!strcasecmp(attrs->type, "help")) { | print_help(); |
print_help(); | exit(0); |
exit(0); | |
} | |
attrs = attrs->next; | |
} |
} |
} |
} |
|
|
static int sysctl_probe(void) | static int |
| sysctl_probe(void) |
{ |
{ |
size_t n; |
size_t n; |
int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; |
int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; |
Line 165 static int sysctl_probe(void)
|
Line 279 static int sysctl_probe(void)
|
return 1; |
return 1; |
} |
} |
|
|
static struct input_module kstat_ops = { | static int sysctl_do_init(void) |
.im_name = "sysctl", | { |
.im_read = sysctl_read, | if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs))) |
.im_set_opts = sysctl_set_opts, | BUG(); |
.im_probe = sysctl_probe, | |
| grp = group_lookup(DEFAULT_GROUP, GROUP_CREATE); |
| if (!grp) |
| BUG(); |
| |
| return 0; |
| } |
| |
| static struct bmon_module kstat_ops = { |
| .m_name = "sysctl", |
| .m_do = sysctl_read, |
| .m_parse_opt = sysctl_set_opts, |
| .m_probe = sysctl_probe, |
| .m_init = sysctl_do_init, |
}; |
}; |
|
|
static void __init sysctl_init(void) | static void __init |
| sysctl_init(void) |
{ |
{ |
register_input_module(&kstat_ops); | input_register(&kstat_ops); |
} |
} |
|
|
#endif |
#endif |