@cryptotaxi247 / netdata-1 / commits / 234c746b3

added /proc/net/sockstat parsing; fixes #14

Costa Tsaousis (ktsaou) committed Nov 7, 2017 at 01:31 UTC 234c746b34c232ed36b925cf20c871d6e7029dde
5 files changed +452
CMakeLists.txt
+1
@@ -49,6 +49,7 @@ set(NETDATA_LINUX_FILES
49 src/proc_net_rpc_nfsd.c
50 src/proc_net_snmp.c
51 src/proc_net_snmp6.c
52 + src/proc_net_sockstat.c
53 src/proc_net_softnet_stat.c
54 src/proc_net_stat_conntrack.c
55 src/proc_net_stat_synproxy.c
src/Makefile.am
+1
@@ -195,6 +195,7 @@ netdata_SOURCES += \
195 proc_net_rpc_nfsd.c \
196 proc_net_snmp.c \
197 proc_net_snmp6.c \
198 + proc_net_sockstat.c \
199 proc_net_softnet_stat.c \
200 proc_net_stat_conntrack.c \
201 proc_net_stat_synproxy.c \
src/plugin_proc.c
+1
@@ -32,6 +32,7 @@ static struct proc_module {
32
33 // network metrics
34 { .name = "/proc/net/dev", .dim = "netdev", .func = do_proc_net_dev },
35 + { .name = "/proc/net/sockstat", .dim = "sockstat", .func = do_proc_net_sockstat },
36 { .name = "/proc/net/netstat", .dim = "netstat", .func = do_proc_net_netstat }, // this has to be before /proc/net/snmp, because there is a shared metric
37 { .name = "/proc/net/snmp", .dim = "snmp", .func = do_proc_net_snmp },
38 { .name = "/proc/net/snmp6", .dim = "snmp6", .func = do_proc_net_snmp6 },
src/plugin_proc.h
+1
@@ -26,6 +26,7 @@ extern int do_proc_uptime(int update_every, usec_t dt);
26 extern int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt);
27 extern int do_proc_sys_devices_system_node(int update_every, usec_t dt);
28 extern int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt);
29 +extern int do_proc_net_sockstat(int update_every, usec_t dt);
30
31 extern int get_numa_node_count(void);
32
src/proc_net_sockstat.c new
+448
@@ -0,0 +1,448 @@
1 +#include "common.h"
2 +
3 +#define RRD_TYPE_NET_SNMP "ipv4"
4 +
5 +static struct proc_net_sockstat {
6 + kernel_uint_t sockets_used;
7 +
8 + kernel_uint_t tcp_inuse;
9 + kernel_uint_t tcp_orphan;
10 + kernel_uint_t tcp_tw;
11 + kernel_uint_t tcp_alloc;
12 + kernel_uint_t tcp_mem;
13 +
14 + kernel_uint_t udp_inuse;
15 + kernel_uint_t udp_mem;
16 +
17 + kernel_uint_t udplite_inuse;
18 +
19 + kernel_uint_t raw_inuse;
20 +
21 + kernel_uint_t frag_inuse;
22 + kernel_uint_t frag_memory;
23 +} sockstat_root = { 0 };
24 +
25 +
26 +static inline void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, const char *value, void *dst) {
27 + (void)name;
28 + (void)hash;
29 +
30 + register kernel_uint_t *d = dst;
31 + *d = str2kernel_uint_t(value);
32 + // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, (unsigned long long)*d);
33 +}
34 +
35 +int do_proc_net_sockstat(int update_every, usec_t dt) {
36 + (void)dt;
37 +
38 + static procfile *ff = NULL;
39 +
40 + static uint32_t hash_sockets = 0,
41 + hash_raw = 0,
42 + hash_frag = 0,
43 + hash_tcp = 0,
44 + hash_udp = 0,
45 + hash_udplite = 0;
46 +
47 +
48 + static ARL_BASE *arl_sockets = NULL;
49 + static ARL_BASE *arl_tcp = NULL;
50 + static ARL_BASE *arl_udp = NULL;
51 + static ARL_BASE *arl_udplite = NULL;
52 + static ARL_BASE *arl_raw = NULL;
53 + static ARL_BASE *arl_frag = NULL;
54 +
55 + static int do_sockets = -1, do_tcp_sockets = -1, do_tcp_mem = -1, do_udp_sockets = -1, do_udp_mem = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1, do_frag_mem = -1;
56 +
57 + static char *keys[6] = { NULL };
58 + static uint32_t hashes[6] = { 0 };
59 + static ARL_BASE *bases[6] = { NULL };
60 +
61 + if(unlikely(!arl_sockets)) {
62 + do_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 sockets", CONFIG_BOOLEAN_AUTO);
63 + do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 TCP sockets", CONFIG_BOOLEAN_AUTO);
64 + do_tcp_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 TCP memory", CONFIG_BOOLEAN_AUTO);
65 + do_udp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDP sockets", CONFIG_BOOLEAN_AUTO);
66 + do_udp_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDP memory", CONFIG_BOOLEAN_AUTO);
67 + do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDPLITE sockets", CONFIG_BOOLEAN_AUTO);
68 + do_raw_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 RAW sockets", CONFIG_BOOLEAN_AUTO);
69 + do_frag_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 FRAG sockets", CONFIG_BOOLEAN_AUTO);
70 + do_frag_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 FRAG memory", CONFIG_BOOLEAN_AUTO);
71 +
72 + arl_sockets = arl_create("sockstat/sockets", arl_callback_str2kernel_uint_t, 60);
73 + arl_expect(arl_sockets, "used", &sockstat_root.sockets_used);
74 +
75 + arl_tcp = arl_create("sockstat/TCP", arl_callback_str2kernel_uint_t, 60);
76 + arl_expect(arl_tcp, "inuse", &sockstat_root.tcp_inuse);
77 + arl_expect(arl_tcp, "orphan", &sockstat_root.tcp_orphan);
78 + arl_expect(arl_tcp, "tw", &sockstat_root.tcp_tw);
79 + arl_expect(arl_tcp, "alloc", &sockstat_root.tcp_alloc);
80 + arl_expect(arl_tcp, "mem", &sockstat_root.tcp_mem);
81 +
82 + arl_udp = arl_create("sockstat/UDP", arl_callback_str2kernel_uint_t, 60);
83 + arl_expect(arl_udp, "inuse", &sockstat_root.udp_inuse);
84 + arl_expect(arl_udp, "mem", &sockstat_root.udp_mem);
85 +
86 + arl_udplite = arl_create("sockstat/UDPLITE", arl_callback_str2kernel_uint_t, 60);
87 + arl_expect(arl_udplite, "inuse", &sockstat_root.udplite_inuse);
88 +
89 + arl_raw = arl_create("sockstat/RAW", arl_callback_str2kernel_uint_t, 60);
90 + arl_expect(arl_raw, "inuse", &sockstat_root.raw_inuse);
91 +
92 + arl_frag = arl_create("sockstat/FRAG", arl_callback_str2kernel_uint_t, 60);
93 + arl_expect(arl_frag, "inuse", &sockstat_root.frag_inuse);
94 + arl_expect(arl_frag, "memory", &sockstat_root.frag_memory);
95 +
96 + hash_sockets = simple_hash("sockets");
97 + hash_tcp = simple_hash("TCP");
98 + hash_udp = simple_hash("UDP");
99 + hash_udplite = simple_hash("UDPLITE");
100 + hash_raw = simple_hash("RAW");
101 + hash_frag = simple_hash("FRAG");
102 +
103 + keys[0] = "sockets"; hashes[0] = hash_sockets; bases[0] = arl_sockets;
104 + keys[1] = "TCP"; hashes[1] = hash_tcp; bases[1] = arl_tcp;
105 + keys[2] = "UDP"; hashes[2] = hash_udp; bases[2] = arl_udp;
106 + keys[3] = "UDPLITE"; hashes[3] = hash_udplite; bases[3] = arl_udplite;
107 + keys[4] = "RAW"; hashes[4] = hash_raw; bases[4] = arl_raw;
108 + keys[5] = "FRAG"; hashes[5] = hash_frag; bases[5] = arl_frag;
109 + }
110 +
111 + if(unlikely(!ff)) {
112 + char filename[FILENAME_MAX + 1];
113 + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat");
114 + ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
115 + if(unlikely(!ff)) return 1;
116 + }
117 +
118 + ff = procfile_readall(ff);
119 + if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
120 +
121 + size_t lines = procfile_lines(ff), l;
122 +
123 + for(l = 0; l < lines ;l++) {
124 + size_t words = procfile_linewords(ff, l);
125 + char *key = procfile_lineword(ff, l, 0);
126 + uint32_t hash = simple_hash(key);
127 +
128 + int k;
129 + for(k = 0; keys[k] ; k++) {
130 + if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) {
131 + // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words);
132 + ARL_BASE *arl = bases[k];
133 + arl_begin(arl);
134 + size_t w = 1;
135 +
136 + while(w + 1 < words) {
137 + char *name = procfile_lineword(ff, l, w); w++;
138 + char *value = procfile_lineword(ff, l, w); w++;
139 + // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words);
140 + if(unlikely(arl_check(arl, name, value) != 0))
141 + break;
142 + }
143 +
144 + break;
145 + }
146 + }
147 + }
148 +
149 + // ------------------------------------------------------------------------
150 +
151 + if(do_sockets == CONFIG_BOOLEAN_YES || (do_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.sockets_used)) {
152 + do_sockets = CONFIG_BOOLEAN_YES;
153 +
154 + static RRDSET *st = NULL;
155 + static RRDDIM *rd_used = NULL;
156 +
157 + if(unlikely(!st)) {
158 + st = rrdset_create_localhost(
159 + "ipv4"
160 + , "sockstat_sockets"
161 + , NULL
162 + , "sockets"
163 + , NULL
164 + , "IPv4 Sockets In Use"
165 + , "sockets"
166 + , "proc"
167 + , "net/sockstat"
168 + , 2400
169 + , update_every
170 + , RRDSET_TYPE_LINE
171 + );
172 +
173 + rd_used = rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
174 + }
175 + else rrdset_next(st);
176 +
177 + rrddim_set_by_pointer(st, rd_used, (collected_number)sockstat_root.sockets_used);
178 + rrdset_done(st);
179 + }
180 +
181 + // ------------------------------------------------------------------------
182 +
183 + if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && (sockstat_root.tcp_inuse || sockstat_root.tcp_orphan || sockstat_root.tcp_tw || sockstat_root.tcp_alloc))) {
184 + do_tcp_sockets = CONFIG_BOOLEAN_YES;
185 +
186 + static RRDSET *st = NULL;
187 + static RRDDIM *rd_inuse = NULL,
188 + *rd_orphan = NULL,
189 + *rd_timewait = NULL,
190 + *rd_alloc = NULL;
191 +
192 + if(unlikely(!st)) {
193 + st = rrdset_create_localhost(
194 + "ipv4"
195 + , "sockstat_tcp_sockets"
196 + , NULL
197 + , "sockets"
198 + , NULL
199 + , "IPv4 TCP Sockets"
200 + , "sockets"
201 + , "proc"
202 + , "net/sockstat"
203 + , 2405
204 + , update_every
205 + , RRDSET_TYPE_LINE
206 + );
207 +
208 + rd_alloc = rrddim_add(st, "alloc", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
209 + rd_orphan = rrddim_add(st, "orphan", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
210 + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
211 + rd_timewait = rrddim_add(st, "timewait", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
212 + }
213 + else rrdset_next(st);
214 +
215 + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.tcp_inuse);
216 + rrddim_set_by_pointer(st, rd_orphan, (collected_number)sockstat_root.tcp_orphan);
217 + rrddim_set_by_pointer(st, rd_timewait, (collected_number)sockstat_root.tcp_tw);
218 + rrddim_set_by_pointer(st, rd_alloc, (collected_number)sockstat_root.tcp_alloc);
219 + rrdset_done(st);
220 + }
221 +
222 + // ------------------------------------------------------------------------
223 +
224 + if(do_tcp_mem == CONFIG_BOOLEAN_YES || (do_tcp_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.tcp_mem)) {
225 + do_tcp_mem = CONFIG_BOOLEAN_YES;
226 +
227 + static RRDSET *st = NULL;
228 + static RRDDIM *rd_mem = NULL;
229 +
230 + if(unlikely(!st)) {
231 + st = rrdset_create_localhost(
232 + "ipv4"
233 + , "sockstat_tcp_mem"
234 + , NULL
235 + , "sockets"
236 + , NULL
237 + , "IPv4 TCP Sockets Memory"
238 + , "KB"
239 + , "proc"
240 + , "net/sockstat"
241 + , 2406
242 + , update_every
243 + , RRDSET_TYPE_LINE
244 + );
245 +
246 + rd_mem = rrddim_add(st, "mem", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_ABSOLUTE);
247 + }
248 + else rrdset_next(st);
249 +
250 + rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.tcp_mem);
251 + rrdset_done(st);
252 + }
253 +
254 + // ------------------------------------------------------------------------
255 +
256 + if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.udp_inuse)) {
257 + do_udp_sockets = CONFIG_BOOLEAN_YES;
258 +
259 + static RRDSET *st = NULL;
260 + static RRDDIM *rd_inuse = NULL;
261 +
262 + if(unlikely(!st)) {
263 + st = rrdset_create_localhost(
264 + "ipv4"
265 + , "sockstat_udp_sockets"
266 + , NULL
267 + , "sockets"
268 + , NULL
269 + , "IPv4 UDP Sockets"
270 + , "sockets"
271 + , "proc"
272 + , "net/sockstat"
273 + , 2410
274 + , update_every
275 + , RRDSET_TYPE_LINE
276 + );
277 +
278 + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
279 + }
280 + else rrdset_next(st);
281 +
282 + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.udp_inuse);
283 + rrdset_done(st);
284 + }
285 +
286 + // ------------------------------------------------------------------------
287 +
288 + if(do_udp_mem == CONFIG_BOOLEAN_YES || (do_udp_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.udp_mem)) {
289 + do_udp_mem = CONFIG_BOOLEAN_YES;
290 +
291 + static RRDSET *st = NULL;
292 + static RRDDIM *rd_mem = NULL;
293 +
294 + if(unlikely(!st)) {
295 + st = rrdset_create_localhost(
296 + "ipv4"
297 + , "sockstat_udp_mem"
298 + , NULL
299 + , "sockets"
300 + , NULL
301 + , "IPv4 UDP Sockets Memory"
302 + , "KB"
303 + , "proc"
304 + , "net/sockstat"
305 + , 2411
306 + , update_every
307 + , RRDSET_TYPE_LINE
308 + );
309 +
310 + rd_mem = rrddim_add(st, "mem", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_ABSOLUTE);
311 + }
312 + else rrdset_next(st);
313 +
314 + rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.udp_mem);
315 + rrdset_done(st);
316 + }
317 +
318 + // ------------------------------------------------------------------------
319 +
320 + if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.udplite_inuse)) {
321 + do_udplite_sockets = CONFIG_BOOLEAN_YES;
322 +
323 + static RRDSET *st = NULL;
324 + static RRDDIM *rd_inuse = NULL;
325 +
326 + if(unlikely(!st)) {
327 + st = rrdset_create_localhost(
328 + "ipv4"
329 + , "sockstat_udplite_sockets"
330 + , NULL
331 + , "sockets"
332 + , NULL
333 + , "IPv4 UDPLITE Sockets"
334 + , "sockets"
335 + , "proc"
336 + , "net/sockstat"
337 + , 2420
338 + , update_every
339 + , RRDSET_TYPE_LINE
340 + );
341 +
342 + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
343 + }
344 + else rrdset_next(st);
345 +
346 + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.udplite_inuse);
347 + rrdset_done(st);
348 + }
349 +
350 + // ------------------------------------------------------------------------
351 +
352 + if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.raw_inuse)) {
353 + do_raw_sockets = CONFIG_BOOLEAN_YES;
354 +
355 + static RRDSET *st = NULL;
356 + static RRDDIM *rd_inuse = NULL;
357 +
358 + if(unlikely(!st)) {
359 + st = rrdset_create_localhost(
360 + "ipv4"
361 + , "sockstat_raw_sockets"
362 + , NULL
363 + , "sockets"
364 + , NULL
365 + , "IPv4 RAW Sockets"
366 + , "sockets"
367 + , "proc"
368 + , "net/sockstat"
369 + , 2430
370 + , update_every
371 + , RRDSET_TYPE_LINE
372 + );
373 +
374 + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
375 + }
376 + else rrdset_next(st);
377 +
378 + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.raw_inuse);
379 + rrdset_done(st);
380 + }
381 +
382 + // ------------------------------------------------------------------------
383 +
384 + if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.frag_inuse)) {
385 + do_frag_sockets = CONFIG_BOOLEAN_YES;
386 +
387 + static RRDSET *st = NULL;
388 + static RRDDIM *rd_inuse = NULL;
389 +
390 + if(unlikely(!st)) {
391 + st = rrdset_create_localhost(
392 + "ipv4"
393 + , "sockstat_frag_sockets"
394 + , NULL
395 + , "sockets"
396 + , NULL
397 + , "IPv4 FRAG Sockets"
398 + , "sockets"
399 + , "proc"
400 + , "net/sockstat"
401 + , 2440
402 + , update_every
403 + , RRDSET_TYPE_LINE
404 + );
405 +
406 + rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
407 + }
408 + else rrdset_next(st);
409 +
410 + rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.frag_inuse);
411 + rrdset_done(st);
412 + }
413 +
414 + // ------------------------------------------------------------------------
415 +
416 + if(do_frag_mem == CONFIG_BOOLEAN_YES || (do_frag_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.frag_memory)) {
417 + do_frag_mem = CONFIG_BOOLEAN_YES;
418 +
419 + static RRDSET *st = NULL;
420 + static RRDDIM *rd_mem = NULL;
421 +
422 + if(unlikely(!st)) {
423 + st = rrdset_create_localhost(
424 + "ipv4"
425 + , "sockstat_frag_mem"
426 + , NULL
427 + , "sockets"
428 + , NULL
429 + , "IPv4 FRAG Sockets Memory"
430 + , "KB"
431 + , "proc"
432 + , "net/sockstat"
433 + , 2441
434 + , update_every
435 + , RRDSET_TYPE_LINE
436 + );
437 +
438 + rd_mem = rrddim_add(st, "mem", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
439 + }
440 + else rrdset_next(st);
441 +
442 + rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.frag_memory);
443 + rrdset_done(st);
444 + }
445 +
446 + return 0;
447 +}
448 +