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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list