[libvirt] [PATCH 3/4] virsh-domain: update attach-interface to support type=hostdev

Pavel Hrdina phrdina at redhat.com
Wed Oct 21 12:22:44 UTC 2015


Adding this feature will allow users to easily attach a hostdev network
interface using PCI passthrough.

The interface can be attached using --type=hostdev and PCI address or
network device name as --source.  This command also allows you to tell,
whether the interface should be managed and to choose a assignment
driver.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=997561

Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
---
 tools/virsh-domain.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 86 insertions(+), 4 deletions(-)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index e8503ec..b124441 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -56,6 +56,7 @@
 #include "virtime.h"
 #include "virtypedparam.h"
 #include "virxml.h"
+#include "virsh-nodedev.h"
 
 /* Gnulib doesn't guarantee SA_SIGINFO support.  */
 #ifndef SA_SIGINFO
@@ -866,6 +867,14 @@ static const vshCmdOptDef opts_attach_interface[] = {
      .type = VSH_OT_BOOL,
      .help = N_("print XML document rather than attach the interface")
     },
+    {.name = "managed",
+     .type = VSH_OT_BOOL,
+     .help = N_("set the interface to be managed by libvirt")
+    },
+    {.name = "driver",
+     .type = VSH_OT_STRING,
+     .help = N_("set driver for hostdev interface, default is 'kvm'")
+    },
     {.name = NULL}
 };
 
@@ -919,7 +928,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
     virDomainPtr dom = NULL;
     const char *mac = NULL, *target = NULL, *script = NULL,
                *type = NULL, *source = NULL, *model = NULL,
-               *inboundStr = NULL, *outboundStr = NULL;
+               *inboundStr = NULL, *outboundStr = NULL, *driver = NULL;
     virNetDevBandwidthRate inbound, outbound;
     virDomainNetType typ;
     int ret;
@@ -931,6 +940,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
     bool config = vshCommandOptBool(cmd, "config");
     bool live = vshCommandOptBool(cmd, "live");
     bool persistent = vshCommandOptBool(cmd, "persistent");
+    bool managed = vshCommandOptBool(cmd, "managed");
 
     VSH_EXCLUSIVE_OPTIONS_VAR(persistent, current);
 
@@ -949,7 +959,8 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
         vshCommandOptStringReq(ctl, cmd, "script", &script) < 0 ||
         vshCommandOptStringReq(ctl, cmd, "model", &model) < 0 ||
         vshCommandOptStringReq(ctl, cmd, "inbound", &inboundStr) < 0 ||
-        vshCommandOptStringReq(ctl, cmd, "outbound", &outboundStr) < 0)
+        vshCommandOptStringReq(ctl, cmd, "outbound", &outboundStr) < 0 ||
+        vshCommandOptStringReq(ctl, cmd, "driver", &driver) < 0)
         goto cleanup;
 
     /* check interface type */
@@ -982,8 +993,23 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
         }
     }
 
+    if (typ != VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        if (managed) {
+            vshError(ctl, _("--managed is usable only with --type=hostdev"));
+            goto cleanup;
+        }
+        if (driver) {
+            vshError(ctl, _("--driver is usable only with --type=hostdev"));
+            goto cleanup;
+        }
+    }
+
     /* Make XML of interface */
-    virBufferAsprintf(&buf, "<interface type='%s'>\n", type);
+    virBufferAsprintf(&buf, "<interface type='%s'", type);
+    if (managed)
+        virBufferAddLit(&buf, " managed='yes'>\n");
+    else
+        virBufferAddLit(&buf, ">\n");
     virBufferAdjustIndent(&buf, 2);
 
     switch (typ) {
@@ -995,6 +1021,63 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
     case VIR_DOMAIN_NET_TYPE_DIRECT:
         virBufferAsprintf(&buf, "<source dev='%s'/>\n", source);
         break;
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    {
+        struct PCIAddress pciAddr = {0, 0, 0, 0};
+
+        if (str2PCIAddress(source, &pciAddr) < 0) {
+            const char *caps[] = {"net"};
+            char *tmpName = NULL;
+            virshNodeDeviceListPtr list = NULL;
+            virNodeDevicePtr netDev = NULL;
+            size_t i;
+
+            list = virshNodeDeviceListCollect(ctl, (char **)caps, 1,
+                                              VIR_CONNECT_LIST_NODE_DEVICES_CAP_NET);
+
+            if (!list) {
+                vshError(ctl, _("cannot list network devices"));
+                goto cleanup;
+            }
+
+            if (virAsprintf(&tmpName, "net_%s", source) < 0)
+                goto cleanup;
+
+            for (i = 0; i < list->ndevices; i++) {
+                if (STREQLEN(tmpName, virNodeDeviceGetName(list->devices[i]),
+                             strlen(tmpName)))
+                    netDev = list->devices[i];
+            }
+            VIR_FREE(tmpName);
+
+            if (!netDev) {
+                vshError(ctl, _("network interface '%s' doesn't exist"),
+                         source);
+                goto cleanup;
+            }
+
+            if (str2PCIAddress(virNodeDeviceGetParent(netDev)+4, &pciAddr) < 0) {
+                virshNodeDeviceListFree(list);
+                vshError(ctl, _("cannot parse pci address for network "
+                                "interface '%s'"), source);
+                goto cleanup;
+            }
+
+            virshNodeDeviceListFree(list);
+        }
+        if (driver)
+            virBufferAsprintf(&buf, "<driver name='%s'/>\n", driver);
+
+        virBufferAddLit(&buf, "<source>\n");
+        virBufferAdjustIndent(&buf, 2);
+        virBufferAsprintf(&buf, "<address type='pci' domain='0x%.4x'"
+                          " bus='0x%.2x' slot='0x%.2x' function='0x%.1x'/>\n",
+                          pciAddr.domain, pciAddr.bus,
+                          pciAddr.slot, pciAddr.function);
+        virBufferAdjustIndent(&buf, -2);
+        virBufferAddLit(&buf, "</source>\n");
+        break;
+    }
 
     case VIR_DOMAIN_NET_TYPE_USER:
     case VIR_DOMAIN_NET_TYPE_ETHERNET:
@@ -1004,7 +1087,6 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
     case VIR_DOMAIN_NET_TYPE_MCAST:
     case VIR_DOMAIN_NET_TYPE_UDP:
     case VIR_DOMAIN_NET_TYPE_INTERNAL:
-    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
     case VIR_DOMAIN_NET_TYPE_LAST:
         vshError(ctl, _("No support for %s in command 'attach-interface'"),
                  type);
-- 
2.6.2




More information about the libvir-list mailing list