[libvirt] [PATCH 08/12] interface_backend_netcf: Implement link speed & state

Michal Privoznik mprivozn at redhat.com
Thu May 29 08:32:42 UTC 2014


While the previous commit was pretty straightforward, things are
different with netcf as it doesn't exposed the bits we need yet.
However, we can work around it by fetching the info we need from
SYSFS.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 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 */
-- 
1.9.3




More information about the libvir-list mailing list