[libvirt] [PATCH v3 0/2] BSD implementation of virNetDevTapCreate() and virNetDevTapDelete()

Changes from v2: * changed error message in virNetDevSetupControl() as per Dan's suggestion * avoid compile time signature change for virNetDevSetupControl() * fixed memleak in virNetDevTapCreate() Roman Bogorodskiy (2): Make virNetDevSetupControl() public. BSD: implement virNetDevTapCreate() and virNetDevTapDelete() src/libvirt_private.syms | 1 + src/util/virnetdev.c | 15 +++++- src/util/virnetdev.h | 15 +++++- src/util/virnetdevtap.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 144 insertions(+), 5 deletions(-) -- 1.8.0

This method is useful not only in virnetdev.c. --- src/libvirt_private.syms | 1 + src/util/virnetdev.c | 15 +++++++++++++-- src/util/virnetdev.h | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b93629f..bd5c010 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1530,6 +1530,7 @@ virNetDevSetMTUFromDevice; virNetDevSetName; virNetDevSetNamespace; virNetDevSetOnline; +virNetDevSetupControl; virNetDevValidateConfig; diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 1a22126..f6b7e12 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -88,11 +88,22 @@ static int virNetDevSetupControlFull(const char *ifname, } -static int virNetDevSetupControl(const char *ifname, - struct ifreq *ifr) +int +virNetDevSetupControl(const char *ifname, + struct ifreq *ifr) { return virNetDevSetupControlFull(ifname, ifr, VIR_NETDEV_FAMILY, SOCK_DGRAM); } +#else +int +virNetDevSetupControl(const char *ifname ATTRIBUTE_UNUSED, + void *ifr ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, + _("Network device configuration is not supported " + "on this platform")); + return -1; +} #endif diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index bc0777c..fb5091d 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2012 Red Hat, Inc. + * Copyright (C) 2007-2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,11 +23,24 @@ #ifndef __VIR_NETDEV_H__ # define __VIR_NETDEV_H__ +# include <config.h> +# include <net/if.h> + # include "virsocketaddr.h" # include "virnetlink.h" # include "virmacaddr.h" # include "virpci.h" +# ifdef HAVE_STRUCT_IFREQ +typedef struct ifreq virIfreq; +# else +struct virIfreq { }; +# endif + +int virNetDevSetupControl(const char *ifname, + virIfreq *ifr) + ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + int virNetDevExists(const char *brname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -- 1.8.0

Implementation uses SIOCIFCREATE2 and SIOCIFDESTROY ioctls. --- src/util/virnetdevtap.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c index bb4b3ba..265676c 100644 --- a/src/util/virnetdevtap.c +++ b/src/util/virnetdevtap.c @@ -275,7 +275,121 @@ cleanup: VIR_FORCE_CLOSE(fd); return ret; } -#else /* ! TUNSETIFF */ +#elif defined(SIOCIFCREATE2) && defined(SIOCIFDESTROY) +int virNetDevTapCreate(char **ifname, + int *tapfd, + int tapfdSize, + unsigned int flags ATTRIBUTE_UNUSED) +{ + int s; + struct ifreq ifr; + int ret = -1; + char *newifname = NULL; + + if (tapfdSize > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Multiqueue devices are not supported on this system")); + goto cleanup; + } + + /* As FreeBSD determines interface type by name, + * we have to create 'tap' interface first and + * then rename it to 'vnet' + */ + if ((s = virNetDevSetupControl("tap", &ifr)) < 0) + return -1; + + if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) { + virReportSystemError(errno, "%s", + _("Unable to create tap device")); + goto cleanup; + } + + /* In case we were given exact interface name (e.g. 'vnetN'), + * we just rename to it. If we have format string like + * 'vnet%d', we need to find the first available name that + * matches this pattern + */ + if (strstr(*ifname, "%d") != NULL) { + int i; + for (i = 0; i <= IF_MAXUNIT; i++) { + char *newname; + if (virAsprintf(&newname, *ifname, i) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virNetDevExists(newname) == 0) { + newifname = newname; + break; + } + + VIR_FREE(newname); + } + if (newifname) { + VIR_FREE(*ifname); + *ifname = newifname; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to generate new name for interface %s"), + ifr.ifr_name); + goto cleanup; + } + } + + if (tapfd) { + char *dev_path = NULL; + if (virAsprintf(&dev_path, "/dev/%s", ifr.ifr_name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((*tapfd = open(dev_path, O_RDWR)) < 0) { + virReportSystemError(errno, + _("Unable to open %s"), + dev_path); + VIR_FREE(dev_path); + goto cleanup; + } + + VIR_FREE(dev_path); + } + + if (virNetDevSetName(ifr.ifr_name, *ifname) == -1) { + goto cleanup; + } + + + ret = 0; +cleanup: + VIR_FORCE_CLOSE(s); + + return ret; +} + +int virNetDevTapDelete(const char *ifname) +{ + int s; + struct ifreq ifr; + int ret = -1; + + if ((s = virNetDevSetupControl(ifname, &ifr)) < 0) + return -1; + + if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) { + virReportSystemError(errno, + _("Unable to remove tap device %s"), + ifname); + goto cleanup; + } + + ret = 0; +cleanup: + VIR_FORCE_CLOSE(s); + return ret; +} + +#else int virNetDevTapCreate(char **ifname ATTRIBUTE_UNUSED, int *tapfd ATTRIBUTE_UNUSED, int tapfdSize ATTRIBUTE_UNUSED, @@ -291,7 +405,7 @@ int virNetDevTapDelete(const char *ifname ATTRIBUTE_UNUSED) _("Unable to delete TAP devices on this platform")); return -1; } -#endif /* ! TUNSETIFF */ +#endif /** -- 1.8.0

Roman Bogorodskiy wrote:
Changes from v2:
* changed error message in virNetDevSetupControl() as per Dan's suggestion * avoid compile time signature change for virNetDevSetupControl() * fixed memleak in virNetDevTapCreate()
I forgot to mention I dropped net/if.h usage part. Eric, do you want me to submit this patch as well or you could commit it yourself?
Roman Bogorodskiy (2): Make virNetDevSetupControl() public. BSD: implement virNetDevTapCreate() and virNetDevTapDelete()
src/libvirt_private.syms | 1 + src/util/virnetdev.c | 15 +++++- src/util/virnetdev.h | 15 +++++- src/util/virnetdevtap.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 144 insertions(+), 5 deletions(-)
-- 1.8.0
Roman Bogorodskiy
participants (1)
-
Roman Bogorodskiy