On 3/26/25 6:03 AM, icefrog1950(a)gmail.com wrote:
Hi,
Is possible to capture pcaps for each VM individually?
QEMU supports command line '-object filter-dump, file=test.pcap'. I'm not
sure if Libvirt supports this features, or there are better ways to solve this.
libvirt doesn't diredctly support this, but it should be (edit: is -
I've now tried it) possible to make it work with <qemu:commandline>,
which is documented here:
https://blog.vmsplice.net/2011/04/how-to-pass-qemu-command-line-options.html
I also see from the docs about filter-dump:
https://wiki.qemu.org/Documentation/Networking#Network_Monitoring
that
1) it will only work if the traffic is all going through QEMU userspace
(which makes sense); since the default for libvirt is that virtio-net
traffic will be processed in the host kernel, you'll need to add <driver
name='qemu'/> to the <interface>, and
2) because you need to give the "id" of the netdev you're trying to
capture in the filter-dump options, you need to manually specify <alias
name='blah'/> in the <interface> so that it will be a known/fixed value
(normally it is auto-generated by libvirt at runtime).
So your <interface> definition will need to be modified something like this:
<interface type='network'>
<model type='virtio'/>
<driver name='qemu'/> <==== add this
<alias name='ua-net0'/> <==== and this
...
</interface>
Once you've made that change, you'll need to add the <qemu:commandline>
bit, first by changing the first line of the domain definition from:
<domain type='kvm'>
to
<domain type='kvm'
xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
and then adding in the following bit immediately after </devices> and
before </domain> at the end of the file:
<qemu:commandline>
<qemu:arg value='-object'/>
<qemu:arg
value='filter-dump,id=f1,netdev=hostua-net0,file=/tmp/xyzzy.pcap'/>
</qemu:commandline>
A couple notes about this:
1) the value of "id" here is unimportant, it can be just about anything
that hasn't already been used in the domain,
2) the setting of "netdev" is *not quite* the same as the "alias name"
of the interface in libvirt's config; it is derived from that setting by
prepending "host" (this is due to internal implementation details that
normally the user doesn't see or care about; you're only seeing it
because you're doing something that isn't supported :-))
3) The file *must* be in a directory where the UID used for running the
qemu-kvm process has permissions to create and write to a file. The
system (privileged) instance of libvirt normally runs the qemu-kvm
process as user "qemu", and a session instance (unprivileged) will run
qemu-kvm as the same UID as the process calling libvirt. In both cases
it should work to give a name in /tmp, since generally any user can
write to /tmp.
I tried this on a guest, started it, then ran
tail /tmp/xyzzy.pcap | tcpdump
and it began spewing out reasonable-looking network traffic, so I guess
it worked :-)
As for alternatives - normally I instead just run tcpdump (or wireshark
or whatever) on the host-side tap device created as the backend for the
guest netdev (you can find the name of this device by looking for
"<target dev='blah'/>" in the output of "virsh dumpxml"
of a running
guest). Of course this won't work if you're using a type of networking
that doesn't involve a tap (or macvtap) device, and also might miss the
first few packets after the guest is started (depending on how quickly
you can issue the "tcpdump -i blah" command after the tap device has
been created as a part of starting up the guest). Another possibility is
to run tcpdump/wireshark on the host bridge device that the tap is
connected to.