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.");