[libvirt] RFC: Supporting IPv6 on libvirt virtual networks

Laine Stump laine at laine.org
Tue Nov 2 18:22:08 UTC 2010


There are a couple of bugzilla records open requesting IPv6 support on
libvirt's virtual networks:

https://bugzilla.redhat.com/show_bug.cgi?id=514749
https://bugzilla.redhat.com/show_bug.cgi?id=586124

This is a first cut at describing what that support will look
like. Please send any comments/criticisms/suggestions you may have.

Changes to network XML
----------------------

1) The <ip> element of the network xml will be expanded in the following 
ways:

a) <ip> can now appear multiple times (although I think only one of
    these can/should be allowed to have a <dhcp> element). The bridge
    interface (eg virbr0) will be configured with all given ips.

b) The address attribute can now be either an ipv4 dotted quad, or an
    ipv6 address, eg "2001:db8:1::10" (the schema will allow either in
    any case, but the parser will validate that it is appropriate for
    the given family - see (b))

b) new attributes:

    family="ipv4|ipv6".

      Optional. It will default to ipv4 if not specified.

    prefix="<some number>"

      Optional. This is used to specify how many significant bits are
      in the ipv6 address. This will also be usable for ipv4, but the
      parser will make sure that only one of netmask or prefix is given
      for an ipv4 address (since netmasks generally aren't specified as
      such in IPv6, the netmask attribute will not be allowed if family
      is ipv6).

2) New subelements of <ip>

    If we want to avoid requiring the admin to login to the hosts to
    configure radvd for advertising addresses, the ipv6 version of <ip>
    is going to need radvd config information. The list of options is
    rather long, and I don't see how we could assume a hardcoded
    default for any of them, so if we're going to have an <radvd>
    subelement, it's going to need a *lot* of attributes/subelements of
    its own:

      http://linux.die.net/man/5/radvd.conf

    For this reason, I think we can at least initially *not* include all 
this config,
    and not attempt to run radvd ourselves.

    However, we can't merely ignore radvd, since our bridges don't
    exist at the time radvd is started by the system, and even if
    you've put the proper config in the static radvd.conf file, it
    can't be recognized until the interface exists, and the method of
    informing radvd that it needs to re-scan the conf file to find new
    interfaces is to send it a SIGHUP.

    So, I'm thinking we can add an <radvd/> subelement to IP that, for
    now, will have no attributes and no subelements. If the ip/radvd
    subelement exists, libvirt will send radvd a SIGHUP when the
    network is brought up, and again if it is brought down.

Here is the example from formatnetwork.html on libvirt.org, updated with 
examples of
the changes I'm proposing:

<network>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.122.100" end="192.168.122.254" />
<host mac="00:16:3e:77:e2:ed" name="foo.example.com" ip="192.168.122.10" />
<host mac="00:16:3e:3e:a9:1a" name="bar.example.com" ip="192.168.122.11" />
</dhcp>
</ip>
<ip family="ipv4" address="192.168.125.1" prefix="24">
<ip family="ipv6" address="2001:db8:1::10" prefix="128"/>
<ip family="ipv6" address="2001:4978:2ac::1" prefix="48">
<radvd/>
</ip>
</network>

The original ipv4 address example remains unchanged, but notice that
we can also give a 2nd ipv4 address, and can use "prefix" instead of
"netmask" if we want.

The example configs the bridge with two ipv6 addresses, so guests
connected to the bridge can be on either of these networks or both. In
addition, radvd will be SIGHUPed when the network is brought up, so if
it is configured properly, it will begin giving out addresses on the
network via IPv6 autoconf (presumably on the 2001:4978:2ac::/28
network, although that's completely dependent on the radvd config.


NB: As previously discussed, we are making the assumptions that

  1) nobody will want to use dhcp6 (although it's available, autoconf
     via radvd is the more accepted method of automatically getting an
     address).

  2) any tftp booting required can be done with the IPv4 facilities
     already in place (ie, if that is needed, the guests will use both
     IPv4 and IPv6). Likewise for any other configuration required that
     isn't covered by ipv6 autoconf.

  3) radvd configuration is outside the scope of libvirt, although
     libvirt can give it a kick now and then.

Configuring the IP addresses of the bridge
------------------------------------------

Currently, libvirt uses the SIOCSIFADDR ioctl to set the (single) ipv4
address of the bridge. This ioctl does not support IPv6. In order to
configure and IPv6 address (or more than one IPv4 address) we will
need to use netlink (ie libnl).

Unfortunately, libnl isn't available on all Linux platforms (libvirt's
virtual networks are only available on Linux), for example RHEL5 has
libnl, but it's an older version that is API-incompatible with the
version used by libvirt.

libvirt already uses libnl directly for macvtap support, and
indirectly for netcf (the iface-* commands), but both of those are
conditionally compiled. In order to continue supporting older
platforms, all this IPv6 stuff will need to be optional, and
conditional on the presence of the right libnl version. If libnl is
available, the default will be --with-ipv6, otherwise, the default
will be --without-ipv6.

Also, src/network/bridge_driver.c:networkDisableIPV6, which tweaks
some kernel tunables to disallow adding IPv6 addresses to a bridge, is
currently called for all networks' bridges when they are brought
up. This will of course now be called only if the network has no IPv6
config.


iptables/ip6tables
------------------

The ip6tables rules setup for the bridge will be similar to those we
already setup for ipv4. See Bug 586124 for a short script that creates
a workable set of rules.

"mode=nat" anomoly
------------------

libvirt's virtual networks have three modes: isolated, routed, and
nat. If mode=isolated or mode=routed, IPv6 and IPv4 will be handled
the same. However, since there is no NAT for IPv6, if you specify
mode='nat' on a network, and give it an IPv6 address, the IPv6 traffic
will be routed, while IPv4 traffic will be NATed. (Since there is a
single mode attribute for the entire network, it will not be possible
to specify isolated IPv6 and routed/nat IPv4, or isolated IPv4 and
routed IPv6).




More information about the libvir-list mailing list