(If you already know about my work on putting a logical switch
abstraction into libvirt's <network>, skip to part 2)
INTRODUCTION
===========
The rudimentary logical network switch capability I'm currently
implementing (see
https://bugzilla.redhat.com/show_bug.cgi?id=643947) is
intended to allow a guest's interface XML to be free of any specific
physical network device name, particularly in bridge and direct modes.
It does this by expanding the definition of a libvirt <network> to
include cases that merely describe a host-configured bridge, or a host
interface (or pool of interfaces) that can be used by a guest in one of
the 'direct' modes (bridge, private, vepa, or passthrough). It will also
allow certain details of the guest's network connection to be configured
by "portgroups" in the <network> definition (initially this will be
limited to a portgroup containing a <virtualportprofile> and bandwidth
limiting information).
For example, in the past, a guest that wanted to connect to interface
eth10 using the direct (aka 'macvtap') "vepa" mode would need to have
this <interface> in its guest XML:
<interface type='direct'>
<mac address='52:54:00:34:a5:aa'/>
<source dev='eth10' mode='vepa'/>
<model type='virtio'/>
<virtualport type='802.1Qbg'>
<parameters managerid='33' typeid='89' typeidversion='3'/>
</virtualport>
</interface>
With my new code, you can instead define a <network> with connections on
several physical ethernets:
<network>
<name>test</name>
<forward mode='vepa'>
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
<interface dev='eth14'/>
<interface dev='eth15'/>
<interface dev='eth16'/>
<interface dev='eth17'/>
</forward>
<portgroup name='accounting'>
<virtualport type='802.1Qbg'>
<parameters managerid='44' typeid='54' typeidversion='1'/>
</virtualport>
</portgroup>
<portgroup name='engineering' default='yes'>
<virtualport type='802.1Qbg'>
<parameters managerid='33' typeid='89' typeidversion='3'/>
</virtualport>
</portgroup>
</network>
and then tell the domain's <interface> to get the information from the
network:
<interface type='network'>
<mac address='52:54:00:34:a5:aa'/>
<source network='test' portgroup='engineering'/>
<model type='virtio'/>
</interface>
When libvirt sets up the interface connection, it will grab the config
for network 'test', see that the forward mode is 'vepa', decide which
physical ethernet to use, add in any extra stuff from the <portgroup>,
and use that as the information for connection. In this manner, 1) it
will remove the hardcoded device name from the domain config, making it
possible to migrate the domain to other hardware, and 2) share a pool of
physical devices over a group of domains.
PROPOSAL
========
After I've determined which physical device to use, I need to save that
information for as long as the domain is running, so that if libvirtd is
restarted, it won't be lost (in some configs, only a single guest can
use any particular netdev at a given time, so we want to be able to
manage allocation of the devices without leaking any). My current idea
is to save this in the domain <interface> XML that's put in the state
directory, but make sure that it's never put into the XML returned by
virsh dumpxml. What I'm thinking of is to add an <actual> subelement
under <interface>, like this:
<interface type='network'>
<mac address='52:54:00:34:a5:aa'/>
<source network='test' porgroup='engineering'/>
<model type='virtio'/>
<actual type='direct'/>
<source dev='eth10' mode='vepa'/>
<virtualport type='802.1Qbg'>
<parameters managerid='33' typeid='89' typeidversion='3'/>
</virtualport>
</actual>
</interface>
This will be a private/internal thing used only within libvirt, however
it does need to be stable, since it has to be understandable by a
libvirtd that has started up while guests are running (eg during a
libvirt upgrade). So I want to make sure I'm doing something reasonable.
So, it is?
Should <actual> contain *everything* from the parent interface, plus the
items that are changed? Or should it contain only:
* type attribute
* source element
* <bridge name=.../> (if applicable)
* <virtualport> (and other items that might come from <portgroup> in
the future
(i.e. the things that have changed)?
I *think* the answer is that it should just contain the items that have
changed, and there should be a wrapper API around the virDomainNetDef
object for retrieving things like type (if (def->actual) return
def->actual.type; else return def->type; and similar) to make sure that
all functions use the correct data.