[libvirt] [PATCH 0/4] virDomainInterfaceStats: Accept MAC address too

*** BLURB HERE *** Michal Privoznik (4): virsh: Document limitation of domifstat virDomainInterfaceStats: Accept MAC address too virsh: Deal with multiple matching devices in domif-getlink virDomainNetFind: Report error if no device found include/libvirt/libvirt-domain.h | 2 +- src/conf/domain_conf.c | 18 ++++++++++-------- src/driver-hypervisor.h | 2 +- src/libvirt-domain.c | 15 ++++++++------- src/libxl/libxl_driver.c | 9 +++------ src/lxc/lxc_driver.c | 9 +++------ src/openvz/openvz_driver.c | 9 +++------ src/qemu/qemu_driver.c | 27 +++++++-------------------- src/remote/remote_protocol.x | 2 +- src/remote_protocol-structs | 2 +- src/test/test_driver.c | 12 +++++------- src/vz/vz_driver.c | 4 ++-- src/vz/vz_sdk.c | 9 +++++++-- src/xen/xen_driver.c | 8 ++++++-- tools/virsh-domain-monitor.c | 5 ++++- tools/virsh.pod | 5 ++++- 16 files changed, 66 insertions(+), 72 deletions(-) -- 2.13.6

https://bugzilla.redhat.com/show_bug.cgi?id=1497396 The current implementation reads the stats from the host. However, this doesn't work for all types of interfaces as not all of them have a representation in the host. For instance, interface type='user' doesn't. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh.pod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index 00d93781a..632f202e8 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -775,7 +775,9 @@ the guest OS via an agent. If unspecified, 'lease' is the default. =item B<domifstat> I<domain> I<interface-device> -Get network interface stats for a running domain. +Get network interface stats for a running domain. This might be +unavailable for some types of interface which don't have +representation in the host, e.g. user. =item B<domif-setlink> I<domain> I<interface-device> I<state> [I<--config>] -- 2.13.6

On 10/05/2017 10:18 AM, Michal Privoznik wrote:
https://bugzilla.redhat.com/show_bug.cgi?id=1497396
The current implementation reads the stats from the host. However, this doesn't work for all types of interfaces as not all of them have a representation in the host. For instance, interface type='user' doesn't.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh.pod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod index 00d93781a..632f202e8 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -775,7 +775,9 @@ the guest OS via an agent. If unspecified, 'lease' is the default.
=item B<domifstat> I<domain> I<interface-device>
-Get network interface stats for a running domain. +Get network interface stats for a running domain. This might be +unavailable for some types of interface which don't have +representation in the host, e.g. user.
What's not really clear is what "don't have representation in the host" actually means. I really think this needs to be a bit more specific as to "why" something will fail. If being too specific is an issue, then consider instead: The network interface stats are only available for interfaces that have a physical source interface. This does not include, for example, a 'user' interface type since it is a virtual LAN with NAT to the outside world. Curious, are there any others that might qualify? Reviewed-by: John Ferlan <jferlan@redhat.com> John
=item B<domif-setlink> I<domain> I<interface-device> I<state> [I<--config>]

On 10/13/2017 10:44 AM, John Ferlan wrote:
On 10/05/2017 10:18 AM, Michal Privoznik wrote:
https://bugzilla.redhat.com/show_bug.cgi?id=1497396
The current implementation reads the stats from the host. However, this doesn't work for all types of interfaces as not all of them have a representation in the host. For instance, interface type='user' doesn't.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh.pod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod index 00d93781a..632f202e8 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -775,7 +775,9 @@ the guest OS via an agent. If unspecified, 'lease' is the default.
=item B<domifstat> I<domain> I<interface-device>
-Get network interface stats for a running domain. +Get network interface stats for a running domain. This might be +unavailable for some types of interface which don't have +representation in the host, e.g. user.
What's not really clear is what "don't have representation in the host" actually means. I really think this needs to be a bit more specific as to "why" something will fail.
If being too specific is an issue, then consider instead:
The network interface stats are only available for interfaces that have a physical source interface. This does not include, for example, a 'user' interface type since it is a virtual LAN with NAT to the outside world.
Okay. I'm going with this version.
Curious, are there any others that might qualify?
I don't know any other from the top of my head.
Reviewed-by: John Ferlan <jferlan@redhat.com>
Thanks. Michal

