]> arthur.barton.de Git - netdata.git/commitdiff
Add IPv4 TCP charts to macOS plugin
authorVladimir Kobal <vlad@prokk.net>
Mon, 9 Jan 2017 18:51:43 +0000 (13:51 -0500)
committerVladimir Kobal <vlad@prokk.net>
Mon, 9 Jan 2017 19:23:33 +0000 (14:23 -0500)
src/macos_sysctl.c

index 1f02a63b121bece5195426b3cf1dbd48aa736c9e..e3d08f7b3b1f5fd87d92249680f04c21a6777648 100644 (file)
@@ -2,6 +2,10 @@
 #include <sys/sysctl.h>
 // NEEDED BY: do_bandwidth
 #include <net/route.h>
+// NEEDED BY do_tcp...
+#include <sys/socketvar.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcp_fsm.h>
 
 #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
 
@@ -13,12 +17,22 @@ int getsysctl(const char *name, void *ptr, size_t len);
 int do_macos_sysctl(int update_every, usec_t dt) {
     (void)dt;
 
-    static int do_loadavg = -1, do_swap = -1, do_bandwidth = -1;
+    static int do_loadavg = -1, do_swap = -1, do_bandwidth = -1,
+               do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_ecn = -1,
+               do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1;
+
 
     if (unlikely(do_loadavg == -1)) {
         do_loadavg              = config_get_boolean("plugin:macos:sysctl", "enable load average", 1);
         do_swap                 = config_get_boolean("plugin:macos:sysctl", "system swap", 1);
         do_bandwidth            = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
+        do_tcp_packets          = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP packets", 1);
+        do_tcp_errors           = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP errors", 1);
+        do_tcp_handshake        = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP handshake issues", 1);
+        do_ecn                  = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);
+        do_tcpext_syscookies    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
+        do_tcpext_ofo           = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
+        do_tcpext_connaborts    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
     }
 
     RRDSET *st;
@@ -45,6 +59,10 @@ int do_macos_sysctl(int update_every, usec_t dt) {
         u_long  ift_obytes;
     } iftot = {0, 0};
 
+    // NEEDED BY: do_tcp...
+    struct tcpstat tcpstat;
+    uint64_t tcps_states[TCP_NSTATES];
+
     if (last_loadavg_usec <= dt) {
         if (likely(do_loadavg)) {
             if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
@@ -142,6 +160,170 @@ int do_macos_sysctl(int update_every, usec_t dt) {
         }
     }
 
+    // --------------------------------------------------------------------
+
+    // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
+    if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syscookies || do_ecn)) {
+        if (unlikely(GETSYSCTL("net.inet.tcp.stats", tcpstat))){
+            do_tcp_packets = 0;
+            error("DISABLED: ipv4.tcppackets");
+            do_tcp_errors = 0;
+            error("DISABLED: ipv4.tcperrors");
+            do_tcp_handshake = 0;
+            error("DISABLED: ipv4.tcphandshake");
+            do_tcpext_connaborts = 0;
+            error("DISABLED: ipv4.tcpconnaborts");
+            do_tcpext_ofo = 0;
+            error("DISABLED: ipv4.tcpofo");
+            do_tcpext_syscookies = 0;
+            error("DISABLED: ipv4.tcpsyncookies");
+            do_ecn = 0;
+            error("DISABLED: ipv4.ecnpkts");
+        } else {
+            if (likely(do_tcp_packets)) {
+                st = rrdset_find("ipv4.tcppackets");
+                if (unlikely(!st)) {
+                    st = rrdset_create("ipv4", "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", tcpstat.tcps_rcvtotal);
+                rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal);
+                rrdset_done(st);
+            }
+
+            // --------------------------------------------------------------------
+
+            if (likely(do_tcp_errors)) {
+                st = rrdset_find("ipv4.tcperrors");
+                if (unlikely(!st)) {
+                    st = rrdset_create("ipv4", "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", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
+                rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum);
+                rrddim_set(st, "RetransSegs", tcpstat.tcps_sndrexmitpack);
+                rrdset_done(st);
+            }
+
+            // --------------------------------------------------------------------
+
+            if (likely(do_tcp_handshake)) {
+                st = rrdset_find("ipv4.tcphandshake");
+                if (unlikely(!st)) {
+                    st = rrdset_create("ipv4", "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, "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", tcpstat.tcps_drops);
+                rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt);
+                rrddim_set(st, "PassiveOpens", tcpstat.tcps_accepts);
+                rrddim_set(st, "AttemptFails", tcpstat.tcps_conndrops);
+                rrdset_done(st);
+            }
+
+            // --------------------------------------------------------------------
+
+            if (do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop))) {
+                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);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "TCPAbortOnData",    tcpstat.tcps_rcvpackafterwin);
+                rrddim_set(st, "TCPAbortOnClose",   tcpstat.tcps_rcvafterclose);
+                rrddim_set(st, "TCPAbortOnMemory",  tcpstat.tcps_rcvmemdrop);
+                rrddim_set(st, "TCPAbortOnTimeout", tcpstat.tcps_persistdrop);
+                rrdset_done(st);
+            }
+
+            // --------------------------------------------------------------------
+
+            if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) {
+                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);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "TCPOFOQueue",   tcpstat.tcps_rcvoopack);
+                rrdset_done(st);
+            }
+
+            // --------------------------------------------------------------------
+
+            if (do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) {
+                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",   tcpstat.tcps_sc_recvcookie);
+                rrddim_set(st, "SyncookiesSent",   tcpstat.tcps_sc_sendcookie);
+                rrddim_set(st, "SyncookiesFailed", tcpstat.tcps_sc_zonefail);
+                rrdset_done(st);
+            }
+
+            // --------------------------------------------------------------------
+
+            if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) {
+                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);
+                }
+                else rrdset_next(st);
+
+                rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_recv_ce);
+                rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported);
+                rrdset_done(st);
+            }
+
+        }
+    }
+
     return 0;
 }