]> arthur.barton.de Git - netdata.git/blob - src/proc_net_stat_conntrack.c
3ccc96260886d0e41dad30c7c37bf2cdd8189349
[netdata.git] / src / proc_net_stat_conntrack.c
1 #include "common.h"
2
3 #define RRD_TYPE_NET_STAT_NETFILTER     "netfilter"
4 #define RRD_TYPE_NET_STAT_CONNTRACK     "conntrack"
5
6 int do_proc_net_stat_conntrack(int update_every, usec_t dt) {
7     static procfile *ff = NULL;
8     static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;
9     static usec_t get_max_every = 10 * USEC_PER_SEC, usec_since_last_max = 0;
10     static int read_full = 1;
11     static char *nf_conntrack_filename, *nf_conntrack_count_filename, *nf_conntrack_max_filename;
12     static RRDVAR *rrdvar_max = NULL;
13
14     unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0,
15             ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0;
16
17     if(unlikely(do_sockets == -1)) {
18         char filename[FILENAME_MAX + 1];
19         snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/nf_conntrack");
20         nf_conntrack_filename = config_get("plugin:proc:/proc/net/stat/nf_conntrack", "filename to monitor", filename);
21
22         snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/sys/net/netfilter/nf_conntrack_max");
23         nf_conntrack_max_filename = config_get("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "filename to monitor", filename);
24         usec_since_last_max = get_max_every = config_get_number("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "read every seconds", 10) * USEC_PER_SEC;
25
26         read_full = 1;
27         ff = procfile_open(nf_conntrack_filename, " \t:", PROCFILE_FLAG_DEFAULT);
28         if(!ff) read_full = 0;
29
30         do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", read_full);
31         do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", read_full);
32         do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", read_full);
33         do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", read_full);
34         do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", read_full);
35
36         do_sockets = 1;
37         if(!read_full) {
38             snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/sys/net/netfilter/nf_conntrack_count");
39             nf_conntrack_count_filename = config_get("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_count", "filename to monitor", filename);
40
41             if(read_single_number_file(nf_conntrack_count_filename, &aentries))
42                 do_sockets = 0;
43         }
44
45         do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", do_sockets);
46
47         if(!do_sockets && !read_full)
48             return 1;
49
50         rrdvar_max = rrdvar_custom_host_variable_create(&localhost, "netfilter.conntrack.max");
51     }
52
53     if(likely(read_full)) {
54         if(unlikely(!ff)) {
55             ff = procfile_open(nf_conntrack_filename, " \t:", PROCFILE_FLAG_DEFAULT);
56             if(unlikely(!ff))
57                 return 0; // we return 0, so that we will retry to open it next time
58         }
59
60         ff = procfile_readall(ff);
61         if(unlikely(!ff))
62             return 0; // we return 0, so that we will retry to open it next time
63
64         uint32_t lines = procfile_lines(ff), l;
65
66         for(l = 1; l < lines ;l++) {
67             uint32_t words = procfile_linewords(ff, l);
68             if(unlikely(words < 17)) {
69                 if(unlikely(words)) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %u.", words);
70                 continue;
71             }
72
73             unsigned long long tentries = 0, tsearched = 0, tfound = 0, tnew = 0, tinvalid = 0, tignore = 0, tdelete = 0, tdelete_list = 0, tinsert = 0, tinsert_failed = 0, tdrop = 0, tearly_drop = 0, ticmp_error = 0, texpect_new = 0, texpect_create = 0, texpect_delete = 0, tsearch_restart = 0;
74
75             tentries        = strtoull(procfile_lineword(ff, l, 0), NULL, 16);
76             tsearched       = strtoull(procfile_lineword(ff, l, 1), NULL, 16);
77             tfound          = strtoull(procfile_lineword(ff, l, 2), NULL, 16);
78             tnew            = strtoull(procfile_lineword(ff, l, 3), NULL, 16);
79             tinvalid        = strtoull(procfile_lineword(ff, l, 4), NULL, 16);
80             tignore         = strtoull(procfile_lineword(ff, l, 5), NULL, 16);
81             tdelete         = strtoull(procfile_lineword(ff, l, 6), NULL, 16);
82             tdelete_list    = strtoull(procfile_lineword(ff, l, 7), NULL, 16);
83             tinsert         = strtoull(procfile_lineword(ff, l, 8), NULL, 16);
84             tinsert_failed  = strtoull(procfile_lineword(ff, l, 9), NULL, 16);
85             tdrop           = strtoull(procfile_lineword(ff, l, 10), NULL, 16);
86             tearly_drop     = strtoull(procfile_lineword(ff, l, 11), NULL, 16);
87             ticmp_error     = strtoull(procfile_lineword(ff, l, 12), NULL, 16);
88             texpect_new     = strtoull(procfile_lineword(ff, l, 13), NULL, 16);
89             texpect_create  = strtoull(procfile_lineword(ff, l, 14), NULL, 16);
90             texpect_delete  = strtoull(procfile_lineword(ff, l, 15), NULL, 16);
91             tsearch_restart = strtoull(procfile_lineword(ff, l, 16), NULL, 16);
92
93             if(unlikely(!aentries)) aentries =  tentries;
94
95             // sum all the cpus together
96             asearched           += tsearched;       // conntrack.search
97             afound              += tfound;          // conntrack.search
98             anew                += tnew;            // conntrack.new
99             ainvalid            += tinvalid;        // conntrack.new
100             aignore             += tignore;         // conntrack.new
101             adelete             += tdelete;         // conntrack.changes
102             adelete_list        += tdelete_list;    // conntrack.changes
103             ainsert             += tinsert;         // conntrack.changes
104             ainsert_failed      += tinsert_failed;  // conntrack.errors
105             adrop               += tdrop;           // conntrack.errors
106             aearly_drop         += tearly_drop;     // conntrack.errors
107             aicmp_error         += ticmp_error;     // conntrack.errors
108             aexpect_new         += texpect_new;     // conntrack.expect
109             aexpect_create      += texpect_create;  // conntrack.expect
110             aexpect_delete      += texpect_delete;  // conntrack.expect
111             asearch_restart     += tsearch_restart; // conntrack.search
112         }
113     }
114     else {
115         if(unlikely(read_single_number_file(nf_conntrack_count_filename, &aentries)))
116             return 0; // we return 0, so that we will retry to open it next time
117     }
118
119     usec_since_last_max += dt;
120     if(unlikely(rrdvar_max && usec_since_last_max >= get_max_every)) {
121         usec_since_last_max = 0;
122
123         unsigned long long max;
124         if(likely(!read_single_number_file(nf_conntrack_max_filename, &max)))
125             rrdvar_custom_host_variable_set(rrdvar_max, max);
126     }
127
128     RRDSET *st;
129
130     // --------------------------------------------------------------------
131
132     if(do_sockets) {
133         st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets");
134         if(unlikely(!st)) {
135             st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 3000, update_every, RRDSET_TYPE_LINE);
136
137             rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE);
138         }
139         else rrdset_next(st);
140
141         rrddim_set(st, "connections", aentries);
142         rrdset_done(st);
143     }
144
145     // --------------------------------------------------------------------
146
147     if(do_new) {
148         st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new");
149         if(unlikely(!st)) {
150             st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 3001, update_every, RRDSET_TYPE_LINE);
151
152             rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
153             rrddim_add(st, "ignore", NULL, -1, 1, RRDDIM_INCREMENTAL);
154             rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
155         }
156         else rrdset_next(st);
157
158         rrddim_set(st, "new", anew);
159         rrddim_set(st, "ignore", aignore);
160         rrddim_set(st, "invalid", ainvalid);
161         rrdset_done(st);
162     }
163
164     // --------------------------------------------------------------------
165
166     if(do_changes) {
167         st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes");
168         if(unlikely(!st)) {
169             st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 3002, update_every, RRDSET_TYPE_LINE);
170             st->isdetail = 1;
171
172             rrddim_add(st, "inserted", NULL, 1, 1, RRDDIM_INCREMENTAL);
173             rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
174             rrddim_add(st, "delete_list", NULL, -1, 1, RRDDIM_INCREMENTAL);
175         }
176         else rrdset_next(st);
177
178         rrddim_set(st, "inserted", ainsert);
179         rrddim_set(st, "deleted", adelete);
180         rrddim_set(st, "delete_list", adelete_list);
181         rrdset_done(st);
182     }
183
184     // --------------------------------------------------------------------
185
186     if(do_expect) {
187         st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect");
188         if(unlikely(!st)) {
189             st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 3003, update_every, RRDSET_TYPE_LINE);
190             st->isdetail = 1;
191
192             rrddim_add(st, "created", NULL, 1, 1, RRDDIM_INCREMENTAL);
193             rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
194             rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
195         }
196         else rrdset_next(st);
197
198         rrddim_set(st, "created", aexpect_create);
199         rrddim_set(st, "deleted", aexpect_delete);
200         rrddim_set(st, "new", aexpect_new);
201         rrdset_done(st);
202     }
203
204     // --------------------------------------------------------------------
205
206     if(do_search) {
207         st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search");
208         if(unlikely(!st)) {
209             st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 3010, update_every, RRDSET_TYPE_LINE);
210             st->isdetail = 1;
211
212             rrddim_add(st, "searched", NULL, 1, 1, RRDDIM_INCREMENTAL);
213             rrddim_add(st, "restarted", NULL, -1, 1, RRDDIM_INCREMENTAL);
214             rrddim_add(st, "found", NULL, 1, 1, RRDDIM_INCREMENTAL);
215         }
216         else rrdset_next(st);
217
218         rrddim_set(st, "searched", asearched);
219         rrddim_set(st, "restarted", asearch_restart);
220         rrddim_set(st, "found", afound);
221         rrdset_done(st);
222     }
223
224     // --------------------------------------------------------------------
225
226     if(do_errors) {
227         st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors");
228         if(unlikely(!st)) {
229             st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 3005, update_every, RRDSET_TYPE_LINE);
230             st->isdetail = 1;
231
232             rrddim_add(st, "icmp_error", NULL, 1, 1, RRDDIM_INCREMENTAL);
233             rrddim_add(st, "insert_failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
234             rrddim_add(st, "drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
235             rrddim_add(st, "early_drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
236         }
237         else rrdset_next(st);
238
239         rrddim_set(st, "icmp_error", aicmp_error);
240         rrddim_set(st, "insert_failed", ainsert_failed);
241         rrddim_set(st, "drop", adrop);
242         rrddim_set(st, "early_drop", aearly_drop);
243         rrdset_done(st);
244     }
245
246     return 0;
247 }