コード例 #1
0
int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt) {
    (void)dt;

    static procfile *ff = NULL;
    static ARL_BASE *arl_base = NULL;

    arcstats.l2exist = -1;

    if(unlikely(!arl_base)) {
        arl_base = arl_create("arcstats", NULL, 60);

        arl_expect(arl_base, "hits", &arcstats.hits);
        arl_expect(arl_base, "misses", &arcstats.misses);
        arl_expect(arl_base, "demand_data_hits", &arcstats.demand_data_hits);
        arl_expect(arl_base, "demand_data_misses", &arcstats.demand_data_misses);
        arl_expect(arl_base, "demand_metadata_hits", &arcstats.demand_metadata_hits);
        arl_expect(arl_base, "demand_metadata_misses", &arcstats.demand_metadata_misses);
        arl_expect(arl_base, "prefetch_data_hits", &arcstats.prefetch_data_hits);
        arl_expect(arl_base, "prefetch_data_misses", &arcstats.prefetch_data_misses);
        arl_expect(arl_base, "prefetch_metadata_hits", &arcstats.prefetch_metadata_hits);
        arl_expect(arl_base, "prefetch_metadata_misses", &arcstats.prefetch_metadata_misses);
        arl_expect(arl_base, "mru_hits", &arcstats.mru_hits);
        arl_expect(arl_base, "mru_ghost_hits", &arcstats.mru_ghost_hits);
        arl_expect(arl_base, "mfu_hits", &arcstats.mfu_hits);
        arl_expect(arl_base, "mfu_ghost_hits", &arcstats.mfu_ghost_hits);
        arl_expect(arl_base, "deleted", &arcstats.deleted);
        arl_expect(arl_base, "mutex_miss", &arcstats.mutex_miss);
        arl_expect(arl_base, "evict_skip", &arcstats.evict_skip);
        arl_expect(arl_base, "evict_not_enough", &arcstats.evict_not_enough);
        arl_expect(arl_base, "evict_l2_cached", &arcstats.evict_l2_cached);
        arl_expect(arl_base, "evict_l2_eligible", &arcstats.evict_l2_eligible);
        arl_expect(arl_base, "evict_l2_ineligible", &arcstats.evict_l2_ineligible);
        arl_expect(arl_base, "evict_l2_skip", &arcstats.evict_l2_skip);
        arl_expect(arl_base, "hash_elements", &arcstats.hash_elements);
        arl_expect(arl_base, "hash_elements_max", &arcstats.hash_elements_max);
        arl_expect(arl_base, "hash_collisions", &arcstats.hash_collisions);
        arl_expect(arl_base, "hash_chains", &arcstats.hash_chains);
        arl_expect(arl_base, "hash_chain_max", &arcstats.hash_chain_max);
        arl_expect(arl_base, "p", &arcstats.p);
        arl_expect(arl_base, "c", &arcstats.c);
        arl_expect(arl_base, "c_min", &arcstats.c_min);
        arl_expect(arl_base, "c_max", &arcstats.c_max);
        arl_expect(arl_base, "size", &arcstats.size);
        arl_expect(arl_base, "hdr_size", &arcstats.hdr_size);
        arl_expect(arl_base, "data_size", &arcstats.data_size);
        arl_expect(arl_base, "metadata_size", &arcstats.metadata_size);
        arl_expect(arl_base, "other_size", &arcstats.other_size);
        arl_expect(arl_base, "anon_size", &arcstats.anon_size);
        arl_expect(arl_base, "anon_evictable_data", &arcstats.anon_evictable_data);
        arl_expect(arl_base, "anon_evictable_metadata", &arcstats.anon_evictable_metadata);
        arl_expect(arl_base, "mru_size", &arcstats.mru_size);
        arl_expect(arl_base, "mru_evictable_data", &arcstats.mru_evictable_data);
        arl_expect(arl_base, "mru_evictable_metadata", &arcstats.mru_evictable_metadata);
        arl_expect(arl_base, "mru_ghost_size", &arcstats.mru_ghost_size);
        arl_expect(arl_base, "mru_ghost_evictable_data", &arcstats.mru_ghost_evictable_data);
        arl_expect(arl_base, "mru_ghost_evictable_metadata", &arcstats.mru_ghost_evictable_metadata);
        arl_expect(arl_base, "mfu_size", &arcstats.mfu_size);
        arl_expect(arl_base, "mfu_evictable_data", &arcstats.mfu_evictable_data);
        arl_expect(arl_base, "mfu_evictable_metadata", &arcstats.mfu_evictable_metadata);
        arl_expect(arl_base, "mfu_ghost_size", &arcstats.mfu_ghost_size);
        arl_expect(arl_base, "mfu_ghost_evictable_data", &arcstats.mfu_ghost_evictable_data);
        arl_expect(arl_base, "mfu_ghost_evictable_metadata", &arcstats.mfu_ghost_evictable_metadata);
        arl_expect(arl_base, "l2_hits", &arcstats.l2_hits);
        arl_expect(arl_base, "l2_misses", &arcstats.l2_misses);
        arl_expect(arl_base, "l2_feeds", &arcstats.l2_feeds);
        arl_expect(arl_base, "l2_rw_clash", &arcstats.l2_rw_clash);
        arl_expect(arl_base, "l2_read_bytes", &arcstats.l2_read_bytes);
        arl_expect(arl_base, "l2_write_bytes", &arcstats.l2_write_bytes);
        arl_expect(arl_base, "l2_writes_sent", &arcstats.l2_writes_sent);
        arl_expect(arl_base, "l2_writes_done", &arcstats.l2_writes_done);
        arl_expect(arl_base, "l2_writes_error", &arcstats.l2_writes_error);
        arl_expect(arl_base, "l2_writes_lock_retry", &arcstats.l2_writes_lock_retry);
        arl_expect(arl_base, "l2_evict_lock_retry", &arcstats.l2_evict_lock_retry);
        arl_expect(arl_base, "l2_evict_reading", &arcstats.l2_evict_reading);
        arl_expect(arl_base, "l2_evict_l1cached", &arcstats.l2_evict_l1cached);
        arl_expect(arl_base, "l2_free_on_write", &arcstats.l2_free_on_write);
        arl_expect(arl_base, "l2_cdata_free_on_write", &arcstats.l2_cdata_free_on_write);
        arl_expect(arl_base, "l2_abort_lowmem", &arcstats.l2_abort_lowmem);
        arl_expect(arl_base, "l2_cksum_bad", &arcstats.l2_cksum_bad);
        arl_expect(arl_base, "l2_io_error", &arcstats.l2_io_error);
        arl_expect(arl_base, "l2_size", &arcstats.l2_size);
        arl_expect(arl_base, "l2_asize", &arcstats.l2_asize);
        arl_expect(arl_base, "l2_hdr_size", &arcstats.l2_hdr_size);
        arl_expect(arl_base, "l2_compress_successes", &arcstats.l2_compress_successes);
        arl_expect(arl_base, "l2_compress_zeros", &arcstats.l2_compress_zeros);
        arl_expect(arl_base, "l2_compress_failures", &arcstats.l2_compress_failures);
        arl_expect(arl_base, "memory_throttle_count", &arcstats.memory_throttle_count);
        arl_expect(arl_base, "duplicate_buffers", &arcstats.duplicate_buffers);
        arl_expect(arl_base, "duplicate_buffers_size", &arcstats.duplicate_buffers_size);
        arl_expect(arl_base, "duplicate_reads", &arcstats.duplicate_reads);
        arl_expect(arl_base, "memory_direct_count", &arcstats.memory_direct_count);
        arl_expect(arl_base, "memory_indirect_count", &arcstats.memory_indirect_count);
        arl_expect(arl_base, "arc_no_grow", &arcstats.arc_no_grow);
        arl_expect(arl_base, "arc_tempreserve", &arcstats.arc_tempreserve);
        arl_expect(arl_base, "arc_loaned_bytes", &arcstats.arc_loaned_bytes);
        arl_expect(arl_base, "arc_prune", &arcstats.arc_prune);
        arl_expect(arl_base, "arc_meta_used", &arcstats.arc_meta_used);
        arl_expect(arl_base, "arc_meta_limit", &arcstats.arc_meta_limit);
        arl_expect(arl_base, "arc_meta_max", &arcstats.arc_meta_max);
        arl_expect(arl_base, "arc_meta_min", &arcstats.arc_meta_min);
        arl_expect(arl_base, "arc_need_free", &arcstats.arc_need_free);
        arl_expect(arl_base, "arc_sys_free", &arcstats.arc_sys_free);
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, ZFS_PROC_ARCSTATS);
        ff = procfile_open(config_get("plugin:proc:" ZFS_PROC_ARCSTATS, "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;

    arl_begin(arl_base);

    for(l = 0; l < lines ;l++) {
        size_t words = procfile_linewords(ff, l);
        if(unlikely(words < 3)) {
            if(unlikely(words)) error("Cannot read " ZFS_PROC_ARCSTATS " line %zu. Expected 3 params, read %zu.", l, words);
            continue;
        }

        const char *key   = procfile_lineword(ff, l, 0);
        const char *value = procfile_lineword(ff, l, 2);

        if(unlikely(arcstats.l2exist == -1)) {
            if(key[0] == 'l' && key[1] == '2' && key[2] == '_')
                arcstats.l2exist = 1;
        }

        if(unlikely(arl_check(arl_base, key, value))) break;
    }

    if(unlikely(arcstats.l2exist == -1))
        arcstats.l2exist = 0;

    generate_charts_arcstats("proc", update_every);
    generate_charts_arc_summary("proc", update_every);

    return 0;
}
コード例 #2
0
ファイル: proc_vmstat.c プロジェクト: dvigne/netdata
int do_proc_vmstat(int update_every, usec_t dt) {
    (void)dt;

    static procfile *ff = NULL;
    static int do_swapio = -1, do_io = -1, do_pgfaults = -1, do_numa = -1;
    static int has_numa = -1;

    static ARL_BASE *arl_base = NULL;
    static unsigned long long numa_foreign = 0ULL;
    static unsigned long long numa_hint_faults = 0ULL;
    static unsigned long long numa_hint_faults_local = 0ULL;
    static unsigned long long numa_huge_pte_updates = 0ULL;
    static unsigned long long numa_interleave = 0ULL;
    static unsigned long long numa_local = 0ULL;
    static unsigned long long numa_other = 0ULL;
    static unsigned long long numa_pages_migrated = 0ULL;
    static unsigned long long numa_pte_updates = 0ULL;
    static unsigned long long pgfault = 0ULL;
    static unsigned long long pgmajfault = 0ULL;
    static unsigned long long pgpgin = 0ULL;
    static unsigned long long pgpgout = 0ULL;
    static unsigned long long pswpin = 0ULL;
    static unsigned long long pswpout = 0ULL;

    if(unlikely(!arl_base)) {
        do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_BOOLEAN_AUTO);
        do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
        do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1);
        do_numa = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "system-wide numa metric summary", CONFIG_BOOLEAN_AUTO);


        arl_base = arl_create("vmstat", NULL, 60);
        arl_expect(arl_base, "pgfault", &pgfault);
        arl_expect(arl_base, "pgmajfault", &pgmajfault);
        arl_expect(arl_base, "pgpgin", &pgpgin);
        arl_expect(arl_base, "pgpgout", &pgpgout);
        arl_expect(arl_base, "pswpin", &pswpin);
        arl_expect(arl_base, "pswpout", &pswpout);

        if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && get_numa_node_count() >= 2)) {
            arl_expect(arl_base, "numa_foreign", &numa_foreign);
            arl_expect(arl_base, "numa_hint_faults_local", &numa_hint_faults_local);
            arl_expect(arl_base, "numa_hint_faults", &numa_hint_faults);
            arl_expect(arl_base, "numa_huge_pte_updates", &numa_huge_pte_updates);
            arl_expect(arl_base, "numa_interleave", &numa_interleave);
            arl_expect(arl_base, "numa_local", &numa_local);
            arl_expect(arl_base, "numa_other", &numa_other);
            arl_expect(arl_base, "numa_pages_migrated", &numa_pages_migrated);
            arl_expect(arl_base, "numa_pte_updates", &numa_pte_updates);
        }
        else {
            // Do not expect numa metrics when they are not needed.
            // By not adding them, the ARL will stop processing the file
            // when all the expected metrics are collected.
            // Also ARL will not parse their values.
            has_numa = 0;
            do_numa = CONFIG_BOOLEAN_NO;
        }
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/vmstat");
        ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "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;

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

        if(unlikely(arl_check(arl_base,
                procfile_lineword(ff, l, 0),
                procfile_lineword(ff, l, 1)))) break;
    }

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

    if(pswpin || pswpout || do_swapio == CONFIG_BOOLEAN_YES) {
        do_swapio = CONFIG_BOOLEAN_YES;

        static RRDSET *st_swapio = NULL;
        static RRDDIM *rd_in = NULL, *rd_out = NULL;

        if(unlikely(!st_swapio)) {
            st_swapio = rrdset_create_localhost(
                    "system"
                    , "swapio"
                    , NULL
                    , "swap"
                    , NULL
                    , "Swap I/O"
                    , "kilobytes/s"
                    , 250
                    , update_every
                    , RRDSET_TYPE_AREA
            );

            rd_in  = rrddim_add(st_swapio, "in",  NULL,  sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
            rd_out = rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
        }
        else rrdset_next(st_swapio);

        rrddim_set_by_pointer(st_swapio, rd_in, pswpin);
        rrddim_set_by_pointer(st_swapio, rd_out, pswpout);
        rrdset_done(st_swapio);
    }

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

    if(do_io) {
        static RRDSET *st_io = NULL;
        static RRDDIM *rd_in = NULL, *rd_out = NULL;

        if(unlikely(!st_io)) {
            st_io = rrdset_create_localhost(
                    "system"
                    , "io"
                    , NULL
                    , "disk"
                    , NULL
                    , "Disk I/O"
                    , "kilobytes/s"
                    , 150
                    , update_every
                    , RRDSET_TYPE_AREA
            );

            rd_in  = rrddim_add(st_io, "in",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_out = rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
        }
        else rrdset_next(st_io);

        rrddim_set_by_pointer(st_io, rd_in, pgpgin);
        rrddim_set_by_pointer(st_io, rd_out, pgpgout);
        rrdset_done(st_io);
    }

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

    if(do_pgfaults) {
        static RRDSET *st_pgfaults = NULL;
        static RRDDIM *rd_minor = NULL, *rd_major = NULL;

        if(unlikely(!st_pgfaults)) {
            st_pgfaults = rrdset_create_localhost(
                    "mem"
                    , "pgfaults"
                    , NULL
                    , "system"
                    , NULL
                    , "Memory Page Faults"
                    , "page faults/s"
                    , 500
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rrdset_flag_set(st_pgfaults, RRDSET_FLAG_DETAIL);

            rd_minor = rrddim_add(st_pgfaults, "minor", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_major = rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
        }
        else rrdset_next(st_pgfaults);

        rrddim_set_by_pointer(st_pgfaults, rd_minor, pgfault);
        rrddim_set_by_pointer(st_pgfaults, rd_major, pgmajfault);
        rrdset_done(st_pgfaults);
    }

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

    // Ondemand criteria for NUMA. Since this won't change at run time, we
    // check it only once. We check whether the node count is >= 2 because
    // single-node systems have uninteresting statistics (since all accesses
    // are local).
    if(unlikely(has_numa == -1))

        has_numa = (numa_local || numa_foreign || numa_interleave || numa_other || numa_pte_updates ||
                     numa_huge_pte_updates || numa_hint_faults || numa_hint_faults_local || numa_pages_migrated) ? 1 : 0;

    if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && has_numa)) {
        do_numa = CONFIG_BOOLEAN_YES;

        static RRDSET *st_numa = NULL;
        static RRDDIM *rd_local = NULL, *rd_foreign = NULL, *rd_interleave = NULL, *rd_other = NULL, *rd_pte_updates = NULL, *rd_huge_pte_updates = NULL, *rd_hint_faults = NULL, *rd_hint_faults_local = NULL, *rd_pages_migrated = NULL;

        if(unlikely(!st_numa)) {
            st_numa = rrdset_create_localhost(
                    "mem"
                    , "numa"
                    , NULL
                    , "numa"
                    , NULL
                    , "NUMA events"
                    , "events/s"
                    , 800
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rrdset_flag_set(st_numa, RRDSET_FLAG_DETAIL);

            // These depend on CONFIG_NUMA in the kernel.
            rd_local             = rrddim_add(st_numa, "local",             NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_foreign           = rrddim_add(st_numa, "foreign",           NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_interleave        = rrddim_add(st_numa, "interleave",        NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_other             = rrddim_add(st_numa, "other",             NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);

            // The following stats depend on CONFIG_NUMA_BALANCING in the
            // kernel.
            rd_pte_updates       = rrddim_add(st_numa, "pte_updates",       NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_huge_pte_updates  = rrddim_add(st_numa, "huge_pte_updates",  NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_hint_faults       = rrddim_add(st_numa, "hint_faults",       NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_hint_faults_local = rrddim_add(st_numa, "hint_faults_local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            rd_pages_migrated    = rrddim_add(st_numa, "pages_migrated",    NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
        }
        else rrdset_next(st_numa);

        rrddim_set_by_pointer(st_numa, rd_local,             numa_local);
        rrddim_set_by_pointer(st_numa, rd_foreign,           numa_foreign);
        rrddim_set_by_pointer(st_numa, rd_interleave,        numa_interleave);
        rrddim_set_by_pointer(st_numa, rd_other,             numa_other);

        rrddim_set_by_pointer(st_numa, rd_pte_updates,       numa_pte_updates);
        rrddim_set_by_pointer(st_numa, rd_huge_pte_updates,  numa_huge_pte_updates);
        rrddim_set_by_pointer(st_numa, rd_hint_faults,       numa_hint_faults);
        rrddim_set_by_pointer(st_numa, rd_hint_faults_local, numa_hint_faults_local);
        rrddim_set_by_pointer(st_numa, rd_pages_migrated,    numa_pages_migrated);

        rrdset_done(st_numa);
    }

    return 0;
}
コード例 #3
0
ファイル: proc_net_netstat.c プロジェクト: cppmx/netdata
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,
        do_tcpext_listen = -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

    // https://perfchron.com/2015/12/26/investigating-linux-network-issues-with-netstat-and-nstat/
    static unsigned long long tcpext_ListenOverflows = 0;   // times the listen queue of a socket overflowed
    static unsigned long long tcpext_ListenDrops = 0;       // SYNs to LISTEN sockets ignored

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

    // shared: tcpext_TCPSynRetrans


    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_BOOLEAN_AUTO);
        do_inerrors  = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_BOOLEAN_AUTO);
        do_mcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_BOOLEAN_AUTO);
        do_bcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO);
        do_mcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_BOOLEAN_AUTO);
        do_bcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_BOOLEAN_AUTO);
        do_ecn       = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_BOOLEAN_AUTO);

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

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

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

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

        if(do_inerrors != CONFIG_BOOLEAN_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_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InMcastOctets", &ipext_InMcastOctets);
            arl_expect(arl_ipext, "OutMcastOctets", &ipext_OutMcastOctets);
        }

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

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

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

        if(do_ecn != CONFIG_BOOLEAN_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_BOOLEAN_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_BOOLEAN_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_BOOLEAN_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_BOOLEAN_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_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures);
        }

        if(do_tcpext_listen != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "ListenOverflows", &tcpext_ListenOverflows);
            arl_expect(arl_tcpext, "ListenDrops",     &tcpext_ListenDrops);
        }

        // shared metrics
        arl_expect(arl_tcpext, "TCPSynRetrans", &tcpext_TCPSynRetrans);
    }

    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);

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

            if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (ipext_InOctets || ipext_OutOctets))) {
                do_bandwidth = CONFIG_BOOLEAN_YES;
                static RRDSET *st_system_ipv4 = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_system_ipv4)) {
                    st_system_ipv4 = rrdset_create_localhost(
                            "system"
                            , "ipv4"
                            , NULL
                            , "network"
                            , NULL
                            , "IPv4 Bandwidth"
                            , "kilobits/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_SYSTEM_IPV4
                            , update_every
                            , RRDSET_TYPE_AREA
                    );

                    rd_in  = rrddim_add(st_system_ipv4, "InOctets",  "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_system_ipv4, "OutOctets", "sent",    -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_system_ipv4);

                rrddim_set_by_pointer(st_system_ipv4, rd_in,  ipext_InOctets);
                rrddim_set_by_pointer(st_system_ipv4, rd_out, ipext_OutOctets);

                rrdset_done(st_system_ipv4);
            }

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

            if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && (ipext_InNoRoutes || ipext_InTruncatedPkts))) {
                do_inerrors = CONFIG_BOOLEAN_YES;
                static RRDSET *st_ipv4_inerrors = NULL;
                static RRDDIM *rd_noroutes = NULL, *rd_truncated = NULL, *rd_checksum = NULL;

                if(unlikely(!st_ipv4_inerrors)) {
                    st_ipv4_inerrors = rrdset_create_localhost(
                            "ipv4"
                            , "inerrors"
                            , NULL
                            , "errors"
                            , NULL
                            , "IPv4 Input Errors"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_ERRORS
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ipv4_inerrors, RRDSET_FLAG_DETAIL);

                    rd_noroutes  = rrddim_add(st_ipv4_inerrors, "InNoRoutes",      "noroutes",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_truncated = rrddim_add(st_ipv4_inerrors, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_checksum  = rrddim_add(st_ipv4_inerrors, "InCsumErrors",    "checksum",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_inerrors);

                rrddim_set_by_pointer(st_ipv4_inerrors, rd_noroutes,  ipext_InNoRoutes);
                rrddim_set_by_pointer(st_ipv4_inerrors, rd_truncated, ipext_InTruncatedPkts);
                rrddim_set_by_pointer(st_ipv4_inerrors, rd_checksum,  ipext_InCsumErrors);

                rrdset_done(st_ipv4_inerrors);
            }

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

            if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (ipext_InMcastOctets || ipext_OutMcastOctets))) {
                do_mcast = CONFIG_BOOLEAN_YES;
                static RRDSET *st_ipv4_mcast = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_mcast)) {
                    st_ipv4_mcast = rrdset_create_localhost(
                            "ipv4"
                            , "mcast"
                            , NULL
                            , "multicast"
                            , NULL
                            , "IPv4 Multicast Bandwidth"
                            , "kilobits/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_MCAST
                            , update_every
                            , RRDSET_TYPE_AREA
                    );

                    rrdset_flag_set(st_ipv4_mcast, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_mcast, "InMcastOctets",  "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_mcast, "OutMcastOctets", "sent",    -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_mcast);

                rrddim_set_by_pointer(st_ipv4_mcast, rd_in,  ipext_InMcastOctets);
                rrddim_set_by_pointer(st_ipv4_mcast, rd_out, ipext_OutMcastOctets);

                rrdset_done(st_ipv4_mcast);
            }

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

            if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (ipext_InBcastOctets || ipext_OutBcastOctets))) {
                do_bcast = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_bcast = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_bcast)) {
                    st_ipv4_bcast = rrdset_create_localhost(
                            "ipv4"
                            , "bcast"
                            , NULL
                            , "broadcast"
                            , NULL
                            , "IPv4 Broadcast Bandwidth"
                            , "kilobits/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_BCAST
                            , update_every
                            , RRDSET_TYPE_AREA
                    );

                    rrdset_flag_set(st_ipv4_bcast, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_bcast, "InBcastOctets",  "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_bcast, "OutBcastOctets", "sent",    -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_bcast);

                rrddim_set_by_pointer(st_ipv4_bcast, rd_in,  ipext_InBcastOctets);
                rrddim_set_by_pointer(st_ipv4_bcast, rd_out, ipext_OutBcastOctets);

                rrdset_done(st_ipv4_bcast);
            }

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

            if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InMcastPkts || ipext_OutMcastPkts))) {
                do_mcast_p = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_mcastpkts = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_mcastpkts)) {
                    st_ipv4_mcastpkts = rrdset_create_localhost(
                            "ipv4"
                            , "mcastpkts"
                            , NULL
                            , "multicast"
                            , NULL
                            , "IPv4 Multicast Packets"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_MCAST + 10
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ipv4_mcastpkts, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_mcastpkts, "InMcastPkts",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_mcastpkts, "OutMcastPkts", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_ipv4_mcastpkts);

                rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_in,  ipext_InMcastPkts);
                rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_out, ipext_OutMcastPkts);

                rrdset_done(st_ipv4_mcastpkts);
            }

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

            if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InBcastPkts || ipext_OutBcastPkts))) {
                do_bcast_p = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_bcastpkts = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_bcastpkts)) {
                    st_ipv4_bcastpkts = rrdset_create_localhost(
                            "ipv4"
                            , "bcastpkts"
                            , NULL
                            , "broadcast"
                            , NULL
                            , "IPv4 Broadcast Packets"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_BCAST + 10
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ipv4_bcastpkts, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_bcastpkts, "InBcastPkts",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_bcastpkts, "OutBcastPkts", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_bcastpkts);

                rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_in,  ipext_InBcastPkts);
                rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_out, ipext_OutBcastPkts);

                rrdset_done(st_ipv4_bcastpkts);
            }

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

            if(do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) {
                do_ecn = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ecnpkts = NULL;
                static RRDDIM *rd_cep = NULL, *rd_noectp = NULL, *rd_ectp0 = NULL, *rd_ectp1 = NULL;

                if(unlikely(!st_ecnpkts)) {
                    st_ecnpkts = rrdset_create_localhost(
                            "ipv4"
                            , "ecnpkts"
                            , NULL
                            , "ecn"
                            , NULL
                            , "IPv4 ECN Statistics"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_ECN
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ecnpkts, RRDSET_FLAG_DETAIL);

                    rd_cep    = rrddim_add(st_ecnpkts, "InCEPkts",    "CEP",     1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_noectp = rrddim_add(st_ecnpkts, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_ectp0  = rrddim_add(st_ecnpkts, "InECT0Pkts",  "ECTP0",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_ectp1  = rrddim_add(st_ecnpkts, "InECT1Pkts",  "ECTP1",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_ecnpkts);

                rrddim_set_by_pointer(st_ecnpkts, rd_cep,    ipext_InCEPkts);
                rrddim_set_by_pointer(st_ecnpkts, rd_noectp, ipext_InNoECTPkts);
                rrddim_set_by_pointer(st_ecnpkts, rd_ectp0,  ipext_InECT0Pkts);
                rrddim_set_by_pointer(st_ecnpkts, rd_ectp1,  ipext_InECT1Pkts);

                rrdset_done(st_ecnpkts);
            }
        }
        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);

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

            if(do_tcpext_memory == CONFIG_BOOLEAN_YES || (do_tcpext_memory == CONFIG_BOOLEAN_AUTO && (tcpext_TCPMemoryPressures))) {
                do_tcpext_memory = CONFIG_BOOLEAN_YES;

                static RRDSET *st_tcpmemorypressures = NULL;
                static RRDDIM *rd_pressures = NULL;

                if(unlikely(!st_tcpmemorypressures)) {
                    st_tcpmemorypressures = rrdset_create_localhost(
                            "ipv4"
                            , "tcpmemorypressures"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Memory Pressures"
                            , "events/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP_MEM
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_pressures = rrddim_add(st_tcpmemorypressures, "TCPMemoryPressures",   "pressures",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_tcpmemorypressures);

                rrddim_set_by_pointer(st_tcpmemorypressures, rd_pressures, tcpext_TCPMemoryPressures);

                rrdset_done(st_tcpmemorypressures);
            }

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

            if(do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) {
                do_tcpext_connaborts = CONFIG_BOOLEAN_YES;

                static RRDSET *st_tcpconnaborts = NULL;
                static RRDDIM *rd_baddata = NULL, *rd_userclosed = NULL, *rd_nomemory = NULL, *rd_timeout = NULL, *rd_linger = NULL, *rd_failed = NULL;

                if(unlikely(!st_tcpconnaborts)) {
                    st_tcpconnaborts = rrdset_create_localhost(
                            "ipv4"
                            , "tcpconnaborts"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Connection Aborts"
                            , "connections/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 10
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_baddata    = rrddim_add(st_tcpconnaborts, "TCPAbortOnData",    "baddata",     1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_userclosed = rrddim_add(st_tcpconnaborts, "TCPAbortOnClose",   "userclosed",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_nomemory   = rrddim_add(st_tcpconnaborts, "TCPAbortOnMemory",  "nomemory",    1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_timeout    = rrddim_add(st_tcpconnaborts, "TCPAbortOnTimeout", "timeout",     1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_linger     = rrddim_add(st_tcpconnaborts, "TCPAbortOnLinger",  "linger",      1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_failed     = rrddim_add(st_tcpconnaborts, "TCPAbortFailed",    "failed",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_tcpconnaborts);

                rrddim_set_by_pointer(st_tcpconnaborts, rd_baddata,    tcpext_TCPAbortOnData);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_userclosed, tcpext_TCPAbortOnClose);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_nomemory,   tcpext_TCPAbortOnMemory);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_timeout,    tcpext_TCPAbortOnTimeout);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_linger,     tcpext_TCPAbortOnLinger);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_failed,     tcpext_TCPAbortFailed);

                rrdset_done(st_tcpconnaborts);
            }

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

            if(do_tcpext_reorder == CONFIG_BOOLEAN_YES || (do_tcpext_reorder == CONFIG_BOOLEAN_AUTO && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) {
                do_tcpext_reorder = CONFIG_BOOLEAN_YES;

                static RRDSET *st_tcpreorders = NULL;
                static RRDDIM *rd_timestamp = NULL, *rd_sack = NULL, *rd_fack = NULL, *rd_reno = NULL;

                if(unlikely(!st_tcpreorders)) {
                    st_tcpreorders = rrdset_create_localhost(
                            "ipv4"
                            , "tcpreorders"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Reordered Packets by Detection Method"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 20
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_timestamp = rrddim_add(st_tcpreorders, "TCPTSReorder",   "timestamp",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_sack      = rrddim_add(st_tcpreorders, "TCPSACKReorder", "sack",        1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_fack      = rrddim_add(st_tcpreorders, "TCPFACKReorder", "fack",        1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_reno      = rrddim_add(st_tcpreorders, "TCPRenoReorder", "reno",        1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_tcpreorders);

                rrddim_set_by_pointer(st_tcpreorders, rd_timestamp, tcpext_TCPTSReorder);
                rrddim_set_by_pointer(st_tcpreorders, rd_sack,      tcpext_TCPSACKReorder);
                rrddim_set_by_pointer(st_tcpreorders, rd_fack,      tcpext_TCPFACKReorder);
                rrddim_set_by_pointer(st_tcpreorders, rd_reno,      tcpext_TCPRenoReorder);

                rrdset_done(st_tcpreorders);
            }

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

            if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) {
                do_tcpext_ofo = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_tcpofo = NULL;
                static RRDDIM *rd_inqueue = NULL, *rd_dropped = NULL, *rd_merged = NULL, *rd_pruned = NULL;

                if(unlikely(!st_ipv4_tcpofo)) {

                    st_ipv4_tcpofo = rrdset_create_localhost(
                            "ipv4"
                            , "tcpofo"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Out-Of-Order Queue"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 50
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_inqueue = rrddim_add(st_ipv4_tcpofo, "TCPOFOQueue", "inqueue",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_dropped = rrddim_add(st_ipv4_tcpofo, "TCPOFODrop",  "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_merged  = rrddim_add(st_ipv4_tcpofo, "TCPOFOMerge", "merged",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_pruned  = rrddim_add(st_ipv4_tcpofo, "OfoPruned",   "pruned",  -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_tcpofo);

                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_inqueue, tcpext_TCPOFOQueue);
                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_dropped, tcpext_TCPOFODrop);
                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_merged,  tcpext_TCPOFOMerge);
                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_pruned,  tcpext_OfoPruned);

                rrdset_done(st_ipv4_tcpofo);
            }

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

            if(do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) {
                do_tcpext_syscookies = CONFIG_BOOLEAN_YES;

                static RRDSET *st_syncookies = NULL;
                static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_failed = NULL;

                if(unlikely(!st_syncookies)) {

                    st_syncookies = rrdset_create_localhost(
                            "ipv4"
                            , "tcpsyncookies"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP SYN Cookies"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 60
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_received = rrddim_add(st_syncookies, "SyncookiesRecv",   "received",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_sent     = rrddim_add(st_syncookies, "SyncookiesSent",   "sent",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_failed   = rrddim_add(st_syncookies, "SyncookiesFailed", "failed",   -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_syncookies);

                rrddim_set_by_pointer(st_syncookies, rd_received, tcpext_SyncookiesRecv);
                rrddim_set_by_pointer(st_syncookies, rd_sent,     tcpext_SyncookiesSent);
                rrddim_set_by_pointer(st_syncookies, rd_failed,   tcpext_SyncookiesFailed);

                rrdset_done(st_syncookies);
            }

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

            if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && (tcpext_ListenOverflows || tcpext_ListenDrops))) {
                do_tcpext_listen = CONFIG_BOOLEAN_YES;

                static RRDSET *st_listen = NULL;
                static RRDDIM *rd_overflows = NULL, *rd_drops = NULL;

                if(unlikely(!st_listen)) {

                    st_listen = rrdset_create_localhost(
                            "ipv4"
                            , "tcplistenissues"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Listen Socket Issues"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 15
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_overflows = rrddim_add(st_listen, "ListenOverflows", "overflows",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_drops     = rrddim_add(st_listen, "ListenDrops",     "drops",      1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_listen);

                rrddim_set_by_pointer(st_listen, rd_overflows, tcpext_ListenOverflows);
                rrddim_set_by_pointer(st_listen, rd_drops,     tcpext_ListenDrops);

                rrdset_done(st_listen);
            }
        }
    }

    return 0;
}
コード例 #4
0
ファイル: proc_net_netstat.c プロジェクト: rlugojr/netdata
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;
}
コード例 #5
0
int do_proc_net_sockstat6(int update_every, usec_t dt) {
    (void)dt;

    static procfile *ff = NULL;

    static uint32_t hash_raw = 0,
                    hash_frag = 0,
                    hash_tcp = 0,
                    hash_udp = 0,
                    hash_udplite = 0;

    static ARL_BASE *arl_tcp = NULL;
    static ARL_BASE *arl_udp = NULL;
    static ARL_BASE *arl_udplite = NULL;
    static ARL_BASE *arl_raw = NULL;
    static ARL_BASE *arl_frag = NULL;

    static int do_tcp_sockets = -1, do_udp_sockets = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1;

    static char     *keys[6]  = { NULL };
    static uint32_t hashes[6] = { 0 };
    static ARL_BASE *bases[6] = { NULL };

    if(unlikely(!arl_tcp)) {
        do_tcp_sockets     = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 TCP sockets", CONFIG_BOOLEAN_AUTO);
        do_udp_sockets     = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDP sockets", CONFIG_BOOLEAN_AUTO);
        do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDPLITE sockets", CONFIG_BOOLEAN_AUTO);
        do_raw_sockets     = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 RAW sockets", CONFIG_BOOLEAN_AUTO);
        do_frag_sockets    = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 FRAG sockets", CONFIG_BOOLEAN_AUTO);

        arl_tcp = arl_create("sockstat6/TCP6", arl_callback_str2kernel_uint_t, 60);
        arl_expect(arl_tcp, "inuse",  &sockstat6_root.tcp6_inuse);

        arl_udp = arl_create("sockstat6/UDP6", arl_callback_str2kernel_uint_t, 60);
        arl_expect(arl_udp, "inuse", &sockstat6_root.udp6_inuse);

        arl_udplite = arl_create("sockstat6/UDPLITE6", arl_callback_str2kernel_uint_t, 60);
        arl_expect(arl_udplite, "inuse", &sockstat6_root.udplite6_inuse);

        arl_raw = arl_create("sockstat6/RAW6", arl_callback_str2kernel_uint_t, 60);
        arl_expect(arl_raw, "inuse", &sockstat6_root.raw6_inuse);

        arl_frag = arl_create("sockstat6/FRAG6", arl_callback_str2kernel_uint_t, 60);
        arl_expect(arl_frag, "inuse", &sockstat6_root.frag6_inuse);

        hash_tcp = simple_hash("TCP6");
        hash_udp = simple_hash("UDP6");
        hash_udplite = simple_hash("UDPLITE6");
        hash_raw = simple_hash("RAW6");
        hash_frag = simple_hash("FRAG6");

        keys[0] = "TCP6";     hashes[0] = hash_tcp;     bases[0] = arl_tcp;
        keys[1] = "UDP6";     hashes[1] = hash_udp;     bases[1] = arl_udp;
        keys[2] = "UDPLITE6"; hashes[2] = hash_udplite; bases[2] = arl_udplite;
        keys[3] = "RAW6";     hashes[3] = hash_raw;     bases[3] = arl_raw;
        keys[4] = "FRAG6";    hashes[4] = hash_frag;    bases[4] = arl_frag;
        keys[5] = NULL; // terminator
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat6");
        ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat6", "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;

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

        int k;
        for(k = 0; keys[k] ; k++) {
            if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) {
                // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words);
                ARL_BASE *arl = bases[k];
                arl_begin(arl);
                size_t w = 1;

                while(w + 1 < words) {
                    char *name  = procfile_lineword(ff, l, w); w++;
                    char *value = procfile_lineword(ff, l, w); w++;
                    // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words);
                    if(unlikely(arl_check(arl, name, value) != 0))
                        break;
                }

                break;
            }
        }
    }

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

    if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && (sockstat6_root.tcp6_inuse))) {
        do_tcp_sockets = CONFIG_BOOLEAN_YES;

        static RRDSET *st = NULL;
        static RRDDIM *rd_inuse = NULL;

        if(unlikely(!st)) {
            st = rrdset_create_localhost(
                    "ipv6"
                    , "sockstat6_tcp_sockets"
                    , NULL
                    , "tcp6"
                    , NULL
                    , "IPv6 TCP Sockets"
                    , "sockets"
                    , PLUGIN_PROC_NAME
                    , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
                    , NETDATA_CHART_PRIO_IPV6_TCP
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rd_inuse    = rrddim_add(st, "inuse",     NULL,   1, 1, RRD_ALGORITHM_ABSOLUTE);
        }
        else rrdset_next(st);

        rrddim_set_by_pointer(st, rd_inuse,    (collected_number)sockstat6_root.tcp6_inuse);
        rrdset_done(st);
    }

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

    if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udp6_inuse)) {
        do_udp_sockets = CONFIG_BOOLEAN_YES;

        static RRDSET *st = NULL;
        static RRDDIM *rd_inuse = NULL;

        if(unlikely(!st)) {
            st = rrdset_create_localhost(
                    "ipv6"
                    , "sockstat6_udp_sockets"
                    , NULL
                    , "udp6"
                    , NULL
                    , "IPv6 UDP Sockets"
                    , "sockets"
                    , PLUGIN_PROC_NAME
                    , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
                    , NETDATA_CHART_PRIO_IPV6_UDP
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rd_inuse    = rrddim_add(st, "inuse",     NULL,   1, 1, RRD_ALGORITHM_ABSOLUTE);
        }
        else rrdset_next(st);

        rrddim_set_by_pointer(st, rd_inuse,    (collected_number)sockstat6_root.udp6_inuse);
        rrdset_done(st);
    }

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

    if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udplite6_inuse)) {
        do_udplite_sockets = CONFIG_BOOLEAN_YES;

        static RRDSET *st = NULL;
        static RRDDIM *rd_inuse = NULL;

        if(unlikely(!st)) {
            st = rrdset_create_localhost(
                    "ipv6"
                    , "sockstat6_udplite_sockets"
                    , NULL
                    , "udplite6"
                    , NULL
                    , "IPv6 UDPLITE Sockets"
                    , "sockets"
                    , PLUGIN_PROC_NAME
                    , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
                    , NETDATA_CHART_PRIO_IPV6_UDPLITE
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rd_inuse    = rrddim_add(st, "inuse",     NULL,   1, 1, RRD_ALGORITHM_ABSOLUTE);
        }
        else rrdset_next(st);

        rrddim_set_by_pointer(st, rd_inuse,    (collected_number)sockstat6_root.udplite6_inuse);
        rrdset_done(st);
    }

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

    if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.raw6_inuse)) {
        do_raw_sockets = CONFIG_BOOLEAN_YES;

        static RRDSET *st = NULL;
        static RRDDIM *rd_inuse = NULL;

        if(unlikely(!st)) {
            st = rrdset_create_localhost(
                    "ipv6"
                    , "sockstat6_raw_sockets"
                    , NULL
                    , "raw6"
                    , NULL
                    , "IPv6 RAW Sockets"
                    , "sockets"
                    , PLUGIN_PROC_NAME
                    , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
                    , NETDATA_CHART_PRIO_IPV6_RAW
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rd_inuse    = rrddim_add(st, "inuse",     NULL,   1, 1, RRD_ALGORITHM_ABSOLUTE);
        }
        else rrdset_next(st);

        rrddim_set_by_pointer(st, rd_inuse,    (collected_number)sockstat6_root.raw6_inuse);
        rrdset_done(st);
    }

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

    if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.frag6_inuse)) {
        do_frag_sockets = CONFIG_BOOLEAN_YES;

        static RRDSET *st = NULL;
        static RRDDIM *rd_inuse = NULL;

        if(unlikely(!st)) {
            st = rrdset_create_localhost(
                    "ipv6"
                    , "sockstat6_frag_sockets"
                    , NULL
                    , "fragments6"
                    , NULL
                    , "IPv6 FRAG Sockets"
                    , "fragments"
                    , PLUGIN_PROC_NAME
                    , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
                    , NETDATA_CHART_PRIO_IPV6_FRAGMENTS
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rd_inuse    = rrddim_add(st, "inuse",     NULL,   1, 1, RRD_ALGORITHM_ABSOLUTE);
        }
        else rrdset_next(st);

        rrddim_set_by_pointer(st, rd_inuse,    (collected_number)sockstat6_root.frag6_inuse);
        rrdset_done(st);
    }

    return 0;
}