]> arthur.barton.de Git - netdata.git/blob - src/proc_net_netstat.c
Merge pull request #1283 from firehol/automate-uploads
[netdata.git] / src / proc_net_netstat.c
1 #include "common.h"
2
3
4 struct netstat_columns {
5     char *name;
6     uint32_t hash;
7     unsigned long long value;
8     int multiplier;     // not needed everywhere
9     char *label;        // not needed everywhere
10 };
11
12 static struct netstat_columns tcpext_data[] = {
13     { "SyncookiesSent", 0, 0, 1, NULL },
14     { "SyncookiesRecv", 0, 0, 1, NULL },
15     { "SyncookiesFailed", 0, 0, 1, NULL },
16     { "EmbryonicRsts", 0, 0, 1, NULL },
17     { "PruneCalled", 0, 0, 1, NULL },
18     { "RcvPruned", 0, 0, 1, NULL },
19     { "OfoPruned", 0, 0, 1, NULL },
20     { "OutOfWindowIcmps", 0, 0, 1, NULL },
21     { "LockDroppedIcmps", 0, 0, 1, NULL },
22     { "ArpFilter", 0, 0, 1, NULL },
23     { "TW", 0, 0, 1, NULL },
24     { "TWRecycled", 0, 0, 1, NULL },
25     { "TWKilled", 0, 0, 1, NULL },
26     { "PAWSPassive", 0, 0, 1, NULL },
27     { "PAWSActive", 0, 0, 1, NULL },
28     { "PAWSEstab", 0, 0, 1, NULL },
29     { "DelayedACKs", 0, 0, 1, NULL },
30     { "DelayedACKLocked", 0, 0, 1, NULL },
31     { "DelayedACKLost", 0, 0, 1, NULL },
32     { "ListenOverflows", 0, 0, 1, NULL },
33     { "ListenDrops", 0, 0, 1, NULL },
34     { "TCPPrequeued", 0, 0, 1, NULL },
35     { "TCPDirectCopyFromBacklog", 0, 0, 1, NULL },
36     { "TCPDirectCopyFromPrequeue", 0, 0, 1, NULL },
37     { "TCPPrequeueDropped", 0, 0, 1, NULL },
38     { "TCPHPHits", 0, 0, 1, NULL },
39     { "TCPHPHitsToUser", 0, 0, 1, NULL },
40     { "TCPPureAcks", 0, 0, 1, NULL },
41     { "TCPHPAcks", 0, 0, 1, NULL },
42     { "TCPRenoRecovery", 0, 0, 1, NULL },
43     { "TCPSackRecovery", 0, 0, 1, NULL },
44     { "TCPSACKReneging", 0, 0, 1, NULL },
45     { "TCPFACKReorder", 0, 0, 1, NULL },
46     { "TCPSACKReorder", 0, 0, 1, NULL },
47     { "TCPRenoReorder", 0, 0, 1, NULL },
48     { "TCPTSReorder", 0, 0, 1, NULL },
49     { "TCPFullUndo", 0, 0, 1, NULL },
50     { "TCPPartialUndo", 0, 0, 1, NULL },
51     { "TCPDSACKUndo", 0, 0, 1, NULL },
52     { "TCPLossUndo", 0, 0, 1, NULL },
53     { "TCPLostRetransmit", 0, 0, 1, NULL },
54     { "TCPRenoFailures", 0, 0, 1, NULL },
55     { "TCPSackFailures", 0, 0, 1, NULL },
56     { "TCPLossFailures", 0, 0, 1, NULL },
57     { "TCPFastRetrans", 0, 0, 1, NULL },
58     { "TCPForwardRetrans", 0, 0, 1, NULL },
59     { "TCPSlowStartRetrans", 0, 0, 1, NULL },
60     { "TCPTimeouts", 0, 0, 1, NULL },
61     { "TCPLossProbes", 0, 0, 1, NULL },
62     { "TCPLossProbeRecovery", 0, 0, 1, NULL },
63     { "TCPRenoRecoveryFail", 0, 0, 1, NULL },
64     { "TCPSackRecoveryFail", 0, 0, 1, NULL },
65     { "TCPSchedulerFailed", 0, 0, 1, NULL },
66     { "TCPRcvCollapsed", 0, 0, 1, NULL },
67     { "TCPDSACKOldSent", 0, 0, 1, NULL },
68     { "TCPDSACKOfoSent", 0, 0, 1, NULL },
69     { "TCPDSACKRecv", 0, 0, 1, NULL },
70     { "TCPDSACKOfoRecv", 0, 0, 1, NULL },
71     { "TCPAbortOnData", 0, 0, 1, NULL },
72     { "TCPAbortOnClose", 0, 0, 1, NULL },
73     { "TCPAbortOnMemory", 0, 0, 1, NULL },
74     { "TCPAbortOnTimeout", 0, 0, 1, NULL },
75     { "TCPAbortOnLinger", 0, 0, 1, NULL },
76     { "TCPAbortFailed", 0, 0, 1, NULL },
77     { "TCPMemoryPressures", 0, 0, 1, NULL },
78     { "TCPSACKDiscard", 0, 0, 1, NULL },
79     { "TCPDSACKIgnoredOld", 0, 0, 1, NULL },
80     { "TCPDSACKIgnoredNoUndo", 0, 0, 1, NULL },
81     { "TCPSpuriousRTOs", 0, 0, 1, NULL },
82     { "TCPMD5NotFound", 0, 0, 1, NULL },
83     { "TCPMD5Unexpected", 0, 0, 1, NULL },
84     { "TCPSackShifted", 0, 0, 1, NULL },
85     { "TCPSackMerged", 0, 0, 1, NULL },
86     { "TCPSackShiftFallback", 0, 0, 1, NULL },
87     { "TCPBacklogDrop", 0, 0, 1, NULL },
88     { "TCPMinTTLDrop", 0, 0, 1, NULL },
89     { "TCPDeferAcceptDrop", 0, 0, 1, NULL },
90     { "IPReversePathFilter", 0, 0, 1, NULL },
91     { "TCPTimeWaitOverflow", 0, 0, 1, NULL },
92     { "TCPReqQFullDoCookies", 0, 0, 1, NULL },
93     { "TCPReqQFullDrop", 0, 0, 1, NULL },
94     { "TCPRetransFail", 0, 0, 1, NULL },
95     { "TCPRcvCoalesce", 0, 0, 1, NULL },
96     { "TCPOFOQueue", 0, 0, 1, NULL },
97     { "TCPOFODrop", 0, 0, 1, NULL },
98     { "TCPOFOMerge", 0, 0, 1, NULL },
99     { "TCPChallengeACK", 0, 0, 1, NULL },
100     { "TCPSYNChallenge", 0, 0, 1, NULL },
101     { "TCPFastOpenActive", 0, 0, 1, NULL },
102     { "TCPFastOpenActiveFail", 0, 0, 1, NULL },
103     { "TCPFastOpenPassive", 0, 0, 1, NULL },
104     { "TCPFastOpenPassiveFail", 0, 0, 1, NULL },
105     { "TCPFastOpenListenOverflow", 0, 0, 1, NULL },
106     { "TCPFastOpenCookieReqd", 0, 0, 1, NULL },
107     { "TCPSpuriousRtxHostQueues", 0, 0, 1, NULL },
108     { "BusyPollRxPackets", 0, 0, 1, NULL },
109     { "TCPAutoCorking", 0, 0, 1, NULL },
110     { "TCPFromZeroWindowAdv", 0, 0, 1, NULL },
111     { "TCPToZeroWindowAdv", 0, 0, 1, NULL },
112     { "TCPWantZeroWindowAdv", 0, 0, 1, NULL },
113     { "TCPSynRetrans", 0, 0, 1, NULL },
114     { "TCPOrigDataSent", 0, 0, 1, NULL },
115     { "TCPHystartTrainDetect", 0, 0, 1, NULL },
116     { "TCPHystartTrainCwnd", 0, 0, 1, NULL },
117     { "TCPHystartDelayDetect", 0, 0, 1, NULL },
118     { "TCPHystartDelayCwnd", 0, 0, 1, NULL },
119     { "TCPACKSkippedSynRecv", 0, 0, 1, NULL },
120     { "TCPACKSkippedPAWS", 0, 0, 1, NULL },
121     { "TCPACKSkippedSeq", 0, 0, 1, NULL },
122     { "TCPACKSkippedFinWait2", 0, 0, 1, NULL },
123     { "TCPACKSkippedTimeWait", 0, 0, 1, NULL },
124     { "TCPACKSkippedChallenge", 0, 0, 1, NULL },
125     { "TCPWinProbe", 0, 0, 1, NULL },
126     { "TCPKeepAlive", 0, 0, 1, NULL },
127     { "TCPMTUPFail", 0, 0, 1, NULL },
128     { "TCPMTUPSuccess", 0, 0, 1, NULL },
129     { NULL, 0, 0, 0, NULL }
130 };
131
132 static struct netstat_columns ipext_data[] = {
133     { "InNoRoutes", 0, 0, 1, NULL },
134     { "InTruncatedPkts", 0, 0, 1, NULL },
135     { "InMcastPkts", 0, 0, 1, NULL },
136     { "OutMcastPkts", 0, 0, 1, NULL },
137     { "InBcastPkts", 0, 0, 1, NULL },
138     { "OutBcastPkts", 0, 0, 1, NULL },
139     { "InOctets", 0, 0, 1, NULL },
140     { "OutOctets", 0, 0, 1, NULL },
141     { "InMcastOctets", 0, 0, 1, NULL },
142     { "OutMcastOctets", 0, 0, 1, NULL },
143     { "InBcastOctets", 0, 0, 1, NULL },
144     { "OutBcastOctets", 0, 0, 1, NULL },
145     { "InCsumErrors", 0, 0, 1, NULL },
146     { "InNoECTPkts", 0, 0, 1, NULL },
147     { "InECT1Pkts", 0, 0, 1, NULL },
148     { "InECT0Pkts", 0, 0, 1, NULL },
149     { "InCEPkts", 0, 0, 1, NULL },
150     { NULL, 0, 0, 0, NULL }
151 };
152
153 static void hash_array(struct netstat_columns *nc) {
154     int i;
155
156     for(i = 0; nc[i].name ;i++)
157         nc[i].hash = simple_hash(nc[i].name);
158 }
159
160 static unsigned long long *netstat_columns_find(struct netstat_columns *nc, const char *name) {
161     uint32_t i, hash = simple_hash(name);
162
163     for(i = 0; nc[i].name ;i++)
164         if(unlikely(nc[i].hash == hash && !strcmp(nc[i].name, name)))
165             return &nc[i].value;
166
167     fatal("Cannot find key '%s' in /proc/net/netstat internal array.", name);
168 }
169
170 static void parse_line_pair(procfile *ff, struct netstat_columns *nc, uint32_t header_line, uint32_t values_line) {
171     uint32_t hwords = procfile_linewords(ff, header_line);
172     uint32_t vwords = procfile_linewords(ff, values_line);
173     uint32_t w, i;
174
175     if(unlikely(vwords > hwords)) {
176         error("File /proc/net/netstat on header line %u has %u words, but on value line %u has %u words.", header_line, hwords, values_line, vwords);
177         vwords = hwords;
178     }
179
180     for(w = 1; w < vwords ;w++) {
181         char *key = procfile_lineword(ff, header_line, w);
182         uint32_t hash = simple_hash(key);
183
184         for(i = 0 ; nc[i].name ;i++) {
185             if(unlikely(hash == nc[i].hash && !strcmp(key, nc[i].name))) {
186                 nc[i].value = strtoull(procfile_lineword(ff, values_line, w), NULL, 10);
187                 break;
188             }
189         }
190     }
191 }
192
193
194 int do_proc_net_netstat(int update_every, usec_t dt) {
195     (void)dt;
196
197     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, \
198         do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1;
199     static uint32_t hash_ipext = 0, hash_tcpext = 0;
200     static procfile *ff = NULL;
201
202     static unsigned long long *tcpext_TCPRenoReorder = NULL;
203     static unsigned long long *tcpext_TCPFACKReorder = NULL;
204     static unsigned long long *tcpext_TCPSACKReorder = NULL;
205     static unsigned long long *tcpext_TCPTSReorder = NULL;
206
207     static unsigned long long *tcpext_SyncookiesSent = NULL;
208     static unsigned long long *tcpext_SyncookiesRecv = NULL;
209     static unsigned long long *tcpext_SyncookiesFailed = NULL;
210
211     static unsigned long long *tcpext_TCPOFOQueue = NULL; // Number of packets queued in OFO queue
212     static unsigned long long *tcpext_TCPOFODrop = NULL;  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
213     static unsigned long long *tcpext_TCPOFOMerge = NULL; // Number of packets in OFO that were merged with other packets.
214     static unsigned long long *tcpext_OfoPruned = NULL;   // packets dropped from out-of-order queue because of socket buffer overrun
215
216     static unsigned long long *tcpext_TCPAbortOnData = NULL;    // connections reset due to unexpected data
217     static unsigned long long *tcpext_TCPAbortOnClose = NULL;   // connections reset due to early user close
218     static unsigned long long *tcpext_TCPAbortOnMemory = NULL;  // connections aborted due to memory pressure
219     static unsigned long long *tcpext_TCPAbortOnTimeout = NULL; // connections aborted due to timeout
220     static unsigned long long *tcpext_TCPAbortOnLinger = NULL;  // connections aborted after user close in linger timeout
221     static unsigned long long *tcpext_TCPAbortFailed = NULL;    // times unable to send RST due to no memory
222
223     static unsigned long long *tcpext_TCPMemoryPressures = NULL;
224
225 /*
226     // connection rejects
227     static unsigned long long *tcpext_PAWSActive = NULL;  // active connections rejected because of time stamp
228     static unsigned long long *tcpext_PAWSPassive = NULL; // passive connections rejected because of time stamp
229
230     static unsigned long long *tcpext_TCPTimeouts = NULL;
231
232     static unsigned long long *tcpext_TCPDSACKUndo = NULL;
233     static unsigned long long *tcpext_TCPDSACKOldSent = NULL;
234     static unsigned long long *tcpext_TCPDSACKOfoSent = NULL;
235     static unsigned long long *tcpext_TCPDSACKRecv = NULL;
236     static unsigned long long *tcpext_TCPDSACKOfoRecv = NULL;
237     static unsigned long long *tcpext_TCPDSACKIgnoredOld = NULL;
238     static unsigned long long *tcpext_TCPDSACKIgnoredNoUndo = NULL;
239
240
241     static unsigned long long *tcpext_EmbryonicRsts = NULL;
242
243     static unsigned long long *tcpext_PruneCalled = NULL;
244     static unsigned long long *tcpext_RcvPruned = NULL;
245     static unsigned long long *tcpext_OutOfWindowIcmps = NULL;
246     static unsigned long long *tcpext_LockDroppedIcmps = NULL;
247     static unsigned long long *tcpext_ArpFilter = NULL;
248
249     static unsigned long long *tcpext_TW = NULL;
250     static unsigned long long *tcpext_TWRecycled = NULL;
251     static unsigned long long *tcpext_TWKilled = NULL;
252
253     static unsigned long long *tcpext_PAWSEstab = NULL;
254
255     static unsigned long long *tcpext_DelayedACKs = NULL;
256     static unsigned long long *tcpext_DelayedACKLocked = NULL;
257     static unsigned long long *tcpext_DelayedACKLost = NULL;
258
259     static unsigned long long *tcpext_ListenOverflows = NULL;
260     static unsigned long long *tcpext_ListenDrops = NULL;
261
262     static unsigned long long *tcpext_TCPPrequeued = NULL;
263
264     static unsigned long long *tcpext_TCPDirectCopyFromBacklog = NULL;
265     static unsigned long long *tcpext_TCPDirectCopyFromPrequeue = NULL;
266     static unsigned long long *tcpext_TCPPrequeueDropped = NULL;
267
268     static unsigned long long *tcpext_TCPHPHits = NULL;
269     static unsigned long long *tcpext_TCPHPHitsToUser = NULL;
270     static unsigned long long *tcpext_TCPHPAcks = NULL;
271
272     static unsigned long long *tcpext_TCPPureAcks = NULL;
273     static unsigned long long *tcpext_TCPRenoRecovery = NULL;
274
275     static unsigned long long *tcpext_TCPSackRecovery = NULL;
276     static unsigned long long *tcpext_TCPSackFailures = NULL;
277     static unsigned long long *tcpext_TCPSACKReneging = NULL;
278     static unsigned long long *tcpext_TCPSackRecoveryFail = NULL;
279     static unsigned long long *tcpext_TCPSACKDiscard = NULL;
280     static unsigned long long *tcpext_TCPSackShifted = NULL;
281     static unsigned long long *tcpext_TCPSackMerged = NULL;
282     static unsigned long long *tcpext_TCPSackShiftFallback = NULL;
283
284
285     static unsigned long long *tcpext_TCPFullUndo = NULL;
286     static unsigned long long *tcpext_TCPPartialUndo = NULL;
287
288     static unsigned long long *tcpext_TCPLossUndo = NULL;
289     static unsigned long long *tcpext_TCPLostRetransmit = NULL;
290
291     static unsigned long long *tcpext_TCPRenoFailures = NULL;
292
293     static unsigned long long *tcpext_TCPLossFailures = NULL;
294     static unsigned long long *tcpext_TCPFastRetrans = NULL;
295     static unsigned long long *tcpext_TCPForwardRetrans = NULL;
296     static unsigned long long *tcpext_TCPSlowStartRetrans = NULL;
297     static unsigned long long *tcpext_TCPLossProbes = NULL;
298     static unsigned long long *tcpext_TCPLossProbeRecovery = NULL;
299     static unsigned long long *tcpext_TCPRenoRecoveryFail = NULL;
300     static unsigned long long *tcpext_TCPSchedulerFailed = NULL;
301     static unsigned long long *tcpext_TCPRcvCollapsed = NULL;
302
303     static unsigned long long *tcpext_TCPSpuriousRTOs = NULL;
304     static unsigned long long *tcpext_TCPMD5NotFound = NULL;
305     static unsigned long long *tcpext_TCPMD5Unexpected = NULL;
306
307     static unsigned long long *tcpext_TCPBacklogDrop = NULL;
308     static unsigned long long *tcpext_TCPMinTTLDrop = NULL;
309     static unsigned long long *tcpext_TCPDeferAcceptDrop = NULL;
310     static unsigned long long *tcpext_IPReversePathFilter = NULL;
311     static unsigned long long *tcpext_TCPTimeWaitOverflow = NULL;
312     static unsigned long long *tcpext_TCPReqQFullDoCookies = NULL;
313     static unsigned long long *tcpext_TCPReqQFullDrop = NULL;
314     static unsigned long long *tcpext_TCPRetransFail = NULL;
315     static unsigned long long *tcpext_TCPRcvCoalesce = NULL;
316
317     static unsigned long long *tcpext_TCPChallengeACK = NULL;
318     static unsigned long long *tcpext_TCPSYNChallenge = NULL;
319
320     static unsigned long long *tcpext_TCPFastOpenActive = NULL;
321     static unsigned long long *tcpext_TCPFastOpenActiveFail = NULL;
322     static unsigned long long *tcpext_TCPFastOpenPassive = NULL;
323     static unsigned long long *tcpext_TCPFastOpenPassiveFail = NULL;
324     static unsigned long long *tcpext_TCPFastOpenListenOverflow = NULL;
325     static unsigned long long *tcpext_TCPFastOpenCookieReqd = NULL;
326
327     static unsigned long long *tcpext_TCPSpuriousRtxHostQueues = NULL;
328     static unsigned long long *tcpext_BusyPollRxPackets = NULL;
329     static unsigned long long *tcpext_TCPAutoCorking = NULL;
330     static unsigned long long *tcpext_TCPFromZeroWindowAdv = NULL;
331     static unsigned long long *tcpext_TCPToZeroWindowAdv = NULL;
332     static unsigned long long *tcpext_TCPWantZeroWindowAdv = NULL;
333     static unsigned long long *tcpext_TCPSynRetrans = NULL;
334     static unsigned long long *tcpext_TCPOrigDataSent = NULL;
335
336     static unsigned long long *tcpext_TCPHystartTrainDetect = NULL;
337     static unsigned long long *tcpext_TCPHystartTrainCwnd = NULL;
338     static unsigned long long *tcpext_TCPHystartDelayDetect = NULL;
339     static unsigned long long *tcpext_TCPHystartDelayCwnd = NULL;
340
341     static unsigned long long *tcpext_TCPACKSkippedSynRecv = NULL;
342     static unsigned long long *tcpext_TCPACKSkippedPAWS = NULL;
343     static unsigned long long *tcpext_TCPACKSkippedSeq = NULL;
344     static unsigned long long *tcpext_TCPACKSkippedFinWait2 = NULL;
345     static unsigned long long *tcpext_TCPACKSkippedTimeWait = NULL;
346     static unsigned long long *tcpext_TCPACKSkippedChallenge = NULL;
347
348     static unsigned long long *tcpext_TCPWinProbe = NULL;
349     static unsigned long long *tcpext_TCPKeepAlive = NULL;
350
351     static unsigned long long *tcpext_TCPMTUPFail = NULL;
352     static unsigned long long *tcpext_TCPMTUPSuccess = NULL;
353 */
354
355     static unsigned long long *ipext_InNoRoutes = NULL;
356     static unsigned long long *ipext_InTruncatedPkts = NULL;
357     static unsigned long long *ipext_InMcastPkts = NULL;
358     static unsigned long long *ipext_OutMcastPkts = NULL;
359     static unsigned long long *ipext_InBcastPkts = NULL;
360     static unsigned long long *ipext_OutBcastPkts = NULL;
361     static unsigned long long *ipext_InOctets = NULL;
362     static unsigned long long *ipext_OutOctets = NULL;
363     static unsigned long long *ipext_InMcastOctets = NULL;
364     static unsigned long long *ipext_OutMcastOctets = NULL;
365     static unsigned long long *ipext_InBcastOctets = NULL;
366     static unsigned long long *ipext_OutBcastOctets = NULL;
367     static unsigned long long *ipext_InCsumErrors = NULL;
368     static unsigned long long *ipext_InNoECTPkts = NULL;
369     static unsigned long long *ipext_InECT1Pkts = NULL;
370     static unsigned long long *ipext_InECT0Pkts = NULL;
371     static unsigned long long *ipext_InCEPkts = NULL;
372
373     if(unlikely(do_bandwidth == -1)) {
374         do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
375         do_inerrors  = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
376         do_mcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
377         do_bcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
378         do_mcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
379         do_bcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);
380         do_ecn       = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);
381
382         do_tcpext_reorder    = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_ONDEMAND_ONDEMAND);
383         do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
384         do_tcpext_ofo        = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
385         do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
386         do_tcpext_memory     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_ONDEMAND_ONDEMAND);
387
388         hash_ipext = simple_hash("IpExt");
389         hash_tcpext = simple_hash("TcpExt");
390
391         hash_array(ipext_data);
392         hash_array(tcpext_data);
393
394         // Reordering
395         tcpext_TCPFACKReorder = netstat_columns_find(tcpext_data, "TCPFACKReorder");
396         tcpext_TCPSACKReorder = netstat_columns_find(tcpext_data, "TCPSACKReorder");
397         tcpext_TCPRenoReorder = netstat_columns_find(tcpext_data, "TCPRenoReorder");
398         tcpext_TCPTSReorder = netstat_columns_find(tcpext_data, "TCPTSReorder");
399
400         // SYN Cookies
401         tcpext_SyncookiesSent = netstat_columns_find(tcpext_data, "SyncookiesSent");
402         tcpext_SyncookiesRecv = netstat_columns_find(tcpext_data, "SyncookiesRecv");
403         tcpext_SyncookiesFailed = netstat_columns_find(tcpext_data, "SyncookiesFailed");
404
405         // Out Of Order Queue
406         // http://www.spinics.net/lists/netdev/msg204696.html
407         tcpext_TCPOFOQueue = netstat_columns_find(tcpext_data, "TCPOFOQueue"); // Number of packets queued in OFO queue
408         tcpext_TCPOFODrop  = netstat_columns_find(tcpext_data, "TCPOFODrop");  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
409         tcpext_TCPOFOMerge = netstat_columns_find(tcpext_data, "TCPOFOMerge"); // Number of packets in OFO that were merged with other packets.
410         tcpext_OfoPruned   = netstat_columns_find(tcpext_data, "OfoPruned");   // packets dropped from out-of-order queue because of socket buffer overrun
411
412         // connection resets
413         // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
414         tcpext_TCPAbortOnData    = netstat_columns_find(tcpext_data, "TCPAbortOnData");    // connections reset due to unexpected data
415         tcpext_TCPAbortOnClose   = netstat_columns_find(tcpext_data, "TCPAbortOnClose");   // connections reset due to early user close
416         tcpext_TCPAbortOnMemory  = netstat_columns_find(tcpext_data, "TCPAbortOnMemory");  // connections aborted due to memory pressure
417         tcpext_TCPAbortOnTimeout = netstat_columns_find(tcpext_data, "TCPAbortOnTimeout"); // connections aborted due to timeout
418         tcpext_TCPAbortOnLinger  = netstat_columns_find(tcpext_data, "TCPAbortOnLinger");  // connections aborted after user close in linger timeout
419         tcpext_TCPAbortFailed    = netstat_columns_find(tcpext_data, "TCPAbortFailed");    // times unable to send RST due to no memory
420
421         tcpext_TCPMemoryPressures = netstat_columns_find(tcpext_data, "TCPMemoryPressures");
422
423         /*
424         tcpext_EmbryonicRsts = netstat_columns_find(tcpext_data, "EmbryonicRsts");
425         tcpext_PruneCalled = netstat_columns_find(tcpext_data, "PruneCalled");
426         tcpext_RcvPruned = netstat_columns_find(tcpext_data, "RcvPruned");
427         tcpext_OutOfWindowIcmps = netstat_columns_find(tcpext_data, "OutOfWindowIcmps");
428         tcpext_LockDroppedIcmps = netstat_columns_find(tcpext_data, "LockDroppedIcmps");
429         tcpext_ArpFilter = netstat_columns_find(tcpext_data, "ArpFilter");
430         tcpext_TW = netstat_columns_find(tcpext_data, "TW");
431         tcpext_TWRecycled = netstat_columns_find(tcpext_data, "TWRecycled");
432         tcpext_TWKilled = netstat_columns_find(tcpext_data, "TWKilled");
433         tcpext_PAWSPassive = netstat_columns_find(tcpext_data, "PAWSPassive");
434         tcpext_PAWSActive = netstat_columns_find(tcpext_data, "PAWSActive");
435         tcpext_PAWSEstab = netstat_columns_find(tcpext_data, "PAWSEstab");
436         tcpext_DelayedACKs = netstat_columns_find(tcpext_data, "DelayedACKs");
437         tcpext_DelayedACKLocked = netstat_columns_find(tcpext_data, "DelayedACKLocked");
438         tcpext_DelayedACKLost = netstat_columns_find(tcpext_data, "DelayedACKLost");
439         tcpext_ListenOverflows = netstat_columns_find(tcpext_data, "ListenOverflows");
440         tcpext_ListenDrops = netstat_columns_find(tcpext_data, "ListenDrops");
441         tcpext_TCPPrequeued = netstat_columns_find(tcpext_data, "TCPPrequeued");
442         tcpext_TCPDirectCopyFromBacklog = netstat_columns_find(tcpext_data, "TCPDirectCopyFromBacklog");
443         tcpext_TCPDirectCopyFromPrequeue = netstat_columns_find(tcpext_data, "TCPDirectCopyFromPrequeue");
444         tcpext_TCPPrequeueDropped = netstat_columns_find(tcpext_data, "TCPPrequeueDropped");
445         tcpext_TCPHPHits = netstat_columns_find(tcpext_data, "TCPHPHits");
446         tcpext_TCPHPHitsToUser = netstat_columns_find(tcpext_data, "TCPHPHitsToUser");
447         tcpext_TCPPureAcks = netstat_columns_find(tcpext_data, "TCPPureAcks");
448         tcpext_TCPHPAcks = netstat_columns_find(tcpext_data, "TCPHPAcks");
449         tcpext_TCPRenoRecovery = netstat_columns_find(tcpext_data, "TCPRenoRecovery");
450         tcpext_TCPSackRecovery = netstat_columns_find(tcpext_data, "TCPSackRecovery");
451         tcpext_TCPSACKReneging = netstat_columns_find(tcpext_data, "TCPSACKReneging");
452         tcpext_TCPFullUndo = netstat_columns_find(tcpext_data, "TCPFullUndo");
453         tcpext_TCPPartialUndo = netstat_columns_find(tcpext_data, "TCPPartialUndo");
454         tcpext_TCPDSACKUndo = netstat_columns_find(tcpext_data, "TCPDSACKUndo");
455         tcpext_TCPLossUndo = netstat_columns_find(tcpext_data, "TCPLossUndo");
456         tcpext_TCPLostRetransmit = netstat_columns_find(tcpext_data, "TCPLostRetransmit");
457         tcpext_TCPRenoFailures = netstat_columns_find(tcpext_data, "TCPRenoFailures");
458         tcpext_TCPSackFailures = netstat_columns_find(tcpext_data, "TCPSackFailures");
459         tcpext_TCPLossFailures = netstat_columns_find(tcpext_data, "TCPLossFailures");
460         tcpext_TCPFastRetrans = netstat_columns_find(tcpext_data, "TCPFastRetrans");
461         tcpext_TCPForwardRetrans = netstat_columns_find(tcpext_data, "TCPForwardRetrans");
462         tcpext_TCPSlowStartRetrans = netstat_columns_find(tcpext_data, "TCPSlowStartRetrans");
463         tcpext_TCPTimeouts = netstat_columns_find(tcpext_data, "TCPTimeouts");
464         tcpext_TCPLossProbes = netstat_columns_find(tcpext_data, "TCPLossProbes");
465         tcpext_TCPLossProbeRecovery = netstat_columns_find(tcpext_data, "TCPLossProbeRecovery");
466         tcpext_TCPRenoRecoveryFail = netstat_columns_find(tcpext_data, "TCPRenoRecoveryFail");
467         tcpext_TCPSackRecoveryFail = netstat_columns_find(tcpext_data, "TCPSackRecoveryFail");
468         tcpext_TCPSchedulerFailed = netstat_columns_find(tcpext_data, "TCPSchedulerFailed");
469         tcpext_TCPRcvCollapsed = netstat_columns_find(tcpext_data, "TCPRcvCollapsed");
470         tcpext_TCPDSACKOldSent = netstat_columns_find(tcpext_data, "TCPDSACKOldSent");
471         tcpext_TCPDSACKOfoSent = netstat_columns_find(tcpext_data, "TCPDSACKOfoSent");
472         tcpext_TCPDSACKRecv = netstat_columns_find(tcpext_data, "TCPDSACKRecv");
473         tcpext_TCPDSACKOfoRecv = netstat_columns_find(tcpext_data, "TCPDSACKOfoRecv");
474         tcpext_TCPSACKDiscard = netstat_columns_find(tcpext_data, "TCPSACKDiscard");
475         tcpext_TCPDSACKIgnoredOld = netstat_columns_find(tcpext_data, "TCPDSACKIgnoredOld");
476         tcpext_TCPDSACKIgnoredNoUndo = netstat_columns_find(tcpext_data, "TCPDSACKIgnoredNoUndo");
477         tcpext_TCPSpuriousRTOs = netstat_columns_find(tcpext_data, "TCPSpuriousRTOs");
478         tcpext_TCPMD5NotFound = netstat_columns_find(tcpext_data, "TCPMD5NotFound");
479         tcpext_TCPMD5Unexpected = netstat_columns_find(tcpext_data, "TCPMD5Unexpected");
480         tcpext_TCPSackShifted = netstat_columns_find(tcpext_data, "TCPSackShifted");
481         tcpext_TCPSackMerged = netstat_columns_find(tcpext_data, "TCPSackMerged");
482         tcpext_TCPSackShiftFallback = netstat_columns_find(tcpext_data, "TCPSackShiftFallback");
483         tcpext_TCPBacklogDrop = netstat_columns_find(tcpext_data, "TCPBacklogDrop");
484         tcpext_TCPMinTTLDrop = netstat_columns_find(tcpext_data, "TCPMinTTLDrop");
485         tcpext_TCPDeferAcceptDrop = netstat_columns_find(tcpext_data, "TCPDeferAcceptDrop");
486         tcpext_IPReversePathFilter = netstat_columns_find(tcpext_data, "IPReversePathFilter");
487         tcpext_TCPTimeWaitOverflow = netstat_columns_find(tcpext_data, "TCPTimeWaitOverflow");
488         tcpext_TCPReqQFullDoCookies = netstat_columns_find(tcpext_data, "TCPReqQFullDoCookies");
489         tcpext_TCPReqQFullDrop = netstat_columns_find(tcpext_data, "TCPReqQFullDrop");
490         tcpext_TCPRetransFail = netstat_columns_find(tcpext_data, "TCPRetransFail");
491         tcpext_TCPRcvCoalesce = netstat_columns_find(tcpext_data, "TCPRcvCoalesce");
492         tcpext_TCPChallengeACK = netstat_columns_find(tcpext_data, "TCPChallengeACK");
493         tcpext_TCPSYNChallenge = netstat_columns_find(tcpext_data, "TCPSYNChallenge");
494         tcpext_TCPFastOpenActive = netstat_columns_find(tcpext_data, "TCPFastOpenActive");
495         tcpext_TCPFastOpenActiveFail = netstat_columns_find(tcpext_data, "TCPFastOpenActiveFail");
496         tcpext_TCPFastOpenPassive = netstat_columns_find(tcpext_data, "TCPFastOpenPassive");
497         tcpext_TCPFastOpenPassiveFail = netstat_columns_find(tcpext_data, "TCPFastOpenPassiveFail");
498         tcpext_TCPFastOpenListenOverflow = netstat_columns_find(tcpext_data, "TCPFastOpenListenOverflow");
499         tcpext_TCPFastOpenCookieReqd = netstat_columns_find(tcpext_data, "TCPFastOpenCookieReqd");
500         tcpext_TCPSpuriousRtxHostQueues = netstat_columns_find(tcpext_data, "TCPSpuriousRtxHostQueues");
501         tcpext_BusyPollRxPackets = netstat_columns_find(tcpext_data, "BusyPollRxPackets");
502         tcpext_TCPAutoCorking = netstat_columns_find(tcpext_data, "TCPAutoCorking");
503         tcpext_TCPFromZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPFromZeroWindowAdv");
504         tcpext_TCPToZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPToZeroWindowAdv");
505         tcpext_TCPWantZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPWantZeroWindowAdv");
506         tcpext_TCPSynRetrans = netstat_columns_find(tcpext_data, "TCPSynRetrans");
507         tcpext_TCPOrigDataSent = netstat_columns_find(tcpext_data, "TCPOrigDataSent");
508         tcpext_TCPHystartTrainDetect = netstat_columns_find(tcpext_data, "TCPHystartTrainDetect");
509         tcpext_TCPHystartTrainCwnd = netstat_columns_find(tcpext_data, "TCPHystartTrainCwnd");
510         tcpext_TCPHystartDelayDetect = netstat_columns_find(tcpext_data, "TCPHystartDelayDetect");
511         tcpext_TCPHystartDelayCwnd = netstat_columns_find(tcpext_data, "TCPHystartDelayCwnd");
512         tcpext_TCPACKSkippedSynRecv = netstat_columns_find(tcpext_data, "TCPACKSkippedSynRecv");
513         tcpext_TCPACKSkippedPAWS = netstat_columns_find(tcpext_data, "TCPACKSkippedPAWS");
514         tcpext_TCPACKSkippedSeq = netstat_columns_find(tcpext_data, "TCPACKSkippedSeq");
515         tcpext_TCPACKSkippedFinWait2 = netstat_columns_find(tcpext_data, "TCPACKSkippedFinWait2");
516         tcpext_TCPACKSkippedTimeWait = netstat_columns_find(tcpext_data, "TCPACKSkippedTimeWait");
517         tcpext_TCPACKSkippedChallenge = netstat_columns_find(tcpext_data, "TCPACKSkippedChallenge");
518         tcpext_TCPWinProbe = netstat_columns_find(tcpext_data, "TCPWinProbe");
519         tcpext_TCPKeepAlive = netstat_columns_find(tcpext_data, "TCPKeepAlive");
520         tcpext_TCPMTUPFail = netstat_columns_find(tcpext_data, "TCPMTUPFail");
521         tcpext_TCPMTUPSuccess = netstat_columns_find(tcpext_data, "TCPMTUPSuccess");
522 */
523         ipext_InNoRoutes = netstat_columns_find(ipext_data, "InNoRoutes");
524         ipext_InTruncatedPkts = netstat_columns_find(ipext_data, "InTruncatedPkts");
525         ipext_InMcastPkts = netstat_columns_find(ipext_data, "InMcastPkts");
526         ipext_OutMcastPkts = netstat_columns_find(ipext_data, "OutMcastPkts");
527         ipext_InBcastPkts = netstat_columns_find(ipext_data, "InBcastPkts");
528         ipext_OutBcastPkts = netstat_columns_find(ipext_data, "OutBcastPkts");
529         ipext_InOctets = netstat_columns_find(ipext_data, "InOctets");
530         ipext_OutOctets = netstat_columns_find(ipext_data, "OutOctets");
531         ipext_InMcastOctets = netstat_columns_find(ipext_data, "InMcastOctets");
532         ipext_OutMcastOctets = netstat_columns_find(ipext_data, "OutMcastOctets");
533         ipext_InBcastOctets = netstat_columns_find(ipext_data, "InBcastOctets");
534         ipext_OutBcastOctets = netstat_columns_find(ipext_data, "OutBcastOctets");
535         ipext_InCsumErrors = netstat_columns_find(ipext_data, "InCsumErrors");
536         ipext_InNoECTPkts = netstat_columns_find(ipext_data, "InNoECTPkts");
537         ipext_InECT1Pkts = netstat_columns_find(ipext_data, "InECT1Pkts");
538         ipext_InECT0Pkts = netstat_columns_find(ipext_data, "InECT0Pkts");
539         ipext_InCEPkts = netstat_columns_find(ipext_data, "InCEPkts");
540     }
541
542     if(unlikely(!ff)) {
543         char filename[FILENAME_MAX + 1];
544         snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat");
545         ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
546         if(unlikely(!ff)) return 1;
547     }
548
549     ff = procfile_readall(ff);
550     if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
551
552     uint32_t lines = procfile_lines(ff), l;
553     uint32_t words;
554
555     for(l = 0; l < lines ;l++) {
556         char *key = procfile_lineword(ff, l, 0);
557         uint32_t hash = simple_hash(key);
558
559         if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
560             uint32_t h = l++;
561
562             if(unlikely(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0)) {
563                 error("Cannot read IpExt line from /proc/net/netstat.");
564                 break;
565             }
566             words = procfile_linewords(ff, l);
567             if(unlikely(words < 2)) {
568                 error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %u.", words);
569                 continue;
570             }
571
572             parse_line_pair(ff, ipext_data, h, l);
573
574             RRDSET *st;
575
576             // --------------------------------------------------------------------
577
578             if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InOctets || *ipext_OutOctets))) {
579                 do_bandwidth = CONFIG_ONDEMAND_YES;
580                 st = rrdset_find("system.ipv4");
581                 if(unlikely(!st)) {
582                     st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
583
584                     rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
585                     rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
586                 }
587                 else rrdset_next(st);
588
589                 rrddim_set(st, "InOctets", *ipext_InOctets);
590                 rrddim_set(st, "OutOctets", *ipext_OutOctets);
591                 rrdset_done(st);
592             }
593
594             // --------------------------------------------------------------------
595
596             if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InNoRoutes || *ipext_InTruncatedPkts))) {
597                 do_inerrors = CONFIG_ONDEMAND_YES;
598                 st = rrdset_find("ipv4.inerrors");
599                 if(unlikely(!st)) {
600                     st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
601                     st->isdetail = 1;
602
603                     rrddim_add(st, "InNoRoutes", "noroutes", 1, 1, RRDDIM_INCREMENTAL);
604                     rrddim_add(st, "InTruncatedPkts", "truncated", 1, 1, RRDDIM_INCREMENTAL);
605                     rrddim_add(st, "InCsumErrors", "checksum", 1, 1, RRDDIM_INCREMENTAL);
606                 }
607                 else rrdset_next(st);
608
609                 rrddim_set(st, "InNoRoutes", *ipext_InNoRoutes);
610                 rrddim_set(st, "InTruncatedPkts", *ipext_InTruncatedPkts);
611                 rrddim_set(st, "InCsumErrors", *ipext_InCsumErrors);
612                 rrdset_done(st);
613             }
614
615             // --------------------------------------------------------------------
616
617             if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastOctets || *ipext_OutMcastOctets))) {
618                 do_mcast = CONFIG_ONDEMAND_YES;
619                 st = rrdset_find("ipv4.mcast");
620                 if(unlikely(!st)) {
621                     st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
622                     st->isdetail = 1;
623
624                     rrddim_add(st, "InMcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
625                     rrddim_add(st, "OutMcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
626                 }
627                 else rrdset_next(st);
628
629                 rrddim_set(st, "InMcastOctets", *ipext_InMcastOctets);
630                 rrddim_set(st, "OutMcastOctets", *ipext_OutMcastOctets);
631                 rrdset_done(st);
632             }
633
634             // --------------------------------------------------------------------
635
636             if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastOctets || *ipext_OutBcastOctets))) {
637                 do_bcast = CONFIG_ONDEMAND_YES;
638                 st = rrdset_find("ipv4.bcast");
639                 if(unlikely(!st)) {
640                     st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
641                     st->isdetail = 1;
642
643                     rrddim_add(st, "InBcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
644                     rrddim_add(st, "OutBcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
645                 }
646                 else rrdset_next(st);
647
648                 rrddim_set(st, "InBcastOctets", *ipext_InBcastOctets);
649                 rrddim_set(st, "OutBcastOctets", *ipext_OutBcastOctets);
650                 rrdset_done(st);
651             }
652
653             // --------------------------------------------------------------------
654
655             if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastPkts || *ipext_OutMcastPkts))) {
656                 do_mcast_p = CONFIG_ONDEMAND_YES;
657                 st = rrdset_find("ipv4.mcastpkts");
658                 if(unlikely(!st)) {
659                     st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 8600, update_every, RRDSET_TYPE_LINE);
660                     st->isdetail = 1;
661
662                     rrddim_add(st, "InMcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
663                     rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
664                 }
665                 else rrdset_next(st);
666
667                 rrddim_set(st, "InMcastPkts", *ipext_InMcastPkts);
668                 rrddim_set(st, "OutMcastPkts", *ipext_OutMcastPkts);
669                 rrdset_done(st);
670             }
671
672             // --------------------------------------------------------------------
673
674             if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastPkts || *ipext_OutBcastPkts))) {
675                 do_bcast_p = CONFIG_ONDEMAND_YES;
676                 st = rrdset_find("ipv4.bcastpkts");
677                 if(unlikely(!st)) {
678                     st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
679                     st->isdetail = 1;
680
681                     rrddim_add(st, "InBcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
682                     rrddim_add(st, "OutBcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
683                 }
684                 else rrdset_next(st);
685
686                 rrddim_set(st, "InBcastPkts", *ipext_InBcastPkts);
687                 rrddim_set(st, "OutBcastPkts", *ipext_OutBcastPkts);
688                 rrdset_done(st);
689             }
690
691             // --------------------------------------------------------------------
692
693             if(do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InCEPkts || *ipext_InECT0Pkts || *ipext_InECT1Pkts || *ipext_InNoECTPkts))) {
694                 do_ecn = CONFIG_ONDEMAND_YES;
695                 st = rrdset_find("ipv4.ecnpkts");
696                 if(unlikely(!st)) {
697                     st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
698                     st->isdetail = 1;
699
700                     rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
701                     rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
702                     rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL);
703                     rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL);
704                 }
705                 else rrdset_next(st);
706
707                 rrddim_set(st, "InCEPkts", *ipext_InCEPkts);
708                 rrddim_set(st, "InNoECTPkts", *ipext_InNoECTPkts);
709                 rrddim_set(st, "InECT0Pkts", *ipext_InECT0Pkts);
710                 rrddim_set(st, "InECT1Pkts", *ipext_InECT1Pkts);
711                 rrdset_done(st);
712             }
713         }
714         else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
715             uint32_t h = l++;
716
717             if(unlikely(strcmp(procfile_lineword(ff, l, 0), "TcpExt") != 0)) {
718                 error("Cannot read TcpExt line from /proc/net/netstat.");
719                 break;
720             }
721             words = procfile_linewords(ff, l);
722             if(unlikely(words < 2)) {
723                 error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %u.", words);
724                 continue;
725             }
726
727             parse_line_pair(ff, tcpext_data, h, l);
728
729             RRDSET *st;
730
731             // --------------------------------------------------------------------
732
733             if(do_tcpext_memory == CONFIG_ONDEMAND_YES || (do_tcpext_memory == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPMemoryPressures))) {
734                 do_tcpext_memory = CONFIG_ONDEMAND_YES;
735                 st = rrdset_find("ipv4.tcpmemorypressures");
736                 if(unlikely(!st)) {
737                     st = rrdset_create("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures", "events/s", 3000, update_every, RRDSET_TYPE_LINE);
738
739                     rrddim_add(st, "TCPMemoryPressures",   "pressures",  1, 1, RRDDIM_INCREMENTAL);
740                 }
741                 else rrdset_next(st);
742
743                 rrddim_set(st, "TCPMemoryPressures", *tcpext_TCPMemoryPressures);
744                 rrdset_done(st);
745             }
746
747             // --------------------------------------------------------------------
748
749             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))) {
750                 do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
751                 st = rrdset_find("ipv4.tcpconnaborts");
752                 if(unlikely(!st)) {
753                     st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);
754
755                     rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
756                     rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
757                     rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
758                     rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
759                     rrddim_add(st, "TCPAbortOnLinger",  "linger",      1, 1, RRDDIM_INCREMENTAL);
760                     rrddim_add(st, "TCPAbortFailed",    "failed",     -1, 1, RRDDIM_INCREMENTAL);
761                 }
762                 else rrdset_next(st);
763
764                 rrddim_set(st, "TCPAbortOnData",    *tcpext_TCPAbortOnData);
765                 rrddim_set(st, "TCPAbortOnClose",   *tcpext_TCPAbortOnClose);
766                 rrddim_set(st, "TCPAbortOnMemory",  *tcpext_TCPAbortOnMemory);
767                 rrddim_set(st, "TCPAbortOnTimeout", *tcpext_TCPAbortOnTimeout);
768                 rrddim_set(st, "TCPAbortOnLinger",  *tcpext_TCPAbortOnLinger);
769                 rrddim_set(st, "TCPAbortFailed",    *tcpext_TCPAbortFailed);
770                 rrdset_done(st);
771             }
772             // --------------------------------------------------------------------
773
774             if(do_tcpext_reorder == CONFIG_ONDEMAND_YES || (do_tcpext_reorder == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPRenoReorder || *tcpext_TCPFACKReorder || *tcpext_TCPSACKReorder || *tcpext_TCPTSReorder))) {
775                 do_tcpext_reorder = CONFIG_ONDEMAND_YES;
776                 st = rrdset_find("ipv4.tcpreorders");
777                 if(unlikely(!st)) {
778                     st = rrdset_create("ipv4", "tcpreorders", NULL, "tcp", NULL, "TCP Reordered Packets by Detection Method", "packets/s", 3020, update_every, RRDSET_TYPE_LINE);
779
780                     rrddim_add(st, "TCPTSReorder",   "timestamp",   1, 1, RRDDIM_INCREMENTAL);
781                     rrddim_add(st, "TCPSACKReorder", "sack",        1, 1, RRDDIM_INCREMENTAL);
782                     rrddim_add(st, "TCPFACKReorder", "fack",        1, 1, RRDDIM_INCREMENTAL);
783                     rrddim_add(st, "TCPRenoReorder", "reno",        1, 1, RRDDIM_INCREMENTAL);
784                 }
785                 else rrdset_next(st);
786
787                 rrddim_set(st, "TCPTSReorder",   *tcpext_TCPTSReorder);
788                 rrddim_set(st, "TCPSACKReorder", *tcpext_TCPSACKReorder);
789                 rrddim_set(st, "TCPFACKReorder", *tcpext_TCPFACKReorder);
790                 rrddim_set(st, "TCPRenoReorder", *tcpext_TCPRenoReorder);
791                 rrdset_done(st);
792             }
793
794             // --------------------------------------------------------------------
795
796             if(do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPOFOQueue || *tcpext_TCPOFODrop || *tcpext_TCPOFOMerge))) {
797                 do_tcpext_ofo = CONFIG_ONDEMAND_YES;
798                 st = rrdset_find("ipv4.tcpofo");
799                 if(unlikely(!st)) {
800                     st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);
801
802                     rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
803                     rrddim_add(st, "TCPOFODrop",  "dropped", -1, 1, RRDDIM_INCREMENTAL);
804                     rrddim_add(st, "TCPOFOMerge", "merged",   1, 1, RRDDIM_INCREMENTAL);
805                     rrddim_add(st, "OfoPruned",   "pruned",  -1, 1, RRDDIM_INCREMENTAL);
806                 }
807                 else rrdset_next(st);
808
809                 rrddim_set(st, "TCPOFOQueue",   *tcpext_TCPOFOQueue);
810                 rrddim_set(st, "TCPOFODrop",    *tcpext_TCPOFODrop);
811                 rrddim_set(st, "TCPOFOMerge",   *tcpext_TCPOFOMerge);
812                 rrddim_set(st, "OfoPruned",     *tcpext_OfoPruned);
813                 rrdset_done(st);
814             }
815
816             // --------------------------------------------------------------------
817
818             if(do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_SyncookiesSent || *tcpext_SyncookiesRecv || *tcpext_SyncookiesFailed))) {
819                 do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
820                 st = rrdset_find("ipv4.tcpsyncookies");
821                 if(unlikely(!st)) {
822                     st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);
823
824                     rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
825                     rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
826                     rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
827                 }
828                 else rrdset_next(st);
829
830                 rrddim_set(st, "SyncookiesRecv",   *tcpext_SyncookiesRecv);
831                 rrddim_set(st, "SyncookiesSent",   *tcpext_SyncookiesSent);
832                 rrddim_set(st, "SyncookiesFailed", *tcpext_SyncookiesFailed);
833                 rrdset_done(st);
834             }
835
836         }
837     }
838
839     return 0;
840 }