]> xenbits.xensource.com Git - libvirt.git/commitdiff
virnetdev: Introduce virNetDevGetLinkInfo
authorMichal Privoznik <mprivozn@redhat.com>
Thu, 5 Jun 2014 14:14:49 +0000 (16:14 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 11 Jun 2014 07:57:39 +0000 (09:57 +0200)
The purpose of this function is to fetch link state
and link speed for given NIC name from the SYSFS.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
src/libvirt_private.syms
src/util/virnetdev.c
src/util/virnetdev.h

index 7a740abfb1f2cb822cee4182abb3adc7b2a76d52..122c572cd2cb6e9ffbaedabb39f682e27543e882 100644 (file)
@@ -1542,6 +1542,7 @@ virNetDevClearIPv4Address;
 virNetDevExists;
 virNetDevGetIndex;
 virNetDevGetIPv4Address;
+virNetDevGetLinkInfo;
 virNetDevGetMAC;
 virNetDevGetMTU;
 virNetDevGetPhysicalFunction;
index 3a60cf7c4380a63119e0b3f14b1e31d13404dd34..cbf086e106ab2cbd824fcd993994b6ec8fc166f4 100644 (file)
@@ -1832,3 +1832,97 @@ virNetDevRestoreNetConfig(const char *linkdev ATTRIBUTE_UNUSED,
 }
 
 #endif /* defined(__linux__) && defined(HAVE_LIBNL) */
+
+#ifdef __linux__
+int
+virNetDevGetLinkInfo(const char *ifname,
+                     virInterfaceLinkPtr lnk)
+{
+    int ret = -1;
+    char *path = NULL;
+    char *buf = NULL;
+    char *tmp;
+    int tmp_state;
+    unsigned int tmp_speed;
+
+    if (virNetDevSysfsFile(&path, ifname, "operstate") < 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 ((tmp_state = virInterfaceStateTypeFromString(buf)) <= 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unable to parse: %s"),
+                       buf);
+        goto cleanup;
+    }
+
+    lnk->state = tmp_state;
+
+    VIR_FREE(path);
+    VIR_FREE(buf);
+
+    if (virNetDevSysfsFile(&path, ifname, "speed") < 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_ui(buf, &tmp, 10, &tmp_speed) < 0 ||
+        *tmp != '\n') {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unable to parse: %s"),
+                       buf);
+        goto cleanup;
+    }
+
+    /* Workaround broken kernel API. If the link is unplugged then
+     * depending on the NIC driver, link speed can be reported as -1.
+     * However, the value is printed out as unsigned integer instead of
+     * signed one. Terrifying but true. */
+    lnk->speed = (int) tmp_speed == -1 ? 0 : tmp_speed;
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(buf);
+    VIR_FREE(path);
+    return ret;
+}
+
+#else
+
+int
+virNetDevGetLinkInfo(const char *ifname,
+                     virInterfaceLinkPtr lnk)
+{
+    /* Port me */
+    VIR_DEBUG("Getting link info on %s is not implemented on this platform");
+    lnk->speed = lnk->state = 0;
+    return 0;
+}
+#endif /* defined(__linux__) */
index 00c82e0d5fc6513b3ce393e340f63138dba60f96..69e365e74184baee708dfd995bbccef109ef4646 100644 (file)
@@ -29,6 +29,7 @@
 # include "virnetlink.h"
 # include "virmacaddr.h"
 # include "virpci.h"
+# include "device_conf.h"
 
 # ifdef HAVE_STRUCT_IFREQ
 typedef struct ifreq virIfreq;
@@ -145,4 +146,8 @@ int virNetDevGetVirtualFunctionInfo(const char *vfname, char **pfname,
                                     int *vf)
     ATTRIBUTE_NONNULL(1);
 
+int virNetDevGetLinkInfo(const char *ifname,
+                         virInterfaceLinkPtr lnk)
+    ATTRIBUTE_NONNULL(1);
+
 #endif /* __VIR_NETDEV_H__ */