[libvirt] [PATCH v2 2/2] libxl: implement virDomainInterfaceStats
Joao Martins
joao.m.martins at oracle.com
Wed Dec 2 19:26:30 UTC 2015
On Wed, Dec 02, 2015 at 11:50:41AM -0700, Jim Fehlig wrote:
> On 12/02/2015 06:02 AM, Joao Martins wrote:
> >
> > On 12/02/2015 12:45 AM, Jim Fehlig wrote:
> >> On 11/23/2015 11:57 AM, Joao Martins wrote:
> >>> Introduce support for domainInterfaceStats API call for querying
> >>> network interface statistics. Consequently it also enables the
> >>> use of `virsh domifstat <dom> <interface name>` command plus
> >>> seeing the interfaces names instead of "-" when doing
> >>> `virsh domiflist <dom>`.
> >>>
> >>> 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<domid>.<devid>[-emu].
> >> One interesting Xen behavior that has existing for many, many years is that a PV
> >> nic is implicitly created for each emulated nic specified in the config. The
> >> guest OS picks which one to use. These days most will use the PV nic, and if
> >> they are nice, "unplug" the emulated one via the unplug protocol. E.g. an HVM
> >> guest with
> >>
> >> <interface type='bridge'>
> >> <source bridge='br0'/>
> >> <mac address='00:16:3e:7a:35:ce'/>
> >> <script path='/etc/xen/scripts/vif-bridge'/>
> >> </interface>
> >>
> >> results in two vif devices on the host
> >>
> >> # ip a | grep vif
> >> 607: vif519.0-emu: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast
> >> master br0 state UNKNOWN group default qlen 500
> >> 608: vif519.0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast
> >> master br0 state UNKNOWN group default qlen 512
> >>
> >> both are connected to the bridge
> >>
> >> # brctl show br0
> >> bridge name bridge id STP enabled interfaces
> >> br0 8000.001e676598f5 no eth0
> >> vif519.0
> >> vif519.0-emu
> >>
> >> In this case, the (not nice) guest OS is using the PV nic but did not unplug the
> >> emulated one. So we have two interfaces, but the virDomainDef only contains one
> >>
> >> # virsh domiflist 519
> >> Interface Type Source Model MAC
> >> -------------------------------------------------------
> >> vif519.0-emu bridge br0 - 00:16:3e:7a:35:ce
> >>
> >> Not a fault of this patch, but we'll need to figure out how to handle the
> >> implicitly created PV nic. The interesting case is identifying emulated nics
> >> that have been unplugged by a nice guest, and hence no longer exist in the host
> >> (e.g. vif519.0-emu in the above example).
> >>
> > Indeed this is an issue I am aware of but wasn't sure on how to handle it. The
> > way I test an HVM guest on libvirt with a (explicitly created) PV nic was with
> > "model=netfront" since there wouldn't be an emulated nic.
>
> Yep, libxl allows us specify a PV nic only, but not an emulated nic only.
>
> > So perhaps we could
> > differ it if this was specified on HVM guests. If that wasn't the case we would
> > add the complementary interface along with checking if indeed the net device
> > exists. On cleanup we would just delete the second interface that would appear
> > with the same name.
>
> Right. So the running config would have the implicitly added PV device. The
> persistent config wouldn't change. Are you volunteering to write a patch? :-).
>
Yeap :-D
> >
> >>> We extract the network interfaces info from libxl in
> >>> libxlDomainStartCallback() and make 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 <joao.m.martins at oracle.com>
> >>> ---
> >>> Changes since v3:
> >>> - Use libxl_device_nic_list() for getting each network interface
> >>> devid in DomainStartCallback.
> >>> - Improve error reporting by appropriately setting the right error
> >>> when no interface is known.
> >>> - Do not unlock vm if libxlDomainObjEndJob() returns false
> >>> - Set vm->def->net[i]->ifname on DomainStartCallback instead of
> >>> DomainStart.
> >>> - Change commit message reflecting the changes on the previous
> >>> item and mention correct interface names when doing domiflist.
> >>>
> >>> Changes since v2:
> >>> - Clear ifname if it's autogenerated, since otherwise will persist
> >>> on successive domain starts. Change commit message reflecting this
> >>> change.
> >>>
> >>> Changes since v1:
> >>> - Fill <virDomainNetDef>.ifname after domain start with generated
> >>> name from libxl based on domain id and devid returned by libxl.
> >>> After that path validation don interfaceStats is enterily based
> >>> on ifname pretty much like the other drivers.
> >>> - Modify commit message reflecting the changes mentioned in
> >>> the previous item.
> >>> - Bump version to 1.2.22
> >>> ---
> >>> src/libxl/libxl_domain.c | 29 +++++++++++++++++++++++++++
> >>> src/libxl/libxl_driver.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
> >>> 2 files changed, 81 insertions(+)
> >>>
> >>> diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
> >>> index a7267b0..141f241 100644
> >>> --- a/src/libxl/libxl_domain.c
> >>> +++ b/src/libxl/libxl_domain.c
> >>> @@ -728,6 +728,17 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
> >>> }
> >>> }
> >>>
> >>> + if ((vm->def->nnets)) {
> >>> + ssize_t i;
> >> size_t
> >>
> > Apologies for the typo.
> >
> >>> +
> >>> + 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);
> >>> @@ -857,6 +868,8 @@ static void
> >>> libxlDomainStartCallback(libxl_ctx *ctx, libxl_event *ev, void *for_callback)
> >>> {
> >>> virDomainObjPtr vm = for_callback;
> >>> + libxl_device_nic *nics;
> >>> + int nnics;
> >>> size_t i;
> >>>
> >>> virObjectLock(vm);
> >>> @@ -883,6 +896,22 @@ libxlDomainStartCallback(libxl_ctx *ctx, libxl_event *ev, void *for_callback)
> >>> VIR_FREE(console);
> >>> }
> >>> }
> >>> +
> >>> + if ((nics = libxl_device_nic_list(ctx, ev->domid, &nnics)) != NULL) {
> >>> + for (i = 0; i < vm->def->nnets && i < nnics; i++) {
> >>> + virDomainNetDefPtr net = vm->def->nets[i];
> >>> + libxl_device_nic *x_nic = &nics[i];
> >>> + const char *suffix =
> >>> + x_nic->nictype != LIBXL_NIC_TYPE_VIF ? "-emu" : "";
> >>> +
> >>> + if (net->ifname)
> >>> + continue;
> >>> +
> >>> + if (virAsprintf(&net->ifname, "vif%d.%d%s",
> >>> + ev->domid, x_nic->devid, suffix) < 0)
> >>> + continue;
> >>> + }
> >>> + }
> >> As mentioned in my reply to 1/2, I think we should simply create the names after
> >> a successful libxl_domain_create_{new,restore}. Aside from the implicit PV nic
> >> issue, the patch works for me with the below diff squashed in. What do you think
> >> of this change? Does it work for you?
> >>
> > Looks great, Perhaps just changing the version to 1.3.0 since it's no longer 1.2.22.
>
> I changed that when resolving a conflict that arose from dropping patch 1. I'm
> going to push this patch with my diff squashed in. It has been on the list for
> quite some time, has actually went through 4 versions as your patch history
> notes indicate, and IMO has been well vetted and tested.I think it is an
> appropriate patch to push even though we entered the 1.3.0 freeze today.
>
Great! Many thanks for the time reviewing it!
> Thanks a lot for your patience!
>
> Regards,
> Jim
>
> >
> > Regards,
> > Joao
> >
> > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> > index b3987b9..aa81570 100644
> > --- a/src/libxl/libxl_driver.c
> > +++ b/src/libxl/libxl_driver.c
> > @@ -5472,7 +5472,7 @@ static virHypervisorDriver libxlHypervisorDriver = {
> > #endif
> > .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
> > .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
> > - .domainInterfaceStats = libxlDomainInterfaceStats, /* 1.2.22 */
> > + .domainInterfaceStats = libxlDomainInterfaceStats, /* 1.3.0 */
> > .domainMemoryStats = libxlDomainMemoryStats, /* 1.3.0 */
> > .domainGetCPUStats = libxlDomainGetCPUStats, /* 1.3.0 */
> > .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
> >
> >
> >> Regards,
> >> Jim
> >>
> >>
> >> diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
> >> index b45cd27..086406b 100644
> >> --- a/src/libxl/libxl_domain.c
> >> +++ b/src/libxl/libxl_domain.c
> >> @@ -729,7 +729,7 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
> >> }
> >>
> >> if ((vm->def->nnets)) {
> >> - ssize_t i;
> >> + size_t i;
> >>
> >> for (i = 0; i < vm->def->nnets; i++) {
> >> virDomainNetDefPtr net = vm->def->nets[i];
> >> @@ -868,8 +868,6 @@ static void
> >> libxlConsoleCallback(libxl_ctx *ctx, libxl_event *ev, void *for_callback)
> >> {
> >> virDomainObjPtr vm = for_callback;
> >> - libxl_device_nic *nics;
> >> - int nnics;
> >> size_t i;
> >>
> >> virObjectLock(vm);
> >> @@ -897,25 +895,35 @@ libxlConsoleCallback(libxl_ctx *ctx, libxl_event *ev, void
> >> *for_callback)
> >> }
> >> }
> >>
> >> - if ((nics = libxl_device_nic_list(ctx, ev->domid, &nnics)) != NULL) {
> >> - for (i = 0; i < vm->def->nnets && i < nnics; i++) {
> >> - virDomainNetDefPtr net = vm->def->nets[i];
> >> - libxl_device_nic *x_nic = &nics[i];
> >> - const char *suffix =
> >> - x_nic->nictype != LIBXL_NIC_TYPE_VIF ? "-emu" : "";
> >> -
> >> - if (net->ifname)
> >> - continue;
> >> -
> >> - if (virAsprintf(&net->ifname, "vif%d.%d%s",
> >> - ev->domid, x_nic->devid, suffix) < 0)
> >> - continue;
> >> - }
> >> - }
> >> virObjectUnlock(vm);
> >> libxl_event_free(ctx, ev);
> >> }
> >>
> >> +/*
> >> + * Create interface names for the network devices in parameter def.
> >> + * Names are created with the pattern 'vif<domid>.<devid><suffix>'.
> >> + * 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.
> >> @@ -1056,6 +1064,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;
> >> j
> >>
>
More information about the libvir-list
mailing list