#include "qemu_driver.h"
#include "qemu_conf.h"
#include "nodeinfo.h"
+#include "stats_linux.h"
static int qemudShutdown(void);
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;
NULL, /* domainMigratePerform */
NULL, /* domainMigrateFinish */
NULL, /* domainBlockStats */
- NULL, /* domainInterfaceStats */
+ qemudDomainInterfaceStats, /* domainInterfaceStats */
NULL, /* nodeGetCellsFreeMemory */
NULL, /* getFreeMemory */
};
{
int path_len;
FILE *fp;
- char line[256];
+ char line[256], *colon;
fp = fopen ("/proc/net/dev", "r");
if (!fp) {
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,