@cryptotaxi247 / netdata-1 / commits / 2881c3e5a

use netnsid for detecting cgroup networks; fixes #5383 (#5413)

Costa Tsaousis committed Feb 18, 2019 at 17:40 UTC 2881c3e5a181d65a95d3f3d68d22bfe2f5c62a1d
2 files changed +67 -6
collectors/cgroups.plugin/cgroup-network-helper.sh
+38 -1
@@ -60,7 +60,7 @@ fatal() {
60 exit 1
61 }
62
63 -debug=0
63 +debug=${NETDATA_CGROUP_NETWORK_HELPER_DEBUG=0}
64 debug() {
65 [ "${debug}" = "1" ] && log DEBUG "${@}"
66 }
@@ -132,6 +132,8 @@ find_tun_tap_interfaces_for_cgroup() {
132 do
133 proc_pid_fdinfo_iff "${p}"
134 done
135 + else
136 + debug "Cannot find file '${c}/emulator/cgroup.procs', not searching for tun/tap interfaces."
137 fi
138 }
139
@@ -184,6 +186,39 @@ virsh_find_all_interfaces_for_cgroup() {
186 fi
187 }
188
189 +# -----------------------------------------------------------------------------
190 +# netnsid detected interfaces
191 +
192 +netnsid_find_all_interfaces_for_pid() {
193 + local pid="${1}"
194 + [ -z "${pid}" ] && return 1
195 +
196 + local nsid=$(lsns -t net -p ${pid} -o NETNSID -nr)
197 + [ -z "${nsid}" -o "${nsid}" = "unassigned" ] && return 1
198 +
199 + set_source "netnsid"
200 + ip link show |\
201 + grep -B 1 -E " link-netnsid ${nsid}($| )" |\
202 + ip link show | grep -B 1 -E " link-netnsid ${nsid}($| )" | sed -n -e "s|^[[:space:]]*[0-9]\+:[[:space:]]\+\([A-Za-z0-9_]\+\)\(@[A-Za-z0-9_]\+\)*:[[:space:]].*$|\1|p"
203 +}
204 +
205 +netnsid_find_all_interfaces_for_cgroup() {
206 + local c="${1}" # the cgroup path
207 +
208 + # for each pid of the cgroup
209 + # find any tun/tap devices linked to the pid
210 + if [ -f "${c}/cgroup.procs" ]
211 + then
212 + local p
213 + for p in $(< "${c}/cgroup.procs" )
214 + do
215 + netnsid_find_all_interfaces_for_pid "${p}"
216 + done
217 + else
218 + debug "Cannot find file '${c}/cgroup.procs', not searching for netnsid interfaces."
219 + fi
220 +}
221 +
222 # -----------------------------------------------------------------------------
223
224 find_all_interfaces_of_pid_or_cgroup() {
@@ -194,6 +229,7 @@ find_all_interfaces_of_pid_or_cgroup() {
229 # we have been called with a pid
230
231 proc_pid_fdinfo_iff "${p}"
232 + netnsid_find_all_interfaces_for_pid "${p}"
233
234 elif [ ! -z "${c}" ]
235 then
@@ -203,6 +239,7 @@ find_all_interfaces_of_pid_or_cgroup() {
239
240 find_tun_tap_interfaces_for_cgroup "${c}"
241 virsh_find_all_interfaces_for_cgroup "${c}"
242 + netnsid_find_all_interfaces_for_cgroup "${c}"
243
244 else
245
collectors/cgroups.plugin/cgroup-network.c
+29 -5
@@ -86,13 +86,18 @@ unsigned int read_iface_ifindex(const char *prefix, const char *iface) {
86 return (unsigned int)ifindex;
87 }
88
89 -struct iface *read_proc_net_dev(const char *prefix) {
89 +struct iface *read_proc_net_dev(const char *scope, const char *prefix) {
90 if(!prefix) prefix = "";
91
92 procfile *ff = NULL;
93 char filename[FILENAME_MAX + 1];
94
95 snprintfz(filename, FILENAME_MAX, "%s%s", prefix, (*prefix)?"/proc/1/net/dev":"/proc/net/dev");
96 +
97 +#ifdef NETDATA_INTERNAL_CHECKS
98 + info("parsing '%s'", filename);
99 +#endif
100 +
101 ff = procfile_open(filename, " \t,:|", PROCFILE_FLAG_DEFAULT);
102 if(unlikely(!ff)) {
103 error("Cannot open file '%s'", filename);
@@ -117,6 +122,10 @@ struct iface *read_proc_net_dev(const char *prefix) {
122 t->iflink = read_iface_iflink(prefix, t->device);
123 t->next = root;
124 root = t;
125 +
126 +#ifdef NETDATA_INTERNAL_CHECKS
127 + info("added %s interface '%s', ifindex %u, iflink %u", scope, t->device, t->ifindex, t->iflink);
128 +#endif
129 }
130
131 procfile_close(ff);
@@ -323,6 +332,11 @@ pid_t read_pid_from_cgroup_file(const char *filename) {
332 }
333
334 fclose(fp);
335 +
336 +#ifdef NETDATA_INTERNAL_CHECKS
337 + if(pid > 0) info("found pid %d on file '%s'", pid, filename);
338 +#endif
339 +
340 return pid;
341 }
342
@@ -380,6 +394,10 @@ struct found_device {
394 } *detected_devices = NULL;
395
396 void add_device(const char *host, const char *guest) {
397 +#ifdef NETDATA_INTERNAL_CHECKS
398 + info("adding device with host '%s', guest '%s'", host, guest);
399 +#endif
400 +
401 uint32_t hash = simple_hash(host);
402
403 if(guest && (!*guest || strcmp(host, guest) == 0))
@@ -387,10 +405,12 @@ void add_device(const char *host, const char *guest) {
405
406 struct found_device *f;
407 for(f = detected_devices; f ; f = f->next) {
390 - if(f->host_device_hash == hash && strcmp(host, f->host_device) == 0) {
408 + if(f->host_device_hash == hash && !strcmp(host, f->host_device)) {
409
392 - if(guest && !f->guest_device)
410 + if(guest && (!f->guest_device || !strcmp(f->host_device, f->guest_device))) {
411 + if(f->guest_device) freez((void *)f->guest_device);
412 f->guest_device = strdupz(guest);
413 + }
414
415 return;
416 }
@@ -425,7 +445,7 @@ void detect_veth_interfaces(pid_t pid) {
445 struct iface *cgroup = NULL;
446 struct iface *host, *h, *c;
447
428 - host = read_proc_net_dev(netdata_configured_host_prefix);
448 + host = read_proc_net_dev("host", netdata_configured_host_prefix);
449 if(!host) {
450 errno = 0;
451 error("cannot read host interface list.");
@@ -444,7 +464,11 @@ void detect_veth_interfaces(pid_t pid) {
464 goto cleanup;
465 }
466
447 - cgroup = read_proc_net_dev(NULL);
467 +#ifdef NETDATA_INTERNAL_CHECKS
468 + info("switched to namespaces of pid %d", pid);
469 +#endif
470 +
471 + cgroup = read_proc_net_dev("cgroup", NULL);
472 if(!cgroup) {
473 errno = 0;
474 error("cannot read cgroup interface list.");