Comment 16 for bug 1480979

Revision history for this message
Andreas Scheuring (andreas-scheuring) wrote :

Alan, thanks for this great discussion. I took the time to discuss this with the libvirt guy that implemented parts of the trustGuestRxFilter stuff. In addition I did some testing.

This is how I think it works with trust rx filter set to yes : Libvirt receives an event if there was a change from within the guest. It queries qemu for the actual state. More details see [1]. Now libvirt does the following
- adds the guests multicasts macs to the macvtaps multicast rx filter list
- if one or more vlans are enabled in the guest, it sets the macvtap into promisc mode
- snychronises the following flags: promisc, multicast, allmulti
- changes the macvtaps mac to the primary mac

What it NOT does is doing anything with the unicast mac list (as far as I understood). This one is being ignored.

What I could NOT verify is the use case of running a bridge in a macvtap attached vm - I mean it works as long as the bridge uses the same mac as the vms eth nic. But as soon as you change that mac - you won't get any inbound traffic for this mac anymore. I was using the bridge mode and tested vm-vm traffic as well as outside-vm traffic.

If that's right the big problems I see are the following:
# Having trustGuest set to NO
- no multicast
- no arbitrary ipv6 addresses (which require special multicast groups for neighbour discovery)
- mac spoofing (and therfore packet sniffing) is not possible, however you can sent out faked packets and confuse the switches in the datacenter

# having trustGuest set to YES
- Guest can change the mac and therefore the mac of the macvtap (this is a big problem, as the mac address will be used for identifying a device in this proposal)
- Guest can mac spoof unicast and therefore do packet sniffing.
But this works only for one mac address at the same time as only one can be set - (i know this doesn't make things better...) Spoofing does NOT work if the target mac is already used on the same host by another libvirt manged guest (if there is already a libvirt configured macvtap with this mac, libvirt does not change the mac of the macvtap device - however if it is not libvirt managed, it will result in a duplicated mac on the host; if a new instance appears on the same host that wants to use this mac, libvirt returns an error)

[1] Show rx-filter information.

Returns a json-array of rx-filter information for all NICs (or for the
given NIC), returning an error if the given NIC doesn't exist, or
given NIC doesn't support rx-filter querying, or given net client
isn't a NIC.

The query will clear the event notification flag of each NIC, then qemu
will start to emit event to QMP monitor.

Each array entry contains the following:

- "name": net client name (json-string)
- "promiscuous": promiscuous mode is enabled (json-bool)
- "multicast": multicast receive state (one of 'normal', 'none', 'all')
- "unicast": unicast receive state (one of 'normal', 'none', 'all')
- "vlan": vlan receive state (one of 'normal', 'none', 'all') (Since 2.0)
- "broadcast-allowed": allow to receive broadcast (json-bool)
- "multicast-overflow": multicast table is overflowed (json-bool)
- "unicast-overflow": unicast table is overflowed (json-bool)
- "main-mac": main macaddr string (json-string)
- "vlan-table": a json-array of active vlan id
- "unicast-table": a json-array of unicast macaddr string
- "multicast-table": a json-array of multicast macaddr string

Example:

-> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } }
<- { "return": [
        {
            "promiscuous": true,
            "name": "vnet0",
            "main-mac": "52:54:00:12:34:56",
            "unicast": "normal",
            "vlan": "normal",
            "vlan-table": [
                4,
                0
            ],
            "unicast-table": [
            ],
            "multicast": "normal",
            "multicast-overflow": false,
            "unicast-overflow": false,
            "multicast-table": [
                "01:00:5e:00:00:01",
                "33:33:00:00:00:01",
                "33:33:ff:12:34:56"
            ],
            "broadcast-allowed": false
        }
      ]
   }