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