[libvirt] [PATCH v3 2/2] qemu: Automaticly create tap device for VIR_DOMAIN_NET_TYPE_ETHERNET

Michal Privoznik mprivozn at redhat.com
Fri Dec 5 11:12:46 UTC 2014


From: Vasiliy Tolstov <v.tolstov at selfip.ru>

If a user doesn't specify script in network type ethernet, assume
that he/she needs a simple tap device created by libvirt. This
commit does not need to run external script to create tap device
or add root to qemu process. Moreover, some functions need to be
mocked now for qemuxml2argvtest, e.g. virNetDevTapCreate() or
virNetDevSetOnline().

Signed-off-by: Vasiliy Tolstov <v.tolstov at selfip.ru>
Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_command.c                            | 86 ++++++++++++++--------
 src/qemu/qemu_hotplug.c                            | 10 +--
 src/qemu/qemu_process.c                            |  4 +
 .../qemuxml2argv-graphics-spice-timeout.args       |  2 +-
 .../qemuxml2argv-net-eth-names.args                |  7 +-
 tests/qemuxml2argvdata/qemuxml2argv-net-eth.args   |  4 +-
 tests/qemuxml2argvmock.c                           | 28 +++++++
 7 files changed, 97 insertions(+), 44 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1831323..0d29d3f 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -313,7 +313,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
     } else if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
         if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0)
             return ret;
-    } else {
+    } else if (actualType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Network type %d is not supported"),
                        virDomainNetGetActualType(net));
@@ -335,30 +335,40 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
         tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
     }
 
-    if (cfg->privileged) {
-        if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac,
-                                           def->uuid, tunpath, tapfd, *tapfdSize,
-                                           virDomainNetGetActualVirtPortProfile(net),
-                                           virDomainNetGetActualVlan(net),
-                                           tap_create_flags) < 0) {
+    if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
+        if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, *tapfdSize,
+                               tap_create_flags) < 0) {
             virDomainAuditNetDevice(def, net, tunpath, false);
             goto cleanup;
         }
+        if (virNetDevSetOnline(net->ifname, !!(tap_create_flags & VIR_NETDEV_TAP_CREATE_IFUP)) < 0)
+            goto cleanup;
     } else {
-        if (qemuCreateInBridgePortWithHelper(cfg, brname,
-                                             &net->ifname,
-                                             tapfd, tap_create_flags) < 0) {
-            virDomainAuditNetDevice(def, net, tunpath, false);
-            goto cleanup;
+        if (cfg->privileged) {
+            if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac,
+                                               def->uuid, tunpath, tapfd, *tapfdSize,
+                                               virDomainNetGetActualVirtPortProfile(net),
+                                               virDomainNetGetActualVlan(net),
+                                               tap_create_flags) < 0) {
+                virDomainAuditNetDevice(def, net, tunpath, false);
+                goto cleanup;
+            }
+        } else {
+            if (qemuCreateInBridgePortWithHelper(cfg, brname,
+                                                 &net->ifname,
+                                                 tapfd, tap_create_flags) < 0) {
+                virDomainAuditNetDevice(def, net, tunpath, false);
+                goto cleanup;
+            }
+            /* qemuCreateInBridgePortWithHelper can only create a single FD */
+            if (*tapfdSize > 1) {
+                VIR_WARN("Ignoring multiqueue network request");
+                *tapfdSize = 1;
+            }
         }
-        /* qemuCreateInBridgePortWithHelper can only create a single FD */
-        if (*tapfdSize > 1) {
-            VIR_WARN("Ignoring multiqueue network request");
-            *tapfdSize = 1;
-        }
-    }
 
-    virDomainAuditNetDevice(def, net, tunpath, true);
+        virDomainAuditNetDevice(def, net, tunpath, true);
+    }
 
     if (cfg->macFilter &&
         ebtablesAddForwardAllowIn(driver->ebtables,
@@ -4534,18 +4544,32 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
         break;
 
     case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        virBufferAddLit(&buf, "tap");
+      virBufferAddLit(&buf, "tap");
+      type_sep = ',';
+      if (net->script) {
         if (net->ifname) {
-            virBufferAsprintf(&buf, "%cifname=%s", type_sep, net->ifname);
-            type_sep = ',';
+          virBufferAsprintf(&buf, "%cifname=%s", type_sep, net->ifname);
+          type_sep = ',';
         }
-        if (net->script) {
-            virBufferAsprintf(&buf, "%cscript=%s", type_sep,
-                              net->script);
-            type_sep = ',';
+        virBufferAsprintf(&buf, "%cscript=%s", type_sep, net->script);
+        type_sep = ',';
+      } else {
+        /* for one tapfd 'fd=' shall be used,
+         * for more than one 'fds=' is the right choice */
+        if (tapfdSize == 1) {
+          virBufferAsprintf(&buf, "%cfd=%s", type_sep, tapfd[0]);
+        } else {
+          virBufferAsprintf(&buf, "%cfds=", type_sep);
+          for (i = 0; i < tapfdSize; i++) {
+            if (i)
+              virBufferAddChar(&buf, ':');
+            virBufferAdd(&buf, tapfd[i], -1);
+          }
         }
-        is_tap = true;
-        break;
+        type_sep = ',';
+      }
+      is_tap = true;
+      break;
 
     case VIR_DOMAIN_NET_TYPE_CLIENT:
        virBufferAsprintf(&buf, "socket%cconnect=%s:%d",
@@ -7366,7 +7390,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
     /* Currently nothing besides TAP devices supports multiqueue. */
     if (net->driver.virtio.queues > 0 &&
         !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
-          actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) {
+          actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+          actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Multiqueue network is not supported for: %s"),
                        virDomainNetTypeToString(actualType));
@@ -7374,7 +7399,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
     }
 
     if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
-        actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+        actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+        actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
         tapfdSize = net->driver.virtio.queues;
         if (!tapfdSize)
             tapfdSize = 1;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 9467d7d..1175259 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -908,7 +908,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
     }
 
     if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
-        actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
+        actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
+        actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
         tapfdSize = vhostfdSize = net->driver.virtio.queues;
         if (!tapfdSize)
             tapfdSize = vhostfdSize = 1;
@@ -939,13 +940,6 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
         iface_connected = true;
         if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0)
             goto cleanup;
-    } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
-        vhostfdSize = 1;
-        if (VIR_ALLOC(vhostfd) < 0)
-            goto cleanup;
-        *vhostfd = -1;
-        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0)
-            goto cleanup;
     }
 
     /* Set Bandwidth */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index a14b6f7..0dbf7fb 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5064,6 +5064,10 @@ void qemuProcessStop(virQEMUDriverPtr driver,
                              cfg->stateDir));
             VIR_FREE(net->ifname);
             break;
