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
+