Exemple #1
0
inline int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url) {
    // get the name of the data to show
    char *tok = mystrsep(&url, "/?&");
    if(tok && *tok) {
        debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);

        // do we have such a data set?
        RRDSET *st = rrdset_find_byname(host, tok);
        if(!st) st = rrdset_find(host, tok);
        if(!st) {
            // we don't have it
            // try to send a file with that name
            buffer_flush(w->response.data);
            return mysendfile(w, tok);
        }
        st->last_accessed_time = now_realtime_sec();

        debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
        w->response.data->contenttype = CT_APPLICATION_JSON;
        buffer_flush(w->response.data);
        rrd_graph2json_api_old(st, url, w->response.data);
        return 200;
    }

    buffer_flush(w->response.data);
    buffer_strcat(w->response.data, "Graph name?\r\n");
    return 400;
}
Exemple #2
0
RRDSET *rrdset_find_bytype(const char *type, const char *id)
{
	debug(D_RRD_CALLS, "rrdset_find_bytype() for chart %s.%s", type, id);

	char buf[RRD_ID_LENGTH_MAX + 1];

	strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1);
	strcat(buf, ".");
	int len = (int) strlen(buf);
	strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len));

	return(rrdset_find(buf));
}
void *cpuidlejitter_main(void *ptr)
{
	if(ptr) { ; }

	info("CPU Idle Jitter thread created with task id %d", gettid());

	if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
		error("Cannot set pthread cancel type to DEFERRED.");

	if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
		error("Cannot set pthread cancel state to ENABLE.");

	int sleep_ms = (int) config_get_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
	if(sleep_ms <= 0) {
		config_set_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
		sleep_ms = CPU_IDLEJITTER_SLEEP_TIME_MS;
	}

	RRDSET *st = rrdset_find("system.idlejitter");
	if(!st) {
		st = rrdset_create("system", "idlejitter", NULL, "cpu", "CPU Idle Jitter", "microseconds lost/s", 9999, rrd_update_every, RRDSET_TYPE_LINE);
		rrddim_add(st, "jitter", NULL, 1, 1, RRDDIM_ABSOLUTE);
	}

	struct timeval before, after;
	unsigned long long counter;
	for(counter = 0; 1 ;counter++) {
		unsigned long long usec = 0, susec = 0;

		while(susec < (rrd_update_every * 1000000ULL)) {

			gettimeofday(&before, NULL);
			usleep(sleep_ms * 1000);
			gettimeofday(&after, NULL);

			// calculate the time it took for a full loop
			usec = usecdiff(&after, &before);
			susec += usec;
		}
		usec -= (sleep_ms * 1000);

		if(counter) rrdset_next(st);
		rrddim_set(st, "jitter", usec);
		rrdset_done(st);
	}

	return NULL;
}
inline int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) {
    int ret = 400;
    char *chart = NULL;

    buffer_flush(w->response.data);

    while(url) {
        char *value = mystrsep(&url, "?&");
        if(!value || !*value) continue;

        char *name = mystrsep(&value, "=");
        if(!name || !*name) continue;
        if(!value || !*value) continue;

        // name and value are now the parameters
        // they are not null and not empty

        if(!strcmp(name, "chart")) chart = value;
        //else {
        /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
        //  goto cleanup;
        //}
    }

    if(!chart || !*chart) {
        buffer_sprintf(w->response.data, "No chart id is given at the request.");
        goto cleanup;
    }

    RRDSET *st = rrdset_find(host, chart);
    if(!st) st = rrdset_find_byname(host, chart);
    if(!st) {
        buffer_strcat(w->response.data, "Chart is not found: ");
        buffer_strcat_htmlescape(w->response.data, chart);
        ret = 404;
        goto cleanup;
    }

    w->response.data->contenttype = CT_APPLICATION_JSON;
    st->last_accessed_time = now_realtime_sec();
    callback(st, w->response.data);
    return 200;

    cleanup:
    return ret;
}
Exemple #5
0
int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type) {
    if(!url || !*url) {
        buffer_flush(w->response.data);
        buffer_sprintf(w->response.data, "Incomplete request.");
        return 400;
    }

    RRDSET *st = NULL;

    char *args = strchr(url, '?');
    if(args) {
        *args='\0';
        args = &args[1];
    }

    // get the name of the data to show
    char *tok = mystrsep(&url, "/");
    if(!tok) tok = "";

    // do we have such a data set?
    if(*tok) {
        debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
        st = rrdset_find_byname(host, tok);
        if(!st) st = rrdset_find(host, tok);
    }

    if(!st) {
        // we don't have it
        // try to send a file with that name
        buffer_flush(w->response.data);
        return(mysendfile(w, tok));
    }

    // we have it
    debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok);

    // how many entries does the client want?
    int lines = (int)st->entries;
    int group_count = 1;
    time_t after = 0, before = 0;
    int group_method = GROUP_AVERAGE;
    int nonzero = 0;

    if(url) {
        // parse the lines required
        tok = mystrsep(&url, "/");
        if(tok) lines = str2i(tok);
        if(lines < 1) lines = 1;
    }
    if(url) {
        // parse the group count required
        tok = mystrsep(&url, "/");
        if(tok && *tok) group_count = str2i(tok);
        if(group_count < 1) group_count = 1;
        //if(group_count > save_history / 20) group_count = save_history / 20;
    }
    if(url) {
        // parse the grouping method required
        tok = mystrsep(&url, "/");
        if(tok && *tok) {
            if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
            else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
            else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
            else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
        }
    }
    if(url) {
        // parse after time
        tok = mystrsep(&url, "/");
        if(tok && *tok) after = str2ul(tok);
        if(after < 0) after = 0;
    }
    if(url) {
        // parse before time
        tok = mystrsep(&url, "/");
        if(tok && *tok) before = str2ul(tok);
        if(before < 0) before = 0;
    }
    if(url) {
        // parse nonzero
        tok = mystrsep(&url, "/");
        if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
    }

    w->response.data->contenttype = CT_APPLICATION_JSON;
    buffer_flush(w->response.data);

    char *google_version = "0.6";
    char *google_reqId = "0";
    char *google_sig = "0";
    char *google_out = "json";
    char *google_responseHandler = "google.visualization.Query.setResponse";
    char *google_outFileName = NULL;
    time_t last_timestamp_in_data = 0;
    if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) {

        w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;

        while(args) {
            tok = mystrsep(&args, "&");
            if(tok && *tok) {
                char *name = mystrsep(&tok, "=");
                if(name && *name && strcmp(name, "tqx") == 0) {
                    char *key = mystrsep(&tok, ":");
                    char *value = mystrsep(&tok, ";");
                    if(key && value && *key && *value) {
                        if(strcmp(key, "version") == 0)
                            google_version = value;

                        else if(strcmp(key, "reqId") == 0)
                            google_reqId = value;

                        else if(strcmp(key, "sig") == 0)
                            google_sig = value;

                        else if(strcmp(key, "out") == 0)
                            google_out = value;

                        else if(strcmp(key, "responseHandler") == 0)
                            google_responseHandler = value;

                        else if(strcmp(key, "outFileName") == 0)
                            google_outFileName = value;
                    }
                }
            }
        }

        debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
                w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName
        );

        if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
            last_timestamp_in_data = strtoul(google_sig, NULL, 0);

            // check the client wants json
            if(strcmp(google_out, "json") != 0) {
                buffer_sprintf(w->response.data,
                        "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
                        google_responseHandler, google_version, google_reqId, google_out);
                return 200;
            }
        }
    }

    if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
        buffer_sprintf(w->response.data,
                "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
                google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
    }

    debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).",
            w->id, st->name, st->id, lines, group_count, group_method, after, before);

    time_t timestamp_in_data = rrdset2json_api_old(datasource_type, st, w->response.data, lines, group_count
                                                   , group_method, (unsigned long) after, (unsigned long) before
                                                   , nonzero);

    if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
        if(timestamp_in_data > last_timestamp_in_data)
            buffer_strcat(w->response.data, "});");

        else {
            // the client already has the latest data
            buffer_flush(w->response.data);
            buffer_sprintf(w->response.data,
                    "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
                    google_responseHandler, google_version, google_reqId);
        }
    }

    return 200;
}
void *checks_main(void *ptr)
{
	if(ptr) { ; }

	info("CHECKS thread created with task id %d", gettid());

	if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
		error("Cannot set pthread cancel type to DEFERRED.");

	if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
		error("Cannot set pthread cancel state to ENABLE.");

	unsigned long long usec = 0, susec = rrd_update_every * 1000000ULL, loop_usec = 0, total_susec = 0;
	struct timeval now, last, loop;

	RRDSET *check1, *check2, *check3, *apps_cpu = NULL;

	check1 = rrdset_create("netdata", "check1", NULL, "netdata", "Caller gives microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE);
	rrddim_add(check1, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE);
	rrddim_add(check1, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL);

	check2 = rrdset_create("netdata", "check2", NULL, "netdata", "Netdata calcs microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE);
	rrddim_add(check2, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE);
	rrddim_add(check2, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL);

	check3 = rrdset_create("netdata", "checkdt", NULL, "netdata", "Clock difference", "microseconds diff", 99999, rrd_update_every, RRDSET_TYPE_LINE);
	rrddim_add(check3, "caller", NULL, 1, 1, RRDDIM_ABSOLUTE);
	rrddim_add(check3, "netdata", NULL, 1, 1, RRDDIM_ABSOLUTE);
	rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRDDIM_ABSOLUTE);

	gettimeofday(&last, NULL);
	while(1) {
		usleep(susec);

		// find the time to sleep in order to wait exactly update_every seconds
		gettimeofday(&now, NULL);
		loop_usec = usecdiff(&now, &last);
		usec = loop_usec - susec;
		debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, sleeped for %llu).", loop_usec, usec, susec);

		if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
		else susec = rrd_update_every * 1000000ULL / 2ULL;

		// --------------------------------------------------------------------
		// Calculate loop time

		last.tv_sec = now.tv_sec;
		last.tv_usec = now.tv_usec;
		total_susec += loop_usec;

		// --------------------------------------------------------------------
		// check chart 1

		if(check1->counter_done) rrdset_next_usec(check1, loop_usec);
		rrddim_set(check1, "absolute", 1000000);
		rrddim_set(check1, "incremental", total_susec);
		rrdset_done(check1);

		// --------------------------------------------------------------------
		// check chart 2

		if(check2->counter_done) rrdset_next(check2);
		rrddim_set(check2, "absolute", 1000000);
		rrddim_set(check2, "incremental", total_susec);
		rrdset_done(check2);

		// --------------------------------------------------------------------
		// check chart 3

		if(!apps_cpu) apps_cpu = rrdset_find("apps.cpu");
		if(check3->counter_done) rrdset_next_usec(check3, loop_usec);
		gettimeofday(&loop, NULL);
		rrddim_set(check3, "caller", (long long)usecdiff(&loop, &check1->last_collected_time));
		rrddim_set(check3, "netdata", (long long)usecdiff(&loop, &check2->last_collected_time));
		if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long)usecdiff(&loop, &apps_cpu->last_collected_time));
		rrdset_done(check3);
	}

	return NULL;
}
int do_proc_net_ip_vs_stats(int update_every, unsigned long long dt) {
	static int do_bandwidth = -1, do_sockets = -1, do_packets = -1;
	static procfile *ff = NULL;

	if(do_bandwidth == -1)	do_bandwidth 	= config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS bandwidth", 1);
	if(do_sockets == -1)	do_sockets 		= config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS connections", 1);
	if(do_packets == -1)	do_packets 		= config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS packets", 1);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/ip_vs_stats");
		ff = procfile_open(config_get("plugin:proc:/proc/net/ip_vs_stats", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
	}
	if(!ff) return 1;

	ff = procfile_readall(ff);
	if(!ff) return 0; // we return 0, so that we will retry to open it next time

	// make sure we have 3 lines
	if(procfile_lines(ff) < 3) return 1;

	// make sure we have 5 words on the 3rd line
	if(procfile_linewords(ff, 2) < 5) return 1;

	unsigned long long entries, InPackets, OutPackets, InBytes, OutBytes;

	entries 	= strtoull(procfile_lineword(ff, 2, 0), NULL, 16);
	InPackets 	= strtoull(procfile_lineword(ff, 2, 1), NULL, 16);
	OutPackets 	= strtoull(procfile_lineword(ff, 2, 2), NULL, 16);
	InBytes 	= strtoull(procfile_lineword(ff, 2, 3), NULL, 16);
	OutBytes 	= strtoull(procfile_lineword(ff, 2, 4), NULL, 16);

	RRDSET *st;

	// --------------------------------------------------------------------

	if(do_sockets) {
		st = rrdset_find(RRD_TYPE_NET_IPVS ".sockets");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);

			rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "connections", entries);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_packets) {
		st = rrdset_find(RRD_TYPE_NET_IPVS ".packets");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Packets", "packets/s", 1002, update_every, RRDSET_TYPE_LINE);

			rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "received", InPackets);
		rrddim_set(st, "sent", OutPackets);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_bandwidth) {
		st = rrdset_find(RRD_TYPE_NET_IPVS ".net");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Bandwidth", "kilobits/s", 1000, update_every, RRDSET_TYPE_AREA);

			rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
			rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "received", InBytes);
		rrddim_set(st, "sent", OutBytes);
		rrdset_done(st);
	}

	return 0;
}
Exemple #8
0
int do_proc_net_netstat(int update_every, usec_t dt) {
    (void)dt;

    static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
        do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1;
    static uint32_t hash_ipext = 0, hash_tcpext = 0;
    static procfile *ff = NULL;

    static ARL_BASE *arl_tcpext = NULL;
    static ARL_BASE *arl_ipext = NULL;

    // --------------------------------------------------------------------
    // IPv4

    // IPv4 bandwidth
    static unsigned long long ipext_InOctets = 0;
    static unsigned long long ipext_OutOctets = 0;

    // IPv4 input errors
    static unsigned long long ipext_InNoRoutes = 0;
    static unsigned long long ipext_InTruncatedPkts = 0;
    static unsigned long long ipext_InCsumErrors = 0;

    // IPv4 multicast bandwidth
    static unsigned long long ipext_InMcastOctets = 0;
    static unsigned long long ipext_OutMcastOctets = 0;

    // IPv4 multicast packets
    static unsigned long long ipext_InMcastPkts = 0;
    static unsigned long long ipext_OutMcastPkts = 0;

    // IPv4 broadcast bandwidth
    static unsigned long long ipext_InBcastOctets = 0;
    static unsigned long long ipext_OutBcastOctets = 0;

    // IPv4 broadcast packets
    static unsigned long long ipext_InBcastPkts = 0;
    static unsigned long long ipext_OutBcastPkts = 0;

    // IPv4 ECN
    static unsigned long long ipext_InNoECTPkts = 0;
    static unsigned long long ipext_InECT1Pkts = 0;
    static unsigned long long ipext_InECT0Pkts = 0;
    static unsigned long long ipext_InCEPkts = 0;

    // --------------------------------------------------------------------
    // IPv4 TCP

    // IPv4 TCP Reordering
    static unsigned long long tcpext_TCPRenoReorder = 0;
    static unsigned long long tcpext_TCPFACKReorder = 0;
    static unsigned long long tcpext_TCPSACKReorder = 0;
    static unsigned long long tcpext_TCPTSReorder = 0;

    // IPv4 TCP SYN Cookies
    static unsigned long long tcpext_SyncookiesSent = 0;
    static unsigned long long tcpext_SyncookiesRecv = 0;
    static unsigned long long tcpext_SyncookiesFailed = 0;

    // IPv4 TCP Out Of Order Queue
    // http://www.spinics.net/lists/netdev/msg204696.html
    static unsigned long long tcpext_TCPOFOQueue = 0; // Number of packets queued in OFO queue
    static unsigned long long tcpext_TCPOFODrop = 0;  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
    static unsigned long long tcpext_TCPOFOMerge = 0; // Number of packets in OFO that were merged with other packets.
    static unsigned long long tcpext_OfoPruned = 0;   // packets dropped from out-of-order queue because of socket buffer overrun

    // IPv4 TCP connection resets
    // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
    static unsigned long long tcpext_TCPAbortOnData = 0;    // connections reset due to unexpected data
    static unsigned long long tcpext_TCPAbortOnClose = 0;   // connections reset due to early user close
    static unsigned long long tcpext_TCPAbortOnMemory = 0;  // connections aborted due to memory pressure
    static unsigned long long tcpext_TCPAbortOnTimeout = 0; // connections aborted due to timeout
    static unsigned long long tcpext_TCPAbortOnLinger = 0;  // connections aborted after user close in linger timeout
    static unsigned long long tcpext_TCPAbortFailed = 0;    // times unable to send RST due to no memory

    // IPv4 TCP memory pressures
    static unsigned long long tcpext_TCPMemoryPressures = 0;

    if(unlikely(!arl_ipext)) {
        hash_ipext = simple_hash("IpExt");
        hash_tcpext = simple_hash("TcpExt");

        do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_inerrors  = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_ecn       = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);

        do_tcpext_reorder    = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_ofo        = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_memory     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_ONDEMAND_ONDEMAND);

        arl_ipext  = arl_create("netstat/ipext", NULL, 60);
        arl_tcpext = arl_create("netstat/tcpext", NULL, 60);

        // --------------------------------------------------------------------
        // IPv4

        if(do_bandwidth != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InOctets",  &ipext_InOctets);
            arl_expect(arl_ipext, "OutOctets", &ipext_OutOctets);
        }

        if(do_inerrors != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InNoRoutes",      &ipext_InNoRoutes);
            arl_expect(arl_ipext, "InTruncatedPkts", &ipext_InTruncatedPkts);
            arl_expect(arl_ipext, "InCsumErrors",    &ipext_InCsumErrors);
        }

        if(do_mcast != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InMcastOctets", &ipext_InMcastOctets);
            arl_expect(arl_ipext, "OutMcastOctets", &ipext_OutMcastOctets);
        }

        if(do_mcast_p != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InMcastPkts",  &ipext_InMcastPkts);
            arl_expect(arl_ipext, "OutMcastPkts", &ipext_OutMcastPkts);
        }

        if(do_bcast != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InBcastPkts",  &ipext_InBcastPkts);
            arl_expect(arl_ipext, "OutBcastPkts", &ipext_OutBcastPkts);
        }

        if(do_bcast_p != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InBcastOctets",  &ipext_InBcastOctets);
            arl_expect(arl_ipext, "OutBcastOctets", &ipext_OutBcastOctets);
        }

        if(do_ecn != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InNoECTPkts", &ipext_InNoECTPkts);
            arl_expect(arl_ipext, "InECT1Pkts",  &ipext_InECT1Pkts);
            arl_expect(arl_ipext, "InECT0Pkts",  &ipext_InECT0Pkts);
            arl_expect(arl_ipext, "InCEPkts",    &ipext_InCEPkts);
        }

        // --------------------------------------------------------------------
        // IPv4 TCP

        if(do_tcpext_reorder != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPFACKReorder", &tcpext_TCPFACKReorder);
            arl_expect(arl_tcpext, "TCPSACKReorder", &tcpext_TCPSACKReorder);
            arl_expect(arl_tcpext, "TCPRenoReorder", &tcpext_TCPRenoReorder);
            arl_expect(arl_tcpext, "TCPTSReorder",   &tcpext_TCPTSReorder);
        }

        if(do_tcpext_syscookies != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "SyncookiesSent",   &tcpext_SyncookiesSent);
            arl_expect(arl_tcpext, "SyncookiesRecv",   &tcpext_SyncookiesRecv);
            arl_expect(arl_tcpext, "SyncookiesFailed", &tcpext_SyncookiesFailed);
        }

        if(do_tcpext_ofo != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPOFOQueue", &tcpext_TCPOFOQueue);
            arl_expect(arl_tcpext, "TCPOFODrop",  &tcpext_TCPOFODrop);
            arl_expect(arl_tcpext, "TCPOFOMerge", &tcpext_TCPOFOMerge);
            arl_expect(arl_tcpext, "OfoPruned",   &tcpext_OfoPruned);
        }

        if(do_tcpext_connaborts != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPAbortOnData",    &tcpext_TCPAbortOnData);
            arl_expect(arl_tcpext, "TCPAbortOnClose",   &tcpext_TCPAbortOnClose);
            arl_expect(arl_tcpext, "TCPAbortOnMemory",  &tcpext_TCPAbortOnMemory);
            arl_expect(arl_tcpext, "TCPAbortOnTimeout", &tcpext_TCPAbortOnTimeout);
            arl_expect(arl_tcpext, "TCPAbortOnLinger",  &tcpext_TCPAbortOnLinger);
            arl_expect(arl_tcpext, "TCPAbortFailed",    &tcpext_TCPAbortFailed);
        }

        if(do_tcpext_memory != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures);
        }
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/netstat");
        ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
        if(unlikely(!ff)) return 1;
    }

    ff = procfile_readall(ff);
    if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time

    size_t lines = procfile_lines(ff), l;
    size_t words;

    arl_begin(arl_ipext);
    arl_begin(arl_tcpext);

    for(l = 0; l < lines ;l++) {
        char *key = procfile_lineword(ff, l, 0);
        uint32_t hash = simple_hash(key);

        if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
            size_t h = l++;

            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %zu.", words);
                continue;
            }

            parse_line_pair(ff, arl_ipext, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (ipext_InOctets || ipext_OutOctets))) {
                do_bandwidth = CONFIG_ONDEMAND_YES;
                st = rrdset_find("system.ipv4");
                if(unlikely(!st)) {
                    st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);

                    rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InOctets", ipext_InOctets);
                rrddim_set(st, "OutOctets", ipext_OutOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (ipext_InNoRoutes || ipext_InTruncatedPkts))) {
                do_inerrors = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.inerrors");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InNoRoutes", "noroutes", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InTruncatedPkts", "truncated", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", "checksum", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InNoRoutes", ipext_InNoRoutes);
                rrddim_set(st, "InTruncatedPkts", ipext_InTruncatedPkts);
                rrddim_set(st, "InCsumErrors", ipext_InCsumErrors);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (ipext_InMcastOctets || ipext_OutMcastOctets))) {
                do_mcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastOctets", ipext_InMcastOctets);
                rrddim_set(st, "OutMcastOctets", ipext_OutMcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (ipext_InBcastOctets || ipext_OutBcastOctets))) {
                do_bcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastOctets", ipext_InBcastOctets);
                rrddim_set(st, "OutBcastOctets", ipext_OutBcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (ipext_InMcastPkts || ipext_OutMcastPkts))) {
                do_mcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 8600, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastPkts", ipext_InMcastPkts);
                rrddim_set(st, "OutMcastPkts", ipext_OutMcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (ipext_InBcastPkts || ipext_OutBcastPkts))) {
                do_bcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastPkts", ipext_InBcastPkts);
                rrddim_set(st, "OutBcastPkts", ipext_OutBcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) {
                do_ecn = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.ecnpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InCEPkts", ipext_InCEPkts);
                rrddim_set(st, "InNoECTPkts", ipext_InNoECTPkts);
                rrddim_set(st, "InECT0Pkts", ipext_InECT0Pkts);
                rrddim_set(st, "InECT1Pkts", ipext_InECT1Pkts);
                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
            size_t h = l++;

            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %zu.", words);
                continue;
            }

            parse_line_pair(ff, arl_tcpext, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_tcpext_memory == CONFIG_ONDEMAND_YES || (do_tcpext_memory == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPMemoryPressures))) {
                do_tcpext_memory = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpmemorypressures");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures", "events/s", 3000, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPMemoryPressures",   "pressures",  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPMemoryPressures", tcpext_TCPMemoryPressures);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) {
                do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpconnaborts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnLinger",  "linger",      1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortFailed",    "failed",     -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPAbortOnData",    tcpext_TCPAbortOnData);
                rrddim_set(st, "TCPAbortOnClose",   tcpext_TCPAbortOnClose);
                rrddim_set(st, "TCPAbortOnMemory",  tcpext_TCPAbortOnMemory);
                rrddim_set(st, "TCPAbortOnTimeout", tcpext_TCPAbortOnTimeout);
                rrddim_set(st, "TCPAbortOnLinger",  tcpext_TCPAbortOnLinger);
                rrddim_set(st, "TCPAbortFailed",    tcpext_TCPAbortFailed);
                rrdset_done(st);
            }
            // --------------------------------------------------------------------

            if(do_tcpext_reorder == CONFIG_ONDEMAND_YES || (do_tcpext_reorder == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) {
                do_tcpext_reorder = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpreorders");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpreorders", NULL, "tcp", NULL, "TCP Reordered Packets by Detection Method", "packets/s", 3020, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPTSReorder",   "timestamp",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPSACKReorder", "sack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPFACKReorder", "fack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPRenoReorder", "reno",        1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPTSReorder",   tcpext_TCPTSReorder);
                rrddim_set(st, "TCPSACKReorder", tcpext_TCPSACKReorder);
                rrddim_set(st, "TCPFACKReorder", tcpext_TCPFACKReorder);
                rrddim_set(st, "TCPRenoReorder", tcpext_TCPRenoReorder);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) {
                do_tcpext_ofo = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpofo");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFODrop",  "dropped", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFOMerge", "merged",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OfoPruned",   "pruned",  -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPOFOQueue",   tcpext_TCPOFOQueue);
                rrddim_set(st, "TCPOFODrop",    tcpext_TCPOFODrop);
                rrddim_set(st, "TCPOFOMerge",   tcpext_TCPOFOMerge);
                rrddim_set(st, "OfoPruned",     tcpext_OfoPruned);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) {
                do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpsyncookies");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "SyncookiesRecv",   tcpext_SyncookiesRecv);
                rrddim_set(st, "SyncookiesSent",   tcpext_SyncookiesSent);
                rrddim_set(st, "SyncookiesFailed", tcpext_SyncookiesFailed);
                rrdset_done(st);
            }

        }
    }

    return 0;
}
Exemple #9
0
RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type)
{
	if(!type || !type[0]) {
		fatal("Cannot create rrd stats without a type.");
		return NULL;
	}

	if(!id || !id[0]) {
		fatal("Cannot create rrd stats without an id.");
		return NULL;
	}

	char fullid[RRD_ID_LENGTH_MAX + 1];
	char fullfilename[FILENAME_MAX + 1];
	RRDSET *st = NULL;

	snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id);

	st = rrdset_find(fullid);
	if(st) {
		error("Cannot create rrd stats for '%s', it already exists.", fullid);
		return st;
	}

	long entries = config_get_number(fullid, "history", rrd_default_history_entries);
	if(entries < 5) entries = config_set_number(fullid, "history", 5);
	if(entries > RRD_HISTORY_ENTRIES_MAX) entries = config_set_number(fullid, "history", RRD_HISTORY_ENTRIES_MAX);

	int enabled = config_get_boolean(fullid, "enabled", 1);
	if(!enabled) entries = 5;

	unsigned long size = sizeof(RRDSET);
	char *cache_dir = rrdset_cache_dir(fullid);

	debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);

	snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
	if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0);
	if(st) {
		if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
			errno = 0;
			info("Initializing file %s.", fullfilename);
			bzero(st, size);
		}
		else if(strcmp(st->id, fullid) != 0) {
			errno = 0;
			error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid);
			// munmap(st, size);
			// st = NULL;
			bzero(st, size);
		}
		else if(st->memsize != size || st->entries != entries) {
			errno = 0;
			error("File %s does not have the desired size. Clearing it.", fullfilename);
			bzero(st, size);
		}
		else if(st->update_every != update_every) {
			errno = 0;
			error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
			bzero(st, size);
		}
		else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) {
			errno = 0;
			error("File %s is too old. Clearing it.", fullfilename);
			bzero(st, size);
		}
	}

	if(st) {
		st->name = NULL;
		st->type = NULL;
		st->family = NULL;
		st->context = NULL;
		st->title = NULL;
		st->units = NULL;
		st->dimensions = NULL;
		st->next = NULL;
		st->mapped = rrd_memory_mode;
	}
	else {
		st = calloc(1, size);
		if(!st) {
			fatal("Cannot allocate memory for RRD_STATS %s.%s", type, id);
			return NULL;
		}
		st->mapped = RRD_MEMORY_MODE_RAM;
	}
	st->memsize = size;
	st->entries = entries;
	st->update_every = update_every;

	if(st->current_entry >= st->entries) st->current_entry = 0;

	strcpy(st->cache_filename, fullfilename);
	strcpy(st->magic, RRDSET_MAGIC);

	strcpy(st->id, fullid);
	st->hash = simple_hash(st->id);

	st->cache_dir = cache_dir;

	st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type)));
	st->type       = config_get(st->id, "type", type);
	st->family     = config_get(st->id, "family", family?family:st->type);
	st->context    = config_get(st->id, "context", context?context:st->id);
	st->units      = config_get(st->id, "units", units?units:"");

	st->priority = config_get_number(st->id, "priority", priority);
	st->enabled = enabled;

	st->isdetail = 0;
	st->debug = 0;

	st->last_collected_time.tv_sec = 0;
	st->last_collected_time.tv_usec = 0;
	st->counter_done = 0;

	st->gap_when_lost_iterations_above = (int) (
			config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2);

	avl_init_lock(&st->dimensions_index, rrddim_compare);

	pthread_rwlock_init(&st->rwlock, NULL);
	pthread_rwlock_wrlock(&rrdset_root_rwlock);

	if(name && *name) rrdset_set_name(st, name);
	else rrdset_set_name(st, id);

	{
		char varvalue[CONFIG_MAX_VALUE + 1];
		snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name);
		st->title = config_get(st->id, "title", varvalue);
	}

	st->next = rrdset_root;
	rrdset_root = st;

	rrdset_index_add(st);

	pthread_rwlock_unlock(&rrdset_root_rwlock);

	return(st);
}
Exemple #10
0
int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) {
    int ret = 400;
    buffer_flush(w->response.data);

    BUFFER *dimensions = NULL;

    const char *chart = NULL
    , *before_str = NULL
    , *after_str = NULL
    , *points_str = NULL
    , *multiply_str = NULL
    , *divide_str = NULL
    , *label = NULL
    , *units = NULL
    , *label_color = NULL
    , *value_color = NULL
    , *refresh_str = NULL
    , *precision_str = NULL
    , *scale_str = NULL
    , *alarm = NULL;

    int group = GROUP_AVERAGE;
    uint32_t options = 0x00000000;

    while(url) {
        char *value = mystrsep(&url, "/?&");
        if(!value || !*value) continue;

        char *name = mystrsep(&value, "=");
        if(!name || !*name) continue;
        if(!value || !*value) continue;

        debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);

        // name and value are now the parameters
        // they are not null and not empty

        if(!strcmp(name, "chart")) chart = value;
        else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
            if(!dimensions)
                dimensions = buffer_create(100);

            buffer_strcat(dimensions, "|");
            buffer_strcat(dimensions, value);
        }
        else if(!strcmp(name, "after")) after_str = value;
        else if(!strcmp(name, "before")) before_str = value;
        else if(!strcmp(name, "points")) points_str = value;
        else if(!strcmp(name, "group")) {
            group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
        }
        else if(!strcmp(name, "options")) {
            options |= web_client_api_request_v1_data_options(value);
        }
        else if(!strcmp(name, "label")) label = value;
        else if(!strcmp(name, "units")) units = value;
        else if(!strcmp(name, "label_color")) label_color = value;
        else if(!strcmp(name, "value_color")) value_color = value;
        else if(!strcmp(name, "multiply")) multiply_str = value;
        else if(!strcmp(name, "divide")) divide_str = value;
        else if(!strcmp(name, "refresh")) refresh_str = value;
        else if(!strcmp(name, "precision")) precision_str = value;
        else if(!strcmp(name, "scale")) scale_str = value;
        else if(!strcmp(name, "alarm")) alarm = value;
    }

    if(!chart || !*chart) {
        buffer_no_cacheable(w->response.data);
        buffer_sprintf(w->response.data, "No chart id is given at the request.");
        goto cleanup;
    }

    int scale = (scale_str && *scale_str)?str2i(scale_str):100;

    RRDSET *st = rrdset_find(host, chart);
    if(!st) st = rrdset_find_byname(host, chart);
    if(!st) {
        buffer_no_cacheable(w->response.data);
        buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0);
        ret = 200;
        goto cleanup;
    }
    st->last_accessed_time = now_realtime_sec();

    RRDCALC *rc = NULL;
    if(alarm) {
        rc = rrdcalc_find(st, alarm);
        if (!rc) {
            buffer_no_cacheable(w->response.data);
            buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0);
            ret = 200;
            goto cleanup;
        }
    }

    long long multiply  = (multiply_str  && *multiply_str )?str2l(multiply_str):1;
    long long divide    = (divide_str    && *divide_str   )?str2l(divide_str):1;
    long long before    = (before_str    && *before_str   )?str2l(before_str):0;
    long long after     = (after_str     && *after_str    )?str2l(after_str):-st->update_every;
    int       points    = (points_str    && *points_str   )?str2i(points_str):1;
    int       precision = (precision_str && *precision_str)?str2i(precision_str):-1;

    if(!multiply) multiply = 1;
    if(!divide) divide = 1;

    int refresh = 0;
    if(refresh_str && *refresh_str) {
        if(!strcmp(refresh_str, "auto")) {
            if(rc) refresh = rc->update_every;
            else if(options & RRDR_OPTION_NOT_ALIGNED)
                refresh = st->update_every;
            else {
                refresh = (int)(before - after);
                if(refresh < 0) refresh = -refresh;
            }
        }
        else {
            refresh = str2i(refresh_str);
            if(refresh < 0) refresh = -refresh;
        }
    }

    if(!label) {
        if(alarm) {
            char *s = (char *)alarm;
            while(*s) {
                if(*s == '_') *s = ' ';
                s++;
            }
            label = alarm;
        }
        else if(dimensions) {
            const char *dim = buffer_tostring(dimensions);
            if(*dim == '|') dim++;
            label = dim;
        }
        else
            label = st->name;
    }
    if(!units) {
        if(alarm) {
            if(rc->units)
                units = rc->units;
            else
                units = "";
        }
        else if(options & RRDR_OPTION_PERCENTAGE)
            units = "%";
        else
            units = st->units;
    }

    debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'"
          , w->id
          , chart
          , alarm?alarm:""
          , (dimensions)?buffer_tostring(dimensions):""
          , after
          , before
          , points
          , group
          , options
    );

    if(rc) {
        if (refresh > 0) {
            buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
            w->response.data->expires = now_realtime_sec() + refresh;
        }
        else buffer_no_cacheable(w->response.data);

        if(!value_color) {
            switch(rc->status) {
                case RRDCALC_STATUS_CRITICAL:
                    value_color = "red";
                    break;

                case RRDCALC_STATUS_WARNING:
                    value_color = "orange";
                    break;

                case RRDCALC_STATUS_CLEAR:
                    value_color = "brightgreen";
                    break;

                case RRDCALC_STATUS_UNDEFINED:
                    value_color = "lightgrey";
                    break;

                case RRDCALC_STATUS_UNINITIALIZED:
                    value_color = "#000";
                    break;

                default:
                    value_color = "grey";
                    break;
            }
        }

        buffer_svg(w->response.data,
                label,
                (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide,
                units,
                label_color,
                value_color,
                precision,
                scale,
                options
        );
        ret = 200;
    }
    else {
        time_t latest_timestamp = 0;
        int value_is_null = 1;
        calculated_number n = NAN;
        ret = 500;

        // if the collected value is too old, don't calculate its value
        if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above)))
            ret = rrdset2value_api_v1(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL
                                      , points, after, before, group, 0, options, NULL, &latest_timestamp, &value_is_null);

        // if the value cannot be calculated, show empty badge
        if (ret != 200) {
            buffer_no_cacheable(w->response.data);
            value_is_null = 1;
            n = 0;
            ret = 200;
        }
        else if (refresh > 0) {
            buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
            w->response.data->expires = now_realtime_sec() + refresh;
        }
        else buffer_no_cacheable(w->response.data);

        // render the badge
        buffer_svg(w->response.data,
                label,
                (value_is_null)?NAN:(n * multiply / divide),
                units,
                label_color,
                value_color,
                precision,
                scale,
                options
        );
    }

    cleanup:
    buffer_free(dimensions);
    return ret;
}
Exemple #11
0
void *proc_main(void *ptr)
{
	if(ptr) { ; }

	if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
		error("Cannot set pthread cancel type to DEFERRED.");

	if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
		error("Cannot set pthread cancel state to ENABLE.");

	struct rusage me, me_last;
	struct timeval last, now;

	gettimeofday(&last, NULL);
	last.tv_sec -= rrd_update_every;
	
	// disable (by default) various interface that are not needed
	config_get_boolean("plugin:proc:/proc/net/dev", "interface lo", 0);
	config_get_boolean("plugin:proc:/proc/net/dev", "interface fireqos_monitor", 0);

	// when ZERO, attempt to do it
	int vdo_proc_net_dev 			= !config_get_boolean("plugin:proc", "/proc/net/dev", 1);
	int vdo_proc_diskstats 			= !config_get_boolean("plugin:proc", "/proc/diskstats", 1);
	int vdo_proc_net_snmp 			= !config_get_boolean("plugin:proc", "/proc/net/snmp", 1);
	int vdo_proc_net_netstat 		= !config_get_boolean("plugin:proc", "/proc/net/netstat", 1);
	int vdo_proc_net_stat_conntrack = !config_get_boolean("plugin:proc", "/proc/net/stat/conntrack", 1);
	int vdo_proc_net_ip_vs_stats 	= !config_get_boolean("plugin:proc", "/proc/net/ip_vs/stats", 1);
	int vdo_proc_stat 				= !config_get_boolean("plugin:proc", "/proc/stat", 1);
	int vdo_proc_meminfo 			= !config_get_boolean("plugin:proc", "/proc/meminfo", 1);
	int vdo_proc_vmstat 			= !config_get_boolean("plugin:proc", "/proc/vmstat", 1);
	int vdo_proc_net_rpc_nfsd		= !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1);
	int vdo_proc_sys_kernel_random_entropy_avail	= !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1);
	int vdo_proc_interrupts			= !config_get_boolean("plugin:proc", "/proc/interrupts", 1);
	int vdo_cpu_netdata 			= !config_get_boolean("plugin:proc", "netdata server resources", 1);

	RRDSET *stcpu = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL;

	gettimeofday(&last, NULL);
	getrusage(RUSAGE_SELF, &me_last);

	unsigned long long usec = 0, susec = 0;
	for(;1;) {
		
		// BEGIN -- the job to be done
		
		if(!vdo_proc_interrupts) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
			vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, usec+susec);
		}
		if(!vdo_proc_sys_kernel_random_entropy_avail) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
			vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, usec+susec);
		}
		if(!vdo_proc_net_dev) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev().");
			vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, usec+susec);
		}
		if(!vdo_proc_diskstats) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats().");
			vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, usec+susec);
		}
		if(!vdo_proc_net_snmp) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp().");
			vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, usec+susec);
		}

		if(!vdo_proc_net_netstat) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat().");
			vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, usec+susec);
		}

		if(!vdo_proc_net_stat_conntrack) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack().");
			vdo_proc_net_stat_conntrack	= do_proc_net_stat_conntrack(rrd_update_every, usec+susec);
		}

		if(!vdo_proc_net_ip_vs_stats) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats().");
			vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, usec+susec);
		}

		if(!vdo_proc_stat) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
			vdo_proc_stat = do_proc_stat(rrd_update_every, usec+susec);
		}

		if(!vdo_proc_meminfo) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo().");
			vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, usec+susec);
		}

		if(!vdo_proc_vmstat) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat().");
			vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, usec+susec);
		}

		if(!vdo_proc_net_rpc_nfsd) {
			debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd().");
			vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, usec+susec);
		}

		// END -- the job is done
		
		// find the time to sleep in order to wait exactly update_every seconds
		gettimeofday(&now, NULL);
		usec = usecdiff(&now, &last) - susec;
		debug(D_PROCNETDEV_LOOP, "PROCNETDEV: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec);
		
		if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
		else susec = rrd_update_every * 1000000ULL / 2ULL;
		
		// --------------------------------------------------------------------

		if(!vdo_cpu_netdata && getrusage(RUSAGE_SELF, &me) == 0) {
		
			unsigned long long cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
			unsigned long long cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;

			if(!stcpu) stcpu = rrdset_find("netdata.server_cpu");
			if(!stcpu) {
				stcpu = rrdset_create("netdata", "server_cpu", NULL, "netdata", "NetData CPU usage", "milliseconds/s", 9999, rrd_update_every, RRDSET_TYPE_STACKED);

				rrddim_add(stcpu, "user",  NULL,  1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
				rrddim_add(stcpu, "system", NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
			}
			else rrdset_next(stcpu);

			rrddim_set(stcpu, "user", cpuuser);
			rrddim_set(stcpu, "system", cpusyst);
			rrdset_done(stcpu);
			
			bcopy(&me, &me_last, sizeof(struct rusage));

			// ----------------------------------------------------------------

			if(!stclients) stclients = rrdset_find("netdata.clients");
			if(!stclients) {
				stclients = rrdset_create("netdata", "clients", NULL, "netdata", "NetData Web Clients", "connected clients", 11000, rrd_update_every, RRDSET_TYPE_LINE);

				rrddim_add(stclients, "clients",  NULL,  1, 1, RRDDIM_ABSOLUTE);
			}
			else rrdset_next(stclients);

			rrddim_set(stclients, "clients", global_statistics.connected_clients);
			rrdset_done(stclients);

			// ----------------------------------------------------------------

			if(!streqs) streqs = rrdset_find("netdata.requests");
			if(!streqs) {
				streqs = rrdset_create("netdata", "requests", NULL, "netdata", "NetData Web Requests", "requests/s", 12000, rrd_update_every, RRDSET_TYPE_LINE);

				rrddim_add(streqs, "requests",  NULL,  1, 1 * rrd_update_every, RRDDIM_INCREMENTAL);
			}
			else rrdset_next(streqs);

			rrddim_set(streqs, "requests", global_statistics.web_requests);
			rrdset_done(streqs);

			// ----------------------------------------------------------------

			if(!stbytes) stbytes = rrdset_find("netdata.net");
			if(!stbytes) {
				stbytes = rrdset_create("netdata", "net", NULL, "netdata", "NetData Network Traffic", "kilobits/s", 13000, rrd_update_every, RRDSET_TYPE_AREA);

				rrddim_add(stbytes, "in",  NULL,  8, 1024 * rrd_update_every, RRDDIM_INCREMENTAL);
				rrddim_add(stbytes, "out",  NULL,  -8, 1024 * rrd_update_every, RRDDIM_INCREMENTAL);
			}
			else rrdset_next(stbytes);

			rrddim_set(stbytes, "in", global_statistics.bytes_received);
			rrddim_set(stbytes, "out", global_statistics.bytes_sent);
			rrdset_done(stbytes);
		}

		usleep(susec);
		
		// copy current to last
		bcopy(&now, &last, sizeof(struct timeval));
	}

	return NULL;
}
int do_proc_net_netstat(int update_every, usec_t dt) {
    (void)dt;

    static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
        do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1;
    static uint32_t hash_ipext = 0, hash_tcpext = 0;
    static procfile *ff = NULL;

    static unsigned long long *tcpext_TCPRenoReorder = NULL;
    static unsigned long long *tcpext_TCPFACKReorder = NULL;
    static unsigned long long *tcpext_TCPSACKReorder = NULL;
    static unsigned long long *tcpext_TCPTSReorder = NULL;

    static unsigned long long *tcpext_SyncookiesSent = NULL;
    static unsigned long long *tcpext_SyncookiesRecv = NULL;
    static unsigned long long *tcpext_SyncookiesFailed = NULL;

    static unsigned long long *tcpext_TCPOFOQueue = NULL; // Number of packets queued in OFO queue
    static unsigned long long *tcpext_TCPOFODrop = NULL;  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
    static unsigned long long *tcpext_TCPOFOMerge = NULL; // Number of packets in OFO that were merged with other packets.
    static unsigned long long *tcpext_OfoPruned = NULL;   // packets dropped from out-of-order queue because of socket buffer overrun

    static unsigned long long *tcpext_TCPAbortOnData = NULL;    // connections reset due to unexpected data
    static unsigned long long *tcpext_TCPAbortOnClose = NULL;   // connections reset due to early user close
    static unsigned long long *tcpext_TCPAbortOnMemory = NULL;  // connections aborted due to memory pressure
    static unsigned long long *tcpext_TCPAbortOnTimeout = NULL; // connections aborted due to timeout
    static unsigned long long *tcpext_TCPAbortOnLinger = NULL;  // connections aborted after user close in linger timeout
    static unsigned long long *tcpext_TCPAbortFailed = NULL;    // times unable to send RST due to no memory

    static unsigned long long *tcpext_TCPMemoryPressures = NULL;

/*
    // connection rejects
    static unsigned long long *tcpext_PAWSActive = NULL;  // active connections rejected because of time stamp
    static unsigned long long *tcpext_PAWSPassive = NULL; // passive connections rejected because of time stamp

    static unsigned long long *tcpext_TCPTimeouts = NULL;

    static unsigned long long *tcpext_TCPDSACKUndo = NULL;
    static unsigned long long *tcpext_TCPDSACKOldSent = NULL;
    static unsigned long long *tcpext_TCPDSACKOfoSent = NULL;
    static unsigned long long *tcpext_TCPDSACKRecv = NULL;
    static unsigned long long *tcpext_TCPDSACKOfoRecv = NULL;
    static unsigned long long *tcpext_TCPDSACKIgnoredOld = NULL;
    static unsigned long long *tcpext_TCPDSACKIgnoredNoUndo = NULL;


    static unsigned long long *tcpext_EmbryonicRsts = NULL;

    static unsigned long long *tcpext_PruneCalled = NULL;
    static unsigned long long *tcpext_RcvPruned = NULL;
    static unsigned long long *tcpext_OutOfWindowIcmps = NULL;
    static unsigned long long *tcpext_LockDroppedIcmps = NULL;
    static unsigned long long *tcpext_ArpFilter = NULL;

    static unsigned long long *tcpext_TW = NULL;
    static unsigned long long *tcpext_TWRecycled = NULL;
    static unsigned long long *tcpext_TWKilled = NULL;

    static unsigned long long *tcpext_PAWSEstab = NULL;

    static unsigned long long *tcpext_DelayedACKs = NULL;
    static unsigned long long *tcpext_DelayedACKLocked = NULL;
    static unsigned long long *tcpext_DelayedACKLost = NULL;

    static unsigned long long *tcpext_ListenOverflows = NULL;
    static unsigned long long *tcpext_ListenDrops = NULL;

    static unsigned long long *tcpext_TCPPrequeued = NULL;

    static unsigned long long *tcpext_TCPDirectCopyFromBacklog = NULL;
    static unsigned long long *tcpext_TCPDirectCopyFromPrequeue = NULL;
    static unsigned long long *tcpext_TCPPrequeueDropped = NULL;

    static unsigned long long *tcpext_TCPHPHits = NULL;
    static unsigned long long *tcpext_TCPHPHitsToUser = NULL;
    static unsigned long long *tcpext_TCPHPAcks = NULL;

    static unsigned long long *tcpext_TCPPureAcks = NULL;
    static unsigned long long *tcpext_TCPRenoRecovery = NULL;

    static unsigned long long *tcpext_TCPSackRecovery = NULL;
    static unsigned long long *tcpext_TCPSackFailures = NULL;
    static unsigned long long *tcpext_TCPSACKReneging = NULL;
    static unsigned long long *tcpext_TCPSackRecoveryFail = NULL;
    static unsigned long long *tcpext_TCPSACKDiscard = NULL;
    static unsigned long long *tcpext_TCPSackShifted = NULL;
    static unsigned long long *tcpext_TCPSackMerged = NULL;
    static unsigned long long *tcpext_TCPSackShiftFallback = NULL;


    static unsigned long long *tcpext_TCPFullUndo = NULL;
    static unsigned long long *tcpext_TCPPartialUndo = NULL;

    static unsigned long long *tcpext_TCPLossUndo = NULL;
    static unsigned long long *tcpext_TCPLostRetransmit = NULL;

    static unsigned long long *tcpext_TCPRenoFailures = NULL;

    static unsigned long long *tcpext_TCPLossFailures = NULL;
    static unsigned long long *tcpext_TCPFastRetrans = NULL;
    static unsigned long long *tcpext_TCPForwardRetrans = NULL;
    static unsigned long long *tcpext_TCPSlowStartRetrans = NULL;
    static unsigned long long *tcpext_TCPLossProbes = NULL;
    static unsigned long long *tcpext_TCPLossProbeRecovery = NULL;
    static unsigned long long *tcpext_TCPRenoRecoveryFail = NULL;
    static unsigned long long *tcpext_TCPSchedulerFailed = NULL;
    static unsigned long long *tcpext_TCPRcvCollapsed = NULL;

    static unsigned long long *tcpext_TCPSpuriousRTOs = NULL;
    static unsigned long long *tcpext_TCPMD5NotFound = NULL;
    static unsigned long long *tcpext_TCPMD5Unexpected = NULL;

    static unsigned long long *tcpext_TCPBacklogDrop = NULL;
    static unsigned long long *tcpext_TCPMinTTLDrop = NULL;
    static unsigned long long *tcpext_TCPDeferAcceptDrop = NULL;
    static unsigned long long *tcpext_IPReversePathFilter = NULL;
    static unsigned long long *tcpext_TCPTimeWaitOverflow = NULL;
    static unsigned long long *tcpext_TCPReqQFullDoCookies = NULL;
    static unsigned long long *tcpext_TCPReqQFullDrop = NULL;
    static unsigned long long *tcpext_TCPRetransFail = NULL;
    static unsigned long long *tcpext_TCPRcvCoalesce = NULL;

    static unsigned long long *tcpext_TCPChallengeACK = NULL;
    static unsigned long long *tcpext_TCPSYNChallenge = NULL;

    static unsigned long long *tcpext_TCPFastOpenActive = NULL;
    static unsigned long long *tcpext_TCPFastOpenActiveFail = NULL;
    static unsigned long long *tcpext_TCPFastOpenPassive = NULL;
    static unsigned long long *tcpext_TCPFastOpenPassiveFail = NULL;
    static unsigned long long *tcpext_TCPFastOpenListenOverflow = NULL;
    static unsigned long long *tcpext_TCPFastOpenCookieReqd = NULL;

    static unsigned long long *tcpext_TCPSpuriousRtxHostQueues = NULL;
    static unsigned long long *tcpext_BusyPollRxPackets = NULL;
    static unsigned long long *tcpext_TCPAutoCorking = NULL;
    static unsigned long long *tcpext_TCPFromZeroWindowAdv = NULL;
    static unsigned long long *tcpext_TCPToZeroWindowAdv = NULL;
    static unsigned long long *tcpext_TCPWantZeroWindowAdv = NULL;
    static unsigned long long *tcpext_TCPSynRetrans = NULL;
    static unsigned long long *tcpext_TCPOrigDataSent = NULL;

    static unsigned long long *tcpext_TCPHystartTrainDetect = NULL;
    static unsigned long long *tcpext_TCPHystartTrainCwnd = NULL;
    static unsigned long long *tcpext_TCPHystartDelayDetect = NULL;
    static unsigned long long *tcpext_TCPHystartDelayCwnd = NULL;

    static unsigned long long *tcpext_TCPACKSkippedSynRecv = NULL;
    static unsigned long long *tcpext_TCPACKSkippedPAWS = NULL;
    static unsigned long long *tcpext_TCPACKSkippedSeq = NULL;
    static unsigned long long *tcpext_TCPACKSkippedFinWait2 = NULL;
    static unsigned long long *tcpext_TCPACKSkippedTimeWait = NULL;
    static unsigned long long *tcpext_TCPACKSkippedChallenge = NULL;

    static unsigned long long *tcpext_TCPWinProbe = NULL;
    static unsigned long long *tcpext_TCPKeepAlive = NULL;

    static unsigned long long *tcpext_TCPMTUPFail = NULL;
    static unsigned long long *tcpext_TCPMTUPSuccess = NULL;
*/

    static unsigned long long *ipext_InNoRoutes = NULL;
    static unsigned long long *ipext_InTruncatedPkts = NULL;
    static unsigned long long *ipext_InMcastPkts = NULL;
    static unsigned long long *ipext_OutMcastPkts = NULL;
    static unsigned long long *ipext_InBcastPkts = NULL;
    static unsigned long long *ipext_OutBcastPkts = NULL;
    static unsigned long long *ipext_InOctets = NULL;
    static unsigned long long *ipext_OutOctets = NULL;
    static unsigned long long *ipext_InMcastOctets = NULL;
    static unsigned long long *ipext_OutMcastOctets = NULL;
    static unsigned long long *ipext_InBcastOctets = NULL;
    static unsigned long long *ipext_OutBcastOctets = NULL;
    static unsigned long long *ipext_InCsumErrors = NULL;
    static unsigned long long *ipext_InNoECTPkts = NULL;
    static unsigned long long *ipext_InECT1Pkts = NULL;
    static unsigned long long *ipext_InECT0Pkts = NULL;
    static unsigned long long *ipext_InCEPkts = NULL;

    if(unlikely(do_bandwidth == -1)) {
        do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_inerrors  = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_ecn       = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);

        do_tcpext_reorder    = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_ofo        = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_memory     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_ONDEMAND_ONDEMAND);

        hash_ipext = simple_hash("IpExt");
        hash_tcpext = simple_hash("TcpExt");

        hash_array(ipext_data);
        hash_array(tcpext_data);

        // Reordering
        tcpext_TCPFACKReorder = netstat_columns_find(tcpext_data, "TCPFACKReorder");
        tcpext_TCPSACKReorder = netstat_columns_find(tcpext_data, "TCPSACKReorder");
        tcpext_TCPRenoReorder = netstat_columns_find(tcpext_data, "TCPRenoReorder");
        tcpext_TCPTSReorder = netstat_columns_find(tcpext_data, "TCPTSReorder");

        // SYN Cookies
        tcpext_SyncookiesSent = netstat_columns_find(tcpext_data, "SyncookiesSent");
        tcpext_SyncookiesRecv = netstat_columns_find(tcpext_data, "SyncookiesRecv");
        tcpext_SyncookiesFailed = netstat_columns_find(tcpext_data, "SyncookiesFailed");

        // Out Of Order Queue
        // http://www.spinics.net/lists/netdev/msg204696.html
        tcpext_TCPOFOQueue = netstat_columns_find(tcpext_data, "TCPOFOQueue"); // Number of packets queued in OFO queue
        tcpext_TCPOFODrop  = netstat_columns_find(tcpext_data, "TCPOFODrop");  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
        tcpext_TCPOFOMerge = netstat_columns_find(tcpext_data, "TCPOFOMerge"); // Number of packets in OFO that were merged with other packets.
        tcpext_OfoPruned   = netstat_columns_find(tcpext_data, "OfoPruned");   // packets dropped from out-of-order queue because of socket buffer overrun

        // connection resets
        // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
        tcpext_TCPAbortOnData    = netstat_columns_find(tcpext_data, "TCPAbortOnData");    // connections reset due to unexpected data
        tcpext_TCPAbortOnClose   = netstat_columns_find(tcpext_data, "TCPAbortOnClose");   // connections reset due to early user close
        tcpext_TCPAbortOnMemory  = netstat_columns_find(tcpext_data, "TCPAbortOnMemory");  // connections aborted due to memory pressure
        tcpext_TCPAbortOnTimeout = netstat_columns_find(tcpext_data, "TCPAbortOnTimeout"); // connections aborted due to timeout
        tcpext_TCPAbortOnLinger  = netstat_columns_find(tcpext_data, "TCPAbortOnLinger");  // connections aborted after user close in linger timeout
        tcpext_TCPAbortFailed    = netstat_columns_find(tcpext_data, "TCPAbortFailed");    // times unable to send RST due to no memory

        tcpext_TCPMemoryPressures = netstat_columns_find(tcpext_data, "TCPMemoryPressures");

        /*
        tcpext_EmbryonicRsts = netstat_columns_find(tcpext_data, "EmbryonicRsts");
        tcpext_PruneCalled = netstat_columns_find(tcpext_data, "PruneCalled");
        tcpext_RcvPruned = netstat_columns_find(tcpext_data, "RcvPruned");
        tcpext_OutOfWindowIcmps = netstat_columns_find(tcpext_data, "OutOfWindowIcmps");
        tcpext_LockDroppedIcmps = netstat_columns_find(tcpext_data, "LockDroppedIcmps");
        tcpext_ArpFilter = netstat_columns_find(tcpext_data, "ArpFilter");
        tcpext_TW = netstat_columns_find(tcpext_data, "TW");
        tcpext_TWRecycled = netstat_columns_find(tcpext_data, "TWRecycled");
        tcpext_TWKilled = netstat_columns_find(tcpext_data, "TWKilled");
        tcpext_PAWSPassive = netstat_columns_find(tcpext_data, "PAWSPassive");
        tcpext_PAWSActive = netstat_columns_find(tcpext_data, "PAWSActive");
        tcpext_PAWSEstab = netstat_columns_find(tcpext_data, "PAWSEstab");
        tcpext_DelayedACKs = netstat_columns_find(tcpext_data, "DelayedACKs");
        tcpext_DelayedACKLocked = netstat_columns_find(tcpext_data, "DelayedACKLocked");
        tcpext_DelayedACKLost = netstat_columns_find(tcpext_data, "DelayedACKLost");
        tcpext_ListenOverflows = netstat_columns_find(tcpext_data, "ListenOverflows");
        tcpext_ListenDrops = netstat_columns_find(tcpext_data, "ListenDrops");
        tcpext_TCPPrequeued = netstat_columns_find(tcpext_data, "TCPPrequeued");
        tcpext_TCPDirectCopyFromBacklog = netstat_columns_find(tcpext_data, "TCPDirectCopyFromBacklog");
        tcpext_TCPDirectCopyFromPrequeue = netstat_columns_find(tcpext_data, "TCPDirectCopyFromPrequeue");
        tcpext_TCPPrequeueDropped = netstat_columns_find(tcpext_data, "TCPPrequeueDropped");
        tcpext_TCPHPHits = netstat_columns_find(tcpext_data, "TCPHPHits");
        tcpext_TCPHPHitsToUser = netstat_columns_find(tcpext_data, "TCPHPHitsToUser");
        tcpext_TCPPureAcks = netstat_columns_find(tcpext_data, "TCPPureAcks");
        tcpext_TCPHPAcks = netstat_columns_find(tcpext_data, "TCPHPAcks");
        tcpext_TCPRenoRecovery = netstat_columns_find(tcpext_data, "TCPRenoRecovery");
        tcpext_TCPSackRecovery = netstat_columns_find(tcpext_data, "TCPSackRecovery");
        tcpext_TCPSACKReneging = netstat_columns_find(tcpext_data, "TCPSACKReneging");
        tcpext_TCPFullUndo = netstat_columns_find(tcpext_data, "TCPFullUndo");
        tcpext_TCPPartialUndo = netstat_columns_find(tcpext_data, "TCPPartialUndo");
        tcpext_TCPDSACKUndo = netstat_columns_find(tcpext_data, "TCPDSACKUndo");
        tcpext_TCPLossUndo = netstat_columns_find(tcpext_data, "TCPLossUndo");
        tcpext_TCPLostRetransmit = netstat_columns_find(tcpext_data, "TCPLostRetransmit");
        tcpext_TCPRenoFailures = netstat_columns_find(tcpext_data, "TCPRenoFailures");
        tcpext_TCPSackFailures = netstat_columns_find(tcpext_data, "TCPSackFailures");
        tcpext_TCPLossFailures = netstat_columns_find(tcpext_data, "TCPLossFailures");
        tcpext_TCPFastRetrans = netstat_columns_find(tcpext_data, "TCPFastRetrans");
        tcpext_TCPForwardRetrans = netstat_columns_find(tcpext_data, "TCPForwardRetrans");
        tcpext_TCPSlowStartRetrans = netstat_columns_find(tcpext_data, "TCPSlowStartRetrans");
        tcpext_TCPTimeouts = netstat_columns_find(tcpext_data, "TCPTimeouts");
        tcpext_TCPLossProbes = netstat_columns_find(tcpext_data, "TCPLossProbes");
        tcpext_TCPLossProbeRecovery = netstat_columns_find(tcpext_data, "TCPLossProbeRecovery");
        tcpext_TCPRenoRecoveryFail = netstat_columns_find(tcpext_data, "TCPRenoRecoveryFail");
        tcpext_TCPSackRecoveryFail = netstat_columns_find(tcpext_data, "TCPSackRecoveryFail");
        tcpext_TCPSchedulerFailed = netstat_columns_find(tcpext_data, "TCPSchedulerFailed");
        tcpext_TCPRcvCollapsed = netstat_columns_find(tcpext_data, "TCPRcvCollapsed");
        tcpext_TCPDSACKOldSent = netstat_columns_find(tcpext_data, "TCPDSACKOldSent");
        tcpext_TCPDSACKOfoSent = netstat_columns_find(tcpext_data, "TCPDSACKOfoSent");
        tcpext_TCPDSACKRecv = netstat_columns_find(tcpext_data, "TCPDSACKRecv");
        tcpext_TCPDSACKOfoRecv = netstat_columns_find(tcpext_data, "TCPDSACKOfoRecv");
        tcpext_TCPSACKDiscard = netstat_columns_find(tcpext_data, "TCPSACKDiscard");
        tcpext_TCPDSACKIgnoredOld = netstat_columns_find(tcpext_data, "TCPDSACKIgnoredOld");
        tcpext_TCPDSACKIgnoredNoUndo = netstat_columns_find(tcpext_data, "TCPDSACKIgnoredNoUndo");
        tcpext_TCPSpuriousRTOs = netstat_columns_find(tcpext_data, "TCPSpuriousRTOs");
        tcpext_TCPMD5NotFound = netstat_columns_find(tcpext_data, "TCPMD5NotFound");
        tcpext_TCPMD5Unexpected = netstat_columns_find(tcpext_data, "TCPMD5Unexpected");
        tcpext_TCPSackShifted = netstat_columns_find(tcpext_data, "TCPSackShifted");
        tcpext_TCPSackMerged = netstat_columns_find(tcpext_data, "TCPSackMerged");
        tcpext_TCPSackShiftFallback = netstat_columns_find(tcpext_data, "TCPSackShiftFallback");
        tcpext_TCPBacklogDrop = netstat_columns_find(tcpext_data, "TCPBacklogDrop");
        tcpext_TCPMinTTLDrop = netstat_columns_find(tcpext_data, "TCPMinTTLDrop");
        tcpext_TCPDeferAcceptDrop = netstat_columns_find(tcpext_data, "TCPDeferAcceptDrop");
        tcpext_IPReversePathFilter = netstat_columns_find(tcpext_data, "IPReversePathFilter");
        tcpext_TCPTimeWaitOverflow = netstat_columns_find(tcpext_data, "TCPTimeWaitOverflow");
        tcpext_TCPReqQFullDoCookies = netstat_columns_find(tcpext_data, "TCPReqQFullDoCookies");
        tcpext_TCPReqQFullDrop = netstat_columns_find(tcpext_data, "TCPReqQFullDrop");
        tcpext_TCPRetransFail = netstat_columns_find(tcpext_data, "TCPRetransFail");
        tcpext_TCPRcvCoalesce = netstat_columns_find(tcpext_data, "TCPRcvCoalesce");
        tcpext_TCPChallengeACK = netstat_columns_find(tcpext_data, "TCPChallengeACK");
        tcpext_TCPSYNChallenge = netstat_columns_find(tcpext_data, "TCPSYNChallenge");
        tcpext_TCPFastOpenActive = netstat_columns_find(tcpext_data, "TCPFastOpenActive");
        tcpext_TCPFastOpenActiveFail = netstat_columns_find(tcpext_data, "TCPFastOpenActiveFail");
        tcpext_TCPFastOpenPassive = netstat_columns_find(tcpext_data, "TCPFastOpenPassive");
        tcpext_TCPFastOpenPassiveFail = netstat_columns_find(tcpext_data, "TCPFastOpenPassiveFail");
        tcpext_TCPFastOpenListenOverflow = netstat_columns_find(tcpext_data, "TCPFastOpenListenOverflow");
        tcpext_TCPFastOpenCookieReqd = netstat_columns_find(tcpext_data, "TCPFastOpenCookieReqd");
        tcpext_TCPSpuriousRtxHostQueues = netstat_columns_find(tcpext_data, "TCPSpuriousRtxHostQueues");
        tcpext_BusyPollRxPackets = netstat_columns_find(tcpext_data, "BusyPollRxPackets");
        tcpext_TCPAutoCorking = netstat_columns_find(tcpext_data, "TCPAutoCorking");
        tcpext_TCPFromZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPFromZeroWindowAdv");
        tcpext_TCPToZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPToZeroWindowAdv");
        tcpext_TCPWantZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPWantZeroWindowAdv");
        tcpext_TCPSynRetrans = netstat_columns_find(tcpext_data, "TCPSynRetrans");
        tcpext_TCPOrigDataSent = netstat_columns_find(tcpext_data, "TCPOrigDataSent");
        tcpext_TCPHystartTrainDetect = netstat_columns_find(tcpext_data, "TCPHystartTrainDetect");
        tcpext_TCPHystartTrainCwnd = netstat_columns_find(tcpext_data, "TCPHystartTrainCwnd");
        tcpext_TCPHystartDelayDetect = netstat_columns_find(tcpext_data, "TCPHystartDelayDetect");
        tcpext_TCPHystartDelayCwnd = netstat_columns_find(tcpext_data, "TCPHystartDelayCwnd");
        tcpext_TCPACKSkippedSynRecv = netstat_columns_find(tcpext_data, "TCPACKSkippedSynRecv");
        tcpext_TCPACKSkippedPAWS = netstat_columns_find(tcpext_data, "TCPACKSkippedPAWS");
        tcpext_TCPACKSkippedSeq = netstat_columns_find(tcpext_data, "TCPACKSkippedSeq");
        tcpext_TCPACKSkippedFinWait2 = netstat_columns_find(tcpext_data, "TCPACKSkippedFinWait2");
        tcpext_TCPACKSkippedTimeWait = netstat_columns_find(tcpext_data, "TCPACKSkippedTimeWait");
        tcpext_TCPACKSkippedChallenge = netstat_columns_find(tcpext_data, "TCPACKSkippedChallenge");
        tcpext_TCPWinProbe = netstat_columns_find(tcpext_data, "TCPWinProbe");
        tcpext_TCPKeepAlive = netstat_columns_find(tcpext_data, "TCPKeepAlive");
        tcpext_TCPMTUPFail = netstat_columns_find(tcpext_data, "TCPMTUPFail");
        tcpext_TCPMTUPSuccess = netstat_columns_find(tcpext_data, "TCPMTUPSuccess");
*/
        ipext_InNoRoutes = netstat_columns_find(ipext_data, "InNoRoutes");
        ipext_InTruncatedPkts = netstat_columns_find(ipext_data, "InTruncatedPkts");
        ipext_InMcastPkts = netstat_columns_find(ipext_data, "InMcastPkts");
        ipext_OutMcastPkts = netstat_columns_find(ipext_data, "OutMcastPkts");
        ipext_InBcastPkts = netstat_columns_find(ipext_data, "InBcastPkts");
        ipext_OutBcastPkts = netstat_columns_find(ipext_data, "OutBcastPkts");
        ipext_InOctets = netstat_columns_find(ipext_data, "InOctets");
        ipext_OutOctets = netstat_columns_find(ipext_data, "OutOctets");
        ipext_InMcastOctets = netstat_columns_find(ipext_data, "InMcastOctets");
        ipext_OutMcastOctets = netstat_columns_find(ipext_data, "OutMcastOctets");
        ipext_InBcastOctets = netstat_columns_find(ipext_data, "InBcastOctets");
        ipext_OutBcastOctets = netstat_columns_find(ipext_data, "OutBcastOctets");
        ipext_InCsumErrors = netstat_columns_find(ipext_data, "InCsumErrors");
        ipext_InNoECTPkts = netstat_columns_find(ipext_data, "InNoECTPkts");
        ipext_InECT1Pkts = netstat_columns_find(ipext_data, "InECT1Pkts");
        ipext_InECT0Pkts = netstat_columns_find(ipext_data, "InECT0Pkts");
        ipext_InCEPkts = netstat_columns_find(ipext_data, "InCEPkts");
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat");
        ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
        if(unlikely(!ff)) return 1;
    }

    ff = procfile_readall(ff);
    if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time

    uint32_t lines = procfile_lines(ff), l;
    uint32_t words;

    for(l = 0; l < lines ;l++) {
        char *key = procfile_lineword(ff, l, 0);
        uint32_t hash = simple_hash(key);

        if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
            uint32_t h = l++;

            if(unlikely(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0)) {
                error("Cannot read IpExt line from /proc/net/netstat.");
                break;
            }
            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, ipext_data, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InOctets || *ipext_OutOctets))) {
                do_bandwidth = CONFIG_ONDEMAND_YES;
                st = rrdset_find("system.ipv4");
                if(unlikely(!st)) {
                    st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);

                    rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InOctets", *ipext_InOctets);
                rrddim_set(st, "OutOctets", *ipext_OutOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InNoRoutes || *ipext_InTruncatedPkts))) {
                do_inerrors = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.inerrors");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InNoRoutes", "noroutes", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InTruncatedPkts", "truncated", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", "checksum", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InNoRoutes", *ipext_InNoRoutes);
                rrddim_set(st, "InTruncatedPkts", *ipext_InTruncatedPkts);
                rrddim_set(st, "InCsumErrors", *ipext_InCsumErrors);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastOctets || *ipext_OutMcastOctets))) {
                do_mcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastOctets", *ipext_InMcastOctets);
                rrddim_set(st, "OutMcastOctets", *ipext_OutMcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastOctets || *ipext_OutBcastOctets))) {
                do_bcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastOctets", *ipext_InBcastOctets);
                rrddim_set(st, "OutBcastOctets", *ipext_OutBcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastPkts || *ipext_OutMcastPkts))) {
                do_mcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 8600, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastPkts", *ipext_InMcastPkts);
                rrddim_set(st, "OutMcastPkts", *ipext_OutMcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastPkts || *ipext_OutBcastPkts))) {
                do_bcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastPkts", *ipext_InBcastPkts);
                rrddim_set(st, "OutBcastPkts", *ipext_OutBcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InCEPkts || *ipext_InECT0Pkts || *ipext_InECT1Pkts || *ipext_InNoECTPkts))) {
                do_ecn = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.ecnpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InCEPkts", *ipext_InCEPkts);
                rrddim_set(st, "InNoECTPkts", *ipext_InNoECTPkts);
                rrddim_set(st, "InECT0Pkts", *ipext_InECT0Pkts);
                rrddim_set(st, "InECT1Pkts", *ipext_InECT1Pkts);
                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
            uint32_t h = l++;

            if(unlikely(strcmp(procfile_lineword(ff, l, 0), "TcpExt") != 0)) {
                error("Cannot read TcpExt line from /proc/net/netstat.");
                break;
            }
            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, tcpext_data, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_tcpext_memory == CONFIG_ONDEMAND_YES || (do_tcpext_memory == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPMemoryPressures))) {
                do_tcpext_memory = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpmemorypressures");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures", "events/s", 3000, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPMemoryPressures",   "pressures",  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPMemoryPressures", *tcpext_TCPMemoryPressures);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPAbortOnData || *tcpext_TCPAbortOnClose || *tcpext_TCPAbortOnMemory || *tcpext_TCPAbortOnTimeout || *tcpext_TCPAbortOnLinger || *tcpext_TCPAbortFailed))) {
                do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpconnaborts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnLinger",  "linger",      1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortFailed",    "failed",     -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPAbortOnData",    *tcpext_TCPAbortOnData);
                rrddim_set(st, "TCPAbortOnClose",   *tcpext_TCPAbortOnClose);
                rrddim_set(st, "TCPAbortOnMemory",  *tcpext_TCPAbortOnMemory);
                rrddim_set(st, "TCPAbortOnTimeout", *tcpext_TCPAbortOnTimeout);
                rrddim_set(st, "TCPAbortOnLinger",  *tcpext_TCPAbortOnLinger);
                rrddim_set(st, "TCPAbortFailed",    *tcpext_TCPAbortFailed);
                rrdset_done(st);
            }
            // --------------------------------------------------------------------

            if(do_tcpext_reorder == CONFIG_ONDEMAND_YES || (do_tcpext_reorder == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPRenoReorder || *tcpext_TCPFACKReorder || *tcpext_TCPSACKReorder || *tcpext_TCPTSReorder))) {
                do_tcpext_reorder = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpreorders");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpreorders", NULL, "tcp", NULL, "TCP Reordered Packets by Detection Method", "packets/s", 3020, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPTSReorder",   "timestamp",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPSACKReorder", "sack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPFACKReorder", "fack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPRenoReorder", "reno",        1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPTSReorder",   *tcpext_TCPTSReorder);
                rrddim_set(st, "TCPSACKReorder", *tcpext_TCPSACKReorder);
                rrddim_set(st, "TCPFACKReorder", *tcpext_TCPFACKReorder);
                rrddim_set(st, "TCPRenoReorder", *tcpext_TCPRenoReorder);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPOFOQueue || *tcpext_TCPOFODrop || *tcpext_TCPOFOMerge))) {
                do_tcpext_ofo = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpofo");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFODrop",  "dropped", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFOMerge", "merged",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OfoPruned",   "pruned",  -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPOFOQueue",   *tcpext_TCPOFOQueue);
                rrddim_set(st, "TCPOFODrop",    *tcpext_TCPOFODrop);
                rrddim_set(st, "TCPOFOMerge",   *tcpext_TCPOFOMerge);
                rrddim_set(st, "OfoPruned",     *tcpext_OfoPruned);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_SyncookiesSent || *tcpext_SyncookiesRecv || *tcpext_SyncookiesFailed))) {
                do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpsyncookies");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "SyncookiesRecv",   *tcpext_SyncookiesRecv);
                rrddim_set(st, "SyncookiesSent",   *tcpext_SyncookiesSent);
                rrddim_set(st, "SyncookiesFailed", *tcpext_SyncookiesFailed);
                rrdset_done(st);
            }

        }
    }

    return 0;
}
// returns the HTTP code
inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) {
    debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);

    int ret = 400;
    BUFFER *dimensions = NULL;

    buffer_flush(w->response.data);

    char    *google_version = "0.6",
            *google_reqId = "0",
            *google_sig = "0",
            *google_out = "json",
            *responseHandler = NULL,
            *outFileName = NULL;

    time_t last_timestamp_in_data = 0, google_timestamp = 0;

    char *chart = NULL
    , *before_str = NULL
    , *after_str = NULL
    , *group_time_str = NULL
    , *points_str = NULL;

    int group = RRDR_GROUPING_AVERAGE;
    uint32_t format = DATASOURCE_JSON;
    uint32_t options = 0x00000000;

    while(url) {
        char *value = mystrsep(&url, "?&");
        if(!value || !*value) continue;

        char *name = mystrsep(&value, "=");
        if(!name || !*name) continue;
        if(!value || !*value) continue;

        debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);

        // name and value are now the parameters
        // they are not null and not empty

        if(!strcmp(name, "chart")) chart = value;
        else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
            if(!dimensions) dimensions = buffer_create(100);
            buffer_strcat(dimensions, "|");
            buffer_strcat(dimensions, value);
        }
        else if(!strcmp(name, "after")) after_str = value;
        else if(!strcmp(name, "before")) before_str = value;
        else if(!strcmp(name, "points")) points_str = value;
        else if(!strcmp(name, "gtime")) group_time_str = value;
        else if(!strcmp(name, "group")) {
            group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE);
        }
        else if(!strcmp(name, "format")) {
            format = web_client_api_request_v1_data_format(value);
        }
        else if(!strcmp(name, "options")) {
            options |= web_client_api_request_v1_data_options(value);
        }
        else if(!strcmp(name, "callback")) {
            responseHandler = value;
        }
        else if(!strcmp(name, "filename")) {
            outFileName = value;
        }
        else if(!strcmp(name, "tqx")) {
            // parse Google Visualization API options
            // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
            char *tqx_name, *tqx_value;

            while(value) {
                tqx_value = mystrsep(&value, ";");
                if(!tqx_value || !*tqx_value) continue;

                tqx_name = mystrsep(&tqx_value, ":");
                if(!tqx_name || !*tqx_name) continue;
                if(!tqx_value || !*tqx_value) continue;

                if(!strcmp(tqx_name, "version"))
                    google_version = tqx_value;
                else if(!strcmp(tqx_name, "reqId"))
                    google_reqId = tqx_value;
                else if(!strcmp(tqx_name, "sig")) {
                    google_sig = tqx_value;
                    google_timestamp = strtoul(google_sig, NULL, 0);
                }
                else if(!strcmp(tqx_name, "out")) {
                    google_out = tqx_value;
                    format = web_client_api_request_v1_data_google_format(google_out);
                }
                else if(!strcmp(tqx_name, "responseHandler"))
                    responseHandler = tqx_value;
                else if(!strcmp(tqx_name, "outFileName"))
                    outFileName = tqx_value;
            }
        }
    }

    if(!chart || !*chart) {
        buffer_sprintf(w->response.data, "No chart id is given at the request.");
        goto cleanup;
    }

    RRDSET *st = rrdset_find(host, chart);
    if(!st) st = rrdset_find_byname(host, chart);
    if(!st) {
        buffer_strcat(w->response.data, "Chart is not found: ");
        buffer_strcat_htmlescape(w->response.data, chart);
        ret = 404;
        goto cleanup;
    }
    st->last_accessed_time = now_realtime_sec();

    long long before = (before_str && *before_str)?str2l(before_str):0;
    long long after  = (after_str  && *after_str) ?str2l(after_str):0;
    int       points = (points_str && *points_str)?str2i(points_str):0;
    long      group_time = (group_time_str && *group_time_str)?str2l(group_time_str):0;

    debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'"
          , w->id
          , chart
          , (dimensions)?buffer_tostring(dimensions):""
          , after
          , before
          , points
          , group
          , format
          , options
    );

    if(outFileName && *outFileName) {
        buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName);
        debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
    }

    if(format == DATASOURCE_DATATABLE_JSONP) {
        if(responseHandler == NULL)
            responseHandler = "google.visualization.Query.setResponse";

        debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
                w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName
        );

        buffer_sprintf(w->response.data,
                "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
                responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
    }
    else if(format == DATASOURCE_JSONP) {
        if(responseHandler == NULL)
            responseHandler = "callback";

        buffer_strcat(w->response.data, responseHandler);
        buffer_strcat(w->response.data, "(");
    }

    ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, group_time
                                 , options, &last_timestamp_in_data);

    if(format == DATASOURCE_DATATABLE_JSONP) {
        if(google_timestamp < last_timestamp_in_data)
            buffer_strcat(w->response.data, "});");

        else {
            // the client already has the latest data
            buffer_flush(w->response.data);
            buffer_sprintf(w->response.data,
                    "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
                    responseHandler, google_version, google_reqId);
        }
    }
    else if(format == DATASOURCE_JSONP)
        buffer_strcat(w->response.data, ");");

    cleanup:
    buffer_free(dimensions);
    return ret;
}
Exemple #14
0
int do_proc_vmstat(int update_every, unsigned long long dt) {
	static procfile *ff = NULL;
	static int do_swapio = -1, do_io = -1, do_pgfaults = -1;

	if(do_swapio == -1)	do_swapio = config_get_boolean("plugin:proc:/proc/vmstat", "swap i/o", 1);
	if(do_io == -1)		do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
	if(do_pgfaults == -1)	do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/vmstat");
		ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
	}
	if(!ff) return 1;

	ff = procfile_readall(ff);
	if(!ff) return 0; // we return 0, so that we will retry to open it next time

	uint32_t lines = procfile_lines(ff), l;
	uint32_t words;

	unsigned long long nr_free_pages = 0, nr_inactive_anon = 0, nr_active_anon = 0, nr_inactive_file = 0, nr_active_file = 0, nr_unevictable = 0, nr_mlock = 0,
		nr_anon_pages = 0, nr_mapped = 0, nr_file_pages = 0, nr_dirty = 0, nr_writeback = 0, nr_slab_reclaimable = 0, nr_slab_unreclaimable = 0, nr_page_table_pages = 0,
		nr_kernel_stack = 0, nr_unstable = 0, nr_bounce = 0, nr_vmscan_write = 0, nr_vmscan_immediate_reclaim = 0, nr_writeback_temp = 0, nr_isolated_anon = 0, nr_isolated_file = 0,
		nr_shmem = 0, nr_dirtied = 0, nr_written = 0, nr_anon_transparent_hugepages = 0, nr_dirty_threshold = 0, nr_dirty_background_threshold = 0,
		pgpgin = 0, pgpgout = 0, pswpin = 0, pswpout = 0, pgalloc_dma = 0, pgalloc_dma32 = 0, pgalloc_normal = 0, pgalloc_movable = 0, pgfree = 0, pgactivate = 0, pgdeactivate = 0,
		pgfault = 0, pgmajfault = 0, pgrefill_dma = 0, pgrefill_dma32 = 0, pgrefill_normal = 0, pgrefill_movable = 0, pgsteal_kswapd_dma = 0, pgsteal_kswapd_dma32 = 0,
		pgsteal_kswapd_normal = 0, pgsteal_kswapd_movable = 0, pgsteal_direct_dma = 0, pgsteal_direct_dma32 = 0, pgsteal_direct_normal = 0, pgsteal_direct_movable = 0, 
		pgscan_kswapd_dma = 0, pgscan_kswapd_dma32 = 0, pgscan_kswapd_normal = 0, pgscan_kswapd_movable = 0, pgscan_direct_dma = 0, pgscan_direct_dma32 = 0, pgscan_direct_normal = 0,
		pgscan_direct_movable = 0, pginodesteal = 0, slabs_scanned = 0, kswapd_inodesteal = 0, kswapd_low_wmark_hit_quickly = 0, kswapd_high_wmark_hit_quickly = 0,
		kswapd_skip_congestion_wait = 0, pageoutrun = 0, allocstall = 0, pgrotated = 0, compact_blocks_moved = 0, compact_pages_moved = 0, compact_pagemigrate_failed = 0,
		compact_stall = 0, compact_fail = 0, compact_success = 0, htlb_buddy_alloc_success = 0, htlb_buddy_alloc_fail = 0, unevictable_pgs_culled = 0, unevictable_pgs_scanned = 0,
		unevictable_pgs_rescued = 0, unevictable_pgs_mlocked = 0, unevictable_pgs_munlocked = 0, unevictable_pgs_cleared = 0, unevictable_pgs_stranded = 0, unevictable_pgs_mlockfreed = 0,
		thp_fault_alloc = 0, thp_fault_fallback = 0, thp_collapse_alloc = 0, thp_collapse_alloc_failed = 0, thp_split = 0;

	for(l = 0; l < lines ;l++) {
		words = procfile_linewords(ff, l);
		if(words < 2) {
			if(words) error("Cannot read /proc/vmstat line %d. Expected 2 params, read %d.", l, words);
			continue;
		}

		char *name = procfile_lineword(ff, l, 0);
		unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);

		     if(!nr_free_pages && strcmp(name, "nr_free_pages") == 0) nr_free_pages = value;
		else if(!nr_inactive_anon && strcmp(name, "nr_inactive_anon") == 0) nr_inactive_anon = value;
		else if(!nr_active_anon && strcmp(name, "nr_active_anon") == 0) nr_active_anon = value;
		else if(!nr_inactive_file && strcmp(name, "nr_inactive_file") == 0) nr_inactive_file = value;
		else if(!nr_active_file && strcmp(name, "nr_active_file") == 0) nr_active_file = value;
		else if(!nr_unevictable && strcmp(name, "nr_unevictable") == 0) nr_unevictable = value;
		else if(!nr_mlock && strcmp(name, "nr_mlock") == 0) nr_mlock = value;
		else if(!nr_anon_pages && strcmp(name, "nr_anon_pages") == 0) nr_anon_pages = value;
		else if(!nr_mapped && strcmp(name, "nr_mapped") == 0) nr_mapped = value;
		else if(!nr_file_pages && strcmp(name, "nr_file_pages") == 0) nr_file_pages = value;
		else if(!nr_dirty && strcmp(name, "nr_dirty") == 0) nr_dirty = value;
		else if(!nr_writeback && strcmp(name, "nr_writeback") == 0) nr_writeback = value;
		else if(!nr_slab_reclaimable && strcmp(name, "nr_slab_reclaimable") == 0) nr_slab_reclaimable = value;
		else if(!nr_slab_unreclaimable && strcmp(name, "nr_slab_unreclaimable") == 0) nr_slab_unreclaimable = value;
		else if(!nr_page_table_pages && strcmp(name, "nr_page_table_pages") == 0) nr_page_table_pages = value;
		else if(!nr_kernel_stack && strcmp(name, "nr_kernel_stack") == 0) nr_kernel_stack = value;
		else if(!nr_unstable && strcmp(name, "nr_unstable") == 0) nr_unstable = value;
		else if(!nr_bounce && strcmp(name, "nr_bounce") == 0) nr_bounce = value;
		else if(!nr_vmscan_write && strcmp(name, "nr_vmscan_write") == 0) nr_vmscan_write = value;
		else if(!nr_vmscan_immediate_reclaim && strcmp(name, "nr_vmscan_immediate_reclaim") == 0) nr_vmscan_immediate_reclaim = value;
		else if(!nr_writeback_temp && strcmp(name, "nr_writeback_temp") == 0) nr_writeback_temp = value;
		else if(!nr_isolated_anon && strcmp(name, "nr_isolated_anon") == 0) nr_isolated_anon = value;
		else if(!nr_isolated_file && strcmp(name, "nr_isolated_file") == 0) nr_isolated_file = value;
		else if(!nr_shmem && strcmp(name, "nr_shmem") == 0) nr_shmem = value;
		else if(!nr_dirtied && strcmp(name, "nr_dirtied") == 0) nr_dirtied = value;
		else if(!nr_written && strcmp(name, "nr_written") == 0) nr_written = value;
		else if(!nr_anon_transparent_hugepages && strcmp(name, "nr_anon_transparent_hugepages") == 0) nr_anon_transparent_hugepages = value;
		else if(!nr_dirty_threshold && strcmp(name, "nr_dirty_threshold") == 0) nr_dirty_threshold = value;
		else if(!nr_dirty_background_threshold && strcmp(name, "nr_dirty_background_threshold") == 0) nr_dirty_background_threshold = value;
		else if(!pgpgin && strcmp(name, "pgpgin") == 0) pgpgin = value;
		else if(!pgpgout && strcmp(name, "pgpgout") == 0) pgpgout = value;
		else if(!pswpin && strcmp(name, "pswpin") == 0) pswpin = value;
		else if(!pswpout && strcmp(name, "pswpout") == 0) pswpout = value;
		else if(!pgalloc_dma && strcmp(name, "pgalloc_dma") == 0) pgalloc_dma = value;
		else if(!pgalloc_dma32 && strcmp(name, "pgalloc_dma32") == 0) pgalloc_dma32 = value;
		else if(!pgalloc_normal && strcmp(name, "pgalloc_normal") == 0) pgalloc_normal = value;
		else if(!pgalloc_movable && strcmp(name, "pgalloc_movable") == 0) pgalloc_movable = value;
		else if(!pgfree && strcmp(name, "pgfree") == 0) pgfree = value;
		else if(!pgactivate && strcmp(name, "pgactivate") == 0) pgactivate = value;
		else if(!pgdeactivate && strcmp(name, "pgdeactivate") == 0) pgdeactivate = value;
		else if(!pgfault && strcmp(name, "pgfault") == 0) pgfault = value;
		else if(!pgmajfault && strcmp(name, "pgmajfault") == 0) pgmajfault = value;
		else if(!pgrefill_dma && strcmp(name, "pgrefill_dma") == 0) pgrefill_dma = value;
		else if(!pgrefill_dma32 && strcmp(name, "pgrefill_dma32") == 0) pgrefill_dma32 = value;
		else if(!pgrefill_normal && strcmp(name, "pgrefill_normal") == 0) pgrefill_normal = value;
		else if(!pgrefill_movable && strcmp(name, "pgrefill_movable") == 0) pgrefill_movable = value;
		else if(!pgsteal_kswapd_dma && strcmp(name, "pgsteal_kswapd_dma") == 0) pgsteal_kswapd_dma = value;
		else if(!pgsteal_kswapd_dma32 && strcmp(name, "pgsteal_kswapd_dma32") == 0) pgsteal_kswapd_dma32 = value;
		else if(!pgsteal_kswapd_normal && strcmp(name, "pgsteal_kswapd_normal") == 0) pgsteal_kswapd_normal = value;
		else if(!pgsteal_kswapd_movable && strcmp(name, "pgsteal_kswapd_movable") == 0) pgsteal_kswapd_movable = value;
		else if(!pgsteal_direct_dma && strcmp(name, "pgsteal_direct_dma") == 0) pgsteal_direct_dma = value;
		else if(!pgsteal_direct_dma32 && strcmp(name, "pgsteal_direct_dma32") == 0) pgsteal_direct_dma32 = value;
		else if(!pgsteal_direct_normal && strcmp(name, "pgsteal_direct_normal") == 0) pgsteal_direct_normal = value;
		else if(!pgsteal_direct_movable && strcmp(name, "pgsteal_direct_movable") == 0) pgsteal_direct_movable = value;
		else if(!pgscan_kswapd_dma && strcmp(name, "pgscan_kswapd_dma") == 0) pgscan_kswapd_dma = value;
		else if(!pgscan_kswapd_dma32 && strcmp(name, "pgscan_kswapd_dma32") == 0) pgscan_kswapd_dma32 = value;
		else if(!pgscan_kswapd_normal && strcmp(name, "pgscan_kswapd_normal") == 0) pgscan_kswapd_normal = value;
		else if(!pgscan_kswapd_movable && strcmp(name, "pgscan_kswapd_movable") == 0) pgscan_kswapd_movable = value;
		else if(!pgscan_direct_dma && strcmp(name, "pgscan_direct_dma") == 0) pgscan_direct_dma = value;
		else if(!pgscan_direct_dma32 && strcmp(name, "pgscan_direct_dma32") == 0) pgscan_direct_dma32 = value;
		else if(!pgscan_direct_normal && strcmp(name, "pgscan_direct_normal") == 0) pgscan_direct_normal = value;
		else if(!pgscan_direct_movable && strcmp(name, "pgscan_direct_movable") == 0) pgscan_direct_movable = value;
		else if(!pginodesteal && strcmp(name, "pginodesteal") == 0) pginodesteal = value;
		else if(!slabs_scanned && strcmp(name, "slabs_scanned") == 0) slabs_scanned = value;
		else if(!kswapd_inodesteal && strcmp(name, "kswapd_inodesteal") == 0) kswapd_inodesteal = value;
		else if(!kswapd_low_wmark_hit_quickly && strcmp(name, "kswapd_low_wmark_hit_quickly") == 0) kswapd_low_wmark_hit_quickly = value;
		else if(!kswapd_high_wmark_hit_quickly && strcmp(name, "kswapd_high_wmark_hit_quickly") == 0) kswapd_high_wmark_hit_quickly = value;
		else if(!kswapd_skip_congestion_wait && strcmp(name, "kswapd_skip_congestion_wait") == 0) kswapd_skip_congestion_wait = value;
		else if(!pageoutrun && strcmp(name, "pageoutrun") == 0) pageoutrun = value;
		else if(!allocstall && strcmp(name, "allocstall") == 0) allocstall = value;
		else if(!pgrotated && strcmp(name, "pgrotated") == 0) pgrotated = value;
		else if(!compact_blocks_moved && strcmp(name, "compact_blocks_moved") == 0) compact_blocks_moved = value;
		else if(!compact_pages_moved && strcmp(name, "compact_pages_moved") == 0) compact_pages_moved = value;
		else if(!compact_pagemigrate_failed && strcmp(name, "compact_pagemigrate_failed") == 0) compact_pagemigrate_failed = value;
		else if(!compact_stall && strcmp(name, "compact_stall") == 0) compact_stall = value;
		else if(!compact_fail && strcmp(name, "compact_fail") == 0) compact_fail = value;
		else if(!compact_success && strcmp(name, "compact_success") == 0) compact_success = value;
		else if(!htlb_buddy_alloc_success && strcmp(name, "htlb_buddy_alloc_success") == 0) htlb_buddy_alloc_success = value;
		else if(!htlb_buddy_alloc_fail && strcmp(name, "htlb_buddy_alloc_fail") == 0) htlb_buddy_alloc_fail = value;
		else if(!unevictable_pgs_culled && strcmp(name, "unevictable_pgs_culled") == 0) unevictable_pgs_culled = value;
		else if(!unevictable_pgs_scanned && strcmp(name, "unevictable_pgs_scanned") == 0) unevictable_pgs_scanned = value;
		else if(!unevictable_pgs_rescued && strcmp(name, "unevictable_pgs_rescued") == 0) unevictable_pgs_rescued = value;
		else if(!unevictable_pgs_mlocked && strcmp(name, "unevictable_pgs_mlocked") == 0) unevictable_pgs_mlocked = value;
		else if(!unevictable_pgs_munlocked && strcmp(name, "unevictable_pgs_munlocked") == 0) unevictable_pgs_munlocked = value;
		else if(!unevictable_pgs_cleared && strcmp(name, "unevictable_pgs_cleared") == 0) unevictable_pgs_cleared = value;
		else if(!unevictable_pgs_stranded && strcmp(name, "unevictable_pgs_stranded") == 0) unevictable_pgs_stranded = value;
		else if(!unevictable_pgs_mlockfreed && strcmp(name, "unevictable_pgs_mlockfreed") == 0) unevictable_pgs_mlockfreed = value;
		else if(!thp_fault_alloc && strcmp(name, "thp_fault_alloc") == 0) thp_fault_alloc = value;
		else if(!thp_fault_fallback && strcmp(name, "thp_fault_fallback") == 0) thp_fault_fallback = value;
		else if(!thp_collapse_alloc && strcmp(name, "thp_collapse_alloc") == 0) thp_collapse_alloc = value;
		else if(!thp_collapse_alloc_failed && strcmp(name, "thp_collapse_alloc_failed") == 0) thp_collapse_alloc_failed = value;
		else if(!thp_split && strcmp(name, "thp_split") == 0) thp_split = value;
	}

	RRDSET *st;

	// --------------------------------------------------------------------
	
	if(do_swapio) {
		st = rrdset_find("system.swapio");
		if(!st) {
			st = rrdset_create("system", "swapio", NULL, "mem", "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);

			rrddim_add(st, "in",  NULL, sysconf(_SC_PAGESIZE), 1024 * update_every, RRDDIM_INCREMENTAL);
			rrddim_add(st, "out", NULL, -sysconf(_SC_PAGESIZE), 1024 * update_every, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "in", pswpin);
		rrddim_set(st, "out", pswpout);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------
	
	if(do_io) {
		st = rrdset_find("system.io");
		if(!st) {
			st = rrdset_create("system", "io", NULL, "disk", "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);

			rrddim_add(st, "in",  NULL,  1, 1 * update_every, RRDDIM_INCREMENTAL);
			rrddim_add(st, "out", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "in", pgpgin);
		rrddim_set(st, "out", pgpgout);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------
	
	if(do_pgfaults) {
		st = rrdset_find("system.pgfaults");
		if(!st) {
			st = rrdset_create("system", "pgfaults", NULL, "mem", "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
			st->isdetail = 1;

			rrddim_add(st, "minor",  NULL,  1, 1 * update_every, RRDDIM_INCREMENTAL);
			rrddim_add(st, "major", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "minor", pgfault);
		rrddim_set(st, "major", pgmajfault);
		rrdset_done(st);
	}

	return 0;
}
Exemple #15
0
int do_proc_net_snmp(int update_every, usec_t dt) {
    (void)dt;

    static procfile *ff = NULL;
    static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
        do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1,
        do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1, do_udplite_packets = -1;
    static uint32_t hash_ip = 0, hash_icmp = 0, hash_tcp = 0, hash_udp = 0, hash_icmpmsg = 0, hash_udplite = 0;

    //static unsigned long long *ip_Forwarding = NULL;
    //static unsigned long long *ip_DefaultTTL = NULL;
    static unsigned long long *ip_InReceives = NULL;
    static unsigned long long *ip_InHdrErrors = NULL;
    static unsigned long long *ip_InAddrErrors = NULL;
    static unsigned long long *ip_ForwDatagrams = NULL;
    static unsigned long long *ip_InUnknownProtos = NULL;
    static unsigned long long *ip_InDiscards = NULL;
    static unsigned long long *ip_InDelivers = NULL;
    static unsigned long long *ip_OutRequests = NULL;
    static unsigned long long *ip_OutDiscards = NULL;
    static unsigned long long *ip_OutNoRoutes = NULL;
    //static unsigned long long *ip_ReasmTimeout = NULL;
    static unsigned long long *ip_ReasmReqds = NULL;
    static unsigned long long *ip_ReasmOKs = NULL;
    static unsigned long long *ip_ReasmFails = NULL;
    static unsigned long long *ip_FragOKs = NULL;
    static unsigned long long *ip_FragFails = NULL;
    static unsigned long long *ip_FragCreates = NULL;

    static unsigned long long *icmp_InMsgs = NULL;
    static unsigned long long *icmp_OutMsgs = NULL;
    static unsigned long long *icmp_InErrors = NULL;
    static unsigned long long *icmp_OutErrors = NULL;
    static unsigned long long *icmp_InCsumErrors = NULL;

    //static unsigned long long *tcp_RtoAlgorithm = NULL;
    //static unsigned long long *tcp_RtoMin = NULL;
    //static unsigned long long *tcp_RtoMax = NULL;
    //static unsigned long long *tcp_MaxConn = NULL;
    static unsigned long long *tcp_ActiveOpens = NULL;
    static unsigned long long *tcp_PassiveOpens = NULL;
    static unsigned long long *tcp_AttemptFails = NULL;
    static unsigned long long *tcp_EstabResets = NULL;
    static unsigned long long *tcp_CurrEstab = NULL;
    static unsigned long long *tcp_InSegs = NULL;
    static unsigned long long *tcp_OutSegs = NULL;
    static unsigned long long *tcp_RetransSegs = NULL;
    static unsigned long long *tcp_InErrs = NULL;
    static unsigned long long *tcp_OutRsts = NULL;
    static unsigned long long *tcp_InCsumErrors = NULL;

    static unsigned long long *udp_InDatagrams = NULL;
    static unsigned long long *udp_NoPorts = NULL;
    static unsigned long long *udp_InErrors = NULL;
    static unsigned long long *udp_OutDatagrams = NULL;
    static unsigned long long *udp_RcvbufErrors = NULL;
    static unsigned long long *udp_SndbufErrors = NULL;
    static unsigned long long *udp_InCsumErrors = NULL;
    static unsigned long long *udp_IgnoredMulti = NULL;

    static unsigned long long *udplite_InDatagrams = NULL;
    static unsigned long long *udplite_NoPorts = NULL;
    static unsigned long long *udplite_InErrors = NULL;
    static unsigned long long *udplite_OutDatagrams = NULL;
    static unsigned long long *udplite_RcvbufErrors = NULL;
    static unsigned long long *udplite_SndbufErrors = NULL;
    static unsigned long long *udplite_InCsumErrors = NULL;
    static unsigned long long *udplite_IgnoredMulti = NULL;

    if(unlikely(do_ip_packets == -1)) {
        do_ip_packets       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1);
        do_ip_fragsout      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", 1);
        do_ip_fragsin       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1);
        do_ip_errors        = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 errors", 1);
        do_tcp_sockets      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", 1);
        do_tcp_packets      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", 1);
        do_tcp_errors       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", 1);
        do_tcp_handshake    = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", 1);
        do_udp_packets      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", 1);
        do_udp_errors       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", 1);
        do_icmp_packets     = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP packets", 1);
        do_icmpmsg          = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP messages", 1);
        do_udplite_packets  = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDPLite packets", 1);

        hash_ip = simple_hash("Ip");
        hash_tcp = simple_hash("Tcp");
        hash_udp = simple_hash("Udp");
        hash_icmp = simple_hash("Icmp");
        hash_icmpmsg = simple_hash("IcmpMsg");
        hash_udplite = simple_hash("UdpLite");

        hash_array(ip_data);
        hash_array(tcp_data);
        hash_array(udp_data);
        hash_array(icmp_data);
        hash_array(icmpmsg_data);
        hash_array(udplite_data);

        //ip_Forwarding = netstat_columns_find(ip_data, "Forwarding");
        //ip_DefaultTTL = netstat_columns_find(ip_data, "DefaultTTL");
        ip_InReceives = netstat_columns_find(ip_data, "InReceives");
        ip_InHdrErrors = netstat_columns_find(ip_data, "InHdrErrors");
        ip_InAddrErrors = netstat_columns_find(ip_data, "InAddrErrors");
        ip_ForwDatagrams = netstat_columns_find(ip_data, "ForwDatagrams");
        ip_InUnknownProtos = netstat_columns_find(ip_data, "InUnknownProtos");
        ip_InDiscards = netstat_columns_find(ip_data, "InDiscards");
        ip_InDelivers = netstat_columns_find(ip_data, "InDelivers");
        ip_OutRequests = netstat_columns_find(ip_data, "OutRequests");
        ip_OutDiscards = netstat_columns_find(ip_data, "OutDiscards");
        ip_OutNoRoutes = netstat_columns_find(ip_data, "OutNoRoutes");
        //ip_ReasmTimeout = netstat_columns_find(ip_data, "ReasmTimeout");
        ip_ReasmReqds = netstat_columns_find(ip_data, "ReasmReqds");
        ip_ReasmOKs = netstat_columns_find(ip_data, "ReasmOKs");
        ip_ReasmFails = netstat_columns_find(ip_data, "ReasmFails");
        ip_FragOKs = netstat_columns_find(ip_data, "FragOKs");
        ip_FragFails = netstat_columns_find(ip_data, "FragFails");
        ip_FragCreates = netstat_columns_find(ip_data, "FragCreates");

        icmp_InMsgs = netstat_columns_find(icmp_data, "InMsgs");
        icmp_OutMsgs = netstat_columns_find(icmp_data, "OutMsgs");
        icmp_InErrors = netstat_columns_find(icmp_data, "InErrors");
        icmp_OutErrors = netstat_columns_find(icmp_data, "OutErrors");
        icmp_InCsumErrors = netstat_columns_find(icmp_data, "InCsumErrors");

        //tcp_RtoAlgorithm = netstat_columns_find(tcp_data, "RtoAlgorithm");
        //tcp_RtoMin = netstat_columns_find(tcp_data, "RtoMin");
        //tcp_RtoMax = netstat_columns_find(tcp_data, "RtoMax");
        //tcp_MaxConn = netstat_columns_find(tcp_data, "MaxConn");
        tcp_ActiveOpens = netstat_columns_find(tcp_data, "ActiveOpens");
        tcp_PassiveOpens = netstat_columns_find(tcp_data, "PassiveOpens");
        tcp_AttemptFails = netstat_columns_find(tcp_data, "AttemptFails");
        tcp_EstabResets = netstat_columns_find(tcp_data, "EstabResets");
        tcp_CurrEstab = netstat_columns_find(tcp_data, "CurrEstab");
        tcp_InSegs = netstat_columns_find(tcp_data, "InSegs");
        tcp_OutSegs = netstat_columns_find(tcp_data, "OutSegs");
        tcp_RetransSegs = netstat_columns_find(tcp_data, "RetransSegs");
        tcp_InErrs = netstat_columns_find(tcp_data, "InErrs");
        tcp_OutRsts = netstat_columns_find(tcp_data, "OutRsts");
        tcp_InCsumErrors = netstat_columns_find(tcp_data, "InCsumErrors");

        udp_InDatagrams = netstat_columns_find(udp_data, "InDatagrams");
        udp_NoPorts = netstat_columns_find(udp_data, "NoPorts");
        udp_InErrors = netstat_columns_find(udp_data, "InErrors");
        udp_OutDatagrams = netstat_columns_find(udp_data, "OutDatagrams");
        udp_RcvbufErrors = netstat_columns_find(udp_data, "RcvbufErrors");
        udp_SndbufErrors = netstat_columns_find(udp_data, "SndbufErrors");
        udp_InCsumErrors = netstat_columns_find(udp_data, "InCsumErrors");
        udp_IgnoredMulti = netstat_columns_find(udp_data, "IgnoredMulti");

        udplite_InDatagrams = netstat_columns_find(udplite_data, "InDatagrams");
        udplite_NoPorts = netstat_columns_find(udplite_data, "NoPorts");
        udplite_InErrors = netstat_columns_find(udplite_data, "InErrors");
        udplite_OutDatagrams = netstat_columns_find(udplite_data, "OutDatagrams");
        udplite_RcvbufErrors = netstat_columns_find(udplite_data, "RcvbufErrors");
        udplite_SndbufErrors = netstat_columns_find(udplite_data, "SndbufErrors");
        udplite_InCsumErrors = netstat_columns_find(udplite_data, "InCsumErrors");
        udplite_IgnoredMulti = netstat_columns_find(udplite_data, "IgnoredMulti");
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/snmp");
        ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
        if(unlikely(!ff)) return 1;
    }

    ff = procfile_readall(ff);
    if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time

    uint32_t lines = procfile_lines(ff), l;
    uint32_t words;

    RRDSET *st;

    for(l = 0; l < lines ;l++) {
        char *key = procfile_lineword(ff, l, 0);
        uint32_t hash = simple_hash(key);

        if(unlikely(hash == hash_ip && strcmp(key, "Ip") == 0)) {
            uint32_t h = l++;

            if(strcmp(procfile_lineword(ff, l, 0), "Ip") != 0) {
                error("Cannot read Ip line from /proc/net/snmp.");
                break;
            }

            words = procfile_linewords(ff, l);
            if(words < 3) {
                error("Cannot read /proc/net/snmp Ip line. Expected 3+ params, read %u.", words);
                continue;
            }

            // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
            parse_line_pair(ff, ip_data, h, l);

            // --------------------------------------------------------------------

            if(do_ip_packets) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".packets");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "InReceives",    "received",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutRequests",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InDelivers",    "delivered", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "OutRequests",   *ip_OutRequests);
                rrddim_set(st, "InReceives",    *ip_InReceives);
                rrddim_set(st, "ForwDatagrams", *ip_ForwDatagrams);
                rrddim_set(st, "InDelivers",    *ip_InDelivers);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_ip_fragsout) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsout");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "FragOKs",     "ok",      1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "FragFails",   "failed", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "FragCreates", "created", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "FragOKs",     *ip_FragOKs);
                rrddim_set(st, "FragFails",   *ip_FragFails);
                rrddim_set(st, "FragCreates", *ip_FragCreates);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_ip_fragsin) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsin");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL, "IPv4 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "ReasmOKs",   "ok",      1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "ReasmFails", "failed", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "ReasmReqds", "all",     1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "ReasmOKs",   *ip_ReasmOKs);
                rrddim_set(st, "ReasmFails", *ip_ReasmFails);
                rrddim_set(st, "ReasmReqds", *ip_ReasmReqds);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_ip_errors) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".errors");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InDiscards",      NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutDiscards",     NULL, -1, 1, RRDDIM_INCREMENTAL);

                    rrddim_add(st, "InHdrErrors",     NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutNoRoutes",     NULL, -1, 1, RRDDIM_INCREMENTAL);

                    rrddim_add(st, "InAddrErrors",    NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InUnknownProtos", NULL,  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InDiscards",      *ip_InDiscards);
                rrddim_set(st, "OutDiscards",     *ip_OutDiscards);
                rrddim_set(st, "InHdrErrors",     *ip_InHdrErrors);
                rrddim_set(st, "InAddrErrors",    *ip_InAddrErrors);
                rrddim_set(st, "InUnknownProtos", *ip_InUnknownProtos);
                rrddim_set(st, "OutNoRoutes",     *ip_OutNoRoutes);
                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_icmp && strcmp(key, "Icmp") == 0)) {
            uint32_t h = l++;

            if(strcmp(procfile_lineword(ff, l, 0), "Icmp") != 0) {
                error("Cannot read Icmp line from /proc/net/snmp.");
                break;
            }

            words = procfile_linewords(ff, l);
            if(words < 3) {
                error("Cannot read /proc/net/snmp Icmp line. Expected 3+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, icmp_data, h, l);

            // --------------------------------------------------------------------

            if(do_icmp_packets) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".icmp");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s", 2602, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "InMsgs",  "received",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMsgs", "sent",     -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMsgs",  *icmp_InMsgs);
                rrddim_set(st, "OutMsgs", *icmp_OutMsgs);

                rrdset_done(st);

                st = rrdset_find(RRD_TYPE_NET_SNMP ".icmp_errors");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors", "packets/s", 2603, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "InErrors",     NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutErrors",    NULL, -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InErrors",     *icmp_InErrors);
                rrddim_set(st, "OutErrors",    *icmp_OutErrors);
                rrddim_set(st, "InCsumErrors", *icmp_InCsumErrors);

                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_icmpmsg && strcmp(key, "IcmpMsg") == 0)) {
            uint32_t h = l++;

            if(strcmp(procfile_lineword(ff, l, 0), "IcmpMsg") != 0) {
                error("Cannot read IcmpMsg line from /proc/net/snmp.");
                break;
            }

            parse_line_pair(ff, icmpmsg_data, h, l);

            // --------------------------------------------------------------------

            if(do_icmpmsg) {
                int i;

                st = rrdset_find(RRD_TYPE_NET_SNMP ".icmpmsg");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages", "packets/s", 2604, update_every, RRDSET_TYPE_LINE);

                    for(i = 0; icmpmsg_data[i].name ;i++)
                        rrddim_add(st, icmpmsg_data[i].name, icmpmsg_data[i].label,  icmpmsg_data[i].multiplier, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                for(i = 0; icmpmsg_data[i].name ;i++)
                    rrddim_set(st, icmpmsg_data[i].name, icmpmsg_data[i].value);

                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_tcp && strcmp(key, "Tcp") == 0)) {
            uint32_t h = l++;

            if(strcmp(procfile_lineword(ff, l, 0), "Tcp") != 0) {
                error("Cannot read Tcp line from /proc/net/snmp.");
                break;
            }

            words = procfile_linewords(ff, l);
            if(words < 3) {
                error("Cannot read /proc/net/snmp Tcp line. Expected 3+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, tcp_data, h, l);

            // --------------------------------------------------------------------

            // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
            if(do_tcp_sockets) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".tcpsock");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections", "active connections", 2500, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "CurrEstab", "connections", 1, 1, RRDDIM_ABSOLUTE);
                }
                else rrdset_next(st);

                rrddim_set(st, "CurrEstab", *tcp_CurrEstab);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcp_packets) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".tcppackets");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets", "packets/s", 2600, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "InSegs",  "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutSegs", "sent",    -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InSegs",  *tcp_InSegs);
                rrddim_set(st, "OutSegs", *tcp_OutSegs);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcp_errors) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".tcperrors");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", "packets/s", 2700, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InErrs",       NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "RetransSegs",  NULL, -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InErrs",       *tcp_InErrs);
                rrddim_set(st, "InCsumErrors", *tcp_InCsumErrors);
                rrddim_set(st, "RetransSegs",  *tcp_RetransSegs);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcp_handshake) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".tcphandshake");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", NULL, "IPv4 TCP Handshake Issues", "events/s", 2900, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "EstabResets",  NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutRsts",      NULL, -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "ActiveOpens",  NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "PassiveOpens", NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "AttemptFails", NULL,  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "EstabResets",  *tcp_EstabResets);
                rrddim_set(st, "OutRsts",      *tcp_OutRsts);
                rrddim_set(st, "ActiveOpens",  *tcp_ActiveOpens);
                rrddim_set(st, "PassiveOpens", *tcp_PassiveOpens);
                rrddim_set(st, "AttemptFails", *tcp_AttemptFails);
                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_udp && strcmp(key, "Udp") == 0)) {
            uint32_t h = l++;

            if(strcmp(procfile_lineword(ff, l, 0), "Udp") != 0) {
                error("Cannot read Udp line from /proc/net/snmp.");
                break;
            }

            words = procfile_linewords(ff, l);
            if(words < 3) {
                error("Cannot read /proc/net/snmp Udp line. Expected 3+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, udp_data, h, l);

            // --------------------------------------------------------------------

            // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
            if(do_udp_packets) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".udppackets");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets", "packets/s", 2601, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "InDatagrams",  "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutDatagrams", "sent",    -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InDatagrams",  *udp_InDatagrams);
                rrddim_set(st, "OutDatagrams", *udp_OutDatagrams);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_udp_errors) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".udperrors");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s", 2701, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "RcvbufErrors", NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InErrors",     NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "NoPorts",      NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "IgnoredMulti", NULL,  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InErrors",     *udp_InErrors);
                rrddim_set(st, "NoPorts",      *udp_NoPorts);
                rrddim_set(st, "RcvbufErrors", *udp_RcvbufErrors);
                rrddim_set(st, "SndbufErrors", *udp_SndbufErrors);
                rrddim_set(st, "InCsumErrors", *udp_InCsumErrors);
                rrddim_set(st, "IgnoredMulti", *udp_IgnoredMulti);
                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_udplite && strcmp(key, "UdpLite") == 0)) {
            uint32_t h = l++;

            if(strcmp(procfile_lineword(ff, l, 0), "UdpLite") != 0) {
                error("Cannot read UdpLite line from /proc/net/snmp.");
                break;
            }

            words = procfile_linewords(ff, l);
            if(words < 3) {
                error("Cannot read /proc/net/snmp UdpLite line. Expected 3+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, udplite_data, h, l);

            // --------------------------------------------------------------------

            if(do_udplite_packets) {
                st = rrdset_find(RRD_TYPE_NET_SNMP ".udplite");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "udplite", NULL, "udplite", NULL, "IPv4 UDPLite Packets", "packets/s", 2603, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "InDatagrams",  "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutDatagrams", "sent",    -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InDatagrams",  *udplite_InDatagrams);
                rrddim_set(st, "OutDatagrams", *udplite_OutDatagrams);
                rrdset_done(st);

                st = rrdset_find(RRD_TYPE_NET_SNMP ".udplite_errors");
                if(!st) {
                    st = rrdset_create(RRD_TYPE_NET_SNMP, "udplite_errors", NULL, "udplite", NULL, "IPv4 UDPLite Errors", "packets/s", 2604, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "RcvbufErrors", NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "NoPorts",      NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "IgnoredMulti", NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InErrors",     NULL,  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "NoPorts",      *udplite_NoPorts);
                rrddim_set(st, "InErrors",     *udplite_InErrors);
                rrddim_set(st, "InCsumErrors", *udplite_InCsumErrors);
                rrddim_set(st, "RcvbufErrors", *udplite_RcvbufErrors);
                rrddim_set(st, "SndbufErrors", *udplite_SndbufErrors);
                rrddim_set(st, "IgnoredMulti", *udplite_IgnoredMulti);
                rrdset_done(st);
            }
        }
    }

    return 0;
}
int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
	static procfile *ff = NULL;
	static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;

	if(do_sockets == -1)	do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", 1);
	if(do_new == -1)		do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", 1);
	if(do_changes == -1)	do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", 1);
	if(do_expect == -1)		do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", 1);
	if(do_search == -1)		do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", 1);
	if(do_errors == -1)		do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", 1);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/nf_conntrack");
		ff = procfile_open(config_get("plugin:proc:/proc/net/stat/nf_conntrack", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
	}
	if(!ff) return 1;

	ff = procfile_readall(ff);
	if(!ff) return 0; // we return 0, so that we will retry to open it next time

	uint32_t lines = procfile_lines(ff), l;
	uint32_t words;

	unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0,
		ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0;

	for(l = 1; l < lines ;l++) {
		words = procfile_linewords(ff, l);
		if(words < 17) {
			if(words) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %d.", words);
			continue;
		}

		unsigned long long tentries = 0, tsearched = 0, tfound = 0, tnew = 0, tinvalid = 0, tignore = 0, tdelete = 0, tdelete_list = 0, tinsert = 0, tinsert_failed = 0, tdrop = 0, tearly_drop = 0, ticmp_error = 0, texpect_new = 0, texpect_create = 0, texpect_delete = 0, tsearch_restart = 0;

		tentries		= strtoull(procfile_lineword(ff, l, 0), NULL, 16);
		tsearched		= strtoull(procfile_lineword(ff, l, 1), NULL, 16);
		tfound			= strtoull(procfile_lineword(ff, l, 2), NULL, 16);
		tnew			= strtoull(procfile_lineword(ff, l, 3), NULL, 16);
		tinvalid		= strtoull(procfile_lineword(ff, l, 4), NULL, 16);
		tignore			= strtoull(procfile_lineword(ff, l, 5), NULL, 16);
		tdelete			= strtoull(procfile_lineword(ff, l, 6), NULL, 16);
		tdelete_list	= strtoull(procfile_lineword(ff, l, 7), NULL, 16);
		tinsert			= strtoull(procfile_lineword(ff, l, 8), NULL, 16);
		tinsert_failed	= strtoull(procfile_lineword(ff, l, 9), NULL, 16);
		tdrop			= strtoull(procfile_lineword(ff, l, 10), NULL, 16);
		tearly_drop		= strtoull(procfile_lineword(ff, l, 11), NULL, 16);
		ticmp_error		= strtoull(procfile_lineword(ff, l, 12), NULL, 16);
		texpect_new		= strtoull(procfile_lineword(ff, l, 13), NULL, 16);
		texpect_create	= strtoull(procfile_lineword(ff, l, 14), NULL, 16);
		texpect_delete	= strtoull(procfile_lineword(ff, l, 15), NULL, 16);
		tsearch_restart	= strtoull(procfile_lineword(ff, l, 16), NULL, 16);

		if(!aentries) aentries =  tentries;

		// sum all the cpus together
		asearched 			+= tsearched;		// conntrack.search
		afound 				+= tfound;			// conntrack.search
		anew 				+= tnew;			// conntrack.new
		ainvalid 			+= tinvalid;		// conntrack.new
		aignore 			+= tignore;			// conntrack.new
		adelete 			+= tdelete;			// conntrack.changes
		adelete_list 		+= tdelete_list;	// conntrack.changes
		ainsert 			+= tinsert;			// conntrack.changes
		ainsert_failed 		+= tinsert_failed;	// conntrack.errors
		adrop 				+= tdrop;			// conntrack.errors
		aearly_drop 		+= tearly_drop;		// conntrack.errors
		aicmp_error 		+= ticmp_error;		// conntrack.errors
		aexpect_new 		+= texpect_new;		// conntrack.expect
		aexpect_create 		+= texpect_create;	// conntrack.expect
		aexpect_delete 		+= texpect_delete;	// conntrack.expect
		asearch_restart 	+= tsearch_restart;	// conntrack.search
	}

	RRDSET *st;

	// --------------------------------------------------------------------

	if(do_sockets) {
		st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 1000, update_every, RRDSET_TYPE_LINE);

			rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "connections", aentries);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_new) {
		st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);

			rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "ignore", NULL, -1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "new", anew);
		rrddim_set(st, "ignore", aignore);
		rrddim_set(st, "invalid", ainvalid);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_changes) {
		st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 1002, update_every, RRDSET_TYPE_LINE);
			st->isdetail = 1;

			rrddim_add(st, "inserted", NULL, 1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "delete_list", NULL, -1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "inserted", ainsert);
		rrddim_set(st, "deleted", adelete);
		rrddim_set(st, "delete_list", adelete_list);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_expect) {
		st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 1003, update_every, RRDSET_TYPE_LINE);
			st->isdetail = 1;

			rrddim_add(st, "created", NULL, 1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "created", aexpect_create);
		rrddim_set(st, "deleted", aexpect_delete);
		rrddim_set(st, "new", aexpect_new);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_search) {
		st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 1010, update_every, RRDSET_TYPE_LINE);
			st->isdetail = 1;

			rrddim_add(st, "searched", NULL, 1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "restarted", NULL, -1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "found", NULL, 1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "searched", asearched);
		rrddim_set(st, "restarted", asearch_restart);
		rrddim_set(st, "found", afound);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_errors) {
		st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors");
		if(!st) {
			st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 1005, update_every, RRDSET_TYPE_LINE);
			st->isdetail = 1;

			rrddim_add(st, "icmp_error", NULL, 1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "insert_failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st, "early_drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st);

		rrddim_set(st, "icmp_error", aicmp_error);
		rrddim_set(st, "insert_failed", ainsert_failed);
		rrddim_set(st, "drop", adrop);
		rrddim_set(st, "early_drop", aearly_drop);
		rrdset_done(st);
	}

	return 0;
}
Exemple #17
0
void *pluginsd_worker_thread(void *arg)
{
	struct plugind *cd = (struct plugind *)arg;
	char line[PLUGINSD_LINE_MAX + 1];

#ifdef DETACH_PLUGINS_FROM_NETDATA
	unsigned long long usec = 0, susec = 0;
	struct timeval last = {0, 0} , now = {0, 0};
#endif

	char *words[MAX_WORDS] = { NULL };
	uint32_t SET_HASH = simple_hash("SET");
	uint32_t BEGIN_HASH = simple_hash("BEGIN");
	uint32_t END_HASH = simple_hash("END");
	uint32_t FLUSH_HASH = simple_hash("FLUSH");
	uint32_t CHART_HASH = simple_hash("CHART");
	uint32_t DIMENSION_HASH = simple_hash("DIMENSION");
	uint32_t DISABLE_HASH = simple_hash("DISABLE");
#ifdef DETACH_PLUGINS_FROM_NETDATA
	uint32_t MYPID_HASH = simple_hash("MYPID");
	uint32_t STOPPING_WAKE_ME_UP_PLEASE_HASH = simple_hash("STOPPING_WAKE_ME_UP_PLEASE");
#endif

	while(likely(1)) {
		if(unlikely(netdata_exit)) break;

		FILE *fp = mypopen(cd->cmd, &cd->pid);
		if(unlikely(!fp)) {
			error("Cannot popen(\"%s\", \"r\").", cd->cmd);
			break;
		}

		info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid);

		RRDSET *st = NULL;
		unsigned long long count = 0;
		char *s;
		uint32_t hash;

		while(likely(fgets(line, PLUGINSD_LINE_MAX, fp) != NULL)) {
			if(unlikely(netdata_exit)) break;

			line[PLUGINSD_LINE_MAX] = '\0';

			// debug(D_PLUGINSD, "PLUGINSD: %s: %s", cd->filename, line);

			int w = pluginsd_split_words(line, words, MAX_WORDS);
			s = words[0];
			if(unlikely(!s || !*s || !w)) {
				// debug(D_PLUGINSD, "PLUGINSD: empty line");
				continue;
			}

			// debug(D_PLUGINSD, "PLUGINSD: words 0='%s' 1='%s' 2='%s' 3='%s' 4='%s' 5='%s' 6='%s' 7='%s' 8='%s' 9='%s'", words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]);

			hash = simple_hash(s);

			if(likely(hash == SET_HASH && !strcmp(s, "SET"))) {
				char *dimension = words[1];
				char *value = words[2];

				if(unlikely(!dimension || !*dimension)) {
					error("PLUGINSD: '%s' is requesting a SET on chart '%s', without a dimension. Disabling it.", cd->fullfilename, st->id);
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				if(unlikely(!value || !*value)) value = NULL;

				if(unlikely(!st)) {
					error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value?value:"<nothing>");
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is setting dimension %s/%s to %s", cd->fullfilename, st->id, dimension, value?value:"<nothing>");

				if(value) rrddim_set(st, dimension, atoll(value));

				count++;
			}
			else if(likely(hash == BEGIN_HASH && !strcmp(s, "BEGIN"))) {
				char *id = words[1];
				char *microseconds_txt = words[2];

				if(unlikely(!id)) {
					error("PLUGINSD: '%s' is requesting a BEGIN without a chart id. Disabling it.", cd->fullfilename);
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				st = rrdset_find(id);
				if(unlikely(!st)) {
					error("PLUGINSD: '%s' is requesting a BEGIN on chart '%s', which does not exist. Disabling it.", cd->fullfilename, id);
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				if(likely(st->counter_done)) {
					unsigned long long microseconds = 0;
					if(microseconds_txt && *microseconds_txt) microseconds = strtoull(microseconds_txt, NULL, 10);
					if(microseconds) rrdset_next_usec(st, microseconds);
					else rrdset_next_plugins(st);
				}
			}
			else if(likely(hash == END_HASH && !strcmp(s, "END"))) {
				if(unlikely(!st)) {
					error("PLUGINSD: '%s' is requesting an END, without a BEGIN. Disabling it.", cd->fullfilename);
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a END on chart %s", cd->fullfilename, st->id);

				rrdset_done(st);
				st = NULL;
			}
			else if(likely(hash == FLUSH_HASH && !strcmp(s, "FLUSH"))) {
				debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a FLUSH", cd->fullfilename);
				st = NULL;
			}
			else if(likely(hash == CHART_HASH && !strcmp(s, "CHART"))) {
				st = NULL;

				char *type = words[1];
				char *id = NULL;
				if(likely(type)) {
					id = strchr(type, '.');
					if(likely(id)) { *id = '\0'; id++; }
				}
				char *name = words[2];
				char *title = words[3];
				char *units = words[4];
				char *family = words[5];
				char *category = words[6];
				char *chart = words[7];
				char *priority_s = words[8];
				char *update_every_s = words[9];

				if(unlikely(!type || !*type || !id || !*id)) {
					error("PLUGINSD: '%s' is requesting a CHART, without a type.id. Disabling it.", cd->fullfilename);
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				int priority = 1000;
				if(likely(priority_s)) priority = atoi(priority_s);

				int update_every = cd->update_every;
				if(likely(update_every_s)) update_every = atoi(update_every_s);
				if(unlikely(!update_every)) update_every = cd->update_every;

				int chart_type = RRDSET_TYPE_LINE;
				if(unlikely(chart)) chart_type = rrdset_type_id(chart);

				if(unlikely(!name || !*name)) name = NULL;
				if(unlikely(!family || !*family)) family = id;
				if(unlikely(!category || !*category)) category = type;

				st = rrdset_find_bytype(type, id);
				if(unlikely(!st)) {
					debug(D_PLUGINSD, "PLUGINSD: Creating chart type='%s', id='%s', name='%s', family='%s', category='%s', chart='%s', priority=%d, update_every=%d"
						, type, id
						, name?name:""
						, family?family:""
						, category?category:""
						, rrdset_type_name(chart_type)
						, priority
						, update_every
						);

					st = rrdset_create(type, id, name, family, title, units, priority, update_every, chart_type);
					cd->update_every = update_every;

					if(unlikely(strcmp(category, "none") == 0)) st->isdetail = 1;
				}
				else debug(D_PLUGINSD, "PLUGINSD: Chart '%s' already exists. Not adding it again.", st->id);
			}
			else if(likely(hash == DIMENSION_HASH && !strcmp(s, "DIMENSION"))) {
				char *id = words[1];
				char *name = words[2];
				char *algorithm = words[3];
				char *multiplier_s = words[4];
				char *divisor_s = words[5];
				char *options = words[6];

				if(unlikely(!id || !*id)) {
					error("PLUGINSD: '%s' is requesting a DIMENSION, without an id. Disabling it.", cd->fullfilename);
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				if(unlikely(!st)) {
					error("PLUGINSD: '%s' is requesting a DIMENSION, without a CHART. Disabling it.", cd->fullfilename);
					cd->enabled = 0;
					killpid(cd->pid, SIGTERM);
					break;
				}

				long multiplier = 1;
				if(multiplier_s && *multiplier_s) multiplier = atol(multiplier_s);
				if(unlikely(!multiplier)) multiplier = 1;

				long divisor = 1;
				if(likely(divisor_s && *divisor_s)) divisor = atol(divisor_s);
				if(unlikely(!divisor)) divisor = 1;

				if(unlikely(!algorithm || !*algorithm)) algorithm = "absolute";

				if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: Creating dimension in chart %s, id='%s', name='%s', algorithm='%s', multiplier=%ld, divisor=%ld, hidden='%s'"
					, st->id
					, id
					, name?name:""
					, rrddim_algorithm_name(rrddim_algorithm_id(algorithm))
					, multiplier
					, divisor
					, options?options:""
					);

				RRDDIM *rd = rrddim_find(st, id);
				if(unlikely(!rd)) {
					rd = rrddim_add(st, id, name, multiplier, divisor, rrddim_algorithm_id(algorithm));
					rd->flags = 0x00000000;
					if(options && *options) {
						if(strstr(options, "hidden") != NULL) rd->flags |= RRDDIM_FLAG_HIDDEN;
						if(strstr(options, "noreset") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
						if(strstr(options, "nooverflow") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
					}
				}
				else if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: dimension %s/%s already exists. Not adding it again.", st->id, id);
			}
			else if(unlikely(hash == DISABLE_HASH && !strcmp(s, "DISABLE"))) {
				error("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename);
				cd->enabled = 0;
				killpid(cd->pid, SIGTERM);
				break;
			}
#ifdef DETACH_PLUGINS_FROM_NETDATA
			else if(likely(hash == MYPID_HASH && !strcmp(s, "MYPID"))) {
				char *pid_s = words[1];
				pid_t pid = atol(pid_s);

				if(likely(pid)) cd->pid = pid;
				debug(D_PLUGINSD, "PLUGINSD: %s is on pid %d", cd->id, cd->pid);
			}
			else if(likely(hash == STOPPING_WAKE_ME_UP_PLEASE_HASH && !strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE"))) {
				error("PLUGINSD: '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid);

				gettimeofday(&now, NULL);
				if(unlikely(!usec && !susec)) {
					// our first run
					susec = cd->rrd_update_every * 1000000ULL;
				}
				else {
					// second+ run
					usec = usecdiff(&now, &last) - susec;
					error("PLUGINSD: %s last loop took %llu usec (worked for %llu, sleeped for %llu).\n", cd->fullfilename, usec + susec, usec, susec);
					if(unlikely(usec < (rrd_update_every * 1000000ULL / 2ULL))) susec = (rrd_update_every * 1000000ULL) - usec;
					else susec = rrd_update_every * 1000000ULL / 2ULL;
				}

				error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
				usleep(susec);
				killpid(cd->pid, SIGCONT);
				bcopy(&now, &last, sizeof(struct timeval));
				break;
			}
#endif
			else {
				error("PLUGINSD: '%s' is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s);
				cd->enabled = 0;
				killpid(cd->pid, SIGTERM);
				break;
			}
		}

		info("PLUGINSD: '%s' on pid %d stopped.", cd->fullfilename, cd->pid);

		// fgets() failed or loop broke
		int code = mypclose(fp, cd->pid);
		if(code == 1 || code == 127) {
			// 1 = DISABLE
			// 127 = cannot even run it
			error("PLUGINSD: '%s' (pid %d) exited with code %d. Disabling it.", cd->fullfilename, cd->pid, code);
			cd->enabled = 0;
		}

		if(netdata_exit) {
			cd->pid = 0;
			cd->enabled = 0;
			cd->obsolete = 1;
			return NULL;
		}

		if(unlikely(!count && cd->enabled)) {
			error("PLUGINSD: '%s' (pid %d) does not generate usefull output. Waiting a bit before starting it again.", cd->fullfilename, cd->pid);
			sleep((unsigned int) (cd->update_every * 10));
		}

		cd->pid = 0;
		if(likely(cd->enabled)) sleep((unsigned int) cd->update_every);
		else break;
	}

	cd->obsolete = 1;
	return NULL;
}
int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) {
    (void)dt;

    static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
    static procfile *ff = NULL;

    if(unlikely(do_entries == -1)) {
        do_entries  = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND);
        do_cookies  = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND);
        do_syns     = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND);
        do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND);
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/synproxy");
        ff = procfile_open(config_get("plugin:proc:/proc/net/stat/synproxy", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
        if(unlikely(!ff))
            return 1;
    }

    ff = procfile_readall(ff);
    if(unlikely(!ff))
        return 0; // we return 0, so that we will retry to open it next time

    // make sure we have 3 lines
    size_t lines = procfile_lines(ff), l;
    if(unlikely(lines < 2)) {
        error("/proc/net/stat/synproxy has %zu lines, expected no less than 2. Disabling it.", lines);
        return 1;
    }

    unsigned long long entries = 0, syn_received = 0, cookie_invalid = 0, cookie_valid = 0, cookie_retrans = 0, conn_reopened = 0;

    // synproxy gives its values per CPU
    for(l = 1; l < lines ;l++) {
        int words = procfile_linewords(ff, l);
        if(unlikely(words < 6))
            continue;

        entries         += strtoull(procfile_lineword(ff, l, 0), NULL, 16);
        syn_received    += strtoull(procfile_lineword(ff, l, 1), NULL, 16);
        cookie_invalid  += strtoull(procfile_lineword(ff, l, 2), NULL, 16);
        cookie_valid    += strtoull(procfile_lineword(ff, l, 3), NULL, 16);
        cookie_retrans  += strtoull(procfile_lineword(ff, l, 4), NULL, 16);
        conn_reopened   += strtoull(procfile_lineword(ff, l, 5), NULL, 16);
    }

    unsigned long long events = entries + syn_received + cookie_invalid + cookie_valid + cookie_retrans + conn_reopened;

    RRDSET *st;

    // --------------------------------------------------------------------

    if((do_entries == CONFIG_ONDEMAND_ONDEMAND && events) || do_entries == CONFIG_ONDEMAND_YES) {
        do_entries = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 3304, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "entries", NULL, 1, 1, RRDDIM_ABSOLUTE);
        }
        else rrdset_next(st);

        rrddim_set(st, "entries", entries);
        rrdset_done(st);
    }

    // --------------------------------------------------------------------

    if((do_syns == CONFIG_ONDEMAND_ONDEMAND && events) || do_syns == CONFIG_ONDEMAND_YES) {
        do_syns = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s", 3301, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
        }
        else rrdset_next(st);

        rrddim_set(st, "received", syn_received);
        rrdset_done(st);
    }

    // --------------------------------------------------------------------

    if((do_reopened == CONFIG_ONDEMAND_ONDEMAND && events) || do_reopened == CONFIG_ONDEMAND_YES) {
        do_reopened = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened", "connections/s", 3303, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "reopened", NULL, 1, 1, RRDDIM_INCREMENTAL);
        }
        else rrdset_next(st);

        rrddim_set(st, "reopened", conn_reopened);
        rrdset_done(st);
    }

    // --------------------------------------------------------------------

    if((do_cookies == CONFIG_ONDEMAND_ONDEMAND && events) || do_cookies == CONFIG_ONDEMAND_YES) {
        do_cookies = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 3302, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "valid", NULL, 1, 1, RRDDIM_INCREMENTAL);
            rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
            rrddim_add(st, "retransmits", NULL, 1, 1, RRDDIM_INCREMENTAL);
        }
        else rrdset_next(st);

        rrddim_set(st, "valid", cookie_valid);
        rrddim_set(st, "invalid", cookie_invalid);
        rrddim_set(st, "retransmits", cookie_retrans);
        rrdset_done(st);
    }

    return 0;
}
Exemple #19
0
int do_proc_net_netstat(int update_every, unsigned long long dt) {
	static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1;
	static procfile *ff = NULL;

	if(do_bandwidth == -1)	do_bandwidth	= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
	if(do_inerrors == -1)	do_inerrors		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
	if(do_mcast == -1)		do_mcast 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
	if(do_bcast == -1)		do_bcast 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
	if(do_mcast_p == -1)	do_mcast_p 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
	if(do_bcast_p == -1)	do_bcast_p 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat");
		ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
	}
	if(!ff) return 1;

	ff = procfile_readall(ff);
	if(!ff) return 0; // we return 0, so that we will retry to open it next time

	uint32_t lines = procfile_lines(ff), l;
	uint32_t words;

	for(l = 0; l < lines ;l++) {
		if(strcmp(procfile_lineword(ff, l, 0), "IpExt") == 0) {
			l++; // we need the next line

			if(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0) {
				error("Cannot read IpExt line from /proc/net/netstat.");
				break;
			}
			words = procfile_linewords(ff, l);
			if(words < 12) {
				error("Cannot read /proc/net/netstat IpExt line. Expected 12 params, read %d.", words);
				continue;
			}

			unsigned long long
				InNoRoutes = 0, InTruncatedPkts = 0,
				InOctets = 0,  InMcastPkts = 0,  InBcastPkts = 0,  InMcastOctets = 0,  InBcastOctets = 0,
				OutOctets = 0, OutMcastPkts = 0, OutBcastPkts = 0, OutMcastOctets = 0, OutBcastOctets = 0;

			InNoRoutes 			= strtoull(procfile_lineword(ff, l, 1), NULL, 10);
			InTruncatedPkts 	= strtoull(procfile_lineword(ff, l, 2), NULL, 10);
			InMcastPkts 		= strtoull(procfile_lineword(ff, l, 3), NULL, 10);
			OutMcastPkts 		= strtoull(procfile_lineword(ff, l, 4), NULL, 10);
			InBcastPkts 		= strtoull(procfile_lineword(ff, l, 5), NULL, 10);
			OutBcastPkts 		= strtoull(procfile_lineword(ff, l, 6), NULL, 10);
			InOctets 			= strtoull(procfile_lineword(ff, l, 7), NULL, 10);
			OutOctets 			= strtoull(procfile_lineword(ff, l, 8), NULL, 10);
			InMcastOctets 		= strtoull(procfile_lineword(ff, l, 9), NULL, 10);
			OutMcastOctets 		= strtoull(procfile_lineword(ff, l, 10), NULL, 10);
			InBcastOctets 		= strtoull(procfile_lineword(ff, l, 11), NULL, 10);
			OutBcastOctets 		= strtoull(procfile_lineword(ff, l, 12), NULL, 10);

			RRDSET *st;

			// --------------------------------------------------------------------

			if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (InOctets || OutOctets))) {
				do_bandwidth = CONFIG_ONDEMAND_YES;
				st = rrdset_find("system.ipv4");
				if(!st) {
					st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);

					rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
					rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
				}
				else rrdset_next(st);

				rrddim_set(st, "sent", OutOctets);
				rrddim_set(st, "received", InOctets);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (InNoRoutes || InTruncatedPkts))) {
				do_inerrors = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.inerrors");
				if(!st) {
					st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					rrddim_add(st, "noroutes", NULL, 1, 1, RRDDIM_INCREMENTAL);
					rrddim_add(st, "truncated", NULL, 1, 1, RRDDIM_INCREMENTAL);
				}
				else rrdset_next(st);

				rrddim_set(st, "noroutes", InNoRoutes);
				rrddim_set(st, "truncated", InTruncatedPkts);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (InMcastOctets || OutMcastOctets))) {
				do_mcast = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.mcast");
				if(!st) {
					st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
					st->isdetail = 1;

					rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
					rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
				}
				else rrdset_next(st);

				rrddim_set(st, "sent", OutMcastOctets);
				rrddim_set(st, "received", InMcastOctets);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (InBcastOctets || OutBcastOctets))) {
				do_bcast = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.bcast");
				if(!st) {
					st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
					st->isdetail = 1;

					rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
					rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
				}
				else rrdset_next(st);

				rrddim_set(st, "sent", OutBcastOctets);
				rrddim_set(st, "received", InBcastOctets);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (InMcastPkts || OutMcastPkts))) {
				do_mcast_p = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.mcastpkts");
				if(!st) {
					st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
					rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
				}
				else rrdset_next(st);

				rrddim_set(st, "sent", OutMcastPkts);
				rrddim_set(st, "received", InMcastPkts);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (InBcastPkts || OutBcastPkts))) {
				do_bcast_p = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.bcastpkts");
				if(!st) {
					st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
					rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
				}
				else rrdset_next(st);

				rrddim_set(st, "sent", OutBcastPkts);
				rrddim_set(st, "received", InBcastPkts);
				rrdset_done(st);
			}
		}
	}

	return 0;
}
Exemple #20
0
int do_proc_meminfo(int update_every, unsigned long long dt) {
	static procfile *ff = NULL;

	static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1;

	if(do_ram == -1)		do_ram 			= config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1);
	if(do_swap == -1)		do_swap 		= config_get_boolean("plugin:proc:/proc/meminfo", "system swap", 1);
	if(do_hwcorrupt == -1)	do_hwcorrupt 	= config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND);
	if(do_committed == -1)	do_committed 	= config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1);
	if(do_writeback == -1)	do_writeback 	= config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1);
	if(do_kernel == -1)		do_kernel 		= config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1);
	if(do_slab == -1)		do_slab 		= config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/meminfo");
		ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
	}
	if(!ff) return 1;

	ff = procfile_readall(ff);
	if(!ff) return 0; // we return 0, so that we will retry to open it next time

	uint32_t lines = procfile_lines(ff), l;
	uint32_t words;

	int hwcorrupted = 0;

	unsigned long long MemTotal = 0, MemFree = 0, Buffers = 0, Cached = 0, SwapCached = 0,
		Active = 0, Inactive = 0, ActiveAnon = 0, InactiveAnon = 0, ActiveFile = 0, InactiveFile = 0,
		Unevictable = 0, Mlocked = 0, SwapTotal = 0, SwapFree = 0, Dirty = 0, Writeback = 0, AnonPages = 0,
		Mapped = 0, Shmem = 0, Slab = 0, SReclaimable = 0, SUnreclaim = 0, KernelStack = 0, PageTables = 0,
		NFS_Unstable = 0, Bounce = 0, WritebackTmp = 0, CommitLimit = 0, Committed_AS = 0,
		VmallocTotal = 0, VmallocUsed = 0, VmallocChunk = 0,
		AnonHugePages = 0, HugePages_Total = 0, HugePages_Free = 0, HugePages_Rsvd = 0, HugePages_Surp = 0, Hugepagesize = 0,
		DirectMap4k = 0, DirectMap2M = 0, HardwareCorrupted = 0;

	for(l = 0; l < lines ;l++) {
		words = procfile_linewords(ff, l);
		if(words < 2) continue;

		char *name = procfile_lineword(ff, l, 0);
		unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);

		     if(!MemTotal && strcmp(name, "MemTotal") == 0) MemTotal = value;
		else if(!MemFree && strcmp(name, "MemFree") == 0) MemFree = value;
		else if(!Buffers && strcmp(name, "Buffers") == 0) Buffers = value;
		else if(!Cached && strcmp(name, "Cached") == 0) Cached = value;
		else if(!SwapCached && strcmp(name, "SwapCached") == 0) SwapCached = value;
		else if(!Active && strcmp(name, "Active") == 0) Active = value;
		else if(!Inactive && strcmp(name, "Inactive") == 0) Inactive = value;
		else if(!ActiveAnon && strcmp(name, "ActiveAnon") == 0) ActiveAnon = value;
		else if(!InactiveAnon && strcmp(name, "InactiveAnon") == 0) InactiveAnon = value;
		else if(!ActiveFile && strcmp(name, "ActiveFile") == 0) ActiveFile = value;
		else if(!InactiveFile && strcmp(name, "InactiveFile") == 0) InactiveFile = value;
		else if(!Unevictable && strcmp(name, "Unevictable") == 0) Unevictable = value;
		else if(!Mlocked && strcmp(name, "Mlocked") == 0) Mlocked = value;
		else if(!SwapTotal && strcmp(name, "SwapTotal") == 0) SwapTotal = value;
		else if(!SwapFree && strcmp(name, "SwapFree") == 0) SwapFree = value;
		else if(!Dirty && strcmp(name, "Dirty") == 0) Dirty = value;
		else if(!Writeback && strcmp(name, "Writeback") == 0) Writeback = value;
		else if(!AnonPages && strcmp(name, "AnonPages") == 0) AnonPages = value;
		else if(!Mapped && strcmp(name, "Mapped") == 0) Mapped = value;
		else if(!Shmem && strcmp(name, "Shmem") == 0) Shmem = value;
		else if(!Slab && strcmp(name, "Slab") == 0) Slab = value;
		else if(!SReclaimable && strcmp(name, "SReclaimable") == 0) SReclaimable = value;
		else if(!SUnreclaim && strcmp(name, "SUnreclaim") == 0) SUnreclaim = value;
		else if(!KernelStack && strcmp(name, "KernelStack") == 0) KernelStack = value;
		else if(!PageTables && strcmp(name, "PageTables") == 0) PageTables = value;
		else if(!NFS_Unstable && strcmp(name, "NFS_Unstable") == 0) NFS_Unstable = value;
		else if(!Bounce && strcmp(name, "Bounce") == 0) Bounce = value;
		else if(!WritebackTmp && strcmp(name, "WritebackTmp") == 0) WritebackTmp = value;
		else if(!CommitLimit && strcmp(name, "CommitLimit") == 0) CommitLimit = value;
		else if(!Committed_AS && strcmp(name, "Committed_AS") == 0) Committed_AS = value;
		else if(!VmallocTotal && strcmp(name, "VmallocTotal") == 0) VmallocTotal = value;
		else if(!VmallocUsed && strcmp(name, "VmallocUsed") == 0) VmallocUsed = value;
		else if(!VmallocChunk && strcmp(name, "VmallocChunk") == 0) VmallocChunk = value;
		else if(!HardwareCorrupted && strcmp(name, "HardwareCorrupted") == 0) { HardwareCorrupted = value; hwcorrupted = 1; }
		else if(!AnonHugePages && strcmp(name, "AnonHugePages") == 0) AnonHugePages = value;
		else if(!HugePages_Total && strcmp(name, "HugePages_Total") == 0) HugePages_Total = value;
		else if(!HugePages_Free && strcmp(name, "HugePages_Free") == 0) HugePages_Free = value;
		else if(!HugePages_Rsvd && strcmp(name, "HugePages_Rsvd") == 0) HugePages_Rsvd = value;
		else if(!HugePages_Surp && strcmp(name, "HugePages_Surp") == 0) HugePages_Surp = value;
		else if(!Hugepagesize && strcmp(name, "Hugepagesize") == 0) Hugepagesize = value;
		else if(!DirectMap4k && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value;
		else if(!DirectMap2M && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value;
	}

	RRDSET *st;

	// --------------------------------------------------------------------

	// http://stackoverflow.com/questions/3019748/how-to-reliably-measure-available-memory-in-linux
	unsigned long long MemUsed = MemTotal - MemFree - Cached - Buffers;

	if(do_ram) {
		st = rrdset_find("system.ram");
		if(!st) {
			st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED);

			rrddim_add(st, "buffers", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "used",    NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "cached",  NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "free",    NULL, 1, 1024, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "used", MemUsed);
		rrddim_set(st, "free", MemFree);
		rrddim_set(st, "cached", Cached);
		rrddim_set(st, "buffers", Buffers);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	unsigned long long SwapUsed = SwapTotal - SwapFree;

	if(do_swap) {
		st = rrdset_find("system.swap");
		if(!st) {
			st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
			st->isdetail = 1;

			rrddim_add(st, "free",    NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "used",    NULL, 1, 1024, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "used", SwapUsed);
		rrddim_set(st, "free", SwapFree);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(hwcorrupted && do_hwcorrupt && HardwareCorrupted > 0) {
		do_hwcorrupt = CONFIG_ONDEMAND_YES;

		st = rrdset_find("mem.hwcorrupt");
		if(!st) {
			st = rrdset_create("mem", "hwcorrupt", NULL, "errors", NULL, "Hardware Corrupted ECC", "MB", 9000, update_every, RRDSET_TYPE_LINE);
			st->isdetail = 1;

			rrddim_add(st, "HardwareCorrupted", NULL, 1, 1024, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "HardwareCorrupted", HardwareCorrupted);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_committed) {
		st = rrdset_find("mem.committed");
		if(!st) {
			st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA);
			st->isdetail = 1;

			rrddim_add(st, "Committed_AS", NULL, 1, 1024, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "Committed_AS", Committed_AS);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_writeback) {
		st = rrdset_find("mem.writeback");
		if(!st) {
			st = rrdset_create("mem", "writeback", NULL, "kernel", NULL, "Writeback Memory", "MB", 4000, update_every, RRDSET_TYPE_LINE);
			st->isdetail = 1;

			rrddim_add(st, "Dirty", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "Writeback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "FuseWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "NfsWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "Bounce", NULL, 1, 1024, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "Dirty", Dirty);
		rrddim_set(st, "Writeback", Writeback);
		rrddim_set(st, "FuseWriteback", WritebackTmp);
		rrddim_set(st, "NfsWriteback", NFS_Unstable);
		rrddim_set(st, "Bounce", Bounce);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_kernel) {
		st = rrdset_find("mem.kernel");
		if(!st) {
			st = rrdset_create("mem", "kernel", NULL, "kernel", NULL, "Memory Used by Kernel", "MB", 6000, update_every, RRDSET_TYPE_STACKED);
			st->isdetail = 1;

			rrddim_add(st, "Slab", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "KernelStack", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "PageTables", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "VmallocUsed", NULL, 1, 1024, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "KernelStack", KernelStack);
		rrddim_set(st, "Slab", Slab);
		rrddim_set(st, "PageTables", PageTables);
		rrddim_set(st, "VmallocUsed", VmallocUsed);
		rrdset_done(st);
	}

	// --------------------------------------------------------------------

	if(do_slab) {
		st = rrdset_find("mem.slab");
		if(!st) {
			st = rrdset_create("mem", "slab", NULL, "slab", NULL, "Reclaimable Kernel Memory", "MB", 6500, update_every, RRDSET_TYPE_STACKED);
			st->isdetail = 1;

			rrddim_add(st, "reclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE);
			rrddim_add(st, "unreclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE);
		}
		else rrdset_next(st);

		rrddim_set(st, "reclaimable", SReclaimable);
		rrddim_set(st, "unreclaimable", SUnreclaim);
		rrdset_done(st);
	}

	return 0;
}
Exemple #21
0
int do_macos_mach_smi(int update_every, usec_t dt) {
    (void)dt;

    static int do_cpu = -1, do_ram = - 1, do_swapio = -1, do_pgfaults = -1;

    if (unlikely(do_cpu == -1)) {
        do_cpu                  = config_get_boolean("plugin:macos:mach_smi", "cpu utilization", 1);
        do_ram                  = config_get_boolean("plugin:macos:mach_smi", "system ram", 1);
        do_swapio               = config_get_boolean("plugin:macos:mach_smi", "swap i/o", 1);
        do_pgfaults             = config_get_boolean("plugin:macos:mach_smi", "memory page faults", 1);
    }

    RRDSET *st;

	kern_return_t kr;
	mach_msg_type_number_t count;
    host_t host;
    vm_size_t system_pagesize;


    // NEEDED BY: do_cpu
    natural_t cp_time[CPU_STATE_MAX];

    // NEEDED BY: do_ram, do_swapio, do_pgfaults
    vm_statistics64_data_t vm_statistics;

    host = mach_host_self();
    kr = host_page_size(host, &system_pagesize);
    if (unlikely(kr != KERN_SUCCESS))
        return -1;

    // --------------------------------------------------------------------

    if (likely(do_cpu)) {
        if (unlikely(HOST_CPU_LOAD_INFO_COUNT != 4)) {
            error("MACOS: There are %d CPU states (4 was expected)", HOST_CPU_LOAD_INFO_COUNT);
            do_cpu = 0;
            error("DISABLED: system.cpu");
        } else {
            count = HOST_CPU_LOAD_INFO_COUNT;
            kr = host_statistics(host, HOST_CPU_LOAD_INFO, (host_info_t)cp_time, &count);
            if (unlikely(kr != KERN_SUCCESS)) {
                error("MACOS: host_statistics() failed: %s", mach_error_string(kr));
                do_cpu = 0;
                error("DISABLED: system.cpu");
            } else {

                st = rrdset_find_bytype("system", "cpu");
                if (unlikely(!st)) {
                    st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED);

                    rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
                    rrddim_add(st, "nice", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
                    rrddim_add(st, "system", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
                    rrddim_add(st, "idle", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
                    rrddim_hide(st, "idle");
                }
                else rrdset_next(st);

                rrddim_set(st, "user", cp_time[CPU_STATE_USER]);
                rrddim_set(st, "nice", cp_time[CPU_STATE_NICE]);
                rrddim_set(st, "system", cp_time[CPU_STATE_SYSTEM]);
                rrddim_set(st, "idle", cp_time[CPU_STATE_IDLE]);
                rrdset_done(st);
            }
        }
     }

    // --------------------------------------------------------------------
    
    if (likely(do_ram || do_swapio || do_pgfaults)) {
        count = sizeof(vm_statistics64_data_t);
        kr = host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vm_statistics, &count);
        if (unlikely(kr != KERN_SUCCESS)) {
            error("MACOS: host_statistics64() failed: %s", mach_error_string(kr));
            do_ram = 0;
            error("DISABLED: system.ram");
            do_swapio = 0;
            error("DISABLED: system.swapio");
            do_pgfaults = 0;
            error("DISABLED: mem.pgfaults");
        } else {
            if (likely(do_ram)) {
                st = rrdset_find("system.ram");
                if (unlikely(!st)) {
                    st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED);

                    rrddim_add(st, "active",    NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                    rrddim_add(st, "wired",     NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                    rrddim_add(st, "throttled", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                    rrddim_add(st, "compressor", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                    rrddim_add(st, "inactive",  NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                    rrddim_add(st, "purgeable", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                    rrddim_add(st, "speculative", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                    rrddim_add(st, "free",      NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
                }
                else rrdset_next(st);

                rrddim_set(st, "active",    vm_statistics.active_count);
                rrddim_set(st, "wired",     vm_statistics.wire_count);
                rrddim_set(st, "throttled", vm_statistics.throttled_count);
                rrddim_set(st, "compressor", vm_statistics.compressor_page_count);
                rrddim_set(st, "inactive",  vm_statistics.inactive_count);
                rrddim_set(st, "purgeable", vm_statistics.purgeable_count);
                rrddim_set(st, "speculative", vm_statistics.speculative_count);
                rrddim_set(st, "free",      (vm_statistics.free_count - vm_statistics.speculative_count));
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if (likely(do_swapio)) {
                st = rrdset_find("system.swapio");
                if (unlikely(!st)) {
                    st = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);

                    rrddim_add(st, "in",  NULL, system_pagesize, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "in", vm_statistics.swapins);
                rrddim_set(st, "out", vm_statistics.swapouts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if (likely(do_pgfaults)) {
                st = rrdset_find("mem.pgfaults");
                if (unlikely(!st)) {
                    st = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "memory",    NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "cow",       NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "pagein",    NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "pageout",   NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "compress",  NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "decompress", NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "zero_fill", NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "reactivate", NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "purge",     NULL, 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "memory", vm_statistics.faults);
                rrddim_set(st, "cow", vm_statistics.cow_faults);
                rrddim_set(st, "pagein", vm_statistics.pageins);
                rrddim_set(st, "pageout", vm_statistics.pageouts);
                rrddim_set(st, "compress", vm_statistics.compressions);
                rrddim_set(st, "decompress", vm_statistics.decompressions);
                rrddim_set(st, "zero_fill", vm_statistics.zero_fill_count);
                rrddim_set(st, "reactivate", vm_statistics.reactivations);
                rrddim_set(st, "purge", vm_statistics.purges);
                rrdset_done(st);
            }
        }
    } 
 
    // --------------------------------------------------------------------

    return 0;
}