+        case VIR_DOMAIN_NET_TYPE_ETHERNET:
+          ignore_value(virNetDevTapDelete(net->ifname, net->backend.tap));
+          VIR_FREE(net->ifname);
+          break;
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
         case VIR_DOMAIN_NET_TYPE_NETWORK:
 #ifdef VIR_NETDEV_TAP_REQUIRE_MANUAL_CLEANUP
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.args
index 8b5d9ee..a5f1486 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.args
@@ -10,7 +10,7 @@ id=virtio-disk0 \
 media=cdrom,id=drive-ide0-1-0 \
 -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
 -device rtl8139,vlan=0,id=net0,mac=52:54:00:71:70:89,bus=pci.0,addr=0x7 \
--net tap,script=/etc/qemu-ifup,vlan=0,name=hostnet0 -serial pty \
+-net tap,ifname=vnet0,script=/etc/qemu-ifup,vlan=0,name=hostnet0 -serial pty \
 -device usb-tablet,id=input0 \
 -spice port=5900 -vga std \
 -device AC97,id=sound0,bus=pci.0,addr=0x3 \
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-eth-names.args b/tests/qemuxml2argvdata/qemuxml2argv-net-eth-names.args
index 6146e84..643b313 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-eth-names.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-eth-names.args
@@ -2,7 +2,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
 /usr/bin/qemu -S -M \
 pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
 -no-acpi -boot c -usb -hda /dev/HostVG/QEMUGuest1 -net nic,\
-macaddr=00:11:22:33:44:55,vlan=0,model=rtl8139,name=net0 -net tap,\
-script=/etc/qemu-ifup,vlan=0,name=hostnet0 -net nic,macaddr=00:11:22:33:44:56,\
-vlan=1,model=e1000,name=net1 -net tap,script=/etc/qemu-ifup,vlan=1,name=hostnet1 \
+macaddr=00:11:22:33:44:55,vlan=0,model=rtl8139,name=net0 \
+-net tap,ifname=vnet0,script=/etc/qemu-ifup,vlan=0,name=hostnet0 \
+-net nic,macaddr=00:11:22:33:44:56,vlan=1,model=e1000,name=net1 \
+-net tap,ifname=vnet0,script=/etc/qemu-ifup,vlan=1,name=hostnet1 \
 -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-eth.args b/tests/qemuxml2argvdata/qemuxml2argv-net-eth.args
index 28a094b..7a75850 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-eth.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-eth.args
@@ -2,5 +2,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
 /usr/bin/qemu -S -M \
 pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
 -no-acpi -boot c -usb -hda /dev/HostVG/QEMUGuest1 -net nic,\
-macaddr=00:11:22:33:44:55,vlan=0,model=rtl8139 -net tap,script=/etc/qemu-ifup,\
-vlan=0 -serial none -parallel none
+macaddr=00:11:22:33:44:55,vlan=0,model=rtl8139 \
+-net tap,ifname=vnet0,script=/etc/qemu-ifup,vlan=0 -serial none -parallel none
diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c
index eccf4b0..2d63659 100644
--- a/tests/qemuxml2argvmock.c
+++ b/tests/qemuxml2argvmock.c
@@ -23,6 +23,11 @@
 #include "internal.h"
 #include "virnuma.h"
 #include <time.h>
+#include "virnetdevtap.h"
+#include "virstring.h"
+#include "virnetdev.h"
+
+#define VIR_FROM_THIS VIR_FROM_QEMU
 
 time_t time(time_t *t)
 {
@@ -51,3 +56,26 @@ virNumaNodeIsAvailable(int node)
     return node >= 0 && node <= virNumaGetMaxNode();
 }
 #endif /* WITH_NUMACTL && HAVE_NUMA_BITMASK_ISBITSET */
+
+int virNetDevTapCreate(char **ifname,
+                       const char *tunpath ATTRIBUTE_UNUSED,
+                       int *tapfd,
+                       int tapfdSize,
+                       unsigned int fakeflags ATTRIBUTE_UNUSED)
+{
+    size_t i;
+
+    if (virAsprintf(ifname, *ifname, 0) < 0)
+        return -1;
+
+    for (i = 0; i < tapfdSize; i++)
+        tapfd[i] = i + STDERR_FILENO + 1;
+
+    return 0;
+}
+
+int virNetDevSetOnline(const char *ifname ATTRIBUTE_UNUSED,
+                       bool online ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
-- 
2.0.4




More information about the libvir-list mailing list