From 2881c3e5a181d65a95d3f3d68d22bfe2f5c62a1d Mon Sep 17 00:00:00 2001 From: Costa Tsaousis Date: Mon, 18 Feb 2019 17:40:44 +0200 Subject: use netnsid for detecting cgroup networks; fixes #5383 (#5413) --- collectors/cgroups.plugin/cgroup-network-helper.sh | 39 +++++++++++++++++++++- collectors/cgroups.plugin/cgroup-network.c | 34 ++++++++++++++++--- 2 files changed, 67 insertions(+), 6 deletions(-) (limited to 'collectors/cgroups.plugin') diff --git a/collectors/cgroups.plugin/cgroup-network-helper.sh b/collectors/cgroups.plugin/cgroup-network-helper.sh index 666f02fc88..4ac25cec80 100755 --- a/collectors/cgroups.plugin/cgroup-network-helper.sh +++ b/collectors/cgroups.plugin/cgroup-network-helper.sh @@ -60,7 +60,7 @@ fatal() { exit 1 } -debug=0 +debug=${NETDATA_CGROUP_NETWORK_HELPER_DEBUG=0} debug() { [ "${debug}" = "1" ] && log DEBUG "${@}" } @@ -132,6 +132,8 @@ find_tun_tap_interfaces_for_cgroup() { do proc_pid_fdinfo_iff "${p}" done + else + debug "Cannot find file '${c}/emulator/cgroup.procs', not searching for tun/tap interfaces." fi } @@ -184,6 +186,39 @@ virsh_find_all_interfaces_for_cgroup() { fi } +# ----------------------------------------------------------------------------- +# netnsid detected interfaces + +netnsid_find_all_interfaces_for_pid() { + local pid="${1}" + [ -z "${pid}" ] && return 1 + + local nsid=$(lsns -t net -p ${pid} -o NETNSID -nr) + [ -z "${nsid}" -o "${nsid}" = "unassigned" ] && return 1 + + set_source "netnsid" + ip link show |\ + grep -B 1 -E " link-netnsid ${nsid}($| )" |\ + 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" +} + +netnsid_find_all_interfaces_for_cgroup() { + local c="${1}" # the cgroup path + + # for each pid of the cgroup + # find any tun/tap devices linked to the pid + if [ -f "${c}/cgroup.procs" ] + then + local p + for p in $(< "${c}/cgroup.procs" ) + do + netnsid_find_all_interfaces_for_pid "${p}" + done + else + debug "Cannot find file '${c}/cgroup.procs', not searching for netnsid interfaces." + fi +} + # ----------------------------------------------------------------------------- find_all_interfaces_of_pid_or_cgroup() { @@ -194,6 +229,7 @@ find_all_interfaces_of_pid_or_cgroup() { # we have been called with a pid proc_pid_fdinfo_iff "${p}" + netnsid_find_all_interfaces_for_pid "${p}" elif [ ! -z "${c}" ] then @@ -203,6 +239,7 @@ find_all_interfaces_of_pid_or_cgroup() { find_tun_tap_interfaces_for_cgroup "${c}" virsh_find_all_interfaces_for_cgroup "${c}" + netnsid_find_all_interfaces_for_cgroup "${c}" else diff --git a/collectors/cgroups.plugin/cgroup-network.c b/collectors/cgroups.plugin/cgroup-network.c index 385672295e..87cb5ef121 100644 --- a/collectors/cgroups.plugin/cgroup-network.c +++ b/collectors/cgroups.plugin/cgroup-network.c @@ -86,13 +86,18 @@ unsigned int read_iface_ifindex(const char *prefix, const char *iface) { return (unsigned int)ifindex; } -struct iface *read_proc_net_dev(const char *prefix) { +struct iface *read_proc_net_dev(const char *scope, const char *prefix) { if(!prefix) prefix = ""; procfile *ff = NULL; char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", prefix, (*prefix)?"/proc/1/net/dev":"/proc/net/dev"); + +#ifdef NETDATA_INTERNAL_CHECKS + info("parsing '%s'", filename); +#endif + ff = procfile_open(filename, " \t,:|", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) { error("Cannot open file '%s'", filename); @@ -117,6 +122,10 @@ struct iface *read_proc_net_dev(const char *prefix) { t->iflink = read_iface_iflink(prefix, t->device); t->next = root; root = t; + +#ifdef NETDATA_INTERNAL_CHECKS + info("added %s interface '%s', ifindex %u, iflink %u", scope, t->device, t->ifindex, t->iflink); +#endif } procfile_close(ff); @@ -323,6 +332,11 @@ pid_t read_pid_from_cgroup_file(const char *filename) { } fclose(fp); + +#ifdef NETDATA_INTERNAL_CHECKS + if(pid > 0) info("found pid %d on file '%s'", pid, filename); +#endif + return pid; } @@ -380,6 +394,10 @@ struct found_device { } *detected_devices = NULL; void add_device(const char *host, const char *guest) { +#ifdef NETDATA_INTERNAL_CHECKS + info("adding device with host '%s', guest '%s'", host, guest); +#endif + uint32_t hash = simple_hash(host); if(guest && (!*guest || strcmp(host, guest) == 0)) @@ -387,10 +405,12 @@ void add_device(const char *host, const char *guest) { struct found_device *f; for(f = detected_devices; f ; f = f->next) { - if(f->host_device_hash == hash && strcmp(host, f->host_device) == 0) { + if(f->host_device_hash == hash && !strcmp(host, f->host_device)) { - if(guest && !f->guest_device) + if(guest && (!f->guest_device || !strcmp(f->host_device, f->guest_device))) { + if(f->guest_device) freez((void *)f->guest_device); f->guest_device = strdupz(guest); + } return; } @@ -425,7 +445,7 @@ void detect_veth_interfaces(pid_t pid) { struct iface *cgroup = NULL; struct iface *host, *h, *c; - host = read_proc_net_dev(netdata_configured_host_prefix); + host = read_proc_net_dev("host", netdata_configured_host_prefix); if(!host) { errno = 0; error("cannot read host interface list."); @@ -444,7 +464,11 @@ void detect_veth_interfaces(pid_t pid) { goto cleanup; } - cgroup = read_proc_net_dev(NULL); +#ifdef NETDATA_INTERNAL_CHECKS + info("switched to namespaces of pid %d", pid); +#endif + + cgroup = read_proc_net_dev("cgroup", NULL); if(!cgroup) { errno = 0; error("cannot read cgroup interface list."); -- cgit v1.2.3