]> arthur.barton.de Git - netdata.git/blob - src/proc_net_snmp.c
Merge pull request #1998 from ktsaou/master
[netdata.git] / src / proc_net_snmp.c
1 #include "common.h"
2
3 #define RRD_TYPE_NET_SNMP           "ipv4"
4
5 struct netstat_columns {
6     char *name;
7     uint32_t hash;
8     unsigned long long value;
9     int multiplier;     // not needed everywhere
10     char *label;        // not needed everywhere
11 };
12
13 static struct netstat_columns ip_data[] = {
14 //    { "Forwarding", 0, 0, 1, NULL },
15 //    { "DefaultTTL", 0, 0, 1, NULL },
16     { "InReceives", 0, 0, 1, NULL },
17     { "InHdrErrors", 0, 0, 1, NULL },
18     { "InAddrErrors", 0, 0, 1, NULL },
19     { "ForwDatagrams", 0, 0, 1, NULL },
20     { "InUnknownProtos", 0, 0, 1, NULL },
21     { "InDiscards", 0, 0, 1, NULL },
22     { "InDelivers", 0, 0, 1, NULL },
23     { "OutRequests", 0, 0, 1, NULL },
24     { "OutDiscards", 0, 0, 1, NULL },
25     { "OutNoRoutes", 0, 0, 1, NULL },
26 //    { "ReasmTimeout", 0, 0, 1, NULL },
27     { "ReasmReqds", 0, 0, 1, NULL },
28     { "ReasmOKs", 0, 0, 1, NULL },
29     { "ReasmFails", 0, 0, 1, NULL },
30     { "FragOKs", 0, 0, 1, NULL },
31     { "FragFails", 0, 0, 1, NULL },
32     { "FragCreates", 0, 0, 1, NULL },
33     { NULL, 0, 0, 0, NULL }
34 };
35
36 static struct netstat_columns icmp_data[] = {
37     { "InMsgs", 0, 0, 1, NULL },
38     { "OutMsgs", 0, 0, -1, NULL },
39     { "InErrors", 0, 0, 1, NULL },
40     { "OutErrors", 0, 0, -1, NULL },
41     { "InCsumErrors", 0, 0, 1, NULL },
42
43     // all these are available in icmpmsg
44 //    { "InDestUnreachs", 0, 0, 1, NULL },
45 //    { "OutDestUnreachs", 0, 0, -1, NULL },
46 //    { "InTimeExcds", 0, 0, 1, NULL },
47 //    { "OutTimeExcds", 0, 0, -1, NULL },
48 //    { "InParmProbs", 0, 0, 1, NULL },
49 //    { "OutParmProbs", 0, 0, -1, NULL },
50 //    { "InSrcQuenchs", 0, 0, 1, NULL },
51 //    { "OutSrcQuenchs", 0, 0, -1, NULL },
52 //    { "InRedirects", 0, 0, 1, NULL },
53 //    { "OutRedirects", 0, 0, -1, NULL },
54 //    { "InEchos", 0, 0, 1, NULL },
55 //    { "OutEchos", 0, 0, -1, NULL },
56 //    { "InEchoReps", 0, 0, 1, NULL },
57 //    { "OutEchoReps", 0, 0, -1, NULL },
58 //    { "InTimestamps", 0, 0, 1, NULL },
59 //    { "OutTimestamps", 0, 0, -1, NULL },
60 //    { "InTimestampReps", 0, 0, 1, NULL },
61 //    { "OutTimestampReps", 0, 0, -1, NULL },
62 //    { "InAddrMasks", 0, 0, 1, NULL },
63 //    { "OutAddrMasks", 0, 0, -1, NULL },
64 //    { "InAddrMaskReps", 0, 0, 1, NULL },
65 //    { "OutAddrMaskReps", 0, 0, -1, NULL },
66
67     { NULL, 0, 0, 0, NULL }
68 };
69
70 static struct netstat_columns icmpmsg_data[] = {
71     { "InType0", 0, 0, 1, "InEchoReps" },
72     { "OutType0", 0, 0, -1, "OutEchoReps" },
73 //    { "InType1", 0, 0, 1, NULL },                   // unassigned
74 //    { "OutType1", 0, 0, -1, NULL },                 // unassigned
75 //    { "InType2", 0, 0, 1, NULL },                   // unassigned
76 //    { "OutType2", 0, 0, -1, NULL },                 // unassigned
77     { "InType3", 0, 0, 1, "InDestUnreachs" },
78     { "OutType3", 0, 0, -1, "OutDestUnreachs" },
79 //    { "InType4", 0, 0, 1, "InSrcQuenchs" },         // deprecated
80 //    { "OutType4", 0, 0, -1, "OutSrcQuenchs" },      // deprecated
81     { "InType5", 0, 0, 1, "InRedirects" },
82     { "OutType5", 0, 0, -1, "OutRedirects" },
83 //    { "InType6", 0, 0, 1, "InAlterHostAddr" },      // deprecated
84 //    { "OutType6", 0, 0, -1, "OutAlterHostAddr" },   // deprecated
85 //    { "InType7", 0, 0, 1, NULL },                   // unassigned
86 //    { "OutType7", 0, 0, -1, NULL },                 // unassigned
87     { "InType8", 0, 0, 1, "InEchos" },
88     { "OutType8", 0, 0, -1, "OutEchos" },
89     { "InType9", 0, 0, 1, "InRouterAdvert" },
90     { "OutType9", 0, 0, -1, "OutRouterAdvert" },
91     { "InType10", 0, 0, 1, "InRouterSelect" },
92     { "OutType10", 0, 0, -1, "OutRouterSelect" },
93     { "InType11", 0, 0, 1, "InTimeExcds" },
94     { "OutType11", 0, 0, -1, "OutTimeExcds" },
95     { "InType12", 0, 0, 1, "InParmProbs" },
96     { "OutType12", 0, 0, -1, "OutParmProbs" },
97     { "InType13", 0, 0, 1, "InTimestamps" },
98     { "OutType13", 0, 0, -1, "OutTimestamps" },
99     { "InType14", 0, 0, 1, "InTimestampReps" },
100     { "OutType14", 0, 0, -1, "OutTimestampReps" },
101 //    { "InType15", 0, 0, 1, "InInfos" },             // deprecated
102 //    { "OutType15", 0, 0, -1, "OutInfos" },          // deprecated
103 //    { "InType16", 0, 0, 1, "InInfoReps" },          // deprecated
104 //    { "OutType16", 0, 0, -1, "OutInfoReps" },       // deprecated
105 //    { "InType17", 0, 0, 1, "InAddrMasks" },         // deprecated
106 //    { "OutType17", 0, 0, -1, "OutAddrMasks" },      // deprecated
107 //    { "InType18", 0, 0, 1, "InAddrMaskReps" },      // deprecated
108 //    { "OutType18", 0, 0, -1, "OutAddrMaskReps" },   // deprecated
109 //    { "InType30", 0, 0, 1, "InTraceroute" },        // deprecated
110 //    { "OutType30", 0, 0, -1, "OutTraceroute" },     // deprecated
111     { NULL, 0, 0, 0, NULL }
112 };
113
114 static struct netstat_columns tcp_data[] = {
115 //    { "RtoAlgorithm", 0, 0, 1, NULL },
116 //    { "RtoMin", 0, 0, 1, NULL },
117 //    { "RtoMax", 0, 0, 1, NULL },
118 //    { "MaxConn", 0, 0, 1, NULL },
119     { "ActiveOpens", 0, 0, 1, NULL },
120     { "PassiveOpens", 0, 0, 1, NULL },
121     { "AttemptFails", 0, 0, 1, NULL },
122     { "EstabResets", 0, 0, 1, NULL },
123     { "CurrEstab", 0, 0, 1, NULL },
124     { "InSegs", 0, 0, 1, NULL },
125     { "OutSegs", 0, 0, 1, NULL },
126     { "RetransSegs", 0, 0, 1, NULL },
127     { "InErrs", 0, 0, 1, NULL },
128     { "OutRsts", 0, 0, 1, NULL },
129     { "InCsumErrors", 0, 0, 1, NULL },
130     { NULL, 0, 0, 0, NULL }
131 };
132
133 static struct netstat_columns udp_data[] = {
134     { "InDatagrams", 0, 0, 1, NULL },
135     { "NoPorts", 0, 0, 1, NULL },
136     { "InErrors", 0, 0, 1, NULL },
137     { "OutDatagrams", 0, 0, 1, NULL },
138     { "RcvbufErrors", 0, 0, 1, NULL },
139     { "SndbufErrors", 0, 0, 1, NULL },
140     { "InCsumErrors", 0, 0, 1, NULL },
141     { "IgnoredMulti", 0, 0, 1, NULL },
142     { NULL, 0, 0, 0, NULL }
143 };
144
145 static struct netstat_columns udplite_data[] = {
146     { "InDatagrams", 0, 0, 1, NULL },
147     { "NoPorts", 0, 0, 1, NULL },
148     { "InErrors", 0, 0, 1, NULL },
149     { "OutDatagrams", 0, 0, 1, NULL },
150     { "RcvbufErrors", 0, 0, 1, NULL },
151     { "SndbufErrors", 0, 0, 1, NULL },
152     { "InCsumErrors", 0, 0, 1, NULL },
153     { "IgnoredMulti", 0, 0, 1, NULL },
154     { NULL, 0, 0, 0, NULL }
155 };
156
157 static void hash_array(struct netstat_columns *nc) {
158     int i;
159
160     for(i = 0; nc[i].name ;i++)
161         nc[i].hash = simple_hash(nc[i].name);
162 }
163
164 static unsigned long long *netstat_columns_find(struct netstat_columns *nc, const char *name) {
165     uint32_t i, hash = simple_hash(name);
166
167     for(i = 0; nc[i].name ;i++)
168         if(unlikely(nc[i].hash == hash && !strcmp(nc[i].name, name)))
169             return &nc[i].value;
170
171     fatal("Cannot find key '%s' in /proc/net/snmp internal array.", name);
172 }
173
174 static void parse_line_pair(procfile *ff, struct netstat_columns *nc, size_t header_line, size_t values_line) {
175     size_t hwords = procfile_linewords(ff, header_line);
176     size_t vwords = procfile_linewords(ff, values_line);
177     size_t w, i;
178
179     if(unlikely(vwords > hwords)) {
180         error("File /proc/net/snmp on header line %zu has %zu words, but on value line %zu has %zu words.", header_line, hwords, values_line, vwords);
181         vwords = hwords;
182     }
183
184     for(w = 1; w < vwords ;w++) {
185         char *key = procfile_lineword(ff, header_line, w);
186         uint32_t hash = simple_hash(key);
187
188         for(i = 0 ; nc[i].name ;i++) {
189             if(unlikely(hash == nc[i].hash && !strcmp(key, nc[i].name))) {
190                 nc[i].value = str2ull(procfile_lineword(ff, values_line, w));
191                 break;
192             }
193         }
194     }
195 }
196
197 int do_proc_net_snmp(int update_every, usec_t dt) {
198     (void)dt;
199
200     static procfile *ff = NULL;
201     static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
202         do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1,
203         do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1, do_udplite_packets = -1;
204     static uint32_t hash_ip = 0, hash_icmp = 0, hash_tcp = 0, hash_udp = 0, hash_icmpmsg = 0, hash_udplite = 0;
205
206     //static unsigned long long *ip_Forwarding = NULL;
207     //static unsigned long long *ip_DefaultTTL = NULL;
208     static unsigned long long *ip_InReceives = NULL;
209     static unsigned long long *ip_InHdrErrors = NULL;
210     static unsigned long long *ip_InAddrErrors = NULL;
211     static unsigned long long *ip_ForwDatagrams = NULL;
212     static unsigned long long *ip_InUnknownProtos = NULL;
213     static unsigned long long *ip_InDiscards = NULL;
214     static unsigned long long *ip_InDelivers = NULL;
215     static unsigned long long *ip_OutRequests = NULL;
216     static unsigned long long *ip_OutDiscards = NULL;
217     static unsigned long long *ip_OutNoRoutes = NULL;
218     //static unsigned long long *ip_ReasmTimeout = NULL;
219     static unsigned long long *ip_ReasmReqds = NULL;
220     static unsigned long long *ip_ReasmOKs = NULL;
221     static unsigned long long *ip_ReasmFails = NULL;
222     static unsigned long long *ip_FragOKs = NULL;
223     static unsigned long long *ip_FragFails = NULL;
224     static unsigned long long *ip_FragCreates = NULL;
225
226     static unsigned long long *icmp_InMsgs = NULL;
227     static unsigned long long *icmp_OutMsgs = NULL;
228     static unsigned long long *icmp_InErrors = NULL;
229     static unsigned long long *icmp_OutErrors = NULL;
230     static unsigned long long *icmp_InCsumErrors = NULL;
231
232     //static unsigned long long *tcp_RtoAlgorithm = NULL;
233     //static unsigned long long *tcp_RtoMin = NULL;
234     //static unsigned long long *tcp_RtoMax = NULL;
235     //static unsigned long long *tcp_MaxConn = NULL;
236     static unsigned long long *tcp_ActiveOpens = NULL;
237     static unsigned long long *tcp_PassiveOpens = NULL;
238     static unsigned long long *tcp_AttemptFails = NULL;
239     static unsigned long long *tcp_EstabResets = NULL;
240     static unsigned long long *tcp_CurrEstab = NULL;
241     static unsigned long long *tcp_InSegs = NULL;
242     static unsigned long long *tcp_OutSegs = NULL;
243     static unsigned long long *tcp_RetransSegs = NULL;
244     static unsigned long long *tcp_InErrs = NULL;
245     static unsigned long long *tcp_OutRsts = NULL;
246     static unsigned long long *tcp_InCsumErrors = NULL;
247
248     static unsigned long long *udp_InDatagrams = NULL;
249     static unsigned long long *udp_NoPorts = NULL;
250     static unsigned long long *udp_InErrors = NULL;
251     static unsigned long long *udp_OutDatagrams = NULL;
252     static unsigned long long *udp_RcvbufErrors = NULL;
253     static unsigned long long *udp_SndbufErrors = NULL;
254     static unsigned long long *udp_InCsumErrors = NULL;
255     static unsigned long long *udp_IgnoredMulti = NULL;
256
257     static unsigned long long *udplite_InDatagrams = NULL;
258     static unsigned long long *udplite_NoPorts = NULL;
259     static unsigned long long *udplite_InErrors = NULL;
260     static unsigned long long *udplite_OutDatagrams = NULL;
261     static unsigned long long *udplite_RcvbufErrors = NULL;
262     static unsigned long long *udplite_SndbufErrors = NULL;
263     static unsigned long long *udplite_InCsumErrors = NULL;
264     static unsigned long long *udplite_IgnoredMulti = NULL;
265
266     if(unlikely(do_ip_packets == -1)) {
267         do_ip_packets       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1);
268         do_ip_fragsout      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", 1);
269         do_ip_fragsin       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1);
270         do_ip_errors        = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 errors", 1);
271         do_tcp_sockets      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", 1);
272         do_tcp_packets      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", 1);
273         do_tcp_errors       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", 1);
274         do_tcp_handshake    = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", 1);
275         do_udp_packets      = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", 1);
276         do_udp_errors       = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", 1);
277         do_icmp_packets     = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP packets", 1);
278         do_icmpmsg          = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP messages", 1);
279         do_udplite_packets  = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDPLite packets", 1);
280
281         hash_ip = simple_hash("Ip");
282         hash_tcp = simple_hash("Tcp");
283         hash_udp = simple_hash("Udp");
284         hash_icmp = simple_hash("Icmp");
285         hash_icmpmsg = simple_hash("IcmpMsg");
286         hash_udplite = simple_hash("UdpLite");
287
288         hash_array(ip_data);
289         hash_array(tcp_data);
290         hash_array(udp_data);
291         hash_array(icmp_data);
292         hash_array(icmpmsg_data);
293         hash_array(udplite_data);
294
295         //ip_Forwarding = netstat_columns_find(ip_data, "Forwarding");
296         //ip_DefaultTTL = netstat_columns_find(ip_data, "DefaultTTL");
297         ip_InReceives = netstat_columns_find(ip_data, "InReceives");
298         ip_InHdrErrors = netstat_columns_find(ip_data, "InHdrErrors");
299         ip_InAddrErrors = netstat_columns_find(ip_data, "InAddrErrors");
300         ip_ForwDatagrams = netstat_columns_find(ip_data, "ForwDatagrams");
301         ip_InUnknownProtos = netstat_columns_find(ip_data, "InUnknownProtos");
302         ip_InDiscards = netstat_columns_find(ip_data, "InDiscards");
303         ip_InDelivers = netstat_columns_find(ip_data, "InDelivers");
304         ip_OutRequests = netstat_columns_find(ip_data, "OutRequests");
305         ip_OutDiscards = netstat_columns_find(ip_data, "OutDiscards");
306         ip_OutNoRoutes = netstat_columns_find(ip_data, "OutNoRoutes");
307         //ip_ReasmTimeout = netstat_columns_find(ip_data, "ReasmTimeout");
308         ip_ReasmReqds = netstat_columns_find(ip_data, "ReasmReqds");
309         ip_ReasmOKs = netstat_columns_find(ip_data, "ReasmOKs");
310         ip_ReasmFails = netstat_columns_find(ip_data, "ReasmFails");
311         ip_FragOKs = netstat_columns_find(ip_data, "FragOKs");
312         ip_FragFails = netstat_columns_find(ip_data, "FragFails");
313         ip_FragCreates = netstat_columns_find(ip_data, "FragCreates");
314
315         icmp_InMsgs = netstat_columns_find(icmp_data, "InMsgs");
316         icmp_OutMsgs = netstat_columns_find(icmp_data, "OutMsgs");
317         icmp_InErrors = netstat_columns_find(icmp_data, "InErrors");
318         icmp_OutErrors = netstat_columns_find(icmp_data, "OutErrors");
319         icmp_InCsumErrors = netstat_columns_find(icmp_data, "InCsumErrors");
320
321         //tcp_RtoAlgorithm = netstat_columns_find(tcp_data, "RtoAlgorithm");
322         //tcp_RtoMin = netstat_columns_find(tcp_data, "RtoMin");
323         //tcp_RtoMax = netstat_columns_find(tcp_data, "RtoMax");
324         //tcp_MaxConn = netstat_columns_find(tcp_data, "MaxConn");
325         tcp_ActiveOpens = netstat_columns_find(tcp_data, "ActiveOpens");
326         tcp_PassiveOpens = netstat_columns_find(tcp_data, "PassiveOpens");
327         tcp_AttemptFails = netstat_columns_find(tcp_data, "AttemptFails");
328         tcp_EstabResets = netstat_columns_find(tcp_data, "EstabResets");
329         tcp_CurrEstab = netstat_columns_find(tcp_data, "CurrEstab");
330         tcp_InSegs = netstat_columns_find(tcp_data, "InSegs");
331         tcp_OutSegs = netstat_columns_find(tcp_data, "OutSegs");
332         tcp_RetransSegs = netstat_columns_find(tcp_data, "RetransSegs");
333         tcp_InErrs = netstat_columns_find(tcp_data, "InErrs");
334         tcp_OutRsts = netstat_columns_find(tcp_data, "OutRsts");
335         tcp_InCsumErrors = netstat_columns_find(tcp_data, "InCsumErrors");
336
337         udp_InDatagrams = netstat_columns_find(udp_data, "InDatagrams");
338         udp_NoPorts = netstat_columns_find(udp_data, "NoPorts");
339         udp_InErrors = netstat_columns_find(udp_data, "InErrors");
340         udp_OutDatagrams = netstat_columns_find(udp_data, "OutDatagrams");
341         udp_RcvbufErrors = netstat_columns_find(udp_data, "RcvbufErrors");
342         udp_SndbufErrors = netstat_columns_find(udp_data, "SndbufErrors");
343         udp_InCsumErrors = netstat_columns_find(udp_data, "InCsumErrors");
344         udp_IgnoredMulti = netstat_columns_find(udp_data, "IgnoredMulti");
345
346         udplite_InDatagrams = netstat_columns_find(udplite_data, "InDatagrams");
347         udplite_NoPorts = netstat_columns_find(udplite_data, "NoPorts");
348         udplite_InErrors = netstat_columns_find(udplite_data, "InErrors");
349         udplite_OutDatagrams = netstat_columns_find(udplite_data, "OutDatagrams");
350         udplite_RcvbufErrors = netstat_columns_find(udplite_data, "RcvbufErrors");
351         udplite_SndbufErrors = netstat_columns_find(udplite_data, "SndbufErrors");
352         udplite_InCsumErrors = netstat_columns_find(udplite_data, "InCsumErrors");
353         udplite_IgnoredMulti = netstat_columns_find(udplite_data, "IgnoredMulti");
354     }
355
356     if(unlikely(!ff)) {
357         char filename[FILENAME_MAX + 1];
358         snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp");
359         ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
360         if(unlikely(!ff)) return 1;
361     }
362
363     ff = procfile_readall(ff);
364     if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
365
366     size_t lines = procfile_lines(ff), l;
367     size_t words;
368
369     RRDSET *st;
370
371     for(l = 0; l < lines ;l++) {
372         char *key = procfile_lineword(ff, l, 0);
373         uint32_t hash = simple_hash(key);
374
375         if(unlikely(hash == hash_ip && strcmp(key, "Ip") == 0)) {
376             size_t h = l++;
377
378             if(strcmp(procfile_lineword(ff, l, 0), "Ip") != 0) {
379                 error("Cannot read Ip line from /proc/net/snmp.");
380                 break;
381             }
382
383             words = procfile_linewords(ff, l);
384             if(words < 3) {
385                 error("Cannot read /proc/net/snmp Ip line. Expected 3+ params, read %zu.", words);
386                 continue;
387             }
388
389             // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
390             parse_line_pair(ff, ip_data, h, l);
391
392             // --------------------------------------------------------------------
393
394             if(do_ip_packets) {
395                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".packets");
396                 if(!st) {
397                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets"
398                                                  , "packets/s", 3000, update_every, RRDSET_TYPE_LINE);
399
400                     rrddim_add(st, "InReceives",    "received",  1, 1, RRD_ALGORITHM_INCREMENTAL);
401                     rrddim_add(st, "OutRequests",   "sent",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
402                     rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL);
403                     rrddim_add(st, "InDelivers",    "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL);
404                 }
405                 else rrdset_next(st);
406
407                 rrddim_set(st, "OutRequests",   *ip_OutRequests);
408                 rrddim_set(st, "InReceives",    *ip_InReceives);
409                 rrddim_set(st, "ForwDatagrams", *ip_ForwDatagrams);
410                 rrddim_set(st, "InDelivers",    *ip_InDelivers);
411                 rrdset_done(st);
412             }
413
414             // --------------------------------------------------------------------
415
416             if(do_ip_fragsout) {
417                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsout");
418                 if(!st) {
419                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL
420                                                  , "IPv4 Fragments Sent", "packets/s", 3010, update_every
421                                                  , RRDSET_TYPE_LINE);
422                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
423
424                     rrddim_add(st, "FragOKs",     "ok",      1, 1, RRD_ALGORITHM_INCREMENTAL);
425                     rrddim_add(st, "FragFails",   "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
426                     rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL);
427                 }
428                 else rrdset_next(st);
429
430                 rrddim_set(st, "FragOKs",     *ip_FragOKs);
431                 rrddim_set(st, "FragFails",   *ip_FragFails);
432                 rrddim_set(st, "FragCreates", *ip_FragCreates);
433                 rrdset_done(st);
434             }
435
436             // --------------------------------------------------------------------
437
438             if(do_ip_fragsin) {
439                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsin");
440                 if(!st) {
441                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL
442                                                  , "IPv4 Fragments Reassembly", "packets/s", 3011, update_every
443                                                  , RRDSET_TYPE_LINE);
444                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
445
446                     rrddim_add(st, "ReasmOKs",   "ok",      1, 1, RRD_ALGORITHM_INCREMENTAL);
447                     rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
448                     rrddim_add(st, "ReasmReqds", "all",     1, 1, RRD_ALGORITHM_INCREMENTAL);
449                 }
450                 else rrdset_next(st);
451
452                 rrddim_set(st, "ReasmOKs",   *ip_ReasmOKs);
453                 rrddim_set(st, "ReasmFails", *ip_ReasmFails);
454                 rrddim_set(st, "ReasmReqds", *ip_ReasmReqds);
455                 rrdset_done(st);
456             }
457
458             // --------------------------------------------------------------------
459
460             if(do_ip_errors) {
461                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".errors");
462                 if(!st) {
463                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors"
464                                                  , "packets/s", 3002, update_every, RRDSET_TYPE_LINE);
465                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
466
467                     rrddim_add(st, "InDiscards",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
468                     rrddim_add(st, "OutDiscards",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
469
470                     rrddim_add(st, "InHdrErrors",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
471                     rrddim_add(st, "OutNoRoutes",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
472
473                     rrddim_add(st, "InAddrErrors",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
474                     rrddim_add(st, "InUnknownProtos", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
475                 }
476                 else rrdset_next(st);
477
478                 rrddim_set(st, "InDiscards",      *ip_InDiscards);
479                 rrddim_set(st, "OutDiscards",     *ip_OutDiscards);
480                 rrddim_set(st, "InHdrErrors",     *ip_InHdrErrors);
481                 rrddim_set(st, "InAddrErrors",    *ip_InAddrErrors);
482                 rrddim_set(st, "InUnknownProtos", *ip_InUnknownProtos);
483                 rrddim_set(st, "OutNoRoutes",     *ip_OutNoRoutes);
484                 rrdset_done(st);
485             }
486         }
487         else if(unlikely(hash == hash_icmp && strcmp(key, "Icmp") == 0)) {
488             size_t h = l++;
489
490             if(strcmp(procfile_lineword(ff, l, 0), "Icmp") != 0) {
491                 error("Cannot read Icmp line from /proc/net/snmp.");
492                 break;
493             }
494
495             words = procfile_linewords(ff, l);
496             if(words < 3) {
497                 error("Cannot read /proc/net/snmp Icmp line. Expected 3+ params, read %zu.", words);
498                 continue;
499             }
500
501             parse_line_pair(ff, icmp_data, h, l);
502
503             // --------------------------------------------------------------------
504
505             if(do_icmp_packets) {
506                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp");
507                 if(!st) {
508                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets"
509                                                  , "packets/s", 2602, update_every, RRDSET_TYPE_LINE);
510
511                     rrddim_add(st, "InMsgs",  "received",  1, 1, RRD_ALGORITHM_INCREMENTAL);
512                     rrddim_add(st, "OutMsgs", "sent",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
513                 }
514                 else rrdset_next(st);
515
516                 rrddim_set(st, "InMsgs",  *icmp_InMsgs);
517                 rrddim_set(st, "OutMsgs", *icmp_OutMsgs);
518
519                 rrdset_done(st);
520
521                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp_errors");
522                 if(!st) {
523                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp_errors", NULL, "icmp", NULL
524                                                  , "IPv4 ICMP Errors", "packets/s", 2603, update_every
525                                                  , RRDSET_TYPE_LINE);
526
527                     rrddim_add(st, "InErrors",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
528                     rrddim_add(st, "OutErrors",    NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
529                     rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
530                 }
531                 else rrdset_next(st);
532
533                 rrddim_set(st, "InErrors",     *icmp_InErrors);
534                 rrddim_set(st, "OutErrors",    *icmp_OutErrors);
535                 rrddim_set(st, "InCsumErrors", *icmp_InCsumErrors);
536
537                 rrdset_done(st);
538             }
539         }
540         else if(unlikely(hash == hash_icmpmsg && strcmp(key, "IcmpMsg") == 0)) {
541             size_t h = l++;
542
543             if(strcmp(procfile_lineword(ff, l, 0), "IcmpMsg") != 0) {
544                 error("Cannot read IcmpMsg line from /proc/net/snmp.");
545                 break;
546             }
547
548             parse_line_pair(ff, icmpmsg_data, h, l);
549
550             // --------------------------------------------------------------------
551
552             if(do_icmpmsg) {
553                 int i;
554
555                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmpmsg");
556                 if(!st) {
557                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages"
558                                                  , "packets/s", 2604, update_every, RRDSET_TYPE_LINE);
559
560                     for(i = 0; icmpmsg_data[i].name ;i++)
561                         rrddim_add(st, icmpmsg_data[i].name, icmpmsg_data[i].label,  icmpmsg_data[i].multiplier, 1, RRD_ALGORITHM_INCREMENTAL);
562                 }
563                 else rrdset_next(st);
564
565                 for(i = 0; icmpmsg_data[i].name ;i++)
566                     rrddim_set(st, icmpmsg_data[i].name, icmpmsg_data[i].value);
567
568                 rrdset_done(st);
569             }
570         }
571         else if(unlikely(hash == hash_tcp && strcmp(key, "Tcp") == 0)) {
572             size_t h = l++;
573
574             if(strcmp(procfile_lineword(ff, l, 0), "Tcp") != 0) {
575                 error("Cannot read Tcp line from /proc/net/snmp.");
576                 break;
577             }
578
579             words = procfile_linewords(ff, l);
580             if(words < 3) {
581                 error("Cannot read /proc/net/snmp Tcp line. Expected 3+ params, read %zu.", words);
582                 continue;
583             }
584
585             parse_line_pair(ff, tcp_data, h, l);
586
587             // --------------------------------------------------------------------
588
589             // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
590             if(do_tcp_sockets) {
591                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcpsock");
592                 if(!st) {
593                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections"
594                                                  , "active connections", 2500, update_every, RRDSET_TYPE_LINE);
595
596                     rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE);
597                 }
598                 else rrdset_next(st);
599
600                 rrddim_set(st, "CurrEstab", *tcp_CurrEstab);
601                 rrdset_done(st);
602             }
603
604             // --------------------------------------------------------------------
605
606             if(do_tcp_packets) {
607                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcppackets");
608                 if(!st) {
609                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets"
610                                                  , "packets/s", 2600, update_every, RRDSET_TYPE_LINE);
611
612                     rrddim_add(st, "InSegs",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
613                     rrddim_add(st, "OutSegs", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
614                 }
615                 else rrdset_next(st);
616
617                 rrddim_set(st, "InSegs",  *tcp_InSegs);
618                 rrddim_set(st, "OutSegs", *tcp_OutSegs);
619                 rrdset_done(st);
620             }
621
622             // --------------------------------------------------------------------
623
624             if(do_tcp_errors) {
625                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcperrors");
626                 if(!st) {
627                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors"
628                                                  , "packets/s", 2700, update_every, RRDSET_TYPE_LINE);
629                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
630
631                     rrddim_add(st, "InErrs",       NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
632                     rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
633                     rrddim_add(st, "RetransSegs",  NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
634                 }
635                 else rrdset_next(st);
636
637                 rrddim_set(st, "InErrs",       *tcp_InErrs);
638                 rrddim_set(st, "InCsumErrors", *tcp_InCsumErrors);
639                 rrddim_set(st, "RetransSegs",  *tcp_RetransSegs);
640                 rrdset_done(st);
641             }
642
643             // --------------------------------------------------------------------
644
645             if(do_tcp_handshake) {
646                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcphandshake");
647                 if(!st) {
648                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", NULL
649                                                  , "IPv4 TCP Handshake Issues", "events/s", 2900, update_every
650                                                  , RRDSET_TYPE_LINE);
651                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
652
653                     rrddim_add(st, "EstabResets",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
654                     rrddim_add(st, "OutRsts",      NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
655                     rrddim_add(st, "ActiveOpens",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
656                     rrddim_add(st, "PassiveOpens", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
657                     rrddim_add(st, "AttemptFails", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
658                 }
659                 else rrdset_next(st);
660
661                 rrddim_set(st, "EstabResets",  *tcp_EstabResets);
662                 rrddim_set(st, "OutRsts",      *tcp_OutRsts);
663                 rrddim_set(st, "ActiveOpens",  *tcp_ActiveOpens);
664                 rrddim_set(st, "PassiveOpens", *tcp_PassiveOpens);
665                 rrddim_set(st, "AttemptFails", *tcp_AttemptFails);
666                 rrdset_done(st);
667             }
668         }
669         else if(unlikely(hash == hash_udp && strcmp(key, "Udp") == 0)) {
670             size_t h = l++;
671
672             if(strcmp(procfile_lineword(ff, l, 0), "Udp") != 0) {
673                 error("Cannot read Udp line from /proc/net/snmp.");
674                 break;
675             }
676
677             words = procfile_linewords(ff, l);
678             if(words < 3) {
679                 error("Cannot read /proc/net/snmp Udp line. Expected 3+ params, read %zu.", words);
680                 continue;
681             }
682
683             parse_line_pair(ff, udp_data, h, l);
684
685             // --------------------------------------------------------------------
686
687             // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
688             if(do_udp_packets) {
689                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udppackets");
690                 if(!st) {
691                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets"
692                                                  , "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
693
694                     rrddim_add(st, "InDatagrams",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
695                     rrddim_add(st, "OutDatagrams", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
696                 }
697                 else rrdset_next(st);
698
699                 rrddim_set(st, "InDatagrams",  *udp_InDatagrams);
700                 rrddim_set(st, "OutDatagrams", *udp_OutDatagrams);
701                 rrdset_done(st);
702             }
703
704             // --------------------------------------------------------------------
705
706             if(do_udp_errors) {
707                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udperrors");
708                 if(!st) {
709                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors"
710                                                  , "events/s", 2701, update_every, RRDSET_TYPE_LINE);
711                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
712
713                     rrddim_add(st, "RcvbufErrors", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
714                     rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
715                     rrddim_add(st, "InErrors",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
716                     rrddim_add(st, "NoPorts",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
717                     rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
718                     rrddim_add(st, "IgnoredMulti", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
719                 }
720                 else rrdset_next(st);
721
722                 rrddim_set(st, "InErrors",     *udp_InErrors);
723                 rrddim_set(st, "NoPorts",      *udp_NoPorts);
724                 rrddim_set(st, "RcvbufErrors", *udp_RcvbufErrors);
725                 rrddim_set(st, "SndbufErrors", *udp_SndbufErrors);
726                 rrddim_set(st, "InCsumErrors", *udp_InCsumErrors);
727                 rrddim_set(st, "IgnoredMulti", *udp_IgnoredMulti);
728                 rrdset_done(st);
729             }
730         }
731         else if(unlikely(hash == hash_udplite && strcmp(key, "UdpLite") == 0)) {
732             size_t h = l++;
733
734             if(strcmp(procfile_lineword(ff, l, 0), "UdpLite") != 0) {
735                 error("Cannot read UdpLite line from /proc/net/snmp.");
736                 break;
737             }
738
739             words = procfile_linewords(ff, l);
740             if(words < 3) {
741                 error("Cannot read /proc/net/snmp UdpLite line. Expected 3+ params, read %zu.", words);
742                 continue;
743             }
744
745             parse_line_pair(ff, udplite_data, h, l);
746
747             // --------------------------------------------------------------------
748
749             if(do_udplite_packets) {
750                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite");
751                 if(!st) {
752                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite", NULL, "udplite", NULL
753                                                  , "IPv4 UDPLite Packets", "packets/s", 2603, update_every
754                                                  , RRDSET_TYPE_LINE);
755
756                     rrddim_add(st, "InDatagrams",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
757                     rrddim_add(st, "OutDatagrams", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
758                 }
759                 else rrdset_next(st);
760
761                 rrddim_set(st, "InDatagrams",  *udplite_InDatagrams);
762                 rrddim_set(st, "OutDatagrams", *udplite_OutDatagrams);
763                 rrdset_done(st);
764
765                 st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite_errors");
766                 if(!st) {
767                     st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite_errors", NULL, "udplite", NULL
768                                                  , "IPv4 UDPLite Errors", "packets/s", 2604, update_every
769                                                  , RRDSET_TYPE_LINE);
770
771                     rrddim_add(st, "RcvbufErrors", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
772                     rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
773                     rrddim_add(st, "NoPorts",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
774                     rrddim_add(st, "IgnoredMulti", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
775                     rrddim_add(st, "InErrors",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
776                     rrddim_add(st, "InCsumErrors", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
777                 }
778                 else rrdset_next(st);
779
780                 rrddim_set(st, "NoPorts",      *udplite_NoPorts);
781                 rrddim_set(st, "InErrors",     *udplite_InErrors);
782                 rrddim_set(st, "InCsumErrors", *udplite_InCsumErrors);
783                 rrddim_set(st, "RcvbufErrors", *udplite_RcvbufErrors);
784                 rrddim_set(st, "SndbufErrors", *udplite_SndbufErrors);
785                 rrddim_set(st, "IgnoredMulti", *udplite_IgnoredMulti);
786                 rrdset_done(st);
787             }
788         }
789     }
790
791     return 0;
792 }
793