From d2e5538b16e325d9095f3ccb0dac88bbd9fc98f0 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Mon, 23 Nov 2015 18:57:00 +0000 Subject: [PATCH] libxl: implement virDomainInterfaceStats Introduce support for domainInterfaceStats API call for querying network interface statistics. Consequently it also enables the use of `virsh domifstat ` command plus seeing the interfaces names instead of "-" when doing `virsh domiflist `. After successful guest creation we fill the network interfaces names based on domain, device id and append suffix if it's emulated in the following form: vif.[-emu]. We extract the network interfaces info from the libxl_domain_config object in libxlDomainCreateIfaceNames() to generate ifname. On domain cleanup we also clear ifname, in case it was set by libvirt (i.e. being prefixed with "vif"). We also skip these two steps in case the name of the interface was manually inserted by the adminstrator. For getting the interface statistics we resort to virNetInterfaceStats and let libvirt handle the platform specific nits. Note that the latter is not yet supported in FreeBSD. Signed-off-by: Joao Martins --- src/libxl/libxl_domain.c | 37 ++++++++++++++++++++++++++++ src/libxl/libxl_driver.c | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 40dcea171c..ef929740af 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -728,6 +728,17 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver, } } + if ((vm->def->nnets)) { + size_t i; + + for (i = 0; i < vm->def->nnets; i++) { + virDomainNetDefPtr net = vm->def->nets[i]; + + if (STRPREFIX(net->ifname, "vif")) + VIR_FREE(net->ifname); + } + } + if (virAsprintf(&file, "%s/%s.xml", cfg->stateDir, vm->def->name) > 0) { if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name); @@ -887,6 +898,31 @@ libxlConsoleCallback(libxl_ctx *ctx, libxl_event *ev, void *for_callback) libxl_event_free(ctx, ev); } +/* + * Create interface names for the network devices in parameter def. + * Names are created with the pattern 'vif.'. + * devid is extracted from the network devices in the d_config + * parameter. User-provided interface names are skipped. + */ +static void +libxlDomainCreateIfaceNames(virDomainDefPtr def, libxl_domain_config *d_config) +{ + size_t i; + + for (i = 0; i < def->nnets && i < d_config->num_nics; i++) { + virDomainNetDefPtr net = def->nets[i]; + libxl_device_nic *x_nic = &d_config->nics[i]; + const char *suffix = + x_nic->nictype != LIBXL_NIC_TYPE_VIF ? "-emu" : ""; + + if (net->ifname) + continue; + + ignore_value(virAsprintf(&net->ifname, "vif%d.%d%s", + def->id, x_nic->devid, suffix)); + } +} + /* * Start a domain through libxenlight. @@ -1027,6 +1063,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW)) goto cleanup_dom; + libxlDomainCreateIfaceNames(vm->def, &d_config); if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL) goto cleanup_dom; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 35d7fae892..05041305a3 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -58,6 +58,7 @@ #include "virhostdev.h" #include "network/bridge_driver.h" #include "locking/domain_lock.h" +#include "virstats.h" #define VIR_FROM_THIS VIR_FROM_LIBXL @@ -4642,6 +4643,56 @@ libxlDomainIsUpdated(virDomainPtr dom) return ret; } +static int +libxlDomainInterfaceStats(virDomainPtr dom, + const char *path, + virDomainInterfaceStatsPtr stats) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + ssize_t i; + int ret = -1; + + if (!(vm = libxlDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + /* Check the path is one of the domain's network interfaces. */ + for (i = 0; i < vm->def->nnets; i++) { + if (vm->def->nets[i]->ifname && + STREQ(vm->def->nets[i]->ifname, path)) { + ret = 0; + break; + } + } + + if (ret == 0) + ret = virNetInterfaceStats(path, stats); + else + virReportError(VIR_ERR_INVALID_ARG, + _("'%s' is not a known interface"), path); + + endjob: + if (!libxlDomainObjEndJob(driver, vm)) + vm = NULL; + + cleanup: + if (vm) + virObjectUnlock(vm); + return ret; +} + static int libxlDomainGetTotalCPUStats(libxlDriverPrivatePtr driver, virDomainObjPtr vm, @@ -5423,6 +5474,7 @@ static virHypervisorDriver libxlHypervisorDriver = { .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */ .domainMemoryStats = libxlDomainMemoryStats, /* 1.3.0 */ .domainGetCPUStats = libxlDomainGetCPUStats, /* 1.3.0 */ + .domainInterfaceStats = libxlDomainInterfaceStats, /* 1.3.0 */ .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */ .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */ .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */ -- GitLab