File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bmon / src / in_sysctl.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 14:58:35 2019 UTC (4 years, 8 months ago) by misho
Branches: bmon, MAIN
CVS tags: v4_0p0, HEAD
bmon ver 4.0

    1: /*
    2:  * in_sysctl.c                 sysctl (BSD)
    3:  *
    4:  * $Id: in_sysctl.c,v 1.1.1.3 2019/10/21 14:58:35 misho Exp $
    5:  *
    6:  * Copyright (c) 2001-2004 Thomas Graf <tgraf@suug.ch>
    7:  * Copyright (c) 2014 Žilvinas Valinskas <zilvinas.valinskas@gmail.com>
    8:  *
    9:  * Permission is hereby granted, free of charge, to any person obtaining a
   10:  * copy of this software and associated documentation files (the "Software"),
   11:  * to deal in the Software without restriction, including without limitation
   12:  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   13:  * and/or sell copies of the Software, and to permit persons to whom the
   14:  * Software is furnished to do so, subject to the following conditions:
   15:  *
   16:  * The above copyright notice and this permission notice shall be included
   17:  * in all copies or substantial portions of the Software.
   18:  *
   19:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   20:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   22:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   23:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   24:  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   25:  * DEALINGS IN THE SOFTWARE.
   26:  */
   27: 
   28: #include <bmon/bmon.h>
   29: #include <bmon/input.h>
   30: #include <bmon/conf.h>
   31: #include <bmon/group.h>
   32: #include <bmon/element.h>
   33: #include <bmon/utils.h>
   34: 
   35: #if defined SYS_BSD
   36: #include <sys/socket.h>
   37: #include <net/if.h>
   38: #include <sys/param.h>
   39: #include <sys/sysctl.h>
   40: #include <net/if_dl.h>
   41: #include <net/route.h>
   42: 
   43: static int c_debug = 0;
   44: static struct element_group *grp;
   45: 
   46: enum {
   47: 	SYSCTL_RX_BYTES = 0x100,
   48: 	SYSCTL_TX_BYTES,
   49: 	SYSCTL_RX_PACKETS,
   50: 	SYSCTL_TX_PACKETS,
   51: 	SYSCTL_RX_ERRORS,
   52: 	SYSCTL_TX_ERRORS,
   53: 	SYSCTL_RX_DROPS,
   54: 	SYSCTL_RX_MCAST,
   55: 	SYSCTL_TX_MCAST,
   56: 	SYSCTL_TX_COLLS,
   57: };
   58: static struct attr_map link_attrs[] = {
   59: {
   60: 	.name		= "bytes",
   61: 	.type		= ATTR_TYPE_COUNTER,
   62: 	.unit		= UNIT_BYTE,
   63: 	.rxid		= SYSCTL_RX_BYTES,
   64: 	.txid		= SYSCTL_TX_BYTES,
   65: 	.description	= "Bytes",
   66: },
   67: {
   68: 	.name		= "packets",
   69: 	.type		= ATTR_TYPE_COUNTER,
   70: 	.unit		= UNIT_NUMBER,
   71: 	.rxid		= SYSCTL_RX_PACKETS,
   72: 	.txid		= SYSCTL_TX_PACKETS,
   73: 	.description	= "Packets",
   74: },
   75: {
   76: 	.name		= "errors",
   77: 	.type		= ATTR_TYPE_COUNTER,
   78: 	.unit		= UNIT_NUMBER,
   79: 	.rxid		= SYSCTL_RX_ERRORS,
   80: 	.txid		= SYSCTL_TX_ERRORS,
   81: 	.description	= "Errors",
   82: },
   83: {
   84: 	.name		= "drop",
   85: 	.type		= ATTR_TYPE_COUNTER,
   86: 	.unit		= UNIT_NUMBER,
   87: 	.rxid		= SYSCTL_RX_DROPS,
   88: 	.description	= "Dropped",
   89: },
   90: {
   91: 	.name		= "coll",
   92: 	.type		= ATTR_TYPE_COUNTER,
   93: 	.unit		= UNIT_NUMBER,
   94: 	.txid		= SYSCTL_TX_COLLS,
   95: 	.description	= "Collisions",
   96: },
   97: {
   98: 	.name		= "mcast",
   99: 	.type		= ATTR_TYPE_COUNTER,
  100: 	.unit		= UNIT_NUMBER,
  101: 	.rxid		= SYSCTL_RX_MCAST,
  102: 	.txid		= SYSCTL_TX_MCAST,
  103: 	.description	= "Multicast",
  104: }
  105: };
  106: 
  107: uint64_t sysctl_get_stats(const struct if_msghdr *ifm, int what)
  108: {
  109: 	switch(what) {
  110: 	case SYSCTL_RX_BYTES:
  111: 		return ifm->ifm_data.ifi_ibytes;
  112: 	case SYSCTL_TX_BYTES:
  113: 		return ifm->ifm_data.ifi_obytes;
  114: 
  115: 	case SYSCTL_RX_PACKETS:
  116: 		return ifm->ifm_data.ifi_ipackets;
  117: 	case SYSCTL_TX_PACKETS:
  118: 		return ifm->ifm_data.ifi_opackets;
  119: 
  120: 	case SYSCTL_RX_ERRORS:
  121: 		return ifm->ifm_data.ifi_ierrors;
  122: 	case SYSCTL_TX_ERRORS:
  123: 		return ifm->ifm_data.ifi_oerrors;
  124: 
  125: 	case SYSCTL_RX_DROPS:
  126: 		return ifm->ifm_data.ifi_iqdrops;
  127: 
  128: 	case SYSCTL_RX_MCAST:
  129: 		return ifm->ifm_data.ifi_imcasts;
  130: 	case SYSCTL_TX_MCAST:
  131: 		return ifm->ifm_data.ifi_omcasts;
  132: 	case SYSCTL_TX_COLLS:
  133: 		return ifm->ifm_data.ifi_collisions;
  134: 
  135: 	default:
  136: 		return 0;
  137: 	};
  138: }
  139: 
  140: static void
  141: sysctl_read(void)
  142: {
  143: 	int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
  144: 	size_t n;
  145: 	char *buf, *next, *lim;
  146: 
  147: 	if (sysctl(mib, 6, NULL, &n, NULL, 0) < 0)
  148: 		quit("sysctl() failed");
  149: 
  150: 	if (c_debug)
  151: 		fprintf(stderr, "sysctl 1-pass n=%zd\n", n);
  152: 
  153: 	buf = xcalloc(1, n);
  154: 
  155: 	if (sysctl(mib, 6, buf, &n, NULL, 0) < 0)
  156: 		quit("sysctl() failed");
  157: 
  158: 	if (c_debug)
  159: 		fprintf(stderr, "sysctl 2-pass n=%zd\n", n);
  160: 
  161: 	lim = (buf + n);
  162: 	for (next = buf; next < lim; ) {
  163: 		struct element *e, *e_parent = NULL;
  164: 		struct if_msghdr *ifm, *nextifm;
  165: 		struct sockaddr_dl *sdl;
  166: 		char info_buf[64];
  167: 
  168: 		ifm = (struct if_msghdr *) next;
  169: 		if (ifm->ifm_type != RTM_IFINFO)
  170: 			break;
  171: 
  172: 		next += ifm->ifm_msglen;
  173: 
  174: 		while (next < lim) {
  175: 			nextifm = (struct if_msghdr *) next;
  176: 			if (nextifm->ifm_type != RTM_NEWADDR)
  177: 				break;
  178: 			next += nextifm->ifm_msglen;
  179: 		}
  180: 
  181: 		sdl = (struct sockaddr_dl *) (ifm + 1);
  182: 
  183: 		if (!cfg_show_all && !(ifm->ifm_flags & IFF_UP))
  184: 			continue;
  185: 
  186: 		if (sdl->sdl_family != AF_LINK)
  187: 			continue;
  188: 
  189: 		if (c_debug)
  190: 			fprintf(stderr, "Processing %s\n", sdl->sdl_data);
  191: 
  192: 		sdl->sdl_data[sdl->sdl_nlen] = '\0';
  193: 		e = element_lookup(grp,
  194: 				   sdl->sdl_data, sdl->sdl_index,
  195: 				   e_parent, ELEMENT_CREAT);
  196: 		if (!e)
  197: 			continue;
  198: 
  199: 		if (e->e_flags & ELEMENT_FLAG_CREATED) {
  200: 			if (e->e_parent)
  201: 				e->e_level = e->e_parent->e_level + 1;
  202: 
  203: 			if (element_set_key_attr(e, "bytes", "packets") ||
  204: 			    element_set_usage_attr(e, "bytes"))
  205: 				BUG();
  206: 
  207: 			e->e_flags &= ~ELEMENT_FLAG_CREATED;
  208: 		}
  209: 
  210: 		int i;
  211: 		for (i = 0; i < ARRAY_SIZE(link_attrs); i++) {
  212: 			struct attr_map *m = &link_attrs[i];
  213: 			uint64_t rx = 0, tx = 0;
  214: 			int flags = 0;
  215: 
  216: 			if (m->rxid) {
  217: 				rx = sysctl_get_stats(ifm, m->rxid);
  218: 				flags |= UPDATE_FLAG_RX;
  219: 			}
  220: 
  221: 			if (m->txid) {
  222: 				tx = sysctl_get_stats(ifm, m->txid);
  223: 				flags |= UPDATE_FLAG_TX;
  224: 			}
  225: 
  226: 			attr_update(e, m->attrid, rx, tx, flags);
  227: 		}
  228: 
  229: 		snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_mtu);
  230: 		element_update_info(e, "MTU", info_buf);
  231: 
  232: 		snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_metric);
  233: 		element_update_info(e, "Metric", info_buf);
  234: 
  235: #if !(defined(__NetBSD__) || defined(__FreeBSD__))
  236: 		snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_recvquota);
  237: 		element_update_info(e, "RX-Quota", info_buf);
  238: 
  239: 		snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_xmitquota);
  240: 		element_update_info(e, "TX-Quota", info_buf);
  241: #endif
  242: 
  243: 		element_notify_update(e, NULL);
  244: 		element_lifesign(e, 1);
  245: 	}
  246: 
  247: 	xfree(buf);
  248: }
  249: 
  250: static void
  251: print_help(void)
  252: {
  253: 	printf(
  254: 		"sysctl - sysctl statistic collector for BSD and Darwin\n" \
  255: 		"\n" \
  256: 		"  BSD and Darwin statistic collector using sysctl()\n" \
  257: 		"  Author: Thomas Graf <tgraf@suug.ch>\n" \
  258: 		"\n");
  259: }
  260: 
  261: static void
  262: sysctl_set_opts(const char* type, const char* value)
  263: {
  264: 	if (!strcasecmp(type, "debug"))
  265: 		c_debug = 1;
  266: 	else if (!strcasecmp(type, "help")) {
  267: 		print_help();
  268: 		exit(0);
  269: 	}
  270: }
  271: 
  272: static int
  273: sysctl_probe(void)
  274: {
  275: 	size_t n;
  276: 	int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
  277: 	if (sysctl(mib, 6, NULL, &n, NULL, 0) < 0)
  278: 		return 0;
  279: 	return 1;
  280: }
  281: 
  282: static int sysctl_do_init(void)
  283: {
  284: 	if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs)))
  285: 		BUG();
  286: 
  287: 	grp = group_lookup(DEFAULT_GROUP, GROUP_CREATE);
  288: 	if (!grp)
  289: 		BUG();
  290: 
  291: 	return 0;
  292: }
  293: 
  294: static struct bmon_module kstat_ops = {
  295: 	.m_name = "sysctl",
  296: 	.m_do = sysctl_read,
  297: 	.m_parse_opt = sysctl_set_opts,
  298: 	.m_probe = sysctl_probe,
  299: 	.m_init = sysctl_do_init,
  300: };
  301: 
  302: static void __init
  303: sysctl_init(void)
  304: {
  305: 	input_register(&kstat_ops);
  306: }
  307: 
  308: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>