[libvirt] [Patch v3 2/3] Add -netdev bridge support

rmarwah at linux.vnet.ibm.com rmarwah at linux.vnet.ibm.com
Fri Aug 3 20:33:06 UTC 2012


From: Richa Marwaha <rmarwah at linux.vnet.ibm.com>

This patch adds the support to run the QEMU network helper
under unprivileged user. It also adds the support for
attach-interface option in virsh to run under unprivileged
user.

Signed-off-by: Richa Marwaha <rmarwah at linux.vnet.ibm.com>
Signed-off-by: Corey Bryant<coreyb at linux.vnet.ibm.com>
---
 src/qemu/qemu_command.c |   57 ++++++++++++++++++++++++++++++++++------------
 src/qemu/qemu_command.h |    2 +
 src/qemu/qemu_hotplug.c |   31 +++++++++++++++++--------
 3 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6ad65a6..83b3d30 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2964,6 +2964,8 @@ error:
 
 char *
 qemuBuildHostNetStr(virDomainNetDefPtr net,
+                    struct qemud_driver *driver,
+                    virBitmapPtr qemuCaps,
                     char type_sep,
                     int vlan,
                     const char *tapfd,
@@ -2972,6 +2974,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
     bool is_tap = false;
     virBuffer buf = VIR_BUFFER_INITIALIZER;
     enum virDomainNetType netType = virDomainNetGetActualType(net);
+    const char *brname = NULL;
 
     if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -2981,8 +2984,21 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
     }
 
     switch (netType) {
-    case VIR_DOMAIN_NET_TYPE_NETWORK:
+    /*
+     * If type='bridge', and we're running as privileged user
+     * or -netdev bridge is not supported then it will fall
+     * through, -net tap,fd
+     */
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
+        if (!driver->privileged &&
+            qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV_BRIDGE)) {
+            brname = virDomainNetGetActualBridgeName(net);
+            virBufferAsprintf(&buf, "bridge%cbr=%s", type_sep, brname);
+            type_sep = ',';
+            is_tap = true;
+            break;
+        }
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
     case VIR_DOMAIN_NET_TYPE_DIRECT:
         virBufferAsprintf(&buf, "tap%cfd=%s", type_sep, tapfd);
         type_sep = ',';
@@ -5125,7 +5141,7 @@ qemuBuildCommandLine(virConnectPtr conn,
         for (i = 0 ; i < def->nnets ; i++) {
             virDomainNetDefPtr net = def->nets[i];
             char *nic, *host;
-            char tapfd_name[50];
+            char tapfd_name[50] = "";
             char vhostfd_name[50] = "";
             int vlan;
             int bootindex = bootNet;
@@ -5162,17 +5178,26 @@ qemuBuildCommandLine(virConnectPtr conn,
 
             if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
                 actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
-                int tapfd = qemuNetworkIfaceConnect(def, conn, driver, net,
-                                                    qemuCaps);
-                if (tapfd < 0)
-                    goto error;
+                /*
+                 * If type='bridge' then we attempt to allocate the tap fd here only if
+                 * running under a privilged user or -netdev bridge option is not
+                 * supported.
+                 */
+                if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
+                    driver->privileged ||
+                    (!qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV_BRIDGE))) {
+                    int tapfd = qemuNetworkIfaceConnect(def, conn, driver, net,
+                                                        qemuCaps);
+                    if (tapfd < 0)
+                        goto error;
 
-                last_good_net = i;
-                virCommandTransferFD(cmd, tapfd);
+                    last_good_net = i;
+                    virCommandTransferFD(cmd, tapfd);
 
-                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
-                             tapfd) >= sizeof(tapfd_name))
-                    goto no_memory;
+                    if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
+                                 tapfd) >= sizeof(tapfd_name))
+                        goto no_memory;
+                }
             } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
                 int tapfd = qemuPhysIfaceConnect(def, driver, net,
                                                  qemuCaps, vmop);
@@ -5215,8 +5240,9 @@ qemuBuildCommandLine(virConnectPtr conn,
             if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
                 qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
                 virCommandAddArg(cmd, "-netdev");
-                if (!(host = qemuBuildHostNetStr(net, ',', vlan,
-                                                 tapfd_name, vhostfd_name)))
+                if (!(host = qemuBuildHostNetStr(net, driver, qemuCaps,
+                                                 ',', vlan, tapfd_name,
+                                                 vhostfd_name)))
                     goto error;
                 virCommandAddArg(cmd, host);
                 VIR_FREE(host);
@@ -5238,8 +5264,9 @@ qemuBuildCommandLine(virConnectPtr conn,
             if (!(qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
                   qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE))) {
                 virCommandAddArg(cmd, "-net");
-                if (!(host = qemuBuildHostNetStr(net, ',', vlan,
-                                                 tapfd_name, vhostfd_name)))
+                if (!(host = qemuBuildHostNetStr(net, driver, qemuCaps,
+                                                 ',', vlan, tapfd_name,
+                                                 vhostfd_name)))
                     goto error;
                 virCommandAddArg(cmd, host);
                 VIR_FREE(host);
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 3ccf4d7..946a7ac 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -62,6 +62,8 @@ qemuBuildChrDeviceStr (virDomainChrDefPtr serial,
 
 /* With vlan == -1, use netdev syntax, else old hostnet */
 char * qemuBuildHostNetStr(virDomainNetDefPtr net,
+                           struct qemud_driver *driver,
+                           virBitmapPtr qemuCaps,
                            char type_sep,
                            int vlan,
                            const char *tapfd,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 71ec484..e128e58 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -695,12 +695,21 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
 
     if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
         actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
-        if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net,
-                                             priv->qemuCaps)) < 0)
-            goto cleanup;
-        iface_connected = true;
-        if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
-            goto cleanup;
+        /*
+         * If type=bridge then we attempt to allocate the tap fd here only if
+         * running under a privilged user or -netdev bridge option is not
+         * supported.
+         */
+        if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
+            driver->privileged ||
+            (!qemuCapsGet (priv->qemuCaps, QEMU_CAPS_NETDEV_BRIDGE))) {
+            if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net,
+                                                 priv->qemuCaps)) < 0)
+                goto cleanup;
+            iface_connected = true;
+            if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
+                goto cleanup;
+        }
     } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
         if ((tapfd = qemuPhysIfaceConnect(vm->def, driver, net,
                                           priv->qemuCaps,
@@ -748,12 +757,14 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
 
     if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) &&
         qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
-        if (!(netstr = qemuBuildHostNetStr(net, ',',
-                                           -1, tapfd_name, vhostfd_name)))
+        if (!(netstr = qemuBuildHostNetStr(net, driver, priv->qemuCaps,
+                                           ',', -1, tapfd_name,
+                                           vhostfd_name)))
             goto cleanup;
     } else {
-        if (!(netstr = qemuBuildHostNetStr(net, ' ',
-                                           vlan, tapfd_name, vhostfd_name)))
+        if (!(netstr = qemuBuildHostNetStr(net, driver, priv->qemuCaps,
+                                           ' ', vlan, tapfd_name,
+                                           vhostfd_name)))
             goto cleanup;
     }
 
-- 
1.7.1




More information about the libvir-list mailing list