[libvirt] [PATCH 4/5] conf: Allow usernet to have an address

Laine Stump laine at laine.org
Tue Sep 12 17:35:08 UTC 2017


On 09/12/2017 05:53 AM, Martin Kletzander wrote:
> On Tue, Sep 12, 2017 at 11:32:52AM +0200, Michal Privoznik wrote:
>> https://bugzilla.redhat.com/show_bug.cgi?id=1075520
>>
>> Currently, all that users can specify for an interface type of
>> 'user' is the common attributes: PCI address, NIC model (and
>> that's basically it). However, some need to configure other
>> address range than the default one.
>>
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> ---
>>
>> Notes:
>>    Frankly, I'm not that convinced about this one. I mean,
>>    this puts IP addresses into net->hostIP while we are
>>    configuring guest side of the SLIRP. However, it just
>>    feels better to have the IP addresses under <source/>
>>    than under <interface/>. Which actually is the other
>>    option. So it's either:
>>
>>    <interface type='user'>
>>      <source>
>>        <ip address='1.2.2.4'/>
>>      </source>
>>    </interface>
>>
>>    for net->hostIP, or it's:
>>
>>    <interface type='user'>
>>      <ip address='1.2.2.4'/>
>>    </interface>
>>
>

In order to be consistent between all different hypervisors and
interface connection types, any ip addresses and routes that are set to
be visible on the host side of the interface "apparatus" must be under
<source>, and those that are set to be visible on the guest side must be
directly under the top level of <interface>. Since the IP you're
configuring in this patch will be seen in the guest, it needs to be at
the toplevel (i.e. it will be parsed into net->guestIP).


> I'm not convinced either.  If you don't like the fact that it's in
> hostIP (even though we're setting up the backend of that device, not the
> device itself, it's just the IP that the internal DHCP server should
> send to the guest) and want to have it in guestIP (which would make
> sense as well) then it should be:
>
>   <interface type='user'>
>     <target>
>       <ip address='1.2.2.4'/>
>     </target>
>   </interface>

When I dropped into this code to add support for specifying the IP
address and routes on the *host* side of a tap device/veth device (see
commit 98fa8f3ef) for QEMU and LXC (along with the "peer IP" for the
other end of a tap/veth, which is *not* the same thing!), I *wished*
that we had added the new <ip> and <route> elements for specifying
guest-side <ip> and <route> under <target> as you suggest, since
<target> is intended to contain items configuring how the device appears
on the guest side[*]. Unfortunately, the decision on the location of
guest-side <ip> was made *long* ago (at least prior to July of 2008, I
didn't feel like spelunking any further), when <ip> was added directly
under <interface> to support setting the guest-side IP address on Xen.

Many years later (2014), when cbossdonnat added support for setting the
guest-side IP of  an LXC veth pair, he also used the same element in
order to provide consistency. So, we are unable to put it under
<target>, and that decision was made sometime befor 2008,


[*] Of course, the <target> element is used inconsistently within
<interface> when compared to other uses - <target dev='blah'/> is used
to specify the name of the tap/macvtap device *as it is known on the
host side*. <target> has been described to me as a place to configure
what things look like to the guest (e.g. the intended name for a disk
device on the guest)(which is anyway ignored everywhere except Xen, but
that's a different topic!), so using it to configure a name that's
visible only to the host seems wrong, but it's been that way since
sometime long before even I was involved with libvirt, so there is no
changing it now :-P


>
> Which would cleanly correlate to that (and I also don't like the look of
> it).  So I'll leave this to a further discussion.

I think it *would* have been good under <target>, if anyone had foreseen
the need for a <target> grouping (and consistently used it) from the
beginning. But that train sailed into space long ago, so in order to be
backward compatible and consistent, the guest-side IP/routes need to be
directly under <interface> (just like the guest-side PCI address for PCI
devices is), and the host-side IP/routes need to go under <source> (just
as host-side PCI addresses of <hostdev> devices are).


>
>>    for net->guestIP. I went for the former one, but I
>>    don't have a strong opinion on that.

That's good, because I *do*! :-P

>>
>> docs/formatdomain.html.in                          | 13 ++++++-
>> docs/schemas/domaincommon.rng                      |  5 +++
>> src/conf/domain_conf.c                             |  5 +--
>> .../qemuxml2argv-net-user-addr.xml                 | 42
>> ++++++++++++++++++++++
>> .../qemuxml2xmlout-net-user-addr.xml               |  1 +
>> tests/qemuxml2xmltest.c                            |  1 +
>> 6 files changed, 64 insertions(+), 3 deletions(-)
>> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml
>> create mode 120000
>> tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml
>>
>> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
>> index 8ca7637a4..65a8886ee 100644
>> --- a/docs/formatdomain.html.in
>> +++ b/docs/formatdomain.html.in
>> @@ -4701,7 +4701,14 @@
>>       starting from <code>10.0.2.15</code>. The default router will be
>>       <code>10.0.2.2</code> and the DNS server will be
>> <code>10.0.2.3</code>.
>>       This networking is the only option for unprivileged users who
>> need their
>> -      VMs to have outgoing access.
>> +      VMs to have outgoing access. However, <span class="since">since
>> +        3.8.0</span>, it is possible to override the default network by
>> +      including <code>source</code> element. The element can have
>> <code>ip</code>
>> +      element for each IPv4 and IPv6. The element has
>> <code>family</code>
>> +      attribute which accepts <code>ipv4</code> and
>> <code>ipv6</code> values.
>> +      Then there's <code>address</code> attribute for specifying IP
>> address
>> +      corresponding to the family. Optionally, the default prefix
>> length can be
>> +      overridden via <code>prefix</code> attribute.

This will of course need to be rewritten (and grammar cleaned up).

You realize now that you've added support for setting the IP address,
inevitably someone will expect you to write patches to support setting
of the DHCP server, DNS server, default route, DHCP range, hostname,
NMBD server, domain name, tftp directory and bootfile,.... :-O)



>>     </p>
>>
>> <pre>
>> @@ -4711,6 +4718,10 @@
>>   ...
>>   <interface type='user'>
>>     <mac address="00:11:22:33:44:55"/>
>> +    <source>
>> +      <ip family='ipv4' address='172.17.2.0' prefix='24'/>
>> +      <ip family='ipv6' address='2001:db8:ac10:fd01::'
>> prefix='64'/>
>> +    </source>
>>   </interface>
>> </devices>
>> ...</pre>
>> diff --git a/docs/schemas/domaincommon.rng
>> b/docs/schemas/domaincommon.rng
>> index c9a4f7a9a..7b5292bd3 100644
>> --- a/docs/schemas/domaincommon.rng
>> +++ b/docs/schemas/domaincommon.rng
>> @@ -2428,6 +2428,11 @@
>>             <value>user</value>
>>           </attribute>
>>           <interleave>
>> +            <optional>
>> +              <element name="source">
>> +                <ref name="interface-ip-info"/>
>
> This also allows <route/> here, I would split the definition and
> disallow that.  Just for the sake of pointless bugs flying by.

Or maybe just check for presence of <route> during parsing and issue an
ENOTSUPP log if it's found (that will be needed anyway in case XML
validation is turned off). There's a certain point of detail when we
stop caring about the exactness of the RNG. Eventually it becomes more
difficult to read the RNG than it's worth, and the error messages
provided when validation fails.


>> +              </element>
>> +            </optional>
>>             <ref name="interface-options"/>
>>           </interleave>
>>         </group>
>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>> index 676fc0f34..ef236757a 100644
>> --- a/src/conf/domain_conf.c
>> +++ b/src/conf/domain_conf.c
>> @@ -5214,12 +5214,13 @@ static int
>> virDomainNetDefValidate(const virDomainNetDef *net)
>> {
>>     if ((net->hostIP.nroutes || net->hostIP.nips) &&
>> -        net->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
>> +        net->type != VIR_DOMAIN_NET_TYPE_ETHERNET &&
>> +        net->type != VIR_DOMAIN_NET_TYPE_USER) {
>>         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>>                        _("Invalid attempt to set network interface "
>>                          "host-side IP route and/or address info on "
>>                          "interface of type '%s'. This is only
>> supported "
>> -                         "on interfaces of type 'ethernet'"),
>> +                         "on interfaces of type 'ethernet' and
>> 'user'"),
>
> Same here, you even give the hint that routes are supported for
> the type='user'

Yeah, this should be separated. It was previously combined for brevity,
only because the two were both only supported in exactly the same cases.

Also, it looks like qemu only supports a single IPv4 and single IPv6
address on each interface, so you need to validate there is at most one
of each type.


>
>>                        virDomainNetTypeToString(net->type));
>>         return -1;
>>     }
>> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml
>> b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml
>> new file mode 100644
>> index 000000000..65362d8aa
>> --- /dev/null
>> +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml
>> @@ -0,0 +1,42 @@
>> +<domain type='qemu'>
>> +  <name>QEMUGuest1</name>
>> +  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
>> +  <memory unit='KiB'>219136</memory>
>> +  <currentMemory unit='KiB'>219136</currentMemory>
>> +  <vcpu placement='static'>1</vcpu>
>> +  <os>
>> +    <type arch='i686' machine='pc'>hvm</type>
>> +    <boot dev='hd'/>
>> +  </os>
>> +  <clock offset='utc'/>
>> +  <on_poweroff>destroy</on_poweroff>
>> +  <on_reboot>restart</on_reboot>
>> +  <on_crash>destroy</on_crash>
>> +  <devices>
>> +    <emulator>/usr/bin/qemu-system-i686</emulator>
>> +    <disk type='block' device='disk'>
>> +      <driver name='qemu' type='raw'/>
>> +      <source dev='/dev/HostVG/QEMUGuest1'/>
>> +      <target dev='hda' bus='ide'/>
>> +      <address type='drive' controller='0' bus='0' target='0'
>> unit='0'/>
>> +    </disk>
>> +    <controller type='usb' index='0'>
>> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x01'
>> function='0x2'/>
>> +    </controller>
>> +    <controller type='ide' index='0'>
>> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x01'
>> function='0x1'/>
>> +    </controlleer>
>> +    <controller type='pci' index='0' model='pci-root'/>
>> +    <interface type='user'>
>> +      <mac address='00:11:22:33:44:55'/>
>> +      <source>
>> +        <ip address='172.17.2.0' family='ipv4' prefix='24'/>
>
> Also add ipv6 into the test.
>
>> +      </source>
>> +      <model type='rtl8139'/>
>> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x03'
>> function='0x0'/>
>> +    </interface>
>> +    <input type='mouse' bus='ps2'/>
>> +    <input type='keyboard' bus='ps2'/>
>> +    <memballoon model='none'/>
>> +  </devices>
>> +</domain>
>> diff --git
>> a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml
>> b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml
>> new file mode 120000
>> index 000000000..fd909ec24
>> --- /dev/null
>> +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml
>> @@ -0,0 +1 @@
>> +../qemuxml2argvdata/qemuxml2argv-net-user-addr.xml
>> \ No newline at end of file
>> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
>> index 0a87cedf2..99b15ad0c 100644
>> --- a/tests/qemuxml2xmltest.c
>> +++ b/tests/qemuxml2xmltest.c
>> @@ -531,6 +531,7 @@ mymain(void)
>>     DO_TEST("misc-uuid", NONE);
>>     DO_TEST("net-vhostuser", NONE);
>>     DO_TEST("net-user", NONE);
>> +    DO_TEST("net-user-addr", NONE);
>>     DO_TEST("net-virtio", NONE);
>>     DO_TEST("net-virtio-device", NONE);
>>     DO_TEST("net-virtio-disable-offloads", NONE);
>> -- 
>> 2.13.5
>>
>> -- 
>> libvir-list mailing list
>> libvir-list at redhat.com
>> https://www.redhat.com/mailman/listinfo/libvir-list





More information about the libvir-list mailing list