]> xenbits.xensource.com Git - libvirt.git/commitdiff
Thu Nov 15 17:43:00 UTC 2007 Richard W.M. Jones <rjones@redhat.com>
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 15 Nov 2007 17:45:44 +0000 (17:45 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 15 Nov 2007 17:45:44 +0000 (17:45 +0000)
* src/stats_linux.c: Fix parsing of short interface names
  occurring in the /proc/net/dev file.
* src/qemu_driver.c: Collect interface stats for QEMU & KVM
  domains.

ChangeLog
src/qemu_driver.c
src/stats_linux.c

index 04b37e9c761dc7ae50f532164cf48d02b6314ab1..e019150fac8ed43a016fabe3fb82ef23c212437a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Nov 15 17:43:00 UTC 2007 Richard W.M. Jones <rjones@redhat.com>
+
+       * src/stats_linux.c: Fix parsing of short interface names
+         occurring in the /proc/net/dev file.
+       * src/qemu_driver.c: Collect interface stats for QEMU & KVM
+         domains.
+
 Thu Nov 15 17:40:15 UTC 2007 Richard W.M. Jones <rjones@redhat.com>
 
        * docs/hvsupport.html, docs/libvir.html: Document HV support
index 62a1f6ba989081c121b37bf0b5cbd9ed4b591d53..da690fa7661ff1d332988a89afc06482a03a580c 100644 (file)
@@ -55,6 +55,7 @@
 #include "qemu_driver.h"
 #include "qemu_conf.h"
 #include "nodeinfo.h"
+#include "stats_linux.h"
 
 static int qemudShutdown(void);
 
@@ -2479,6 +2480,65 @@ static int qemudDomainSetAutostart(virDomainPtr dom,
     return 0;
 }
 
+static int
+qemudDomainInterfaceStats (virDomainPtr dom,
+                           const char *path,
+                           struct _virDomainInterfaceStats *stats)
+{
+#ifdef __linux__
+    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+    struct qemud_vm *vm = qemudFindVMByID (driver, dom->id);
+    struct qemud_vm_net_def *net;
+
+    if (!vm) {
+        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+                          "no domain with matching id %d", dom->id);
+        return -1;
+    }
+
+    if (!qemudIsActiveVM(vm)) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                         "domain is not running");
+        return -1;
+    }
+
+    if (!path || path[0] == '\0') {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
+                         "NULL or empty path");
+        return -1;
+    }
+
+    /* Check the path is one of the domain's network interfaces. */
+    for (net = vm->def->nets; net; net = net->next) {
+        switch (net->type) {
+        case QEMUD_NET_NETWORK:
+            if (STREQ (net->dst.network.ifname, path))
+                goto ok;
+            break;
+        case QEMUD_NET_ETHERNET:
+            if (STREQ (net->dst.ethernet.ifname, path))
+                goto ok;
+            break;
+        case QEMUD_NET_BRIDGE:
+            if (STREQ (net->dst.bridge.ifname, path))
+                goto ok;
+            break;
+        }
+    }
+
+    qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
+                      "invalid path, '%s' is not a known interface", path);
+    return -1;
+ ok:
+
+    return linuxDomainInterfaceStats (dom->conn, path, stats);
+#else
+    qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+                      "%s", __FUNCTION__);
+    return -1;
+#endif
+}
+
 static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
                                      const unsigned char *uuid) {
     struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
@@ -2822,7 +2882,7 @@ static virDriver qemuDriver = {
     NULL, /* domainMigratePerform */
     NULL, /* domainMigrateFinish */
     NULL, /* domainBlockStats */
-    NULL, /* domainInterfaceStats */
+    qemudDomainInterfaceStats, /* domainInterfaceStats */
     NULL, /* nodeGetCellsFreeMemory */
     NULL, /* getFreeMemory */
 };
index 125af45fcddfff59ed1c04749b5001c683d56ccc..f35d5dd4e10520b9f8664fb7d1b54110317e6bd6 100644 (file)
@@ -291,7 +291,7 @@ linuxDomainInterfaceStats (virConnectPtr conn, const char *path,
 {
     int path_len;
     FILE *fp;
-    char line[256];
+    char line[256], *colon;
 
     fp = fopen ("/proc/net/dev", "r");
     if (!fp) {
@@ -313,16 +313,22 @@ linuxDomainInterfaceStats (virConnectPtr conn, const char *path,
         long long tx_errs;
         long long tx_drop;
 
-        if (STREQLEN (line, path, path_len) &&
-            line[path_len] == ':' &&
-            line[path_len+1] == ' ') {
+        /* The line looks like:
+         *   "   eth0:..."
+         * Split it at the colon.
+         */
+        colon = strchr (line, ':');
+        if (!colon) continue;
+        *colon = '\0';
+        if (colon-path_len >= line &&
+            STREQ (colon-path_len, path)) {
             /* IMPORTANT NOTE!
              * /proc/net/dev vif<domid>.nn sees the network from the point
              * of view of dom0 / hypervisor.  So bytes TRANSMITTED by dom0
              * are bytes RECEIVED by the domain.  That's why the TX/RX fields
              * appear to be swapped here.
              */
-            if (sscanf (&line[path_len+2],
+            if (sscanf (colon+1,
                         "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
                         &tx_bytes, &tx_packets, &tx_errs, &tx_drop,
                         &dummy, &dummy, &dummy, &dummy,