@cryptotaxi247 / netdata-1 / commits / 8d397b116

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