On 05/29/2014 11:32 AM, Michal Privoznik wrote: > While the previous commit was pretty straightforward, things are > different with netcf as it doesn't exposed the bits we need yet. Rather than tacking these onto the XML returned from netcf after the fact, we should instead modify netcf to directly provide the desired information in the XML returned from ncf_if_xml_state(). I can help with that. Also, note that the interface XML only returns items that can be configured when the VIR_INTERFACE_XML_INACTIVE flag is set, or when the interface isn't active. If these values are read-only, I think they should only be present when the interface is active and the INACTIVE flag isn't set (i.e. they are part of the interface status rather than config). Of course netcf has a separate API (ncf_if_status) that checks the interface IFF_UP and IFF_RUNNING flags, and uses that to determine what is returned from libvirt's virInterfaceIsActive() API. We should probably try to at least be sure that what is returned from that is enough differentiated in documentation from what is returned in this new <state> element that they aren't confused with each other (if they are in fact different in practice). And that brings up another possible issue (depending on exactly how "<link state='up'> meshes with IFF_UP|IFF_RUNNING) - within the current virInterfaceGetXMLDesc() paradigm of "interface *status* is only returned when an interface is 'active'" (which was directly copied from libvirt's behavior in the case of domains and networks), 1) it will never be possible to learn about the state of the interface when the interface is inactive (and if the cable is unplugged, it is considered inactive), and 2) it will then be a bit pointless to report the active/inactive status of the interface in the XML since it will by definition always report "active" (state='up') if the element is present at all. In order to make it useful, we'll need to modify the semantics of virInterfaceGetXMLDesc() in some way such that it is always possible to get the current status even when the interface is down; for example, possibly we could add a VIR_INTERFACE_XML_STATUS flag that would indicate to always return the status of the interface, even when it is inactive. > However, we can work around it by fetching the info we need from > SYSFS. > > Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> > --- > src/interface/interface_backend_netcf.c | 99 +++++++++++++++++++++++++++++++++ > 1 file changed, 99 insertions(+) > > diff --git a/src/interface/interface_backend_netcf.c b/src/interface/interface_backend_netcf.c > index 1b9ace5..40181ef 100644 > --- a/src/interface/interface_backend_netcf.c > +++ b/src/interface/interface_backend_netcf.c > @@ -33,6 +33,7 @@ > #include "virlog.h" > #include "virstring.h" > #include "viraccessapicheck.h" > +#include "virfile.h" > > #define VIR_FROM_THIS VIR_FROM_INTERFACE > > @@ -240,6 +241,96 @@ static struct netcf_if *interfaceDriverGetNetcfIF(struct netcf *ncf, virInterfac > return iface; > } > > +/* Okay, the following two doesn't really belong here as they dump the info > + * from SYSFS rather than netcf. But netcf is not yet exposing the info we > + * need, so what. */ > +#define SYSFS_PREFIX "/sys/class/net/" > + > +static int > +interfaceGetState(const char *name, > + virInterfaceState *state) > +{ > + int ret = -1; > + char *path = NULL; > + char *buf = NULL; > + char *tmp; > + > + if (virAsprintf(&path, SYSFS_PREFIX "%s/operstate", name) < 0) > + goto cleanup; > + > + if (virFileReadAll(path, 1024, &buf) < 0) { > + virReportSystemError(errno, > + _("unable to read: %s"), > + path); > + goto cleanup; > + } > + > + if (!(tmp = strchr(buf, '\n'))) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Unable to parse: %s"), > + buf); > + goto cleanup; > + } > + > + *tmp = '\0'; > + > + /* We shouldn't allow 0 here, because > + * virInterfaceState enum starts from 1. */ > + if ((*state = virInterfaceStateTypeFromString(buf)) <= 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Unable to parse: %s"), > + buf); > + goto cleanup; > + } > + > + ret = 0; > + cleanup: > + VIR_FREE(buf); > + VIR_FREE(path); > + return ret; > +} > + > +static int > +interfaceGetSpeed(const char *name, > + unsigned long *speed) > +{ > + int ret = -1; > + char *path = NULL; > + char *buf = NULL; > + char *tmp; > + > + if (virAsprintf(&path, SYSFS_PREFIX "%s/speed", name) < 0) > + goto cleanup; > + > + if (virFileReadAll(path, 1024, &buf) < 0) { > + /* Some devices doesn't report speed, in which case we get EINVAL */ > + if (errno == EINVAL) { > + ret = 0; > + goto cleanup; > + } > + virReportSystemError(errno, > + _("unable to read: %s"), > + path); > + goto cleanup; > + } > + > + if (virStrToLong_ul(buf, &tmp, 10, speed) < 0 || > + *tmp != '\n') { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Unable to parse: %s"), > + buf); > + goto cleanup; > + } > + > + ret = 1; > + cleanup: > + VIR_FREE(buf); > + VIR_FREE(path); > + return ret; > +} > + > +/* Ond of sysfs hacks */ > + > static int > netcfInterfaceObjIsActive(struct netcf_if *iface, > bool *active) > @@ -840,6 +931,14 @@ static char *netcfInterfaceGetXMLDesc(virInterfacePtr ifinfo, > if (virInterfaceGetXMLDescEnsureACL(ifinfo->conn, ifacedef) < 0) > goto cleanup; > > + if (interfaceGetState(ifacedef->name, &ifacedef->state) < 0) > + goto cleanup; > + > + /* querying inteface speed makes sense only sometimes */ > + if (ifacedef->state == VIR_INTERFACE_STATE_UP && > + interfaceGetSpeed(ifacedef->name, &ifacedef->speed) < 0) > + goto cleanup; > + > ret = virInterfaceDefFormat(ifacedef); > if (!ret) { > /* error was already reported */ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list