mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 11:31:16 +00:00
Fix vlan ID detection in udev interface driver
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
This commit is contained in:
parent
5c2f782f76
commit
a65871aaae
@ -25,6 +25,7 @@
|
|||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
|
|
||||||
#include "virerror.h"
|
#include "virerror.h"
|
||||||
|
#include "virfile.h"
|
||||||
#include "c-ctype.h"
|
#include "c-ctype.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "domain_conf.h"
|
#include "domain_conf.h"
|
||||||
@ -966,31 +967,64 @@ udevGetIfaceDefVlan(struct udev *udev ATTRIBUTE_UNUSED,
|
|||||||
const char *name,
|
const char *name,
|
||||||
virInterfaceDef *ifacedef)
|
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;
|
||||||
|
|
||||||
/* Find the DEVICE.VID again */
|
if (virAsprintf(&procpath, "/proc/net/vlan/%s", name) < 0)
|
||||||
vid = strrchr(name, '.');
|
goto cleanup;
|
||||||
if (!vid) {
|
|
||||||
|
if (virFileReadAll(procpath, BUFSIZ, &buf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((vid_pos = strstr(buf, vid_prefix)) == NULL) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("failed to find the VID for the VLAN device '%s'"),
|
_("failed to find the VID for the VLAN device '%s'"),
|
||||||
name);
|
name);
|
||||||
return -1;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
vid_pos += strlen(vid_prefix);
|
||||||
|
|
||||||
|
if ((vid_len = strspn(vid_pos, "0123456789")) == 0 ||
|
||||||
|
!c_isspace(vid_pos[vid_len])) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("failed to find the VID for the VLAN device '%s'"),
|
||||||
|
name);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the VLAN specifics */
|
if ((dev_pos = strstr(vid_pos + vid_len, dev_prefix)) == NULL) {
|
||||||
if (VIR_STRDUP(ifacedef->data.vlan.tag, vid + 1) < 0)
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
goto error;
|
_("failed to find the real device for the VLAN device '%s'"),
|
||||||
if (VIR_STRNDUP(ifacedef->data.vlan.devname,
|
name);
|
||||||
name, (vid - name)) < 0)
|
goto cleanup;
|
||||||
goto error;
|
}
|
||||||
|
dev_pos += strlen(dev_prefix);
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
if (VIR_STRNDUP(ifacedef->data.vlan.tag, vid_pos, vid_len) < 0)
|
||||||
VIR_FREE(ifacedef->data.vlan.tag);
|
goto cleanup;
|
||||||
VIR_FREE(ifacedef->data.vlan.devname);
|
if (VIR_STRNDUP(ifacedef->data.vlan.devname, dev_pos, dev_len) < 0) {
|
||||||
|
VIR_FREE(ifacedef->data.vlan.tag);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(procpath);
|
||||||
|
VIR_FREE(buf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static virInterfaceDef * ATTRIBUTE_NONNULL(1)
|
static virInterfaceDef * ATTRIBUTE_NONNULL(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user