]> arthur.barton.de Git - netdata.git/blob - src/proc_net_stat_conntrack.c
Merge pull request #1998 from ktsaou/master
[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", netdata_configured_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", netdata_configured_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", netdata_configured_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         size_t lines = procfile_lines(ff), l;
65
66         for(l = 1; l < lines ;l++) {
67             size_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 %zu.", 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_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets");
134         if(unlikely(!st)) {
135             st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL
136                                          , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections"
137                                          , "active connections", 3000, update_every, RRDSET_TYPE_LINE);
138
139             rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
140         }
141         else rrdset_next(st);
142
143         rrddim_set(st, "connections", aentries);
144         rrdset_done(st);
145     }
146
147     // --------------------------------------------------------------------
148
149     if(do_new) {
150         st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new");
151         if(unlikely(!st)) {
152             st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL
153                                          , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections"
154                                          , "connections/s", 3001, update_every, RRDSET_TYPE_LINE);
155
156             rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
157             rrddim_add(st, "ignore", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
158             rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
159         }
160         else rrdset_next(st);
161
162         rrddim_set(st, "new", anew);
163         rrddim_set(st, "ignore", aignore);
164         rrddim_set(st, "invalid", ainvalid);
165         rrdset_done(st);
166     }
167
168     // --------------------------------------------------------------------
169
170     if(do_changes) {
171         st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes");
172         if(unlikely(!st)) {
173             st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL
174                                          , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s"
175                                          , 3002, update_every, RRDSET_TYPE_LINE);
176             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
177
178             rrddim_add(st, "inserted", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
179             rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
180             rrddim_add(st, "delete_list", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
181         }
182         else rrdset_next(st);
183
184         rrddim_set(st, "inserted", ainsert);
185         rrddim_set(st, "deleted", adelete);
186         rrddim_set(st, "delete_list", adelete_list);
187         rrdset_done(st);
188     }
189
190     // --------------------------------------------------------------------
191
192     if(do_expect) {
193         st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect");
194         if(unlikely(!st)) {
195             st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL
196                                          , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations"
197                                          , "expectations/s", 3003, update_every, RRDSET_TYPE_LINE);
198             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
199
200             rrddim_add(st, "created", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
201             rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
202             rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
203         }
204         else rrdset_next(st);
205
206         rrddim_set(st, "created", aexpect_create);
207         rrddim_set(st, "deleted", aexpect_delete);
208         rrddim_set(st, "new", aexpect_new);
209         rrdset_done(st);
210     }
211
212     // --------------------------------------------------------------------
213
214     if(do_search) {
215         st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search");
216         if(unlikely(!st)) {
217             st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL
218                                          , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches"
219                                          , "searches/s", 3010, update_every, RRDSET_TYPE_LINE);
220             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
221
222             rrddim_add(st, "searched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
223             rrddim_add(st, "restarted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
224             rrddim_add(st, "found", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
225         }
226         else rrdset_next(st);
227
228         rrddim_set(st, "searched", asearched);
229         rrddim_set(st, "restarted", asearch_restart);
230         rrddim_set(st, "found", afound);
231         rrdset_done(st);
232     }
233
234     // --------------------------------------------------------------------
235
236     if(do_errors) {
237         st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors");
238         if(unlikely(!st)) {
239             st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL
240                                          , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s"
241                                          , 3005, update_every, RRDSET_TYPE_LINE);
242             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
243
244             rrddim_add(st, "icmp_error", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
245             rrddim_add(st, "insert_failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
246             rrddim_add(st, "drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
247             rrddim_add(st, "early_drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
248         }
249         else rrdset_next(st);
250
251         rrddim_set(st, "icmp_error", aicmp_error);
252         rrddim_set(st, "insert_failed", ainsert_failed);
253         rrddim_set(st, "drop", adrop);
254         rrddim_set(st, "early_drop", aearly_drop);
255         rrdset_done(st);
256     }
257
258     return 0;
259 }