Instead of guessing it from the interface name, look into /proc/net/vlan/<interface>. This works for devices not named <real_device>.<vlan ID>, avoiding an error flood when virt-manager keeps asking about them every second: https://bugzilla.redhat.com/show_bug.cgi?id=966329 --- src/interface/interface_backend_udev.c | 67 ++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/src/interface/interface_backend_udev.c b/src/interface/interface_backend_udev.c index b05ac0e..bec8c45 100644 --- a/src/interface/interface_backend_udev.c +++ b/src/interface/interface_backend_udev.c @@ -20,11 +20,13 @@ */ #include <config.h> +#include <ctype.h> #include <errno.h> #include <dirent.h> #include <libudev.h> #include "virerror.h" +#include "virfile.h" #include "c-ctype.h" #include "datatypes.h" #include "domain_conf.h" @@ -966,31 +968,64 @@ udevGetIfaceDefVlan(struct udev *udev ATTRIBUTE_UNUSED, const char *name, virInterfaceDef *ifacedef) { - const char *vid; + char *procpath = NULL; + char *buf = NULL; + char *vid_pos, *dev_pos; + size_t vid_len, dev_len; + const char *vid_prefix = "VID: "; + const char *dev_prefix = "\nDevice: "; + int ret = -1; + + if (virAsprintf(&procpath, "/proc/net/vlan/%s", name) < 0) + goto cleanup; + + if (virFileReadAll(procpath, BUFSIZ, &buf) < 0) + goto cleanup; - /* Find the DEVICE.VID again */ - vid = strrchr(name, '.'); - if (!vid) { + if ((vid_pos = strstr(buf, vid_prefix)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to find the VID for the VLAN device '%s'"), name); - return -1; + goto cleanup; } + vid_pos += strlen(vid_prefix); - /* Set the VLAN specifics */ - if (VIR_STRDUP(ifacedef->data.vlan.tag, vid + 1) < 0) - goto error; - if (VIR_STRNDUP(ifacedef->data.vlan.devname, - name, (vid - name)) < 0) - goto error; + if ((vid_len = strspn(vid_pos, "0123456789")) == 0 || + !isspace(vid_pos[vid_len])) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to find the VID for the VLAN device '%s'"), + name); + goto cleanup; + } - return 0; + if ((dev_pos = strstr(vid_pos + vid_len, dev_prefix)) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to find the real device for the VLAN device '%s'"), + name); + goto cleanup; + } + dev_pos += strlen(dev_prefix); - error: - VIR_FREE(ifacedef->data.vlan.tag); - VIR_FREE(ifacedef->data.vlan.devname); + if ((dev_len = strcspn(dev_pos, "\n")) == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to find the real device for the VLAN device '%s'"), + name); + goto cleanup; + } - return -1; + if (VIR_STRNDUP(ifacedef->data.vlan.tag, vid_pos, vid_len) < 0) + goto cleanup; + if (VIR_STRNDUP(ifacedef->data.vlan.devname, dev_pos, dev_len) < 0) { + VIR_FREE(ifacedef->data.vlan.tag); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(procpath); + VIR_FREE(buf); + return ret; } static virInterfaceDef * ATTRIBUTE_NONNULL(1) -- 1.8.3.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list