[libvirt] inconsistency in attribute usage between hv drivers

Laine Stump laine at laine.org
Fri May 27 17:11:54 UTC 2016

I just came across this problem while looking for the proper place to 
put <ip> info for the host side of <interface type='ethernet'>. I don't 
think there's really anything that can be done about it now, since 
everything below has been in place for so long, but maybe it can serve 
as a cautionary tale.

Prologue: A week or two ago, I made patches to support <interface 
type='ethernet'> in the LXC driver. I did this not because I have a need 
for that, but because it seemed like the perfect avenue for 
investigating the best way to add IP address and route config to 
<interface>, as it is one environment where we have a need *and* the 
ability to setup IP info for both the host and guest sides of the 
interface. I accomplished this by simply generalizing the existing 
<interface type='bridge'> code to not attach the host-side veth device 
to a bridge.

This makes all common attributes between type='ethernet' and 
type='bridge' consistent, including the configuration of guest-side and 
host-side device names, and here we come to the first inconsistency - 
the device name for the veth/tap on the host side is  in the <target> 
element (which I've always been told is supposed to be used for 
device-specific info about how the device will be presented on the 
*guest* side, but I suppose this is because <interface type='direct'> 
uses <source dev='blah'> to provide the name of the physical device that 
the macvtap device (named in <target dev='macvblah'/> is attached to).  
And I guess because the dev attribute was already in-use in <target> the 
much more recently added guest-side name is given in the <guest> 
subelement (in LXC at least):

     <interface type='ethernet'>

       <target dev='hostblah'/>  <-- name of veth on host side

       <guest dev='guestblah'/> <-- name of veth on guest side


Now, this "is what it is". There is no changing it. In particular, the 
use of <target dev> for the host-side device name has been in use for so 
long and is so deeply ingrained that it's just part of the scenery.

Moving for a minute to  the IP address/route info for the guest side is 
already configured in the toplevel <ip> and <route> subelements of 

    <interface type='ethernet'>

      <ip address='' .../>


My first thought was to put the <ip> for the host side inside <source>:

    <interface type='ethernet'>


        <ip address='' .../> <-- host side


      <ip address='' .../> <-- guest side


That makes sense to me because it parallels what we do with PCI 
addresses for hostdev - the PCI address in <source> tells what the 
address is on the host, and the one at the toplevel of <hostdev> tells 
what the PCI address will be in the guest. It *doesn't* fit well with 
the fact that the device we're setting up is named in <target> though, 
so we're already inconsistent, but putting the host-side IP config in 
<target> seems like an invitation to mix things up even more in the 
future, since <target> is used everywhere else as a place to put stuff 
related to what the device looks like in the guest (although... for 
<interface>, <target> *is* currently used only for the host-side 
tap/veth device name; so maybe we just can define the purpose of 
<target> differently in this one case... But I digress).

So I went to the code to add parsing of <ip> inside <source>, and found 
that the type-specific data for ethernet has a dev, and that field in 
the object is set during parsing from <source dev='blah'/>, *and* that 
the openvz driver uses that dev name as the name of the network device 
in the *guest*! (even though my understanding of <source>  is that it is 
supposed to be used for information about the *host* side of any device. 
Sigh.) So on openvz, we have this:

     <interface type='ethernet'>

       <target dev='hostblah'/>  <-- name of interface on host side

       <source dev='guestblah'/> <-- name of interface on guest side


which seems exactly the opposite of what it should be. Note that this 
doesn't seem to be documented anywhere except in the few lines in 
openvz_driver.c that implement it. (Note that, prior to commit 9a4b705f7 
back in 2010, which added support for type='ethernet' in openvz, the 
"dev" field was already in the ethernet-specific sub-object of 
virDomainNetDef, but it was only used to hold the name of the bridge 
that a tap device was attached to when converting from a qemu 
commandline to XML (also, as previously stated, for type='direct' it is 
used to name the physical device on the host that the macvtap interface 
is connected to, i.e. *exactly* the opposite end of the chain). It looks 
like the poster of the openvz patch just saw an opportune 
existing-but-unused-by-type=ethernet attribute and took advantage, and 
it wasn't noticed in review).

I'm actually skeptical that anyone even uses this, since openvz is a 
less-used driver, type='ethernet' is less used among interface types, 
and even after that it's valid to not provide a name, in which case one 
is automatically generated. But there is no way to verify that, so we're 
stuck with it. It is true that the LXC version of type='ethernet' was 
added only a few days ago, and there hasn't yet been a release, so I 
*could* modify it to be consistent with the attribute usage in the 
openvz driver. But that would make <interface type='ethernet'> in LXC 
inconsistent with <interface type='bridge'> in LXC, which is a much 
worse situation. IT seems there is nothing to change. As I said above 
"it is what it is".

So why am I writing this message? Partly to just vent frustration (aka 
"whine") I suppose :-). Also partly as public testimony that my 
seemingly excessive worrying over attribute naming and placement is 
justified, and not just OCD. Also, as I said above, as a cautionary tale 
that any patch adding *any* XML config knob, or making use of an 
existing XML config knob needs extra scrutiny to help minimize such 
messes in the future.

More information about the libvir-list mailing list