Added support for retrieving the XML defining a specific interface via
the udev based backend to virInterface. Implement the following APIs
for the udev based backend:
* virInterfaceGetXMLDesc()
Note: Does not support bond devices.
---
***
* NOTE: I'm aware this is incomplete (e.g. no bond support) and we aren't
* showing devices in a bridge. This patch can be considered only a RFC
* or it can be applied and I'll work on further support as I figure
* out how to implement it. Waiting for feedback from LKML and from
* the udev ML on some questions or patches.
***
change since v1:
* support vlans
* cleanups for simplifications
src/interface/interface_backend_udev.c | 128 ++++++++++++++++++++++++++++++++
1 files changed, 128 insertions(+), 0 deletions(-)
diff --git a/src/interface/interface_backend_udev.c
b/src/interface/interface_backend_udev.c
index b001e6e..2f37bed 100644
--- a/src/interface/interface_backend_udev.c
+++ b/src/interface/interface_backend_udev.c
@@ -489,6 +489,133 @@ err:
return ret;
}
+static char *
+udevIfaceGetXMLDesc(virInterfacePtr ifinfo,
+ unsigned int flags)
+{
+ struct udev_iface_driver *driverState = ifinfo->conn->interfacePrivateData;
+ struct udev *udev = udev_ref(driverState->udev);
+ struct udev_device *dev;
+ virInterfaceDef ifacedef;
+ unsigned int mtu;
+ const char *mtu_str;
+ char *vlan_parent_dev = NULL;
+ char *xmlstr = NULL;
+
+ virCheckFlags(VIR_INTERFACE_XML_INACTIVE, NULL);
+
+ /* Lookup the device we've been asked about */
+ dev = udev_device_new_from_subsystem_sysname(udev, "net",
+ ifinfo->name);
+ if (!dev) {
+ virReportError(VIR_ERR_NO_INTERFACE,
+ _("couldn't find interface named '%s'"),
+ ifinfo->name);
+ goto cleanup;
+ }
+
+ /* Zero it all out */
+ memset(&ifacedef, 0, sizeof(ifacedef));
+
+ /* Common pieces */
+ ifacedef.name = ifinfo->name;
+ ifacedef.mac = ifinfo->mac;
+ ifacedef.startmode = VIR_INTERFACE_START_UNSPECIFIED;
+
+ /* MTU */
+ mtu_str = udev_device_get_sysattr_value(dev, "mtu");
+ if (virStrToLong_ui(mtu_str, NULL, 10, &mtu) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse MTU value '%s'"), mtu_str);
+ goto cleanup;
+ }
+ ifacedef.mtu = mtu;
+
+ /* Number of IP protocols this interface has assigned */
+ /* XXX: Do we want a netlink query or a call out to ip or leave it? */
+ ifacedef.nprotos = 0;
+ ifacedef.protos = NULL;
+
+ /* Check if its a VLAN since we can have a VLAN of any of the
+ * other devices */
+ vlan_parent_dev = strrchr(ifinfo->name, '.');
+ if (vlan_parent_dev) {
+ /* Found the VLAN dot */
+ char *vid;
+
+ vlan_parent_dev = strdup(ifinfo->name);
+ if (!vlan_parent_dev) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Find the DEVICE.VID separator again */
+ vid = strrchr(vlan_parent_dev, '.');
+ if (!vid) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to find the VID for the VLAN device
'%s'"),
+ ifinfo->name);
+ goto cleanup;
+ }
+
+ /* Replace the dot with a NULL so we can have the device and VID */
+ vid[0] = '\0';
+ vid++;
+
+ /* Set our type to VLAN */
+ ifacedef.type = VIR_INTERFACE_TYPE_VLAN;
+
+ /* Set the VLAN specifics */
+ ifacedef.data.vlan.tag = vid;
+ ifacedef.data.vlan.devname = vlan_parent_dev;
+ } else if (STREQ_NULLABLE(udev_device_get_devtype(dev), "bridge")) {
+ /* Check if its a bridge device */
+ const char *stp_str;
+ int stp;
+
+ /* Set our type to Bridge */
+ ifacedef.type = VIR_INTERFACE_TYPE_BRIDGE;
+
+ /* Bridge specifics */
+ ifacedef.data.bridge.delay =
+ strdup(udev_device_get_sysattr_value(dev,
"bridge/forward_delay"));
+ if (!ifacedef.data.bridge.delay) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ stp_str = udev_device_get_sysattr_value(dev, "bridge/stp_state");
+ if (virStrToLong_i(stp_str, NULL, 10, &stp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse STP state '%s'"),
stp_str);
+ goto cleanup;
+ }
+ ifacedef.data.bridge.stp = stp;
+
+ /* Members of the bridge */
+ /* XXX: Waiting to hear back from the udev/systemd ML how to
+ * successfully query this.
+ */
+ ifacedef.data.bridge.nbItf = 0;
+ ifacedef.data.bridge.itf = NULL;
+ } else {
+ /* Set our type to ethernet */
+ ifacedef.type = VIR_INTERFACE_TYPE_ETHERNET;
+ }
+
+ /* Convert our interface to XML */
+ xmlstr = virInterfaceDefFormat(&ifacedef);
+
+cleanup:
+ if (ifacedef.type == VIR_INTERFACE_TYPE_BRIDGE)
+ VIR_FREE(ifacedef.data.bridge.delay);
+
+ VIR_FREE(vlan_parent_dev);
+
+ udev_unref(udev);
+ return xmlstr;
+}
+
static virInterfaceDriver udevIfaceDriver = {
"udev",
.open = udevIfaceOpenInterface, /* 0.10.3 */
@@ -500,6 +627,7 @@ static virInterfaceDriver udevIfaceDriver = {
.listAllInterfaces = udevIfaceListAllInterfaces, /* 0.10.3 */
.interfaceLookupByName = udevIfaceLookupByName, /* 0.10.3 */
.interfaceLookupByMACString = udevIfaceLookupByMACString, /* 0.10.3 */
+ .interfaceGetXMLDesc = udevIfaceGetXMLDesc, /* 0.10.3 */
};
int
--
1.7.8.6