]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Tue Aug 21 10:58:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
authorRichard W.M. Jones <rjones@redhat.com>
Tue, 21 Aug 2007 10:08:12 +0000 (10:08 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Tue, 21 Aug 2007 10:08:12 +0000 (10:08 +0000)
* src/libvirt.c (virDomainBlockStats, virDomainInterfaceStats):
  Added block device and network interface statistics.
* src/xen_internal.c: Support for stats from Xen domains.
* qemud/remote.c, qemud/remote_protocol.x, qemud/remote_internal.c:
  Support for fetching device and network interface stats
  across remote connections.
* src/virsh.c: Added 'virsh domblkstat' and 'virsh domifstat'
  commands to display stats.
* docs/libvir.html, docs/hvsupport.html: Updated hvsupport
  documentation.

22 files changed:
ChangeLog
docs/hvsupport.html
docs/libvir.html
include/libvirt/libvirt.h
include/libvirt/libvirt.h.in
qemud/remote.c
qemud/remote_dispatch_localvars.h
qemud/remote_dispatch_proc_switch.h
qemud/remote_dispatch_prototypes.h
qemud/remote_protocol.c
qemud/remote_protocol.h
qemud/remote_protocol.x
src/driver.h
src/libvirt.c
src/libvirt_sym.version
src/qemu_driver.c
src/remote_internal.c
src/test.c
src/virsh.c
src/xen_internal.c
src/xen_internal.h
src/xen_unified.c

index 415c9601ef188133aa2aeb79ac1c996219a75534..2473f4dd06eb857f30f0ef4841872e20b5e9e009 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Tue Aug 21 10:58:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
+
+       * src/libvirt.c (virDomainBlockStats, virDomainInterfaceStats):
+         Added block device and network interface statistics.
+       * src/xen_internal.c: Support for stats from Xen domains.
+       * qemud/remote.c, qemud/remote_protocol.x, qemud/remote_internal.c:
+         Support for fetching device and network interface stats
+         across remote connections.
+       * src/virsh.c: Added 'virsh domblkstat' and 'virsh domifstat'
+         commands to display stats.
+       * docs/libvir.html, docs/hvsupport.html: Updated hvsupport
+         documentation.
+
 Tue Aug 21 10:36:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
 
        * tests/xencapsdata/*.xml: Fixed tests to include new
index fe7f30faf3409891c4ec9a712362b2f1f32d09c7..b6244e088e7422e1318422f9e849fb0ee08772ed 100644 (file)
@@ -96,6 +96,12 @@ updated on <i>2007-08-20</i>.
   <td> x </td>
   <td> x </td>
   <td> &#8805; 0.3.0 </td>
+</tr><tr><td> virDomainBlockStats </td>
+  <td> 0.3.2 </td>
+  <td> &#8805; 0.3.2 </td>
+  <td> x </td>
+  <td> x </td>
+  <td> &#8805; 0.3.2 </td>
 </tr><tr><td> virDomainCoreDump </td>
   <td> 0.1.9 </td>
   <td> &#8805; 0.1.9 </td>
@@ -213,6 +219,12 @@ updated on <i>2007-08-20</i>.
   <td> x </td>
   <td> x </td>
   <td> &#8805; 0.3.0 </td>
+</tr><tr><td> virDomainInterfaceStats </td>
+  <td> 0.3.2 </td>
+  <td> &#8805; 0.3.2 </td>
+  <td> x </td>
+  <td> x </td>
+  <td> &#8805; 0.3.2 </td>
 </tr><tr><td> virDomainGetXMLDesc </td>
   <td> All </td>
   <td> All </td>
index 0e7539d8db0b34cbbd71ca7008cbeaa44f8485be..2365653c88050b5708f9a24104b69970c6953446 100644 (file)
@@ -2799,6 +2799,14 @@ updated on <i>2007-08-20</i>.
   <td> x </td>
   <td> &ge; 0.3.0 </td>
 </tr>
+<tr>
+  <td> virDomainBlockStats </td>
+  <td> 0.3.2 </td>
+  <td> &ge; 0.3.2 </td>
+  <td> x </td>
+  <td> x </td>
+  <td> &ge; 0.3.2 </td>
+</tr>
 <tr>
   <td> virDomainCoreDump </td>
   <td> 0.1.9 </td>
@@ -2956,6 +2964,14 @@ updated on <i>2007-08-20</i>.
   <td> x </td>
   <td> &ge; 0.3.0 </td>
 </tr>
+<tr>
+  <td> virDomainInterfaceStats </td>
+  <td> 0.3.2 </td>
+  <td> &ge; 0.3.2 </td>
+  <td> x </td>
+  <td> x </td>
+  <td> &ge; 0.3.2 </td>
+</tr>
 <tr>
   <td> virDomainGetXMLDesc </td>
   <td> All </td>
index 0ef4e2708012d1b1eb54e5742021c104a1373c52..3a22f9a09ab74c94688bb46d3bc92bc08816fa36 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef __VIR_VIRLIB_H__
 #define __VIR_VIRLIB_H__
 
+#include <sys/types.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -197,6 +199,41 @@ int        virDomainSetSchedulerParameters (virDomainPtr domain,
                                         virSchedParameterPtr params,
                                         int nparams);
 
+/* Block device stats for virDomainBlockStats.
+ *
+ * Hypervisors may return a field set to ((long long)-1) which indicates
+ * that the hypervisor does not support that statistic.
+ *
+ * NB. Here 'long long' means 64 bit integer.
+ */
+struct _virDomainBlockStats {
+  long long rd_req;
+  long long rd_bytes;
+  long long wr_req;
+  long long wr_bytes;
+  long long errs;   // In Xen this returns the mysterious 'oo_req'.
+};
+typedef struct _virDomainBlockStats *virDomainBlockStatsPtr;
+
+/* Network interface stats for virDomainInterfaceStats.
+ *
+ * Hypervisors may return a field set to ((long long)-1) which indicates
+ * that the hypervisor does not support that statistic.
+ *
+ * NB. Here 'long long' means 64 bit integer.
+ */
+struct _virDomainInterfaceStats {
+  long long rx_bytes;
+  long long rx_packets;
+  long long rx_errs;
+  long long rx_drop;
+  long long tx_bytes;
+  long long tx_packets;
+  long long tx_errs;
+  long long tx_drop;
+};
+typedef struct _virDomainInterfaceStats *virDomainInterfaceStatsPtr;
+
 /* Domain migration flags. */
 typedef enum {
   VIR_MIGRATE_LIVE              = 1, /* live migration */
@@ -379,6 +416,16 @@ int                        virDomainGetMaxVcpus    (virDomainPtr domain);
 char *                 virDomainGetXMLDesc     (virDomainPtr domain,
                                                 int flags);
 
+int                     virDomainBlockStats     (virDomainPtr dom,
+                                                const char *path,
+                                                virDomainBlockStatsPtr stats,
+                                                size_t size);
+int                     virDomainInterfaceStats (virDomainPtr dom,
+                                                const char *path,
+                                                virDomainInterfaceStatsPtr stats,
+                                                size_t size);
+
+
 /*
  * defined but not running domains
  */
index 255d11e2d0e221bc6523fee9df5f964b9b8fdf08..7a0df52d11b50e6c57310016b7f8d2f3fd4a21ac 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef __VIR_VIRLIB_H__
 #define __VIR_VIRLIB_H__
 
+#include <sys/types.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -197,6 +199,41 @@ int        virDomainSetSchedulerParameters (virDomainPtr domain,
                                         virSchedParameterPtr params,
                                         int nparams);
 
+/* Block device stats for virDomainBlockStats.
+ *
+ * Hypervisors may return a field set to ((long long)-1) which indicates
+ * that the hypervisor does not support that statistic.
+ *
+ * NB. Here 'long long' means 64 bit integer.
+ */
+struct _virDomainBlockStats {
+  long long rd_req;
+  long long rd_bytes;
+  long long wr_req;
+  long long wr_bytes;
+  long long errs;   // In Xen this returns the mysterious 'oo_req'.
+};
+typedef struct _virDomainBlockStats *virDomainBlockStatsPtr;
+
+/* Network interface stats for virDomainInterfaceStats.
+ *
+ * Hypervisors may return a field set to ((long long)-1) which indicates
+ * that the hypervisor does not support that statistic.
+ *
+ * NB. Here 'long long' means 64 bit integer.
+ */
+struct _virDomainInterfaceStats {
+  long long rx_bytes;
+  long long rx_packets;
+  long long rx_errs;
+  long long rx_drop;
+  long long tx_bytes;
+  long long tx_packets;
+  long long tx_errs;
+  long long tx_drop;
+};
+typedef struct _virDomainInterfaceStats *virDomainInterfaceStatsPtr;
+
 /* Domain migration flags. */
 typedef enum {
   VIR_MIGRATE_LIVE              = 1, /* live migration */
@@ -379,6 +416,16 @@ int                        virDomainGetMaxVcpus    (virDomainPtr domain);
 char *                 virDomainGetXMLDesc     (virDomainPtr domain,
                                                 int flags);
 
+int                     virDomainBlockStats     (virDomainPtr dom,
+                                                const char *path,
+                                                virDomainBlockStatsPtr stats,
+                                                size_t size);
+int                     virDomainInterfaceStats (virDomainPtr dom,
+                                                const char *path,
+                                                virDomainInterfaceStatsPtr stats,
+                                                size_t size);
+
+
 /*
  * defined but not running domains
  */
index 90ee1529d7a27d9962220486495ebb898be027b1..7bbe51024e860b25c2befe56abad32abd3106bce 100644 (file)
@@ -714,6 +714,69 @@ remoteDispatchDomainSetSchedulerParameters (struct qemud_client *client,
     return 0;
 }
 
+static int
+remoteDispatchDomainBlockStats (struct qemud_client *client,
+                                remote_message_header *req,
+                                remote_domain_block_stats_args *args,
+                                remote_domain_block_stats_ret *ret)
+{
+    virDomainPtr dom;
+    char *path;
+    struct _virDomainBlockStats stats;
+    CHECK_CONN (client);
+
+    dom = get_nonnull_domain (client->conn, args->dom);
+    if (dom == NULL) {
+        remoteDispatchError (client, req, "domain not found");
+        return -2;
+    }
+    path = args->path;
+
+    if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1)
+        return -1;
+
+    ret->rd_req = stats.rd_req;
+    ret->rd_bytes = stats.rd_bytes;
+    ret->wr_req = stats.wr_req;
+    ret->wr_bytes = stats.wr_bytes;
+    ret->errs = stats.errs;
+
+    return 0;
+}
+
+static int
+remoteDispatchDomainInterfaceStats (struct qemud_client *client,
+                                    remote_message_header *req,
+                                    remote_domain_interface_stats_args *args,
+                                    remote_domain_interface_stats_ret *ret)
+{
+    virDomainPtr dom;
+    char *path;
+    struct _virDomainInterfaceStats stats;
+    CHECK_CONN (client);
+
+    dom = get_nonnull_domain (client->conn, args->dom);
+    if (dom == NULL) {
+        remoteDispatchError (client, req, "domain not found");
+        return -2;
+    }
+    path = args->path;
+
+    if (virDomainInterfaceStats (dom, path, &stats, sizeof stats) == -1)
+        return -1;
+
+    ret->rx_bytes = stats.rx_bytes;
+    ret->rx_packets = stats.rx_packets;
+    ret->rx_errs = stats.rx_errs;
+    ret->rx_drop = stats.rx_drop;
+    ret->tx_bytes = stats.tx_bytes;
+    ret->tx_packets = stats.tx_packets;
+    ret->tx_errs = stats.tx_errs;
+    ret->tx_drop = stats.tx_drop;
+
+    return 0;
+}
+
 static int
 remoteDispatchDomainAttachDevice (struct qemud_client *client,
                                   remote_message_header *req,
index 07795d7c9e0b92f3f83ca1e24883a84199e43311..92ec482f852d397a261f1ee1210cd117f9586755 100644 (file)
@@ -2,94 +2,98 @@
  * Do not edit this file.  Any changes you make will be lost.
  */
 
-remote_network_lookup_by_name_args lv_remote_network_lookup_by_name_args;
-remote_network_lookup_by_name_ret lv_remote_network_lookup_by_name_ret;
 remote_domain_lookup_by_uuid_args lv_remote_domain_lookup_by_uuid_args;
 remote_domain_lookup_by_uuid_ret lv_remote_domain_lookup_by_uuid_ret;
-remote_num_of_defined_domains_ret lv_remote_num_of_defined_domains_ret;
-remote_domain_detach_device_args lv_remote_domain_detach_device_args;
-remote_domain_save_args lv_remote_domain_save_args;
 remote_domain_shutdown_args lv_remote_domain_shutdown_args;
 remote_list_defined_domains_args lv_remote_list_defined_domains_args;
 remote_list_defined_domains_ret lv_remote_list_defined_domains_ret;
-remote_domain_migrate_prepare_args lv_remote_domain_migrate_prepare_args;
-remote_domain_migrate_prepare_ret lv_remote_domain_migrate_prepare_ret;
 remote_get_capabilities_ret lv_remote_get_capabilities_ret;
 remote_domain_set_max_memory_args lv_remote_domain_set_max_memory_args;
-remote_domain_undefine_args lv_remote_domain_undefine_args;
 remote_domain_get_os_type_args lv_remote_domain_get_os_type_args;
 remote_domain_get_os_type_ret lv_remote_domain_get_os_type_ret;
 remote_domain_get_autostart_args lv_remote_domain_get_autostart_args;
 remote_domain_get_autostart_ret lv_remote_domain_get_autostart_ret;
 remote_domain_set_vcpus_args lv_remote_domain_set_vcpus_args;
-remote_domain_get_scheduler_type_args lv_remote_domain_get_scheduler_type_args;
-remote_domain_get_scheduler_type_ret lv_remote_domain_get_scheduler_type_ret;
 remote_get_hostname_ret lv_remote_get_hostname_ret;
 remote_network_undefine_args lv_remote_network_undefine_args;
 remote_domain_create_args lv_remote_domain_create_args;
-remote_domain_suspend_args lv_remote_domain_suspend_args;
-remote_get_version_ret lv_remote_get_version_ret;
 remote_network_destroy_args lv_remote_network_destroy_args;
-remote_network_set_autostart_args lv_remote_network_set_autostart_args;
-remote_network_get_autostart_args lv_remote_network_get_autostart_args;
-remote_network_get_autostart_ret lv_remote_network_get_autostart_ret;
 remote_domain_pin_vcpu_args lv_remote_domain_pin_vcpu_args;
 remote_list_defined_networks_args lv_remote_list_defined_networks_args;
 remote_list_defined_networks_ret lv_remote_list_defined_networks_ret;
 remote_network_create_xml_args lv_remote_network_create_xml_args;
 remote_network_create_xml_ret lv_remote_network_create_xml_ret;
-remote_domain_core_dump_args lv_remote_domain_core_dump_args;
 remote_open_args lv_remote_open_args;
 remote_list_domains_args lv_remote_list_domains_args;
 remote_list_domains_ret lv_remote_list_domains_ret;
 remote_network_define_xml_args lv_remote_network_define_xml_args;
 remote_network_define_xml_ret lv_remote_network_define_xml_ret;
-remote_domain_get_max_memory_args lv_remote_domain_get_max_memory_args;
-remote_domain_get_max_memory_ret lv_remote_domain_get_max_memory_ret;
 remote_get_type_ret lv_remote_get_type_ret;
-remote_num_of_domains_ret lv_remote_num_of_domains_ret;
-remote_list_networks_args lv_remote_list_networks_args;
-remote_list_networks_ret lv_remote_list_networks_ret;
 remote_network_dump_xml_args lv_remote_network_dump_xml_args;
 remote_network_dump_xml_ret lv_remote_network_dump_xml_ret;
-remote_domain_set_autostart_args lv_remote_domain_set_autostart_args;
 remote_domain_reboot_args lv_remote_domain_reboot_args;
 remote_domain_set_memory_args lv_remote_domain_set_memory_args;
 remote_domain_create_linux_args lv_remote_domain_create_linux_args;
 remote_domain_create_linux_ret lv_remote_domain_create_linux_ret;
 remote_domain_set_scheduler_parameters_args lv_remote_domain_set_scheduler_parameters_args;
-remote_domain_attach_device_args lv_remote_domain_attach_device_args;
-remote_domain_lookup_by_id_args lv_remote_domain_lookup_by_id_args;
-remote_domain_lookup_by_id_ret lv_remote_domain_lookup_by_id_ret;
-remote_num_of_networks_ret lv_remote_num_of_networks_ret;
-remote_domain_restore_args lv_remote_domain_restore_args;
+remote_domain_interface_stats_args lv_remote_domain_interface_stats_args;
+remote_domain_interface_stats_ret lv_remote_domain_interface_stats_ret;
 remote_domain_get_max_vcpus_args lv_remote_domain_get_max_vcpus_args;
 remote_domain_get_max_vcpus_ret lv_remote_domain_get_max_vcpus_ret;
 remote_domain_get_info_args lv_remote_domain_get_info_args;
 remote_domain_get_info_ret lv_remote_domain_get_info_ret;
-remote_network_create_args lv_remote_network_create_args;
-remote_num_of_defined_networks_ret lv_remote_num_of_defined_networks_ret;
 remote_supports_feature_args lv_remote_supports_feature_args;
 remote_supports_feature_ret lv_remote_supports_feature_ret;
 remote_domain_lookup_by_name_args lv_remote_domain_lookup_by_name_args;
 remote_domain_lookup_by_name_ret lv_remote_domain_lookup_by_name_ret;
-remote_network_lookup_by_uuid_args lv_remote_network_lookup_by_uuid_args;
-remote_network_lookup_by_uuid_ret lv_remote_network_lookup_by_uuid_ret;
 remote_domain_resume_args lv_remote_domain_resume_args;
 remote_network_get_bridge_name_args lv_remote_network_get_bridge_name_args;
 remote_network_get_bridge_name_ret lv_remote_network_get_bridge_name_ret;
 remote_domain_destroy_args lv_remote_domain_destroy_args;
-remote_domain_define_xml_args lv_remote_domain_define_xml_args;
-remote_domain_define_xml_ret lv_remote_domain_define_xml_ret;
 remote_domain_migrate_finish_args lv_remote_domain_migrate_finish_args;
 remote_domain_migrate_finish_ret lv_remote_domain_migrate_finish_ret;
 remote_domain_get_vcpus_args lv_remote_domain_get_vcpus_args;
 remote_domain_get_vcpus_ret lv_remote_domain_get_vcpus_ret;
 remote_domain_get_scheduler_parameters_args lv_remote_domain_get_scheduler_parameters_args;
 remote_domain_get_scheduler_parameters_ret lv_remote_domain_get_scheduler_parameters_ret;
+remote_node_get_info_ret lv_remote_node_get_info_ret;
+remote_network_lookup_by_name_args lv_remote_network_lookup_by_name_args;
+remote_network_lookup_by_name_ret lv_remote_network_lookup_by_name_ret;
+remote_num_of_defined_domains_ret lv_remote_num_of_defined_domains_ret;
+remote_domain_block_stats_args lv_remote_domain_block_stats_args;
+remote_domain_block_stats_ret lv_remote_domain_block_stats_ret;
+remote_domain_detach_device_args lv_remote_domain_detach_device_args;
+remote_domain_save_args lv_remote_domain_save_args;
+remote_domain_migrate_prepare_args lv_remote_domain_migrate_prepare_args;
+remote_domain_migrate_prepare_ret lv_remote_domain_migrate_prepare_ret;
+remote_domain_undefine_args lv_remote_domain_undefine_args;
+remote_domain_get_scheduler_type_args lv_remote_domain_get_scheduler_type_args;
+remote_domain_get_scheduler_type_ret lv_remote_domain_get_scheduler_type_ret;
+remote_get_version_ret lv_remote_get_version_ret;
+remote_domain_suspend_args lv_remote_domain_suspend_args;
+remote_network_set_autostart_args lv_remote_network_set_autostart_args;
+remote_network_get_autostart_args lv_remote_network_get_autostart_args;
+remote_network_get_autostart_ret lv_remote_network_get_autostart_ret;
+remote_domain_core_dump_args lv_remote_domain_core_dump_args;
+remote_domain_get_max_memory_args lv_remote_domain_get_max_memory_args;
+remote_domain_get_max_memory_ret lv_remote_domain_get_max_memory_ret;
+remote_num_of_domains_ret lv_remote_num_of_domains_ret;
+remote_list_networks_args lv_remote_list_networks_args;
+remote_list_networks_ret lv_remote_list_networks_ret;
+remote_domain_set_autostart_args lv_remote_domain_set_autostart_args;
+remote_domain_lookup_by_id_args lv_remote_domain_lookup_by_id_args;
+remote_domain_lookup_by_id_ret lv_remote_domain_lookup_by_id_ret;
+remote_domain_attach_device_args lv_remote_domain_attach_device_args;
+remote_num_of_networks_ret lv_remote_num_of_networks_ret;
+remote_domain_restore_args lv_remote_domain_restore_args;
+remote_network_create_args lv_remote_network_create_args;
+remote_num_of_defined_networks_ret lv_remote_num_of_defined_networks_ret;
+remote_network_lookup_by_uuid_args lv_remote_network_lookup_by_uuid_args;
+remote_network_lookup_by_uuid_ret lv_remote_network_lookup_by_uuid_ret;
+remote_domain_define_xml_args lv_remote_domain_define_xml_args;
+remote_domain_define_xml_ret lv_remote_domain_define_xml_ret;
 remote_domain_dump_xml_args lv_remote_domain_dump_xml_args;
 remote_domain_dump_xml_ret lv_remote_domain_dump_xml_ret;
 remote_get_max_vcpus_args lv_remote_get_max_vcpus_args;
 remote_get_max_vcpus_ret lv_remote_get_max_vcpus_ret;
-remote_node_get_info_ret lv_remote_node_get_info_ret;
 remote_domain_migrate_perform_args lv_remote_domain_migrate_perform_args;
index e58d8e97fd5008c978c9116167162baf6932bf18..ba000f1f11453753aaef7ba60b022b08c4502327 100644 (file)
@@ -11,6 +11,15 @@ case REMOTE_PROC_DOMAIN_ATTACH_DEVICE:
        args = (char *) &lv_remote_domain_attach_device_args;
        memset (&lv_remote_domain_attach_device_args, 0, sizeof lv_remote_domain_attach_device_args);
        break;
+case REMOTE_PROC_DOMAIN_BLOCK_STATS:
+       fn = (dispatch_fn) remoteDispatchDomainBlockStats;
+       args_filter = (xdrproc_t) xdr_remote_domain_block_stats_args;
+       args = (char *) &lv_remote_domain_block_stats_args;
+       memset (&lv_remote_domain_block_stats_args, 0, sizeof lv_remote_domain_block_stats_args);
+       ret_filter = (xdrproc_t) xdr_remote_domain_block_stats_ret;
+       ret = (char *) &lv_remote_domain_block_stats_ret;
+       memset (&lv_remote_domain_block_stats_ret, 0, sizeof lv_remote_domain_block_stats_ret);
+       break;
 case REMOTE_PROC_DOMAIN_CORE_DUMP:
        fn = (dispatch_fn) remoteDispatchDomainCoreDump;
        args_filter = (xdrproc_t) xdr_remote_domain_core_dump_args;
@@ -134,6 +143,15 @@ case REMOTE_PROC_DOMAIN_GET_VCPUS:
        ret = (char *) &lv_remote_domain_get_vcpus_ret;
        memset (&lv_remote_domain_get_vcpus_ret, 0, sizeof lv_remote_domain_get_vcpus_ret);
        break;
+case REMOTE_PROC_DOMAIN_INTERFACE_STATS:
+       fn = (dispatch_fn) remoteDispatchDomainInterfaceStats;
+       args_filter = (xdrproc_t) xdr_remote_domain_interface_stats_args;
+       args = (char *) &lv_remote_domain_interface_stats_args;
+       memset (&lv_remote_domain_interface_stats_args, 0, sizeof lv_remote_domain_interface_stats_args);
+       ret_filter = (xdrproc_t) xdr_remote_domain_interface_stats_ret;
+       ret = (char *) &lv_remote_domain_interface_stats_ret;
+       memset (&lv_remote_domain_interface_stats_ret, 0, sizeof lv_remote_domain_interface_stats_ret);
+       break;
 case REMOTE_PROC_DOMAIN_LOOKUP_BY_ID:
        fn = (dispatch_fn) remoteDispatchDomainLookupById;
        args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_args;
index 9ad9fb9b32daceedb78d6abde1c4c1e32240f6fa..c1925fcc7a534bfca1483ce7c69d95cc2ea7cadc 100644 (file)
@@ -4,6 +4,7 @@
 
 static int remoteDispatchClose (struct qemud_client *client, remote_message_header *req, void *args, void *ret);
 static int remoteDispatchDomainAttachDevice (struct qemud_client *client, remote_message_header *req, remote_domain_attach_device_args *args, void *ret);
+static int remoteDispatchDomainBlockStats (struct qemud_client *client, remote_message_header *req, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret);
 static int remoteDispatchDomainCoreDump (struct qemud_client *client, remote_message_header *req, remote_domain_core_dump_args *args, void *ret);
 static int remoteDispatchDomainCreate (struct qemud_client *client, remote_message_header *req, remote_domain_create_args *args, void *ret);
 static int remoteDispatchDomainCreateLinux (struct qemud_client *client, remote_message_header *req, remote_domain_create_linux_args *args, remote_domain_create_linux_ret *ret);
@@ -19,6 +20,7 @@ static int remoteDispatchDomainGetOsType (struct qemud_client *client, remote_me
 static int remoteDispatchDomainGetSchedulerParameters (struct qemud_client *client, remote_message_header *req, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret);
 static int remoteDispatchDomainGetSchedulerType (struct qemud_client *client, remote_message_header *req, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret);
 static int remoteDispatchDomainGetVcpus (struct qemud_client *client, remote_message_header *req, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret);
+static int remoteDispatchDomainInterfaceStats (struct qemud_client *client, remote_message_header *req, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret);
 static int remoteDispatchDomainLookupById (struct qemud_client *client, remote_message_header *req, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret);
 static int remoteDispatchDomainLookupByName (struct qemud_client *client, remote_message_header *req, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret);
 static int remoteDispatchDomainLookupByUuid (struct qemud_client *client, remote_message_header *req, remote_domain_lookup_by_uuid_args *args, remote_domain_lookup_by_uuid_ret *ret);
index e5dfb1c2cbe7cb3e35d0d9db58fe384ab8ca3f13..b0f7c7c996a649bc14321ad9b2b8b25d58108b13 100644 (file)
@@ -390,6 +390,68 @@ xdr_remote_domain_set_scheduler_parameters_args (XDR *xdrs, remote_domain_set_sc
        return TRUE;
 }
 
+bool_t
+xdr_remote_domain_block_stats_args (XDR *xdrs, remote_domain_block_stats_args *objp)
+{
+
+        if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+                return FALSE;
+        if (!xdr_remote_nonnull_string (xdrs, &objp->path))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_remote_domain_block_stats_ret (XDR *xdrs, remote_domain_block_stats_ret *objp)
+{
+
+        if (!xdr_quad_t (xdrs, &objp->rd_req))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->rd_bytes))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->wr_req))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->wr_bytes))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->errs))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_remote_domain_interface_stats_args (XDR *xdrs, remote_domain_interface_stats_args *objp)
+{
+
+        if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+                return FALSE;
+        if (!xdr_remote_nonnull_string (xdrs, &objp->path))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_remote_domain_interface_stats_ret (XDR *xdrs, remote_domain_interface_stats_ret *objp)
+{
+
+        if (!xdr_quad_t (xdrs, &objp->rx_bytes))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->rx_packets))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->rx_errs))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->rx_drop))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->tx_bytes))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->tx_packets))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->tx_errs))
+                return FALSE;
+        if (!xdr_quad_t (xdrs, &objp->tx_drop))
+                return FALSE;
+       return TRUE;
+}
+
 bool_t
 xdr_remote_list_domains_args (XDR *xdrs, remote_list_domains_args *objp)
 {
index 5a0310b561315e74b372af04791e25f5f3cee24c..a17a0d733fc528a445bf9883e3c4eb51037a34fc 100644 (file)
@@ -182,6 +182,39 @@ struct remote_domain_set_scheduler_parameters_args {
 };
 typedef struct remote_domain_set_scheduler_parameters_args remote_domain_set_scheduler_parameters_args;
 
+struct remote_domain_block_stats_args {
+       remote_nonnull_domain dom;
+       remote_nonnull_string path;
+};
+typedef struct remote_domain_block_stats_args remote_domain_block_stats_args;
+
+struct remote_domain_block_stats_ret {
+       quad_t rd_req;
+       quad_t rd_bytes;
+       quad_t wr_req;
+       quad_t wr_bytes;
+       quad_t errs;
+};
+typedef struct remote_domain_block_stats_ret remote_domain_block_stats_ret;
+
+struct remote_domain_interface_stats_args {
+       remote_nonnull_domain dom;
+       remote_nonnull_string path;
+};
+typedef struct remote_domain_interface_stats_args remote_domain_interface_stats_args;
+
+struct remote_domain_interface_stats_ret {
+       quad_t rx_bytes;
+       quad_t rx_packets;
+       quad_t rx_errs;
+       quad_t rx_drop;
+       quad_t tx_bytes;
+       quad_t tx_packets;
+       quad_t tx_errs;
+       quad_t tx_drop;
+};
+typedef struct remote_domain_interface_stats_ret remote_domain_interface_stats_ret;
+
 struct remote_list_domains_args {
        int maxids;
 };
@@ -693,6 +726,8 @@ enum remote_procedure {
        REMOTE_PROC_DOMAIN_MIGRATE_PREPARE = 61,
        REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62,
        REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63,
+       REMOTE_PROC_DOMAIN_BLOCK_STATS = 64,
+       REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -748,6 +783,10 @@ extern  bool_t xdr_remote_domain_get_scheduler_type_ret (XDR *, remote_domain_ge
 extern  bool_t xdr_remote_domain_get_scheduler_parameters_args (XDR *, remote_domain_get_scheduler_parameters_args*);
 extern  bool_t xdr_remote_domain_get_scheduler_parameters_ret (XDR *, remote_domain_get_scheduler_parameters_ret*);
 extern  bool_t xdr_remote_domain_set_scheduler_parameters_args (XDR *, remote_domain_set_scheduler_parameters_args*);
+extern  bool_t xdr_remote_domain_block_stats_args (XDR *, remote_domain_block_stats_args*);
+extern  bool_t xdr_remote_domain_block_stats_ret (XDR *, remote_domain_block_stats_ret*);
+extern  bool_t xdr_remote_domain_interface_stats_args (XDR *, remote_domain_interface_stats_args*);
+extern  bool_t xdr_remote_domain_interface_stats_ret (XDR *, remote_domain_interface_stats_ret*);
 extern  bool_t xdr_remote_list_domains_args (XDR *, remote_list_domains_args*);
 extern  bool_t xdr_remote_list_domains_ret (XDR *, remote_list_domains_ret*);
 extern  bool_t xdr_remote_num_of_domains_ret (XDR *, remote_num_of_domains_ret*);
@@ -856,6 +895,10 @@ extern bool_t xdr_remote_domain_get_scheduler_type_ret ();
 extern bool_t xdr_remote_domain_get_scheduler_parameters_args ();
 extern bool_t xdr_remote_domain_get_scheduler_parameters_ret ();
 extern bool_t xdr_remote_domain_set_scheduler_parameters_args ();
+extern bool_t xdr_remote_domain_block_stats_args ();
+extern bool_t xdr_remote_domain_block_stats_ret ();
+extern bool_t xdr_remote_domain_interface_stats_args ();
+extern bool_t xdr_remote_domain_interface_stats_ret ();
 extern bool_t xdr_remote_list_domains_args ();
 extern bool_t xdr_remote_list_domains_ret ();
 extern bool_t xdr_remote_num_of_domains_ret ();
index c9012ad8f3a8e36c4948264b133b4e4b6f25ccd1..3120d0be1c0d8a9a5901f5f51820c86f4174de94 100644 (file)
@@ -242,6 +242,35 @@ struct remote_domain_set_scheduler_parameters_args {
     remote_sched_param params<REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX>;
 };
 
+struct remote_domain_block_stats_args {
+    remote_nonnull_domain dom;
+    remote_nonnull_string path;
+};
+
+struct remote_domain_block_stats_ret {
+    hyper rd_req;
+    hyper rd_bytes;
+    hyper wr_req;
+    hyper wr_bytes;
+    hyper errs;
+};
+
+struct remote_domain_interface_stats_args {
+    remote_nonnull_domain dom;
+    remote_nonnull_string path;
+};
+
+struct remote_domain_interface_stats_ret {
+    hyper rx_bytes;
+    hyper rx_packets;
+    hyper rx_errs;
+    hyper rx_drop;
+    hyper tx_bytes;
+    hyper tx_packets;
+    hyper tx_errs;
+    hyper tx_drop;
+};
+
 struct remote_list_domains_args {
     int maxids;
 };
@@ -652,7 +681,9 @@ enum remote_procedure {
     REMOTE_PROC_SUPPORTS_FEATURE = 60,
     REMOTE_PROC_DOMAIN_MIGRATE_PREPARE = 61,
     REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62,
-    REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63
+    REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63,
+    REMOTE_PROC_DOMAIN_BLOCK_STATS = 64,
+    REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65
 };
 
 /* Custom RPC structure. */
index d73a940c7aa6abc7ae14516d4fda970128934155..7d6a2d808f7659b90c28b223c4604f3a73b5f170 100644 (file)
@@ -211,6 +211,17 @@ typedef int
                                         virSchedParameterPtr params,
                                         int nparams);
 
+typedef int
+    (*virDrvDomainBlockStats)
+                    (virDomainPtr domain,
+                     const char *path,
+                     struct _virDomainBlockStats *stats);
+typedef int
+    (*virDrvDomainInterfaceStats)
+                    (virDomainPtr domain,
+                     const char *path,
+                     struct _virDomainInterfaceStats *stats);
+
 typedef int
     (*virDrvDomainMigratePrepare)
                     (virConnectPtr dconn,
@@ -309,6 +320,8 @@ struct _virDriver {
     virDrvDomainMigratePrepare domainMigratePrepare;
     virDrvDomainMigratePerform domainMigratePerform;
     virDrvDomainMigrateFinish  domainMigrateFinish;
+    virDrvDomainBlockStats      domainBlockStats;
+    virDrvDomainInterfaceStats  domainInterfaceStats;
 };
 
 typedef int
index fa81ea868ce54f703c2ff8994627abb111ec40bd..4ed40b914ad34198eb1441075f0394883675ceee 100644 (file)
@@ -2063,6 +2063,113 @@ virDomainSetSchedulerParameters(virDomainPtr domain,
 }
 
 
+/**
+ * virDomainBlockStats
+ * @dom: pointer to the domain object
+ * @path: path to the block device
+ * @stats: block device stats (returned)
+ * @size: size of stats structure
+ *
+ * This function returns block device (disk) stats for block
+ * devices attached to the domain.
+ *
+ * The path parameter is the name of the block device.  Get this
+ * by calling virDomainGetXMLDesc and finding the <target dev='...'>
+ * attribute within //domain/devices/disk.  (For example, "xvda").
+ *
+ * Domains may have more than one block device.  To get stats for
+ * each you should make multiple calls to this function.
+ *
+ * Individual fields within the stats structure may be returned
+ * as -1, which indicates that the hypervisor does not support
+ * that particular statistic.
+ *
+ * Returns: 0 in case of success or -1 in case of failure.
+ */
+int
+virDomainBlockStats (virDomainPtr dom, const char *path,
+                     virDomainBlockStatsPtr stats, size_t size)
+{
+    virConnectPtr conn;
+    struct _virDomainBlockStats stats2 = { -1, -1, -1, -1, -1 };
+    DEBUG("domain=%p, path=%s, stats=%p, size=%zi", dom, path, stats, size);
+
+    if (!stats || size > sizeof stats2) {
+        virLibDomainError (dom, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return -1;
+    }
+    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
+        virLibDomainError (dom, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return -1;
+    }
+    conn = dom->conn;
+
+    if (conn->driver->domainBlockStats) {
+        if (conn->driver->domainBlockStats (dom, path, &stats2) == -1)
+            return -1;
+
+        memcpy (stats, &stats2, size);
+        return 0;
+    }
+
+    virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+/**
+ * virDomainInterfaceStats
+ * @dom: pointer to the domain object
+ * @path: path to the interface
+ * @stats: network interface stats (returned)
+ * @size: size of stats structure
+ *
+ * This function returns network interface stats for interfaces
+ * attached to the domain.
+ *
+ * The path parameter is the name of the network interface.
+ *
+ * Domains may have more than network interface.  To get stats for
+ * each you should make multiple calls to this function.
+ *
+ * Individual fields within the stats structure may be returned
+ * as -1, which indicates that the hypervisor does not support
+ * that particular statistic.
+ *
+ * Returns: 0 in case of success or -1 in case of failure.
+ */
+int
+virDomainInterfaceStats (virDomainPtr dom, const char *path,
+                         virDomainInterfaceStatsPtr stats, size_t size)
+{
+    virConnectPtr conn;
+    struct _virDomainInterfaceStats stats2 = { -1, -1, -1, -1,
+                                               -1, -1, -1, -1 };
+    DEBUG("domain=%p, path=%s, stats=%p, size=%zi", dom, path, stats, size);
+
+    if (!stats || size > sizeof stats2) {
+        virLibDomainError (dom, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return -1;
+    }
+    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
+        virLibDomainError (dom, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return -1;
+    }
+    conn = dom->conn;
+
+    if (conn->driver->domainInterfaceStats) {
+        if (conn->driver->domainInterfaceStats (dom, path, &stats2) == -1)
+            return -1;
+
+        memcpy (stats, &stats2, size);
+        return 0;
+    }
+
+    virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+
+
 
 /************************************************************************
  *                                                                     *
index b218ec0837b20b8d0ba6a05241fc77cf8831fff6..d04a6cd5455eca36eb4476cbf97c3143f6421b25 100644 (file)
@@ -65,7 +65,8 @@
        virDomainGetSchedulerType;
        virDomainGetSchedulerParameters;
        virDomainSetSchedulerParameters;
-
+       virDomainBlockStats;
+       virDomainInterfaceStats;
        virDomainAttachDevice;
        virDomainDetachDevice;
 
index e00d449df4e16de9e414e53dd31b233911a39951..f912c86bc4923d76ac962e932c16b5ae15ae1418 100644 (file)
@@ -2665,6 +2665,8 @@ static virDriver qemuDriver = {
     NULL, /* domainMigratePrepare */
     NULL, /* domainMigratePerform */
     NULL, /* domainMigrateFinish */
+    NULL, /* domainBlockStats */
+    NULL, /* domainInterfaceStats */
 };
 
 static virNetworkDriver qemuNetworkDriver = {
index d952374a5afd4ffcaec6599dbbb447b70364382c..7ac70b9ee18fcd03ac76f1782cbe0584a1b803cf 100644 (file)
@@ -2263,6 +2263,64 @@ remoteDomainSetSchedulerParameters (virDomainPtr domain,
     return 0;
 }
 
+static int
+remoteDomainBlockStats (virDomainPtr domain, const char *path,
+                        struct _virDomainBlockStats *stats)
+{
+    remote_domain_block_stats_args args;
+    remote_domain_block_stats_ret ret;
+    GET_PRIVATE (domain->conn, -1);
+
+    make_nonnull_domain (&args.dom, domain);
+    args.path = (char *) path;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS,
+              (xdrproc_t) xdr_remote_domain_block_stats_args, (char *) &args,
+              (xdrproc_t) xdr_remote_domain_block_stats_ret, (char *) &ret)
+        == -1)
+        return -1;
+
+    stats->rd_req = ret.rd_req;
+    stats->rd_bytes = ret.rd_bytes;
+    stats->wr_req = ret.wr_req;
+    stats->wr_bytes = ret.wr_bytes;
+    stats->errs = ret.errs;
+
+    return 0;
+}
+
+static int
+remoteDomainInterfaceStats (virDomainPtr domain, const char *path,
+                            struct _virDomainInterfaceStats *stats)
+{
+    remote_domain_interface_stats_args args;
+    remote_domain_interface_stats_ret ret;
+    GET_PRIVATE (domain->conn, -1);
+
+    make_nonnull_domain (&args.dom, domain);
+    args.path = (char *) path;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACE_STATS,
+              (xdrproc_t) xdr_remote_domain_interface_stats_args,
+                (char *) &args,
+              (xdrproc_t) xdr_remote_domain_interface_stats_ret,
+                (char *) &ret) == -1)
+        return -1;
+
+    stats->rx_bytes = ret.rx_bytes;
+    stats->rx_packets = ret.rx_packets;
+    stats->rx_errs = ret.rx_errs;
+    stats->rx_drop = ret.rx_drop;
+    stats->tx_bytes = ret.tx_bytes;
+    stats->tx_packets = ret.tx_packets;
+    stats->tx_errs = ret.tx_errs;
+    stats->tx_drop = ret.tx_drop;
+
+    return 0;
+}
+
 /*----------------------------------------------------------------------*/
 
 static int
@@ -3057,6 +3115,8 @@ static virDriver driver = {
     .domainMigratePrepare = remoteDomainMigratePrepare,
     .domainMigratePerform = remoteDomainMigratePerform,
     .domainMigrateFinish = remoteDomainMigrateFinish,
+    .domainBlockStats = remoteDomainBlockStats,
+    .domainInterfaceStats = remoteDomainInterfaceStats,
 };
 
 static virNetworkDriver network_driver = {
index 82522410695fec80f169e1d76b5e254fbd17d287..59e1d4b9587ce73c4e95dc7a6bb4ec6af23b3c30 100644 (file)
@@ -1967,6 +1967,8 @@ static virDriver testDriver = {
     NULL, /* domainMigratePrepare */
     NULL, /* domainMigratePerform */
     NULL, /* domainMigrateFinish */
+    NULL, /* domainBlockStats */
+    NULL, /* domainInterfaceStats */
 };
 
 static virNetworkDriver testNetworkDriver = {
index dc68a719ff9d866af7a03960b0199347b7106d61..ec9146aa611fe86d1659afafb2b6536f18b1714c 100644 (file)
@@ -31,6 +31,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <sys/stat.h>
+#include <inttypes.h>
 #include <test.h>
 
 #include <libxml/parser.h>
@@ -659,6 +660,129 @@ cmdDomstate(vshControl * ctl, vshCmd * cmd)
     return ret;
 }
 
+/* "domblkstat" command
+ */
+static vshCmdInfo info_domblkstat[] = {
+    {"syntax", "domblkstat <domain> <dev>"},
+    {"help", gettext_noop("get device block stats for a domain")},
+    {"desc", gettext_noop("Get device block stats for a running domain.")},
+    {NULL,NULL}
+};
+
+static vshCmdOptDef opts_domblkstat[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
+    {"device", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("block device")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdDomblkstat (vshControl *ctl, vshCmd *cmd)
+{
+    virDomainPtr dom;
+    char *name, *device;
+    struct _virDomainBlockStats stats;
+
+    if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(dom = vshCommandOptDomain (ctl, cmd, "domain", &name)))
+        return FALSE;
+
+    if (!(device = vshCommandOptString (cmd, "device", NULL)))
+        return FALSE;
+
+    if (virDomainBlockStats (dom, device, &stats, sizeof stats) == -1) {
+        vshError (ctl, FALSE, _("Failed to get block stats %s %s"),
+                  name, device);
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    if (stats.rd_req >= 0)
+        vshPrint (ctl, "%s rd_req %lld\n", device, stats.rd_req);
+
+    if (stats.rd_bytes >= 0)
+        vshPrint (ctl, "%s rd_bytes %lld\n", device, stats.rd_bytes);
+
+    if (stats.wr_req >= 0)
+        vshPrint (ctl, "%s wr_req %lld\n", device, stats.wr_req);
+
+    if (stats.wr_bytes >= 0)
+        vshPrint (ctl, "%s wr_bytes %lld\n", device, stats.wr_bytes);
+
+    if (stats.errs >= 0)
+        vshPrint (ctl, "%s errs %lld\n", device, stats.errs);
+
+    virDomainFree(dom);
+    return TRUE;
+}
+
+/* "domifstat" command
+ */
+static vshCmdInfo info_domifstat[] = {
+    {"syntax", "domifstat <domain> <dev>"},
+    {"help", gettext_noop("get network interface stats for a domain")},
+    {"desc", gettext_noop("Get network interface stats for a running domain.")},
+    {NULL,NULL}
+};
+
+static vshCmdOptDef opts_domifstat[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface device")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdDomIfstat (vshControl *ctl, vshCmd *cmd)
+{
+    virDomainPtr dom;
+    char *name, *device;
+    struct _virDomainInterfaceStats stats;
+
+    if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(dom = vshCommandOptDomain (ctl, cmd, "domain", &name)))
+        return FALSE;
+
+    if (!(device = vshCommandOptString (cmd, "interface", NULL)))
+        return FALSE;
+
+    if (virDomainInterfaceStats (dom, device, &stats, sizeof stats) == -1) {
+        vshError (ctl, FALSE, _("Failed to get interface stats %s %s"),
+                  name, device);
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    if (stats.rx_bytes >= 0)
+        vshPrint (ctl, "%s rx_bytes %lld\n", device, stats.rx_bytes);
+
+    if (stats.rx_packets >= 0)
+        vshPrint (ctl, "%s rx_packets %lld\n", device, stats.rx_packets);
+
+    if (stats.rx_errs >= 0)
+        vshPrint (ctl, "%s rx_errs %lld\n", device, stats.rx_errs);
+
+    if (stats.rx_drop >= 0)
+        vshPrint (ctl, "%s rx_drop %lld\n", device, stats.rx_drop);
+
+    if (stats.tx_bytes >= 0)
+        vshPrint (ctl, "%s tx_bytes %lld\n", device, stats.tx_bytes);
+
+    if (stats.tx_packets >= 0)
+        vshPrint (ctl, "%s tx_packets %lld\n", device, stats.tx_packets);
+
+    if (stats.tx_errs >= 0)
+        vshPrint (ctl, "%s tx_errs %lld\n", device, stats.tx_errs);
+
+    if (stats.tx_drop >= 0)
+        vshPrint (ctl, "%s tx_drop %lld\n", device, stats.tx_drop);
+
+    virDomainFree(dom);
+    return TRUE;
+}
+
 /*
  * "suspend" command
  */
@@ -3529,6 +3653,8 @@ static vshCmdDef commands[] = {
     {"dominfo", cmdDominfo, opts_dominfo, info_dominfo},
     {"domname", cmdDomname, opts_domname, info_domname},
     {"domstate", cmdDomstate, opts_domstate, info_domstate},
+    {"domblkstat", cmdDomblkstat, opts_domblkstat, info_domblkstat},
+    {"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat},
     {"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml},
     {"hostname", cmdHostname, NULL, info_hostname},
     {"list", cmdList, opts_list, info_list},
index de7021b55d0edcdbc4c0779c62c9177f8f89bee5..ebba04de25325d0683b49154aa5eafbac1d35d6c 100644 (file)
@@ -1306,6 +1306,152 @@ xenHypervisorSetSchedulerParameters(virDomainPtr domain,
     return 0;
 }
 
+static int64_t
+read_stat (const char *path)
+{
+    char str[64];
+    int64_t r;
+    int i;
+    FILE *fp;
+
+    fp = fopen (path, "r");
+    if (!fp) return -1;
+    /* stupid GCC warning */ i = fread (str, sizeof str, 1, fp);
+    r = strtoll (str, NULL, 10);
+    fclose (fp);
+    return r;
+}
+
+static int64_t
+read_bd_stat (int device, int domid, const char *str)
+{
+    char path[PATH_MAX];
+    int64_t r;
+
+    snprintf (path, sizeof path,
+              "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s_req",
+              domid, device, str);
+    r = read_stat (path);
+    if (r >= 0) return r;
+
+    snprintf (path, sizeof path,
+              "/sys/devices/xen-backend/tap-%d-%d/statistics/%s_req",
+              domid, device, str);
+    r = read_stat (path);
+    return r;
+}
+
+/* Paths have the form "xvd[a-]" and map to paths /sys/devices/xen-backend/
+ * (vbd|tap)-domid-major:minor/statistics/(rd|wr|oo)_req.  The major:minor
+ * is in this case fixed as 202*256 + 16*minor where minor is 0 for xvda,
+ * 1 for xvdb and so on.
+ */
+int
+xenHypervisorDomainBlockStats (virDomainPtr dom,
+                               const char *path,
+                               struct _virDomainBlockStats *stats)
+{
+    int minor, device;
+
+    if (strlen (path) != 4 ||
+        STRNEQLEN (path, "xvd", 3) ||
+        (minor = path[3] - 'a') < 0 ||
+        minor > 26) {
+        virXenErrorFunc (VIR_ERR_INVALID_ARG, __FUNCTION__,
+                         "invalid path, should be xvda, xvdb, etc.", 0);
+        return -1;
+    }
+    device = 202 * 256 + minor;
+
+    stats->rd_req = read_bd_stat (device, dom->id, "rd");
+    stats->wr_req = read_bd_stat (device, dom->id, "wr");
+    stats->errs =   read_bd_stat (device, dom->id, "oo");
+
+    if (stats->rd_req == -1 && stats->wr_req == -1 && stats->errs == -1) {
+        virXenErrorFunc (VIR_ERR_NO_SUPPORT, __FUNCTION__,
+                         "Failed to read any block statistics", dom->id);
+        return -1;
+    }
+
+    return 0;
+}
+
+/* Paths have the form vif<domid>.<n> (this interface checks that
+ * <domid> is the real domain ID and returns an error if not).
+ *
+ * In future we may allow you to query bridge stats (virbrX or
+ * xenbrX), but that will probably be through a separate
+ * virNetwork interface, as yet not decided.
+ *
+ * On Linux we open /proc/net/dev and look for the device
+ * called vif<domid>.<n>.
+ */
+int
+xenHypervisorDomainInterfaceStats (virDomainPtr dom,
+                                   const char *path,
+                                   struct _virDomainInterfaceStats *stats)
+{
+    int rqdomid, device;
+    FILE *fp;
+    char line[256];
+
+    if (sscanf (path, "vif%d.%d", &rqdomid, &device) != 2) {
+        virXenErrorFunc (VIR_ERR_INVALID_ARG, __FUNCTION__,
+                         "invalid path, should be vif<domid>.<n>.", 0);
+        return -1;
+    }
+    if (rqdomid != dom->id) {
+        virXenErrorFunc (VIR_ERR_INVALID_ARG, __FUNCTION__,
+                         "invalid path, vif<domid> should match this domain ID", 0);
+        return -1;
+    }
+
+    fp = fopen ("/proc/net/dev", "r");
+    if (!fp) {
+        virXenErrorFunc (VIR_ERR_NO_SUPPORT, __FUNCTION__,
+                         "/proc/net/dev", errno);
+        return -1;
+    }
+    while (fgets (line, sizeof line, fp)) {
+        int domid, port;
+        long long dummy;
+        long long rx_bytes;
+        long long rx_packets;
+        long long rx_errs;
+        long long rx_drop;
+        long long tx_bytes;
+        long long tx_packets;
+        long long tx_errs;
+        long long tx_drop;
+
+        if (sscanf (line, "vif%d.%d: %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
+                    &domid, &port,
+                    &rx_bytes, &rx_packets, &rx_errs, &rx_drop,
+                    &dummy, &dummy, &dummy, &dummy,
+                    &tx_bytes, &tx_packets, &tx_errs, &tx_drop,
+                    &dummy, &dummy, &dummy, &dummy) != 18)
+            continue;
+
+        if (domid == dom->id && port == device) {
+            stats->rx_bytes = rx_bytes;
+            stats->rx_packets = rx_packets;
+            stats->rx_errs = rx_errs;
+            stats->rx_drop = rx_drop;
+            stats->tx_bytes = tx_bytes;
+            stats->tx_packets = tx_packets;
+            stats->tx_errs = tx_errs;
+            stats->tx_drop = tx_drop;
+            fclose (fp);
+            return 0;
+        }
+    }
+    fclose (fp);
+
+    virXenErrorFunc (VIR_ERR_NO_SUPPORT, __FUNCTION__,
+                     "/proc/net/dev: Interface not found", 0);
+    return -1;
+}
+
 /**
  * virXen_pausedomain:
  * @handle: the hypervisor handle
index 6d5c1cbce4793d8fc02ee22c7b0cce7de3de952b..be4d79e834b389bf188ae40011c9b1381086451e 100644 (file)
@@ -86,6 +86,13 @@ int  xenHypervisorSetSchedulerParameters             (virDomainPtr domain,
                                         virSchedParameterPtr params,
                                         int nparams);
 
+int     xenHypervisorDomainBlockStats   (virDomainPtr domain,
+                                        const char *path,
+                                        struct _virDomainBlockStats *stats);
+int     xenHypervisorDomainInterfaceStats (virDomainPtr domain,
+                                        const char *path,
+                                        struct _virDomainInterfaceStats *stats);
+
 #ifdef __cplusplus
 }
 #endif
index fafc24ca580a01e455f02ca24488cf26b09fb0f2..dcf89278724e5a7837c61d9fb2250efcb1bbc6a5 100644 (file)
@@ -1023,6 +1023,32 @@ xenUnifiedDomainSetSchedulerParameters (virDomainPtr dom,
     return(-1);
 }
 
+static int
+xenUnifiedDomainBlockStats (virDomainPtr dom, const char *path,
+                            struct _virDomainBlockStats *stats)
+{
+    GET_PRIVATE (dom->conn);
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
+        return xenHypervisorDomainBlockStats (dom, path, stats);
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static int
+xenUnifiedDomainInterfaceStats (virDomainPtr dom, const char *path,
+                                struct _virDomainInterfaceStats *stats)
+{
+    GET_PRIVATE (dom->conn);
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
+        return xenHypervisorDomainInterfaceStats (dom, path, stats);
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
 /*----- Register with libvirt.c, and initialise Xen drivers. -----*/
 
 #define VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
@@ -1081,6 +1107,8 @@ static virDriver xenUnifiedDriver = {
     .domainMigratePrepare              = xenUnifiedDomainMigratePrepare,
     .domainMigratePerform              = xenUnifiedDomainMigratePerform,
     .domainMigrateFinish               = xenUnifiedDomainMigrateFinish,
+    .domainBlockStats  = xenUnifiedDomainBlockStats,
+    .domainInterfaceStats = xenUnifiedDomainInterfaceStats,
 };
 
 /**