[libvirt] [PATCH v2] Fix dnsmasq/radvd on bridges not being able to be bound to IPv6 address on "recent" kernels
Daniel P. Berrange
berrange at redhat.com
Wed Jun 20 13:27:20 UTC 2012
On Wed, Jun 20, 2012 at 01:49:30PM +0200, Benjamin Cama wrote:
> Le mercredi 20 juin 2012 à 11:05 +0100, Daniel P. Berrange a écrit :
> > I think you also need to have a VIR_FOFRCE_CLOSE(tapfd) in the
> > very last of the cleanup jump labels. Since between the time
> > we open the tapfd & close it, we might have done a 'goto err1'
> > or similar.
>
> Yes, I forgot that. New patch following.
>
> > Looks reasonable apart from the cleanup bug.
>
> Thanks. BTW, if this patch is commited, I'm already in AUTHORS under
> another email address, which is OK.
>
> ---
> src/network/bridge_driver.c | 22 ++++++++++++++++++++--
> src/uml/uml_conf.c | 2 +-
> src/util/virnetdevtap.c | 24 ++++++++++++++----------
> src/util/virnetdevtap.h | 2 ++
> 4 files changed, 37 insertions(+), 13 deletions(-)
>
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index 79d3010..e9f3c90 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -62,6 +62,7 @@
> #include "virnetdev.h"
> #include "virnetdevbridge.h"
> #include "virnetdevtap.h"
> +#include "virfile.h"
>
> #define NETWORK_PID_DIR LOCALSTATEDIR "/run/libvirt/network"
> #define NETWORK_STATE_DIR LOCALSTATEDIR "/lib/libvirt/network"
> @@ -840,6 +841,7 @@ networkStartRadvd(virNetworkObjPtr network)
> " AdvSendAdvert on;\n"
> " AdvManagedFlag off;\n"
> " AdvOtherConfigFlag off;\n"
> + " IgnoreIfMissing on;\n"
> "\n",
> network->def->bridge);
> for (ii = 0;
> @@ -1744,6 +1746,7 @@ networkStartNetworkVirtual(struct network_driver *driver,
> virErrorPtr save_err = NULL;
> virNetworkIpDefPtr ipdef;
> char *macTapIfName = NULL;
> + int tapfd = -1;
>
> /* Check to see if any network IP collides with an existing route */
> if (networkCheckRouteCollision(network) < 0)
> @@ -1765,10 +1768,13 @@ networkStartNetworkVirtual(struct network_driver *driver,
> virReportOOMError();
> goto err0;
> }
> + /* Keep tun fd open and interface up to allow for IPv6 DAD to happen */
> if (virNetDevTapCreateInBridgePort(network->def->bridge,
> &macTapIfName, network->def->mac,
> - NULL, NULL, NULL,
> - VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE) < 0) {
> + NULL, &tapfd, NULL,
> + VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE
> + |VIR_NETDEV_TAP_CREATE_IFUP
> + |VIR_NETDEV_TAP_CREATE_PERSIST) < 0) {
> VIR_FREE(macTapIfName);
> goto err0;
> }
> @@ -1828,6 +1834,16 @@ networkStartNetworkVirtual(struct network_driver *driver,
> if (v6present && networkStartRadvd(network) < 0)
> goto err4;
>
> + /* DAD has happened (dnsmasq waits for it), dnsmasq is now bound to the
> + * bridge's IPv6 address, and radvd to the interface, so we can now set the
> + * dummy tun down.
> + */
> + if (tapfd >= 0) {
> + if (virNetDevSetOnline(macTapIfName, false) < 0)
> + goto err4;
> + VIR_FORCE_CLOSE(tapfd);
> + }
> +
> if (virNetDevBandwidthSet(network->def->bridge, network->def->bandwidth) < 0) {
> networkReportError(VIR_ERR_INTERNAL_ERROR,
> _("cannot set bandwidth limits on %s"),
> @@ -1866,6 +1882,8 @@ networkStartNetworkVirtual(struct network_driver *driver,
> save_err = virSaveLastError();
>
> if (macTapIfName) {
> + if (tapfd >= 0)
> + VIR_FORCE_CLOSE(tapfd);
> ignore_value(virNetDevTapDelete(macTapIfName));
> VIR_FREE(macTapIfName);
> }
> diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
> index 79b249d..c9b5044 100644
> --- a/src/uml/uml_conf.c
> +++ b/src/uml/uml_conf.c
> @@ -141,7 +141,7 @@ umlConnectTapDevice(virConnectPtr conn,
> if (virNetDevTapCreateInBridgePort(bridge, &net->ifname, net->mac,
> vm->uuid, NULL,
> virDomainNetGetActualVirtPortProfile(net),
> - VIR_NETDEV_TAP_CREATE_IFUP) < 0) {
> + VIR_NETDEV_TAP_CREATE_IFUP|VIR_NETDEV_TAP_CREATE_PERSIST) < 0) {
> if (template_ifname)
> VIR_FREE(net->ifname);
> goto error;
> diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
> index 5d21164..45ff20f 100644
> --- a/src/util/virnetdevtap.c
> +++ b/src/util/virnetdevtap.c
> @@ -118,18 +118,20 @@ virNetDevProbeVnetHdr(int tapfd)
> *
> * VIR_NETDEV_TAP_CREATE_VNET_HDR
> * - Enable IFF_VNET_HDR on the tap device
> + * VIR_NETDEV_TAP_CREATE_PERSIST
> + * - The device will persist after the file descriptor is closed
> *
> * Creates a tap interface.
> - * If the @tapfd parameter is supplied, the open tap device file
> - * descriptor will be returned, otherwise the TAP device will be made
> - * persistent and closed. The caller must use virNetDevTapDelete to
> - * remove a persistent TAP devices when it is no longer needed.
> + * If the @tapfd parameter is supplied, the open tap device file descriptor
> + * will be returned, otherwise the TAP device will be closed. The caller must
> + * use virNetDevTapDelete to remove a persistent TAP device when it is no
> + * longer needed.
> *
> * Returns 0 in case of success or an errno code in case of failure.
> */
> int virNetDevTapCreate(char **ifname,
> int *tapfd,
> - unsigned int flags ATTRIBUTE_UNUSED)
> + unsigned int flags)
> {
> int fd;
> struct ifreq ifr;
> @@ -166,7 +168,7 @@ int virNetDevTapCreate(char **ifname,
> goto cleanup;
> }
>
> - if (!tapfd &&
> + if ((flags & VIR_NETDEV_TAP_CREATE_PERSIST) &&
> (errno = ioctl(fd, TUNSETPERSIST, 1))) {
> virReportSystemError(errno,
> _("Unable to set tap device %s to persistent"),
> @@ -267,14 +269,16 @@ int virNetDevTapDelete(const char *ifname ATTRIBUTE_UNUSED)
> * - Enable IFF_VNET_HDR on the tap device
> * VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE
> * - Set this interface's MAC as the bridge's MAC address
> + * VIR_NETDEV_TAP_CREATE_PERSIST
> + * - The device will persist after the file descriptor is closed
> *
> * This function creates a new tap device on a bridge. @ifname can be either
> * a fixed name or a name template with '%d' for dynamic name allocation.
> * in either case the final name for the bridge will be stored in @ifname.
> - * If the @tapfd parameter is supplied, the open tap device file
> - * descriptor will be returned, otherwise the TAP device will be made
> - * persistent and closed. The caller must use virNetDevTapDelete to remove
> - * a persistent TAP devices when it is no longer needed.
> + * If the @tapfd parameter is supplied, the open tap device file descriptor
> + * will be returned, otherwise the TAP device will be closed. The caller must
> + * use virNetDevTapDelete to remove a persistent TAP device when it is no
> + * longer needed.
> *
> * Returns 0 in case of success or -1 on failure
> */
> diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h
> index d9a3593..f1355ba 100644
> --- a/src/util/virnetdevtap.h
> +++ b/src/util/virnetdevtap.h
> @@ -42,6 +42,8 @@ typedef enum {
> VIR_NETDEV_TAP_CREATE_VNET_HDR = 1 << 1,
> /* Set this interface's MAC as the bridge's MAC address */
> VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE = 1 << 2,
> + /* The device will persist after the file descriptor is closed */
> + VIR_NETDEV_TAP_CREATE_PERSIST = 1 << 3,
> } virNetDevTapCreateFlags;
>
> int virNetDevTapCreateInBridgePort(const char *brname,
>
ACK
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list