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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list