https://bugzilla.redhat.com/show_bug.cgi?id=1497396 The other APIs accept both, ifname and MAC address. There's no reason virDomainInterfaceStats can't do the same. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 2 +- src/driver-hypervisor.h | 2 +- src/libvirt-domain.c | 15 ++++++++------- src/libxl/libxl_driver.c | 8 ++++---- src/lxc/lxc_driver.c | 8 ++++---- src/openvz/openvz_driver.c | 8 ++++---- src/qemu/qemu_driver.c | 10 +++++----- src/remote/remote_protocol.x | 2 +- src/remote_protocol-structs | 2 +- src/test/test_driver.c | 11 ++++++----- src/vz/vz_driver.c | 4 ++-- src/vz/vz_sdk.c | 9 +++++++-- src/xen/xen_driver.c | 11 +++++++++-- tools/virsh.pod | 3 ++- 14 files changed, 55 insertions(+), 40 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 030a62c43..ebf47a9bb 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1571,7 +1571,7 @@ int virDomainBlockStatsFlags (virDomainPtr dom, int *nparams, unsigned int flags); int virDomainInterfaceStats (virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats, size_t size); diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 6c3f7d795..4de0581c3 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -486,7 +486,7 @@ typedef int typedef int (*virDrvDomainInterfaceStats)(virDomainPtr domain, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats); typedef int diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index d2d022a66..34a91d683 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -5507,14 +5507,15 @@ virDomainBlockStatsFlags(virDomainPtr dom, /** * virDomainInterfaceStats: * @dom: pointer to the domain object - * @path: path to the interface + * @device: the interface name or MAC address * @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. + * The @device parameter is the name of the network interface or + * its MAC address. * * Domains may have more than one network interface. To get stats for * each you should make multiple calls to this function. @@ -5528,20 +5529,20 @@ virDomainBlockStatsFlags(virDomainPtr dom, * Returns: 0 in case of success or -1 in case of failure. */ int -virDomainInterfaceStats(virDomainPtr dom, const char *path, +virDomainInterfaceStats(virDomainPtr dom, const char *device, virDomainInterfaceStatsPtr stats, size_t size) { virConnectPtr conn; virDomainInterfaceStatsStruct stats2 = { -1, -1, -1, -1, -1, -1, -1, -1 }; - VIR_DOMAIN_DEBUG(dom, "path=%s, stats=%p, size=%zi", - path, stats, size); + VIR_DOMAIN_DEBUG(dom, "device=%s, stats=%p, size=%zi", + device, stats, size); virResetLastError(); virCheckDomainReturn(dom, -1); - virCheckNonNullArgGoto(path, error); + virCheckNonNullArgGoto(device, error); virCheckNonNullArgGoto(stats, error); if (size > sizeof(stats2)) { virReportInvalidArg(size, @@ -5553,7 +5554,7 @@ virDomainInterfaceStats(virDomainPtr dom, const char *path, conn = dom->conn; if (conn->driver->domainInterfaceStats) { - if (conn->driver->domainInterfaceStats(dom, path, &stats2) == -1) + if (conn->driver->domainInterfaceStats(dom, device, &stats2) == -1) goto error; memcpy(stats, &stats2, size); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 8483d6ecf..9db6f3503 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -4956,7 +4956,7 @@ libxlDomainIsUpdated(virDomainPtr dom) static int libxlDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { libxlDriverPrivatePtr driver = dom->conn->privateData; @@ -4979,13 +4979,13 @@ libxlDomainInterfaceStats(virDomainPtr dom, goto endjob; } - if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), path); + _("'%s' is not a known interface"), device); goto endjob; } - if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto endjob; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 6ad61bdb7..4ab05a7ff 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2849,7 +2849,7 @@ lxcDomainGetBlkioParameters(virDomainPtr dom, static int lxcDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { virDomainObjPtr vm; @@ -2872,13 +2872,13 @@ lxcDomainInterfaceStats(virDomainPtr dom, goto endjob; } - if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("Invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device); goto endjob; } - if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto endjob; diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 11173898d..05ed2bcae 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1980,7 +1980,7 @@ openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason) static int openvzDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { struct openvz_driver *driver = dom->conn->privateData; @@ -2006,13 +2006,13 @@ openvzDomainInterfaceStats(virDomainPtr dom, goto cleanup; } - if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device); goto cleanup; } - if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto cleanup; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7c6f1674a..f2cc0f0a5 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11021,7 +11021,7 @@ qemuDomainBlockStatsFlags(virDomainPtr dom, static int qemuDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { virDomainObjPtr vm; @@ -11040,17 +11040,17 @@ qemuDomainInterfaceStats(virDomainPtr dom, goto cleanup; } - if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device); goto cleanup; } if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_VHOSTUSER) { - if (virNetDevOpenvswitchInterfaceStats(path, stats) < 0) + if (virNetDevOpenvswitchInterfaceStats(device, stats) < 0) goto cleanup; } else { - if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto cleanup; } diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 07463b781..e3014f66b 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -682,7 +682,7 @@ struct remote_domain_block_stats_flags_ret { struct remote_domain_interface_stats_args { remote_nonnull_domain dom; - remote_nonnull_string path; + remote_nonnull_string device; }; struct remote_domain_interface_stats_ret { /* insert@2 */ diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 6038bf138..dc78d51c4 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -348,7 +348,7 @@ struct remote_domain_block_stats_flags_ret { }; struct remote_domain_interface_stats_args { remote_nonnull_domain dom; - remote_nonnull_string path; + remote_nonnull_string device; }; struct remote_domain_interface_stats_ret { int64_t rx_bytes; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index e92768a97..3e286635e 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -3160,9 +3160,10 @@ static int testDomainBlockStats(virDomainPtr domain, return ret; } -static int testDomainInterfaceStats(virDomainPtr domain, - const char *path, - virDomainInterfaceStatsPtr stats) +static int +testDomainInterfaceStats(virDomainPtr domain, + const char *device, + virDomainInterfaceStatsPtr stats) { virDomainObjPtr privdom; struct timeval tv; @@ -3180,9 +3181,9 @@ static int testDomainInterfaceStats(virDomainPtr domain, goto error; } - if (!(net = virDomainNetFindByName(privdom->def, path))) { + if (!(net = virDomainNetFind(privdom->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device); goto error; } diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index 9ebb51d60..c33962229 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -1873,7 +1873,7 @@ vzDomainBlockStatsFlags(virDomainPtr domain, static int vzDomainInterfaceStats(virDomainPtr domain, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { virDomainObjPtr dom = NULL; @@ -1888,7 +1888,7 @@ vzDomainInterfaceStats(virDomainPtr domain, privdom = dom->privateData; - ret = prlsdkGetNetStats(privdom->stats, privdom->sdkdom, path, stats); + ret = prlsdkGetNetStats(privdom->stats, privdom->sdkdom, device, stats); cleanup: virDomainObjEndAPI(&dom); diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 6ead47a0f..5f377147c 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -4484,7 +4484,7 @@ prlsdkFindNetByPath(PRL_HANDLE sdkdom, const char *path) } int -prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *path, +prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *device, virDomainInterfaceStatsPtr stats) { int ret = -1; @@ -4492,8 +4492,13 @@ prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *path, char *name = NULL; PRL_RESULT pret; PRL_HANDLE net = PRL_INVALID_HANDLE; + virMacAddr mac; + + if (virMacAddrParse(device, &mac) == 0) + net = prlsdkFindNetByMAC(sdkdom, device); + else + net = prlsdkFindNetByPath(sdkdom, device); - net = prlsdkFindNetByPath(sdkdom, path); if (net == PRL_INVALID_HANDLE) goto cleanup; diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index dae0f4f28..4235ca0ce 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2109,10 +2109,11 @@ xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path, } static int -xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path, +xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *device, virDomainInterfaceStatsPtr stats) { virDomainDefPtr def = NULL; + virDomainNetDefPtr net = NULL; int ret = -1; if (!(def = xenGetDomainDefForDom(dom))) @@ -2121,7 +2122,13 @@ xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path, if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0) goto cleanup; - ret = xenHypervisorDomainInterfaceStats(def, path, stats); + if (!(net = virDomainNetFind(def, device))) { + virReportError(VIR_ERR_INVALID_ARG, + _("'%s' is not a known interface"), device); + goto cleanup; + } + + ret = xenHypervisorDomainInterfaceStats(def, net->ifname, stats); cleanup: virDomainDefFree(def); diff --git a/tools/virsh.pod b/tools/virsh.pod index 632f202e8..d21c5df72 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -777,7 +777,8 @@ the guest OS via an agent. If unspecified, 'lease' is the default. Get network interface stats for a running domain. This might be unavailable for some types of interface which don't have -representation in the host, e.g. user. +representation in the host, e.g. user. I<interface-device> can be +the interface's target name or the MAC address. =item B<domif-setlink> I<domain> I<interface-device> I<state> [I<--config>] -- 2.13.6

