On Mon, Feb 08, 2010 at 02:37:18PM -0500, Stefan Berger wrote:
This part adds support for qemu making a macvtap tap device
available
via file descriptor passed to qemu command line. This also attempts to
tear down the macvtap device when a VM terminates. This includes support
for attachment and detachment to/from running VM.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
Index: libvirt-macvtap/src/qemu/qemu_conf.c
===================================================================
--- libvirt-macvtap.orig/src/qemu/qemu_conf.c
+++ libvirt-macvtap/src/qemu/qemu_conf.c
@@ -52,6 +52,7 @@
#include "nodeinfo.h"
#include "logging.h"
#include "network.h"
+#include "macvtap.h"
#include "cpu/cpu.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1423,6 +1424,43 @@ int qemudExtractVersion(virConnectPtr co
int
+qemudPhysIfaceConnect(virConnectPtr conn,
+ virDomainNetDefPtr net,
+ char *linkdev,
+ int brmode)
+{
+ int rc;
+#if defined(WITH_MACVTAP)
+ char *res_ifname = NULL;
+ int hasBusyDev = 0;
+
+ delMacvtapByMACAddress(conn, net->mac, &hasBusyDev);
+
+ if (hasBusyDev) {
+ virReportSystemError(NULL, errno, "%s",
+ _("A macvtap with the same MAC address is in
use"));
+ return -1;
+ }
+
+ rc = openMacvtapTap(conn, net->ifname, net->mac, linkdev, brmode,
+ &res_ifname);
+ if (rc > 0) {
+ VIR_FREE(net->ifname);
+ net->ifname = res_ifname;
+ }
+#else
+ (void)net;
+ (void)linkdev;
+ (void)brmode;
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No support for macvtap device"));
+ rc = -1;
+#endif
+ return rc;
+}
+
+
+int
qemudNetworkIfaceConnect(virConnectPtr conn,
struct qemud_driver *driver,
virDomainNetDefPtr net,
@@ -2520,6 +2558,7 @@ qemuBuildHostNetStr(virConnectPtr conn,
switch (net->type) {
case VIR_DOMAIN_NET_TYPE_NETWORK:
case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
virBufferAddLit(&buf, "tap");
virBufferVSprintf(&buf, "%cfd=%s", type_sep, tapfd);
type_sep = ',';
@@ -3636,6 +3675,22 @@ int qemudBuildCommandLine(virConnectPtr
if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd)
>= sizeof(tapfd_name))
goto no_memory;
+ } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ int tapfd = qemudPhysIfaceConnect(conn, net,
+ net->data.direct.linkdev,
+ net->data.direct.mode);
+ if (tapfd < 0)
+ goto error;
+
+ if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) {
+ close(tapfd);
+ goto no_memory;
+ }
+
+ (*tapfds)[(*ntapfds)++] = tapfd;
+
+ if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd)
>= sizeof(tapfd_name))
+ goto no_memory;
}
/* Possible combinations:
Index: libvirt-macvtap/src/qemu/qemu_driver.c
===================================================================
--- libvirt-macvtap.orig/src/qemu/qemu_driver.c
+++ libvirt-macvtap/src/qemu/qemu_driver.c
@@ -75,6 +75,7 @@
#include "libvirt_internal.h"
#include "xml.h"
#include "cpu/cpu.h"
+#include "macvtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -2825,6 +2826,8 @@ static void qemudShutdownVMDaemon(virCon
int retries = 0;
qemuDomainObjPrivatePtr priv = vm->privateData;
virErrorPtr orig_err;
+ virDomainDefPtr def;
+ int i;
if (!virDomainObjIsActive(vm))
return;
@@ -2836,8 +2839,7 @@ static void qemudShutdownVMDaemon(virCon
orig_err = virSaveLastError();
if (driver->macFilter) {
- int i;
- virDomainDefPtr def = vm->def;
+ def = vm->def;
for (i = 0 ; i < def->nnets ; i++) {
virDomainNetDefPtr net = def->nets[i];
if (net->ifname == NULL)
@@ -2851,6 +2853,17 @@ static void qemudShutdownVMDaemon(virCon
}
}
+#if defined(WITH_MACVTAP)
+ def = vm->def;
+ for (i = 0; i < def->nnets; i++) {
+ virDomainNetDefPtr net = def->nets[i];
+ if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ int dummy;
+ delMacvtapByMACAddress(conn, net->mac, &dummy);
+ }
+ }
+#endif
+
if (virKillProcess(vm->pid, 0) == 0 &&
virKillProcess(vm->pid, SIGTERM) < 0)
virReportSystemError(conn, errno,
@@ -5629,6 +5642,19 @@ static int qemudDomainAttachNetDevice(vi
if ((tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags)) < 0)
return -1;
+ } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+ _("direct device type '%s' cannot be attached:
"
+ "qemu is not using a unix socket monitor"),
+ virDomainNetTypeToString(net->type));
+ return -1;
+ }
+
+ if ((tapfd = qemudPhysIfaceConnect(conn, net,
+ net->data.direct.linkdev,
+ net->data.direct.mode)) < 0)
+ return -1;
}
if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0)
@@ -6242,6 +6268,11 @@ qemudDomainDetachNetDevice(virConnectPtr
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
+ if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ int dummy;
+ delMacvtapByMACAddress(conn, detach->mac, &dummy);
+ }
+
if ((driver->macFilter) && (detach->ifname != NULL)) {
if ((errno = networkDisallowMacOnPort(conn,
driver,
Index: libvirt-macvtap/src/qemu/qemu_conf.h
===================================================================
--- libvirt-macvtap.orig/src/qemu/qemu_conf.h
+++ libvirt-macvtap/src/qemu/qemu_conf.h
@@ -247,6 +247,11 @@ int qemudNetworkIfaceConnect
virDomainNetDefPtr net,
int qemuCmdFlags);
+int qemudPhysIfaceConnect(virConnectPtr conn,
+ virDomainNetDefPtr net,
+ char *linkdev,
+ int brmode);
+
int qemudProbeMachineTypes (const char *binary,
virCapsGuestMachinePtr **machines,
int *nmachines);
ACK
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|