cleanup proc net-dev renames (#16745)
* cleanup proc net-dev renames * more cleanup * remove unused variable * fix memory leak in pluginsd parser * fix double-free
Costa Tsaousis committed
Jan 10, 2024 at 00:49 UTC
8d397b116a9f817e1d184dc867f66cc0382f69c6
7 files changed
+143
-246
CMakeLists.txt
+2
@@ -1124,6 +1124,8 @@ set(PROC_PLUGIN_FILES
1124
collectors/proc.plugin/proc_meminfo.c
1125
collectors/proc.plugin/proc_pagetypeinfo.c
1126
collectors/proc.plugin/proc_net_dev.c
1127
+ collectors/proc.plugin/proc_net_dev_renames.c
1128
+ collectors/proc.plugin/proc_net_dev_renames.h
1129
collectors/proc.plugin/proc_net_wireless.c
1130
collectors/proc.plugin/proc_net_ip_vs_stats.c
1131
collectors/proc.plugin/proc_net_netstat.c
collectors/cgroups.plugin/cgroup-discovery.c
+8
-3
@@ -42,7 +42,7 @@ static inline void cgroup_free_network_interfaces(struct cgroup *cg) {
42
cg->interfaces = i->next;
43
44
// delete the registration of proc_net_dev rename
45
- netdev_rename_device_del(i->host_device);
45
+ cgroup_rename_task_device_del(i->host_device);
46
47
freez((void *)i->host_device);
48
freez((void *)i->container_device);
@@ -1084,8 +1084,13 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) {
1084
collector_info("CGROUP: cgroup '%s' has network interface '%s' as '%s'", cg->id, i->host_device, i->container_device);
1085
1086
// register a device rename to proc_net_dev.c
1087
- netdev_rename_device_add(i->host_device, i->container_device, cg->chart_id, cg->chart_labels,
1088
- k8s_is_kubepod(cg) ? "k8s." : "", cgroup_netdev_get(cg));
1087
+ cgroup_rename_task_add(
1088
+ i->host_device,
1089
+ i->container_device,
1090
+ cg->chart_id,
1091
+ cg->chart_labels,
1092
+ k8s_is_kubepod(cg) ? "k8s." : "",
1093
+ cgroup_netdev_get(cg));
1094
}
1095
}
1096
collectors/plugins.d/pluginsd_parser.c
+1
-2
@@ -1225,7 +1225,7 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp_plugi
1225
ND_LOG_STACK_PUSH(lgs);
1226
1227
buffered_reader_init(&parser->reader);
1228
- BUFFER *buffer = buffer_create(sizeof(parser->reader.read_buffer) + 2, NULL);
1228
+ CLEAN_BUFFER *buffer = buffer_create(sizeof(parser->reader.read_buffer) + 2, NULL);
1229
while(likely(service_running(SERVICE_COLLECTORS))) {
1230
1231
if(unlikely(!buffered_reader_next_line(&parser->reader, buffer))) {
@@ -1247,7 +1247,6 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp_plugi
1247
buffer->len = 0;
1248
buffer->buffer[0] = '\0';
1249
}
1250
- buffer_free(buffer);
1250
1251
cd->unsafe.enabled = parser->user.enabled;
1252
count = parser->user.data_collections_count;
collectors/proc.plugin/plugin_proc.h
+2
-2
@@ -54,7 +54,7 @@ extern unsigned long long zfs_arcstats_shrinkable_cache_size_bytes;
54
extern bool inside_lxc_container;
55
56
// netdev renames
57
-void netdev_rename_device_add(
57
+void cgroup_rename_task_add(
58
const char *host_device,
59
const char *container_device,
60
const char *container_name,
@@ -62,7 +62,7 @@ void netdev_rename_device_add(
62
const char *ctx_prefix,
63
const DICTIONARY_ITEM *cgroup_netdev_link);
64
65
-void netdev_rename_device_del(const char *host_device);
65
+void cgroup_rename_task_device_del(const char *host_device);
66
67
#include "proc_self_mountinfo.h"
68
#include "proc_pressure.h"
collectors/proc.plugin/proc_net_dev.c
+51
-239
@@ -1,6 +1,7 @@
1
// SPDX-License-Identifier: GPL-3.0-or-later
2
3
#include "plugin_proc.h"
4
+#include "proc_net_dev_renames.h"
5
6
#define PLUGIN_PROC_MODULE_NETDEV_NAME "/proc/net/dev"
7
#define CONFIG_SECTION_PLUGIN_PROC_NETDEV "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NETDEV_NAME
@@ -13,19 +14,13 @@
14
15
time_t double_linked_device_collect_delay_secs = 120;
16
16
-void cgroup_netdev_reset_all(void);
17
-void cgroup_netdev_release(const DICTIONARY_ITEM *link);
18
-const void *cgroup_netdev_dup(const DICTIONARY_ITEM *link);
19
-void cgroup_netdev_add_bandwidth(const DICTIONARY_ITEM *link, NETDATA_DOUBLE received, NETDATA_DOUBLE sent);
20
-
17
enum {
18
NETDEV_DUPLEX_UNKNOWN,
19
NETDEV_DUPLEX_HALF,
20
NETDEV_DUPLEX_FULL
21
};
22
27
-static const char *get_duplex_string(int duplex)
28
-{
23
+static const char *get_duplex_string(int duplex) {
24
switch (duplex) {
25
case NETDEV_DUPLEX_FULL:
26
return "full";
@@ -46,8 +41,7 @@ enum {
41
NETDEV_OPERSTATE_UP
42
};
43
49
-static inline int get_operstate(char *operstate)
50
-{
44
+static inline int get_operstate(char *operstate) {
45
// As defined in https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net
46
if (!strcmp(operstate, "up"))
47
return NETDEV_OPERSTATE_UP;
@@ -65,8 +59,7 @@ static inline int get_operstate(char *operstate)
59
return NETDEV_OPERSTATE_UNKNOWN;
60
}
61
68
-static const char *get_operstate_string(int operstate)
69
-{
62
+static const char *get_operstate_string(int operstate) {
63
switch (operstate) {
64
case NETDEV_OPERSTATE_UP:
65
return "up";
@@ -94,13 +87,11 @@ static struct netdev {
87
size_t len;
88
89
// flags
97
- int virtual;
98
- int configured;
90
+ bool virtual;
91
+ bool configured;
92
int enabled;
100
- int updated;
101
-
93
+ bool updated;
94
bool function_ready;
103
-
95
bool double_linked; // iflink != ifindex
96
97
time_t discover_time;
@@ -255,10 +246,8 @@ static struct netdev {
246
247
const DICTIONARY_ITEM *cgroup_netdev_link;
248
258
- struct netdev *next;
259
-} *netdev_root = NULL, *netdev_last_used = NULL;
260
-
261
-static size_t netdev_added = 0, netdev_found = 0;
249
+ struct netdev *prev, *next;
250
+} *netdev_root = NULL;
251
252
// ----------------------------------------------------------------------------
253
@@ -382,133 +371,21 @@ static void netdev_free(struct netdev *d) {
371
freez((void *)d->filename_carrier);
372
freez((void *)d->filename_mtu);
373
freez((void *)d);
385
- netdev_added--;
386
-}
387
-
388
-// ----------------------------------------------------------------------------
389
-// netdev renames
390
-
391
-static struct netdev_rename {
392
- const char *host_device;
393
- uint32_t hash;
394
-
395
- const char *container_device;
396
- const char *container_name;
397
- const char *ctx_prefix;
398
-
399
- RRDLABELS *chart_labels;
400
-
401
- int processed;
402
-
403
- const DICTIONARY_ITEM *cgroup_netdev_link;
404
-
405
- struct netdev_rename *next;
406
-} *netdev_rename_root = NULL;
407
-
408
-static int netdev_pending_renames = 0;
409
-static netdata_mutex_t netdev_rename_mutex = NETDATA_MUTEX_INITIALIZER;
410
-static netdata_mutex_t netdev_dev_mutex = NETDATA_MUTEX_INITIALIZER;
411
-
412
-static struct netdev_rename *netdev_rename_find(const char *host_device, uint32_t hash) {
413
- struct netdev_rename *r;
414
-
415
- for(r = netdev_rename_root; r ; r = r->next)
416
- if(r->hash == hash && !strcmp(host_device, r->host_device))
417
- return r;
418
-
419
- return NULL;
420
-}
421
-
422
-// other threads can call this function to register a rename to a netdev
423
-void netdev_rename_device_add(
424
- const char *host_device,
425
- const char *container_device,
426
- const char *container_name,
427
- RRDLABELS *labels,
428
- const char *ctx_prefix,
429
- const DICTIONARY_ITEM *cgroup_netdev_link)
430
-{
431
- netdata_mutex_lock(&netdev_rename_mutex);
432
-
433
- uint32_t hash = simple_hash(host_device);
434
- struct netdev_rename *r = netdev_rename_find(host_device, hash);
435
- if(!r) {
436
- r = callocz(1, sizeof(struct netdev_rename));
437
- r->host_device = strdupz(host_device);
438
- r->container_device = strdupz(container_device);
439
- r->container_name = strdupz(container_name);
440
- r->ctx_prefix = strdupz(ctx_prefix);
441
- r->chart_labels = rrdlabels_create();
442
- rrdlabels_migrate_to_these(r->chart_labels, labels);
443
- r->hash = hash;
444
- r->next = netdev_rename_root;
445
- r->processed = 0;
446
- r->cgroup_netdev_link = cgroup_netdev_link;
447
-
448
- netdev_rename_root = r;
449
- netdev_pending_renames++;
450
- collector_info("CGROUP: registered network interface rename for '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
451
- }
452
- else {
453
- if(strcmp(r->container_device, container_device) != 0 || strcmp(r->container_name, container_name) != 0) {
454
- freez((void *) r->container_device);
455
- freez((void *) r->container_name);
456
-
457
- r->container_device = strdupz(container_device);
458
- r->container_name = strdupz(container_name);
459
-
460
- rrdlabels_migrate_to_these(r->chart_labels, labels);
461
-
462
- r->processed = 0;
463
- r->cgroup_netdev_link = cgroup_netdev_link;
464
-
465
- netdev_pending_renames++;
466
- collector_info("CGROUP: altered network interface rename for '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
467
- }
468
- }
469
-
470
- netdata_mutex_unlock(&netdev_rename_mutex);
374
}
375
473
-// other threads can call this function to delete a rename to a netdev
474
-void netdev_rename_device_del(const char *host_device) {
475
- netdata_mutex_lock(&netdev_rename_mutex);
476
-
477
- struct netdev_rename *r, *last = NULL;
478
-
479
- uint32_t hash = simple_hash(host_device);
480
- for(r = netdev_rename_root; r ; last = r, r = r->next) {
481
- if (r->hash == hash && !strcmp(host_device, r->host_device)) {
482
- if (netdev_rename_root == r)
483
- netdev_rename_root = r->next;
484
- else if (last)
485
- last->next = r->next;
486
-
487
- if(!r->processed)
488
- netdev_pending_renames--;
489
-
490
- collector_info("CGROUP: unregistered network interface rename for '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
491
-
492
- freez((void *) r->host_device);
493
- freez((void *) r->container_name);
494
- freez((void *) r->container_device);
495
- freez((void *) r->ctx_prefix);
496
- rrdlabels_destroy(r->chart_labels);
497
- cgroup_netdev_release(r->cgroup_netdev_link);
498
- freez((void *) r);
499
- break;
500
- }
501
- }
376
+static netdata_mutex_t netdev_mutex = NETDATA_MUTEX_INITIALIZER;
377
503
- netdata_mutex_unlock(&netdev_rename_mutex);
504
-}
378
+// ----------------------------------------------------------------------------
379
506
-static inline void netdev_rename_cgroup(struct netdev *d, struct netdev_rename *r) {
507
- collector_info("CGROUP: renaming network interface '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
380
+static inline void netdev_rename(struct netdev *d, struct rename_task *r) {
381
+ collector_info("CGROUP: renaming network interface '%s' as '%s' under '%s'", d->name, r->container_device, r->container_name);
382
383
netdev_charts_release(d);
384
netdev_free_chart_strings(d);
385
+
386
+ cgroup_netdev_release(d->cgroup_netdev_link);
387
d->cgroup_netdev_link = cgroup_netdev_dup(r->cgroup_netdev_link);
388
+ d->discover_time = 0;
389
390
char buffer[RRD_ID_LENGTH_MAX + 1];
391
@@ -585,33 +462,15 @@ static inline void netdev_rename_cgroup(struct netdev *d, struct netdev_rename *
462
d->flipped = 1;
463
}
464
588
-static inline void netdev_rename(struct netdev *d) {
589
- struct netdev_rename *r = netdev_rename_find(d->name, d->hash);
590
- if(unlikely(r && !r->processed)) {
591
- netdev_rename_cgroup(d, r);
592
- r->processed = 1;
593
- d->discover_time = 0;
594
- netdev_pending_renames--;
465
+static void netdev_rename_this_device(struct netdev *d) {
466
+ const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(netdev_renames, d->name);
467
+ if(item) {
468
+ struct rename_task *r = dictionary_acquired_item_value(item);
469
+ netdev_rename(d, r);
470
+ dictionary_acquired_item_release(netdev_renames, item);
471
}
472
}
473
598
-static inline void netdev_rename_lock(struct netdev *d) {
599
- netdata_mutex_lock(&netdev_rename_mutex);
600
- netdev_rename(d);
601
- netdata_mutex_unlock(&netdev_rename_mutex);
602
-}
603
-
604
-static inline void netdev_rename_all_lock(void) {
605
- netdata_mutex_lock(&netdev_rename_mutex);
606
-
607
- struct netdev *d;
608
- for(d = netdev_root; d ; d = d->next)
609
- netdev_rename(d);
610
-
611
- netdev_pending_renames = 0;
612
- netdata_mutex_unlock(&netdev_rename_mutex);
613
-}
614
-
474
// ----------------------------------------------------------------------------
475
476
int netdev_function_net_interfaces(uuid_t *transaction __maybe_unused, BUFFER *wb,
@@ -645,11 +504,11 @@ int netdev_function_net_interfaces(uuid_t *transaction __maybe_unused, BUFFER *w
504
double max_drops_rx = 0.0;
505
double max_drops_tx = 0.0;
506
648
- netdata_mutex_lock(&netdev_dev_mutex);
507
+ netdata_mutex_lock(&netdev_mutex);
508
509
RRDDIM *rd = NULL;
510
652
- for (struct netdev *d = netdev_root; d != netdev_last_used; d = d->next) {
511
+ for (struct netdev *d = netdev_root; d ; d = d->next) {
512
if (unlikely(!d->function_ready))
513
continue;
514
@@ -709,7 +568,7 @@ int netdev_function_net_interfaces(uuid_t *transaction __maybe_unused, BUFFER *w
568
buffer_json_array_close(wb);
569
}
570
712
- netdata_mutex_unlock(&netdev_dev_mutex);
571
+ netdata_mutex_unlock(&netdev_mutex);
572
573
buffer_json_array_close(wb); // data
574
buffer_json_member_add_object(wb, "columns");
@@ -918,49 +777,26 @@ int netdev_function_net_interfaces(uuid_t *transaction __maybe_unused, BUFFER *w
777
buffer_json_member_add_time_t(wb, "expires", now_realtime_sec() + 1);
778
buffer_json_finalize(wb);
779
921
- int response = HTTP_RESP_OK;
922
- if(is_cancelled_cb && is_cancelled_cb(is_cancelled_cb_data)) {
923
- buffer_flush(wb);
924
- response = HTTP_RESP_CLIENT_CLOSED_REQUEST;
925
- }
926
-
927
- if(result_cb)
928
- result_cb(wb, response, result_cb_data);
929
-
930
- return response;
780
+ return HTTP_RESP_OK;
781
}
782
783
// netdev data collection
784
785
static void netdev_cleanup() {
936
- if(likely(netdev_found == netdev_added)) return;
937
-
938
- netdev_added = 0;
939
- struct netdev *d = netdev_root, *last = NULL;
786
+ struct netdev *d = netdev_root;
787
while(d) {
788
if(unlikely(!d->updated)) {
942
- // collector_info("Removing network device '%s', linked after '%s'", d->name, last?last->name:"ROOT");
943
-
944
- if(netdev_last_used == d)
945
- netdev_last_used = last;
789
+ struct netdev *next = d->next; // keep the next, to continue;
790
947
- struct netdev *t = d;
791
+ DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(netdev_root, d, prev, next);
792
949
- if(d == netdev_root || !last)
950
- netdev_root = d = d->next;
951
-
952
- else
953
- last->next = d = d->next;
954
-
955
- t->next = NULL;
956
- netdev_free(t);
957
- }
958
- else {
959
- netdev_added++;
960
- last = d;
961
- d->updated = 0;
962
- d = d->next;
793
+ netdev_free(d);
794
+ d = next;
795
+ continue;
796
}
797
+
798
+ d->updated = false;
799
+ d = d->next;
800
}
801
}
802
@@ -970,19 +806,9 @@ static struct netdev *get_netdev(const char *name) {
806
uint32_t hash = simple_hash(name);
807
808
// search it, from the last position to the end
973
- for(d = netdev_last_used ; d ; d = d->next) {
974
- if(unlikely(hash == d->hash && !strcmp(name, d->name))) {
975
- netdev_last_used = d->next;
809
+ for(d = netdev_root ; d ; d = d->next) {
810
+ if(unlikely(hash == d->hash && !strcmp(name, d->name)))
811
return d;
977
- }
978
- }
979
-
980
- // search it from the beginning to the last position we used
981
- for(d = netdev_root ; d != netdev_last_used ; d = d->next) {
982
- if(unlikely(hash == d->hash && !strcmp(name, d->name))) {
983
- netdev_last_used = d->next;
984
- return d;
985
- }
812
}
813
814
// create a new one
@@ -1036,18 +862,7 @@ static struct netdev *get_netdev(const char *name) {
862
d->chart_family = strdupz(d->name);
863
d->priority = NETDATA_CHART_PRIO_FIRST_NET_IFACE;
864
1039
- netdev_rename_lock(d);
1040
-
1041
- netdev_added++;
1042
-
1043
- // link it to the end
1044
- if(netdev_root) {
1045
- struct netdev *e;
1046
- for(e = netdev_root; e->next ; e = e->next) ;
1047
- e->next = d;
1048
- }
1049
- else
1050
- netdev_root = d;
865
+ DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(netdev_root, d, prev, next);
866
867
return d;
868
}
@@ -1125,6 +940,8 @@ int do_proc_net_dev(int update_every, usec_t dt) {
940
disabled_list = simple_pattern_create(
941
config_get(CONFIG_SECTION_PLUGIN_PROC_NETDEV, "disable by default interfaces matching",
942
"lo fireqos* *-ifb fwpr* fwbr* fwln*"), NULL, SIMPLE_PATTERN_EXACT, true);
943
+
944
+ netdev_renames_init();
945
}
946
947
if(unlikely(!ff)) {
@@ -1135,12 +952,6 @@ int do_proc_net_dev(int update_every, usec_t dt) {
952
ff = procfile_readall(ff);
953
if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
954
1138
- // rename all the devices, if we have pending renames
1139
- if(unlikely(netdev_pending_renames))
1140
- netdev_rename_all_lock();
1141
-
1142
- netdev_found = 0;
1143
-
955
kernel_uint_t system_rbytes = 0;
956
kernel_uint_t system_tbytes = 0;
957
@@ -1156,14 +967,13 @@ int do_proc_net_dev(int update_every, usec_t dt) {
967
if(name[len - 1] == ':') name[len - 1] = '\0';
968
969
struct netdev *d = get_netdev(name);
1159
- d->updated = 1;
1160
- netdev_found++;
970
+ d->updated = true;
971
972
if(unlikely(!d->configured)) {
1163
- // this is the first time we see this interface
973
+ // the first time we see this interface
974
975
// remember we configured it
1166
- d->configured = 1;
976
+ d->configured = true;
977
d->discover_time = now;
978
979
d->enabled = enable_new_interfaces;
@@ -1174,12 +984,12 @@ int do_proc_net_dev(int update_every, usec_t dt) {
984
char buf[FILENAME_MAX + 1];
985
snprintfz(buf, FILENAME_MAX, path_to_sys_devices_virtual_net, d->name);
986
1177
- d->virtual = likely(access(buf, R_OK) == 0) ? 1 : 0;
987
+ d->virtual = likely(access(buf, R_OK) == 0) ? true : false;
988
989
// At least on Proxmox inside LXC: eth0 is virtual.
990
// Virtual interfaces are not taken into account in system.net calculations
991
if (inside_lxc_container && d->virtual && strncmp(d->name, "eth", 3) == 0)
1182
- d->virtual = 0;
992
+ d->virtual = false;
993
994
if (d->virtual)
995
rrdlabels_add(d->chart_labels, "interface_type", "virtual", RRDLABEL_SRC_AUTO);
@@ -1260,13 +1070,15 @@ int do_proc_net_dev(int update_every, usec_t dt) {
1070
if(unlikely(!d->enabled))
1071
continue;
1072
1073
+ if(!d->cgroup_netdev_link)
1074
+ netdev_rename_this_device(d);
1075
+
1076
// See https://github.com/netdata/netdata/issues/15206
1077
// This is necessary to prevent the creation of charts for virtual interfaces that will later be
1078
// recreated as container interfaces (create container) or
1079
// rediscovered and recreated only to be deleted almost immediately (stop/remove container)
1267
- if (d->double_linked && d->virtual && (now - d->discover_time < double_linked_device_collect_delay_secs)) {
1080
+ if (d->double_linked && d->virtual && (now - d->discover_time < double_linked_device_collect_delay_secs))
1081
continue;
1269
- }
1082
1083
if(likely(d->do_bandwidth != CONFIG_BOOLEAN_NO || !d->virtual)) {
1084
d->rbytes = str2kernel_uint_t(procfile_lineword(ff, l, 1));
@@ -1974,10 +1786,10 @@ void *netdev_main(void *ptr)
1786
1787
worker_is_busy(0);
1788
1977
- netdata_mutex_lock(&netdev_dev_mutex);
1789
+ netdata_mutex_lock(&netdev_mutex);
1790
if (do_proc_net_dev(localhost->rrd_update_every, hb_dt))
1791
break;
1980
- netdata_mutex_unlock(&netdev_dev_mutex);
1792
+ netdata_mutex_unlock(&netdev_mutex);
1793
}
1794
}
1795
netdata_thread_cleanup_pop(1);
collectors/proc.plugin/proc_net_dev_renames.c
new
+53
@@ -0,0 +1,53 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "proc_net_dev_renames.h"
4
+
5
+DICTIONARY *netdev_renames = NULL;
6
+
7
+static void dictionary_netdev_rename_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
8
+ struct rename_task *r = value;
9
+
10
+ cgroup_netdev_release(r->cgroup_netdev_link);
11
+ rrdlabels_destroy(r->chart_labels);
12
+ freez((void *) r->container_name);
13
+ freez((void *) r->container_device);
14
+ freez((void *) r->ctx_prefix);
15
+}
16
+
17
+void netdev_renames_init(void) {
18
+ static SPINLOCK spinlock = NETDATA_SPINLOCK_INITIALIZER;
19
+
20
+ spinlock_lock(&spinlock);
21
+ if(!netdev_renames) {
22
+ netdev_renames = dictionary_create_advanced(DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct rename_task));
23
+ dictionary_register_delete_callback(netdev_renames, dictionary_netdev_rename_delete_cb, NULL);
24
+ }
25
+ spinlock_unlock(&spinlock);
26
+}
27
+
28
+void cgroup_rename_task_add(
29
+ const char *host_device,
30
+ const char *container_device,
31
+ const char *container_name,
32
+ RRDLABELS *labels,
33
+ const char *ctx_prefix,
34
+ const DICTIONARY_ITEM *cgroup_netdev_link)
35
+{
36
+ netdev_renames_init();
37
+
38
+ struct rename_task tmp = {
39
+ .container_device = strdupz(container_device),
40
+ .container_name = strdupz(container_name),
41
+ .ctx_prefix = strdupz(ctx_prefix),
42
+ .chart_labels = rrdlabels_create(),
43
+ .cgroup_netdev_link = cgroup_netdev_link,
44
+ };
45
+ rrdlabels_migrate_to_these(tmp.chart_labels, labels);
46
+
47
+ dictionary_set(netdev_renames, host_device, &tmp, sizeof(tmp));
48
+}
49
+
50
+// other threads can call this function to delete a rename to a netdev
51
+void cgroup_rename_task_device_del(const char *host_device) {
52
+ dictionary_del(netdev_renames, host_device);
53
+}
collectors/proc.plugin/proc_net_dev_renames.h
new
+26
@@ -0,0 +1,26 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_PROC_NET_DEV_RENAMES_H
4
+#define NETDATA_PROC_NET_DEV_RENAMES_H
5
+
6
+#include "plugin_proc.h"
7
+
8
+extern DICTIONARY *netdev_renames;
9
+
10
+struct rename_task {
11
+ const char *container_device;
12
+ const char *container_name;
13
+ const char *ctx_prefix;
14
+ RRDLABELS *chart_labels;
15
+ const DICTIONARY_ITEM *cgroup_netdev_link;
16
+};
17
+
18
+void netdev_renames_init(void);
19
+
20
+void cgroup_netdev_reset_all(void);
21
+void cgroup_netdev_release(const DICTIONARY_ITEM *link);
22
+const void *cgroup_netdev_dup(const DICTIONARY_ITEM *link);
23
+void cgroup_netdev_add_bandwidth(const DICTIONARY_ITEM *link, NETDATA_DOUBLE received, NETDATA_DOUBLE sent);
24
+
25
+
26
+#endif //NETDATA_PROC_NET_DEV_RENAMES_H