To ease mocking for bhyve unit tests move virBhyveTapGetRealDeviceName() out of bhyve_command.c to virnetdevtap and rename it to virNetDevTapGetRealDeviceName(). --- src/bhyve/bhyve_command.c | 74 +--------------------------------------- src/libvirt_private.syms | 1 + src/util/virnetdevtap.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdevtap.h | 3 ++ 4 files changed, 92 insertions(+), 73 deletions(-) diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index 42b71fb..3373cfc 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -21,10 +21,7 @@ #include <config.h> -#include <fcntl.h> #include <sys/types.h> -#include <dirent.h> -#include <sys/ioctl.h> #include <net/if.h> #include <net/if_tap.h> @@ -41,75 +38,6 @@ VIR_LOG_INIT("bhyve.bhyve_command"); -static char* -virBhyveTapGetRealDeviceName(char *name) -{ - /* This is an ugly hack, because if we rename - * tap device to vnet%d, its device name will be - * still /dev/tap%d, and bhyve tries to open /dev/tap%d, - * so we have to find the real name - */ - char *ret = NULL; - struct dirent *dp; - char *devpath = NULL; - int fd; - - DIR *dirp = opendir("/dev"); - if (dirp == NULL) { - virReportSystemError(errno, - _("Failed to opendir path '%s'"), - "/dev"); - return NULL; - } - - while ((dp = readdir(dirp)) != NULL) { - if (STRPREFIX(dp->d_name, "tap")) { - struct ifreq ifr; - if (virAsprintf(&devpath, "/dev/%s", dp->d_name) < 0) { - goto cleanup; - } - if ((fd = open(devpath, O_RDWR)) < 0) { - if (errno == EBUSY) { - VIR_FREE(devpath); - continue; - } - virReportSystemError(errno, _("Unable to open '%s'"), devpath); - goto cleanup; - } - - if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) { - virReportSystemError(errno, "%s", - _("Unable to query tap interface name")); - goto cleanup; - } - - if (STREQ(name, ifr.ifr_name)) { - /* we can ignore the return value - * because we still have nothing - * to do but return; - */ - ignore_value(VIR_STRDUP(ret, dp->d_name)); - goto cleanup; - } - - VIR_FREE(devpath); - VIR_FORCE_CLOSE(fd); - } - - errno = 0; - } - - if (errno != 0) - virReportSystemError(errno, "%s", - _("Unable to iterate over TAP devices")); - - cleanup: - VIR_FREE(devpath); - VIR_FORCE_CLOSE(fd); - closedir(dirp); - return ret; -} - static int bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd) { @@ -161,7 +89,7 @@ bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd) } } - realifname = virBhyveTapGetRealDeviceName(net->ifname); + realifname = virNetDevTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2357f95..38fbf63 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1584,6 +1584,7 @@ virNetDevTapCreate; virNetDevTapCreateInBridgePort; virNetDevTapDelete; virNetDevTapGetName; +virNetDevTapGetRealDeviceName; # util/virnetdevveth.h diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c index 32ad406..3072146 100644 --- a/src/util/virnetdevtap.c +++ b/src/util/virnetdevtap.c @@ -22,6 +22,9 @@ #include <config.h> +#include <sys/types.h> +#include <dirent.h> + #include "virmacaddr.h" #include "virnetdevtap.h" #include "virnetdev.h" @@ -38,8 +41,11 @@ #include <fcntl.h> #ifdef __linux__ # include <linux/if_tun.h> /* IFF_TUN, IFF_NO_PI */ +#elif defined(__FreeBSD__) +# include <net/if_tap.h> #endif + #define VIR_FROM_THIS VIR_FROM_NONE VIR_LOG_INIT("util.netdevtap"); @@ -72,6 +78,87 @@ virNetDevTapGetName(int tapfd ATTRIBUTE_UNUSED, char **ifname ATTRIBUTE_UNUSED) #endif } +/** + * virNetDevTapGetRealDeviceName: + * @ifname: the interface name + * + * Lookup real interface name (i.e. name of the device entry in /dev), + * because e.g. on FreeBSD if we rename tap device to vnetN its device + * entry still remains unchanged (/dev/tapX), but bhyve needs a name + * that matches /dev entry. + * + * Returns the proper interface name or NULL if no corresponding interface + * found. + */ +char* +virNetDevTapGetRealDeviceName(char *ifname ATTRIBUTE_UNUSED) +{ +#ifdef TAPGIFNAME + char *ret = NULL; + struct dirent *dp; + char *devpath = NULL; + int fd; + + DIR *dirp = opendir("/dev"); + if (dirp == NULL) { + virReportSystemError(errno, + _("Failed to opendir path '%s'"), + "/dev"); + return NULL; + } + + while ((dp = readdir(dirp)) != NULL) { + if (STRPREFIX(dp->d_name, "tap")) { + struct ifreq ifr; + if (virAsprintf(&devpath, "/dev/%s", dp->d_name) < 0) { + goto cleanup; + } + if ((fd = open(devpath, O_RDWR)) < 0) { + if (errno == EBUSY) { + VIR_FREE(devpath); + continue; + } + + virReportSystemError(errno, _("Unable to open '%s'"), devpath); + goto cleanup; + } + + if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) { + virReportSystemError(errno, "%s", + _("Unable to query tap interface name")); + goto cleanup; + } + + if (STREQ(ifname, ifr.ifr_name)) { + /* we can ignore the return value + * because we still have nothing + * to do but return; + */ + ignore_value(VIR_STRDUP(ret, dp->d_name)); + goto cleanup; + } + + VIR_FREE(devpath); + VIR_FORCE_CLOSE(fd); + } + + errno = 0; + } + + if (errno != 0) + virReportSystemError(errno, "%s", + _("Unable to iterate over TAP devices")); + + cleanup: + VIR_FREE(devpath); + VIR_FORCE_CLOSE(fd); + closedir(dirp); + return ret; +#else + return NULL; +#endif +} + /** * virNetDevProbeVnetHdr: diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h index 1e5bd19..03fb5f8 100644 --- a/src/util/virnetdevtap.h +++ b/src/util/virnetdevtap.h @@ -45,6 +45,9 @@ int virNetDevTapDelete(const char *ifname) int virNetDevTapGetName(int tapfd, char **ifname) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; +char* virNetDevTapGetRealDeviceName(char *ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + typedef enum { VIR_NETDEV_TAP_CREATE_NONE = 0, /* Bring the interface up */ -- 1.8.4.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list