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

Michal Privoznik mprivozn at redhat.com
Wed Sep 13 08:11:38 UTC 2017


On 09/12/2017 07:35 PM, Laine Stump wrote:
> 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

Okay, I'll move it up so that it's under <interface/> directly.

> 
> 
>>
>> 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)

For that I have already an answer prepared: Patches are welcome :-P

> 
> 
> 
>>>     </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.

Agreed. There's a lot of places where our schema is looser than our
parser. And I don't think that's a problem. The only way we could have
1:1 correspondence is if we generated the parser from RNG schema. And
even then there are per driver nuances (what's allowed in driver X is
forbidden/not yet implemented in driver Y).

> 
> 
>>> +              </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.

Yep. I'm doing that in the next patch. Since this patch aims on config
only, I wanted to keep it generic enough and check only obviously wrong
values, e.g. IP addresses from movies like 218.108.149.373 (Mr Robot
ftw! But apart from that I was surprised how quite accurate it was).
Then, if a driver poses stricter limits those should be checked there
now that we have per driver per device validation callbacks.
One exception to this rule is, if all drivers forbid certain
value/combination, it can go to the generic src/conf/ callback instead
of copying the same lines all over the place.

Michal




More information about the libvir-list mailing list