On 3/26/25 6:03 AM, icefrog1...@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.

Reply via email to