On 10/05/2017 10:18 AM, Michal Privoznik wrote:
https://bugzilla.redhat.com/show_bug.cgi?id=1497396
The other APIs accept both, ifname and MAC address. There's no reason virDomainInterfaceStats can't do the same.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 2 +- src/driver-hypervisor.h | 2 +- src/libvirt-domain.c | 15 ++++++++------- src/libxl/libxl_driver.c | 8 ++++---- src/lxc/lxc_driver.c | 8 ++++---- src/openvz/openvz_driver.c | 8 ++++---- src/qemu/qemu_driver.c | 10 +++++----- src/remote/remote_protocol.x | 2 +- src/remote_protocol-structs | 2 +- src/test/test_driver.c | 11 ++++++----- src/vz/vz_driver.c | 4 ++-- src/vz/vz_sdk.c | 9 +++++++-- src/xen/xen_driver.c | 11 +++++++++-- tools/virsh.pod | 3 ++- 14 files changed, 55 insertions(+), 40 deletions(-)
Order-wise - I think patch 4 should go after patch 1. That way this patch doesn't need all those error messages adjusted - they can just be removed when calling virDomainNetFind since it would already provide the message.
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 030a62c43..ebf47a9bb 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1571,7 +1571,7 @@ int virDomainBlockStatsFlags (virDomainPtr dom, int *nparams, unsigned int flags); int virDomainInterfaceStats (virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats, size_t size);
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 6c3f7d795..4de0581c3 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -486,7 +486,7 @@ typedef int
typedef int (*virDrvDomainInterfaceStats)(virDomainPtr domain, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats);
typedef int diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index d2d022a66..34a91d683 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -5507,14 +5507,15 @@ virDomainBlockStatsFlags(virDomainPtr dom, /** * virDomainInterfaceStats: * @dom: pointer to the domain object - * @path: path to the interface + * @device: the interface name or MAC address * @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. + * The @device parameter is the name of the network interface or + * its MAC address.
The @device parameter is the network interface either by name or MAC addresss.
* * Domains may have more than one network interface. To get stats for * each you should make multiple calls to this function. @@ -5528,20 +5529,20 @@ virDomainBlockStatsFlags(virDomainPtr dom, * Returns: 0 in case of success or -1 in case of failure. */ int -virDomainInterfaceStats(virDomainPtr dom, const char *path, +virDomainInterfaceStats(virDomainPtr dom, const char *device, virDomainInterfaceStatsPtr stats, size_t size) { virConnectPtr conn; virDomainInterfaceStatsStruct stats2 = { -1, -1, -1, -1, -1, -1, -1, -1 };
- VIR_DOMAIN_DEBUG(dom, "path=%s, stats=%p, size=%zi", - path, stats, size); + VIR_DOMAIN_DEBUG(dom, "device=%s, stats=%p, size=%zi", + device, stats, size);
virResetLastError();
virCheckDomainReturn(dom, -1); - virCheckNonNullArgGoto(path, error); + virCheckNonNullArgGoto(device, error); virCheckNonNullArgGoto(stats, error); if (size > sizeof(stats2)) { virReportInvalidArg(size, @@ -5553,7 +5554,7 @@ virDomainInterfaceStats(virDomainPtr dom, const char *path, conn = dom->conn;
if (conn->driver->domainInterfaceStats) { - if (conn->driver->domainInterfaceStats(dom, path, &stats2) == -1) + if (conn->driver->domainInterfaceStats(dom, device, &stats2) == -1) goto error;
memcpy(stats, &stats2, size); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 8483d6ecf..9db6f3503 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -4956,7 +4956,7 @@ libxlDomainIsUpdated(virDomainPtr dom)
static int libxlDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { libxlDriverPrivatePtr driver = dom->conn->privateData; @@ -4979,13 +4979,13 @@ libxlDomainInterfaceStats(virDomainPtr dom, goto endjob; }
- if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), path); + _("'%s' is not a known interface"), device);
If you adjust the order of patches, then message just gets deleted.
goto endjob; }
- if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto endjob;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 6ad61bdb7..4ab05a7ff 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2849,7 +2849,7 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
static int lxcDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { virDomainObjPtr vm; @@ -2872,13 +2872,13 @@ lxcDomainInterfaceStats(virDomainPtr dom, goto endjob; }
- if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("Invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device);
Same...
goto endjob; }
- if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto endjob;
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 11173898d..05ed2bcae 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1980,7 +1980,7 @@ openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason)
static int openvzDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { struct openvz_driver *driver = dom->conn->privateData; @@ -2006,13 +2006,13 @@ openvzDomainInterfaceStats(virDomainPtr dom, goto cleanup; }
- if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device);
Same...
goto cleanup; }
- if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto cleanup;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7c6f1674a..f2cc0f0a5 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11021,7 +11021,7 @@ qemuDomainBlockStatsFlags(virDomainPtr dom,
static int qemuDomainInterfaceStats(virDomainPtr dom, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { virDomainObjPtr vm; @@ -11040,17 +11040,17 @@ qemuDomainInterfaceStats(virDomainPtr dom, goto cleanup; }
- if (!(net = virDomainNetFindByName(vm->def, path))) { + if (!(net = virDomainNetFind(vm->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device);
Same.
goto cleanup; }
if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_VHOSTUSER) { - if (virNetDevOpenvswitchInterfaceStats(path, stats) < 0) + if (virNetDevOpenvswitchInterfaceStats(device, stats) < 0) goto cleanup; } else { - if (virNetDevTapInterfaceStats(path, stats, + if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) goto cleanup; } diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 07463b781..e3014f66b 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -682,7 +682,7 @@ struct remote_domain_block_stats_flags_ret {
struct remote_domain_interface_stats_args { remote_nonnull_domain dom; - remote_nonnull_string path; + remote_nonnull_string device; };
struct remote_domain_interface_stats_ret { /* insert@2 */ diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 6038bf138..dc78d51c4 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -348,7 +348,7 @@ struct remote_domain_block_stats_flags_ret { }; struct remote_domain_interface_stats_args { remote_nonnull_domain dom; - remote_nonnull_string path; + remote_nonnull_string device; }; struct remote_domain_interface_stats_ret { int64_t rx_bytes; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index e92768a97..3e286635e 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -3160,9 +3160,10 @@ static int testDomainBlockStats(virDomainPtr domain, return ret; }
-static int testDomainInterfaceStats(virDomainPtr domain, - const char *path, - virDomainInterfaceStatsPtr stats) +static int +testDomainInterfaceStats(virDomainPtr domain, + const char *device, + virDomainInterfaceStatsPtr stats) { virDomainObjPtr privdom; struct timeval tv; @@ -3180,9 +3181,9 @@ static int testDomainInterfaceStats(virDomainPtr domain, goto error; }
- if (!(net = virDomainNetFindByName(privdom->def, path))) { + if (!(net = virDomainNetFind(privdom->def, device))) { virReportError(VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); + _("'%s' is not a known interface"), device);
Same...
goto error; }
diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index 9ebb51d60..c33962229 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -1873,7 +1873,7 @@ vzDomainBlockStatsFlags(virDomainPtr domain,
static int vzDomainInterfaceStats(virDomainPtr domain, - const char *path, + const char *device, virDomainInterfaceStatsPtr stats) { virDomainObjPtr dom = NULL; @@ -1888,7 +1888,7 @@ vzDomainInterfaceStats(virDomainPtr domain,
privdom = dom->privateData;
- ret = prlsdkGetNetStats(privdom->stats, privdom->sdkdom, path, stats); + ret = prlsdkGetNetStats(privdom->stats, privdom->sdkdom, device, stats);
cleanup: virDomainObjEndAPI(&dom); diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 6ead47a0f..5f377147c 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -4484,7 +4484,7 @@ prlsdkFindNetByPath(PRL_HANDLE sdkdom, const char *path) }
int -prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *path, +prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *device, virDomainInterfaceStatsPtr stats) { int ret = -1; @@ -4492,8 +4492,13 @@ prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *path, char *name = NULL; PRL_RESULT pret; PRL_HANDLE net = PRL_INVALID_HANDLE; + virMacAddr mac; + + if (virMacAddrParse(device, &mac) == 0) + net = prlsdkFindNetByMAC(sdkdom, device); + else + net = prlsdkFindNetByPath(sdkdom, device);
- net = prlsdkFindNetByPath(sdkdom, path); if (net == PRL_INVALID_HANDLE) goto cleanup;
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index dae0f4f28..4235ca0ce 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2109,10 +2109,11 @@ xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path, }
static int -xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path, +xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *device, virDomainInterfaceStatsPtr stats) { virDomainDefPtr def = NULL; + virDomainNetDefPtr net = NULL; int ret = -1;
if (!(def = xenGetDomainDefForDom(dom))) @@ -2121,7 +2122,13 @@ xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path, if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0) goto cleanup;
- ret = xenHypervisorDomainInterfaceStats(def, path, stats); + if (!(net = virDomainNetFind(def, device))) { + virReportError(VIR_ERR_INVALID_ARG, + _("'%s' is not a known interface"), device);
Same...
+ goto cleanup; + } + + ret = xenHypervisorDomainInterfaceStats(def, net->ifname, stats);
cleanup: virDomainDefFree(def); diff --git a/tools/virsh.pod b/tools/virsh.pod index 632f202e8..d21c5df72 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -777,7 +777,8 @@ the guest OS via an agent. If unspecified, 'lease' is the default.
Get network interface stats for a running domain. This might be unavailable for some types of interface which don't have -representation in the host, e.g. user. +representation in the host, e.g. user. I<interface-device> can be +the interface's target name or the MAC address.
the interface target by name or MAC address. With ordering adjustment.... Reviewed-by: John Ferlan <jferlan@redhat.com> John
=item B<domif-setlink> I<domain> I<interface-device> I<state> [I<--config>]

On 10/13/2017 10:45 AM, John Ferlan wrote:
On 10/05/2017 10:18 AM, Michal Privoznik wrote:
https://bugzilla.redhat.com/show_bug.cgi?id=1497396
The other APIs accept both, ifname and MAC address. There's no reason virDomainInterfaceStats can't do the same.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 2 +- src/driver-hypervisor.h | 2 +- src/libvirt-domain.c | 15 ++++++++------- src/libxl/libxl_driver.c | 8 ++++---- src/lxc/lxc_driver.c | 8 ++++---- src/openvz/openvz_driver.c | 8 ++++---- src/qemu/qemu_driver.c | 10 +++++----- src/remote/remote_protocol.x | 2 +- src/remote_protocol-structs | 2 +- src/test/test_driver.c | 11 ++++++----- src/vz/vz_driver.c | 4 ++-- src/vz/vz_sdk.c | 9 +++++++-- src/xen/xen_driver.c | 11 +++++++++-- tools/virsh.pod | 3 ++- 14 files changed, 55 insertions(+), 40 deletions(-)
Order-wise - I think patch 4 should go after patch 1. That way this patch doesn't need all those error messages adjusted - they can just be removed when calling virDomainNetFind since it would already provide the message.
With ordering adjustment....
Ah, okay. I'll fix the ordering then.
Reviewed-by: John Ferlan <jferlan@redhat.com>
Thanks, Michal

The command tries to match interface in domain definition by MAC address or interface name. However, since it's possible to configure two interfaces with the same MAC address, it may happen that the XPath returns two or more nodes. We should check for that. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain-monitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index 0ca53e438..4c50155e1 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -707,13 +707,16 @@ cmdDomIfGetLink(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - if (ninterfaces != 1) { + if (ninterfaces < 1) { if (macstr[0]) vshError(ctl, _("Interface (mac: %s) not found."), macstr); else vshError(ctl, _("Interface (dev: %s) not found."), iface); goto cleanup; + } else if (ninterfaces > 1) { + vshError(ctl, _("multiple matching interfaces found")); + goto cleanup; } ctxt->node = interfaces[0]; -- 2.13.6

On 10/05/2017 10:18 AM, Michal Privoznik wrote:
The command tries to match interface in domain definition by MAC address or interface name. However, since it's possible to configure two interfaces with the same MAC address, it may happen that the XPath returns two or more nodes. We should check for that.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain-monitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> John

Every caller reports the error themselves. Might as well move it into the function and thus unify it. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/conf/domain_conf.c | 18 ++++++++++-------- src/libxl/libxl_driver.c | 5 +---- src/lxc/lxc_driver.c | 5 +---- src/openvz/openvz_driver.c | 5 +---- src/qemu/qemu_driver.c | 21 ++++----------------- src/test/test_driver.c | 5 +---- src/xen/xen_driver.c | 5 +---- 7 files changed, 19 insertions(+), 45 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 54be9028d..caffa896d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -26983,13 +26983,12 @@ virDomainGraphicsListenAppendSocket(virDomainGraphicsDefPtr def, * * Finds a domain's net def, given the interface name or MAC address * - * Returns a pointer to the net def or NULL if not found. + * Returns a pointer to the net def or NULL if not found (error is reported). */ virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device) { bool isMac = false; - virDomainNetDefPtr net = NULL; virMacAddr mac; size_t i; @@ -26998,16 +26997,19 @@ virDomainNetFind(virDomainDefPtr def, const char *device) if (isMac) { for (i = 0; i < def->nnets; i++) { - if (virMacAddrCmp(&mac, &def->nets[i]->mac) == 0) { - net = def->nets[i]; - break; - } + if (virMacAddrCmp(&mac, &def->nets[i]->mac) == 0) + return def->nets[i]; } } else { /* ifname */ - net = virDomainNetFindByName(def, device); + virDomainNetDefPtr net = NULL; + + if ((net = virDomainNetFindByName(def, device))) + return net; } - return net; + virReportError(VIR_ERR_INVALID_ARG, + _("'%s' is not a known interface"), device); + return NULL; } diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 9db6f3503..08b0f0317 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -4979,11 +4979,8 @@ libxlDomainInterfaceStats(virDomainPtr dom, goto endjob; } - if (!(net = virDomainNetFind(vm->def, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), device); + if (!(net = virDomainNetFind(vm->def, device))) goto endjob; - } if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 4ab05a7ff..6cf499367 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2872,11 +2872,8 @@ lxcDomainInterfaceStats(virDomainPtr dom, goto endjob; } - if (!(net = virDomainNetFind(vm->def, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), device); + if (!(net = virDomainNetFind(vm->def, device))) goto endjob; - } if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 05ed2bcae..ffd64da04 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -2006,11 +2006,8 @@ openvzDomainInterfaceStats(virDomainPtr dom, goto cleanup; } - if (!(net = virDomainNetFind(vm->def, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), device); + if (!(net = virDomainNetFind(vm->def, device))) goto cleanup; - } if (virNetDevTapInterfaceStats(device, stats, !virDomainNetTypeSharesHostView(net)) < 0) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f2cc0f0a5..7b79c0950 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11040,11 +11040,8 @@ qemuDomainInterfaceStats(virDomainPtr dom, goto cleanup; } - if (!(net = virDomainNetFind(vm->def, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), device); + if (!(net = virDomainNetFind(vm->def, device))) goto cleanup; - } if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_VHOSTUSER) { if (virNetDevOpenvswitchInterfaceStats(device, stats) < 0) @@ -11114,18 +11111,12 @@ qemuDomainSetInterfaceParameters(virDomainPtr dom, goto endjob; if (def && - !(net = virDomainNetFind(vm->def, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("Can't find device %s"), device); + !(net = virDomainNetFind(vm->def, device))) goto endjob; - } if (persistentDef && - !(persistentNet = virDomainNetFind(persistentDef, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("Can't find device %s"), device); + !(persistentNet = virDomainNetFind(persistentDef, device))) goto endjob; - } if ((VIR_ALLOC(bandwidth) < 0) || (VIR_ALLOC(bandwidth->in) < 0) || @@ -11291,12 +11282,8 @@ qemuDomainGetInterfaceParameters(virDomainPtr dom, goto cleanup; } - net = virDomainNetFind(def, device); - if (!net) { - virReportError(VIR_ERR_INVALID_ARG, - _("Can't find device %s"), device); + if (!(net = virDomainNetFind(def, device))) goto cleanup; - } for (i = 0; i < *nparams && i < QEMU_NB_BANDWIDTH_PARAM; i++) { switch (i) { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 3e286635e..be9e8a7aa 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -3181,11 +3181,8 @@ testDomainInterfaceStats(virDomainPtr domain, goto error; } - if (!(net = virDomainNetFind(privdom->def, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), device); + if (!(net = virDomainNetFind(privdom->def, device))) goto error; - } if (gettimeofday(&tv, NULL) < 0) { virReportSystemError(errno, diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 4235ca0ce..901b6ba4b 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2122,11 +2122,8 @@ xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *device, if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0) goto cleanup; - if (!(net = virDomainNetFind(def, device))) { - virReportError(VIR_ERR_INVALID_ARG, - _("'%s' is not a known interface"), device); + if (!(net = virDomainNetFind(def, device))) goto cleanup; - } ret = xenHypervisorDomainInterfaceStats(def, net->ifname, stats); -- 2.13.6

On 10/05/2017 10:18 AM, Michal Privoznik wrote:
Every caller reports the error themselves. Might as well move it into the function and thus unify it.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/conf/domain_conf.c | 18 ++++++++++-------- src/libxl/libxl_driver.c | 5 +---- src/lxc/lxc_driver.c | 5 +---- src/openvz/openvz_driver.c | 5 +---- src/qemu/qemu_driver.c | 21 ++++----------------- src/test/test_driver.c | 5 +---- src/xen/xen_driver.c | 5 +---- 7 files changed, 19 insertions(+), 45 deletions(-)
As noted eariler, I think this patch should go earlier thus affecting less files to change in the long run. With the adjustment, Reviewed-by: John Ferlan <jferlan@redhat.com> John

On 10/05/2017 07:18 AM, Michal Privoznik wrote:
*** BLURB HERE ***
Michal Privoznik (4): virsh: Document limitation of domifstat virDomainInterfaceStats: Accept MAC address too virsh: Deal with multiple matching devices in domif-getlink virDomainNetFind: Report error if no device found
include/libvirt/libvirt-domain.h | 2 +- src/conf/domain_conf.c | 18 ++++++++++-------- src/driver-hypervisor.h | 2 +- src/libvirt-domain.c | 15 ++++++++------- src/libxl/libxl_driver.c | 9 +++------ src/lxc/lxc_driver.c | 9 +++------ src/openvz/openvz_driver.c | 9 +++------ src/qemu/qemu_driver.c | 27 +++++++-------------------- src/remote/remote_protocol.x | 2 +- src/remote_protocol-structs | 2 +- src/test/test_driver.c | 12 +++++------- src/vz/vz_driver.c | 4 ++-- src/vz/vz_sdk.c | 9 +++++++-- src/xen/xen_driver.c | 8 ++++++-- tools/virsh-domain-monitor.c | 5 ++++- tools/virsh.pod | 5 ++++- 16 files changed, 66 insertions(+), 72 deletions(-)
Thanks John for the review. I've fixed the ordering (and subsequent conflicts that resulted from that change) and the man page and pushed. Michal
participants (2)
-
John Ferlan
-
Michal Privoznik