summaryrefslogtreecommitdiff
path: root/src/pmdas/linux/proc_net_netstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/linux/proc_net_netstat.c')
-rw-r--r--src/pmdas/linux/proc_net_netstat.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/pmdas/linux/proc_net_netstat.c b/src/pmdas/linux/proc_net_netstat.c
new file mode 100644
index 0000000..a7bd34a
--- /dev/null
+++ b/src/pmdas/linux/proc_net_netstat.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2014 Red Hat.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "indom.h"
+#include "proc_net_netstat.h"
+
+extern proc_net_netstat_t _pm_proc_net_netstat;
+
+typedef struct {
+ const char *field;
+ __uint64_t *offset;
+} netstat_fields_t;
+
+netstat_fields_t netstat_ip_fields[] = {
+ { .field = "InNoRoutes",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_INNOROUTES] },
+ { .field = "InTruncatedPkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_INTRUNCATEDPKTS] },
+ { .field = "InMcastPkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_INMCASTPKTS] },
+ { .field = "OutMcastPkts ",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_OUTMCASTPKTS] },
+ { .field = "InBcastPkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_INBCASTPKTS] },
+ { .field = "OutBcastPkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_OUTBCASTPKTS] },
+ { .field = "InOctets",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_INOCTETS] },
+ { .field = "OutOctets",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_OUTOCTETS] },
+ { .field = "InMcastOctets",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_INMCASTOCTETS] },
+ { .field = "OutMcastOctets",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_OUTMCASTOCTETS] },
+ { .field = "InBcastOctets",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_INBCASTOCTETS] },
+ { .field = "OutBcastOctets",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_OUTBCASTOCTETS] },
+ { .field = "InCsumErrors",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_CSUMERRORS] },
+ { .field = "InNoECTPkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_NOECTPKTS] },
+ { .field = "InECT1Pkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_ECT1PKTS] },
+ { .field = "InECT0Pkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_ECT0PKTS] },
+ { .field = "InCEPkts",
+ .offset = &_pm_proc_net_netstat.ip[_PM_NETSTAT_IPEXT_CEPKTS] }
+};
+
+
+netstat_fields_t netstat_tcp_fields[] = {
+ { .field = "SyncookiesSent",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_SYNCOOKIESSENT] },
+ { .field = "SyncookiesRecv",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_SYNCOOKIESRECV] },
+ { .field = "SyncookiesFailed",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_SYNCOOKIESFAILED] },
+ { .field = "EmbryonicRsts",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_EMBRYONICRSTS] },
+ { .field = "PruneCalled",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_PRUNECALLED] },
+ { .field = "RcvPruned",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_RCVPRUNED] },
+ { .field = "OfoPruned",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_OFOPRUNED] },
+ { .field = "OutOfWindowIcmps",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_OUTOFWINDOWICMPS] },
+ { .field = "LockDroppedIcmps",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_LOCKDROPPEDICMPS] },
+ { .field = "ArpFilter",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_ARPFILTER] },
+ { .field = "TW",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TIMEWAITED] },
+ { .field = "TWRecycled",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TIMEWAITRECYCLED] },
+ { .field = "TWKilled",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TIMEWAITKILLED] },
+ { .field = "PAWSPassive",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_PAWSPASSIVEREJECTED] },
+ { .field = "PAWSActive",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_PAWSACTIVEREJECTED] },
+ { .field = "PAWSEstab",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_PAWSESTABREJECTED] },
+ { .field = "DelayedACKs",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_DELAYEDACKS] },
+ { .field = "DelayedACKLocked",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_DELAYEDACKLOCKED] },
+ { .field = "DelayedACKLost",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_DELAYEDACKLOST] },
+ { .field = "ListenOverflows",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_LISTENOVERFLOWS] },
+ { .field = "ListenDrops",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_LISTENDROPS] },
+ { .field = "TCPPrequeued",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPPREQUEUED] },
+ { .field = "TCPDirectCopyFromBacklog",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDIRECTCOPYFROMBACKLOG] },
+ { .field = "TCPDirectCopyFromPrequeue",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDIRECTCOPYFROMPREQUEUE] },
+ { .field = "TCPPrequeueDropped",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPPREQUEUEDROPPED] },
+ { .field = "TCPHPHits",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPHPHITS] },
+ { .field = "TCPHPHitsToUser",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPHPHITSTOUSER] },
+ { .field = "TCPPureAcks",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPPUREACKS] },
+ { .field = "TCPHPAcks",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPHPACKS] },
+ { .field = "TCPRenoRecovery",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPRENORECOVERY] },
+ { .field = "TCPSackRecovery",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSACKRECOVERY] },
+ { .field = "TCPSACKReneging",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSACKRENEGING] },
+ { .field = "TCPFACKReorder",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFACKREORDER] },
+ { .field = "TCPSACKReorder",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSACKREORDER] },
+ { .field = "TCPRenoReorder",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPRENOREORDER] },
+ { .field = "TCPTSReorder",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPTSREORDER] },
+ { .field = "TCPFullUndo",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFULLUNDO] },
+ { .field = "TCPPartialUndo",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPPARTIALUNDO] },
+ { .field = "TCPDSACKUndo",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDSACKUNDO] },
+ { .field = "TCPLossUndo",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPLOSSUNDO] },
+ { .field = "TCPLostRetransmit",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPLOSTRETRANSMIT] },
+ { .field = "TCPRenoFailures",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPRENOFAILURES] },
+ { .field = "TCPSackFailures",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSACKFAILURES] },
+ { .field = "TCPLossFailures",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPLOSSFAILURES] },
+ { .field = "TCPFastRetrans",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFASTRETRANS] },
+ { .field = "TCPForwardRetrans",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFORWARDRETRANS] },
+ { .field = "TCPSlowStartRetrans",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSLOWSTARTRETRANS] },
+ { .field = "TCPTimeouts",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPTIMEOUTS] },
+ { .field = "TCPLossProbes",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPLOSSPROBES] },
+ { .field = "TCPLossProbeRecovery",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPLOSSPROBERECOVERY] },
+ { .field = "TCPRenoRecoveryFail",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPRENORECOVERYFAIL] },
+ { .field = "TCPSackRecoveryFail",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSACKRECOVERYFAIL] },
+ { .field = "TCPSchedulerFailed",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSCHEDULERFAILED] },
+ { .field = "TCPRcvCollapsed",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPRCVCOLLAPSED] },
+ { .field = "TCPDSACKOldSent",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDSACKOLDSENT] },
+ { .field = "TCPDSACKOfoSent",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDSACKOFOSENT] },
+ { .field = "TCPDSACKRecv",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDSACKRECV] },
+ { .field = "TCPDSACKOfoRecv",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDSACKOFORECV] },
+ { .field = "TCPAbortOnData",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPABORTONDATA] },
+ { .field = "TCPAbortOnClose",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPABORTONCLOSE] },
+ { .field = "TCPAbortOnMemory",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPABORTONMEMORY] },
+ { .field = "TCPAbortOnTimeout",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPABORTONTIMEOUT] },
+ { .field = "TCPAbortOnLinger",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPABORTONLINGER] },
+ { .field = "TCPAbortFailed",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPABORTFAILED] },
+ { .field = "TCPMemoryPressures",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPMEMORYPRESSURES] },
+ { .field = "TCPSACKDiscard",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSACKDISCARD] },
+ { .field = "TCPDSACKIgnoredOld",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDSACKIGNOREDOLD] },
+ { .field = "TCPDSACKIgnoredNoUndo",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDSACKIGNOREDNOUNDO] },
+ { .field = "TCPSpuriousRTOs",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSPURIOUSRTOS] },
+ { .field = "TCPMD5NotFound",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPMD5NOTFOUND] },
+ { .field = "TCPMD5Unexpected",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPMD5UNEXPECTED] },
+ { .field = "TCPSackShifted",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_SACKSHIFTED] },
+ { .field = "TCPSackMerged",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_SACKMERGED] },
+ { .field = "TCPSackShiftFallback",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_SACKSHIFTFALLBACK] },
+ { .field = "TCPBacklogDrop",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPBACKLOGDROP] },
+ { .field = "TCPMinTTLDrop",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPMINTTLDROP] },
+ { .field = "TCPDeferAcceptDrop",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPDEFERACCEPTDROP] },
+ { .field = "IPReversePathFilter",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_IPRPFILTER] },
+ { .field = "TCPTimeWaitOverflow",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPTIMEWAITOVERFLOW] },
+ { .field = "TCPReqQFullDoCookies",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPREQQFULLDOCOOKIES] },
+ { .field = "TCPReqQFullDrop",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPREQQFULLDROP] },
+ { .field = "TCPRetransFail",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPRETRANSFAIL] },
+ { .field = "TCPRcvCoalesce",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPRCVCOALESCE] },
+ { .field = "TCPOFOQueue",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPOFOQUEUE] },
+ { .field = "TCPOFODrop",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPOFODROP] },
+ { .field = "TCPOFOMerge",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPOFOMERGE] },
+ { .field = "TCPChallengeACK",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPCHALLENGEACK] },
+ { .field = "TCPSYNChallenge",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSYNCHALLENGE] },
+ { .field = "TCPFastOpenActive",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFASTOPENACTIVE] },
+ { .field = "TCPFastOpenPassive",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFASTOPENACTIVEFAIL] },
+ { .field = "TCPFastOpenPassiveFail",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFASTOPENPASSIVEFAIL] },
+ { .field = "TCPFastOpenListenOverflow",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFASTOPENLISTENOVERFLOW] },
+ { .field = "TCPFastOpenCookieReqd",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFASTOPENCOOKIEREQD] },
+ { .field = "TCPSpuriousRtxHostQueues",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSPURIOUS_RTX_HOSTQUEUES] },
+ { .field = "BusyPollRxPackets",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_BUSYPOLLRXPACKETS] },
+ { .field = "TCPAutoCorking",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPAUTOCORKING] },
+ { .field = "TCPFromZeroWindowAdv",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPFROMZEROWINDOWADV] },
+ { .field = "TCPToZeroWindowAdv",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPTOZEROWINDOWADV] },
+ { .field = "TCPWantZeroWindowAdv",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPWANTZEROWINDOWADV] },
+ { .field = "TCPSynRetrans",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPSYNRETRANS] },
+ { .field = "TCPOrigDataSent",
+ .offset = &_pm_proc_net_netstat.tcp[_PM_NETSTAT_TCPEXT_TCPORIGDATASENT] }
+};
+
+static void
+get_fields(netstat_fields_t *fields, char *header, char *buffer)
+{
+ int i, j, count;
+ char *p, *indices[NETSTAT_MAX_COLUMNS];
+
+ /* first get pointers to each of the column headings */
+ strtok(header, " ");
+ for (i = 0; i < NETSTAT_MAX_COLUMNS; i++) {
+ if ((p = strtok(NULL, " \n")) == NULL)
+ break;
+ indices[i] = p;
+ }
+ count = i;
+
+ /*
+ * Extract values via back-referencing column headings.
+ * "i" is the last found index, which we use for a bit
+ * of optimisation for the (common) in-order maps case
+ * (where "in order" means in the order defined by the
+ * passed in "fields" table which typically matches the
+ * kernel - but may be out-of-order for older kernels).
+ */
+ strtok(buffer, " ");
+ for (i = j = 0; j < count && fields[i].field; j++, i++) {
+ if ((p = strtok(NULL, " \n")) == NULL)
+ break;
+ if (strcmp(fields[i].field, indices[j]) == 0)
+ *fields[i].offset = strtoull(p, NULL, 10);
+ else {
+ for (i = 0; fields[i].field; i++) {
+ if (strcmp(fields[i].field, indices[j]) != 0)
+ continue;
+ *fields[i].offset = strtoull(p, NULL, 10);
+ break;
+ }
+ if (fields[i].field == NULL) /* not found, ignore */
+ i = 0;
+ }
+ }
+}
+
+
+#define NETSTAT_IP_OFFSET(ii, pp) (int64_t *)((char *)pp + \
+ (__psint_t)netstat_ip_fields[ii].offset - (__psint_t)&_pm_proc_net_netstat.ip)
+#define NETSTAT_TCP_OFFSET(ii, pp) (int64_t *)((char *)pp + \
+ (__psint_t)netstat_tcp_fields[ii].offset - (__psint_t)&_pm_proc_net_netstat.tcp)
+
+static void
+init_refresh_proc_net_netstat(proc_net_netstat_t *netstat)
+{
+ int i;
+
+ /* initially, all marked as "no value available" */
+ for (i = 0; netstat_ip_fields[i].field != NULL; i++)
+ *(NETSTAT_IP_OFFSET(i, netstat->ip)) = -1;
+ for (i = 0; netstat_tcp_fields[i].field != NULL; i++)
+ *(NETSTAT_TCP_OFFSET(i, netstat->tcp)) = -1;
+}
+
+int
+refresh_proc_net_netstat(proc_net_netstat_t *netstat)
+{
+ /* Need a sufficiently large value to hold a full line */
+ char buf[MAXPATHLEN];
+ char header[2048];
+ FILE *fp;
+
+ init_refresh_proc_net_netstat(netstat);
+ if ((fp = linux_statsfile("/proc/net/netstat", buf, sizeof(buf))) == NULL)
+ return -oserror();
+ while (fgets(header, sizeof(header), fp) != NULL) {
+ if (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (strncmp(buf, "IpExt:", 6) == 0)
+ get_fields(netstat_ip_fields, header, buf);
+ else if (strncmp(buf, "TcpExt:", 7) == 0)
+ get_fields(netstat_tcp_fields, header, buf);
+ else
+ __pmNotifyErr(LOG_ERR, "Unrecognised netstat row: %s\n", buf);
+ }
+ }
+ fclose(fp);
+ return 0;
+}