提交 a1b1ab14 编写于 作者: S Stefan Berger 提交者: Daniel Veillard

macvtap support for libvirt -- qemu support

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.
* src/qemu/qemu_conf.[ch] src/qemu/qemu_driver.c: add support in the
  QEmu driver
上级 315baab9
......@@ -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
......@@ -1420,6 +1421,53 @@ int qemudExtractVersion(struct qemud_driver *driver) {
return 0;
}
/**
* qemudPhysIfaceConnect:
* @conn: pointer to virConnect object
* @net: pointer to he VM's interface description with direct device type
* @linkdev: The name of the physical interface to link the macvtap to
* @brmode: The mode to put the macvtap device into
*
* Returns a filedescriptor on success or -1 in case of error.
*/
int
qemudPhysIfaceConnect(virConnectPtr conn,
virDomainNetDefPtr net,
char *linkdev,
int brmode)
{
int rc;
#if WITH_MACVTAP
char *res_ifname = NULL;
int hasBusyDev = 0;
delMacvtapByMACAddress(net->mac, &hasBusyDev);
if (hasBusyDev) {
virReportSystemError(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)conn;
(void)net;
(void)linkdev;
(void)brmode;
(void)conn;
qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("No support for macvtap device"));
rc = -1;
#endif
return rc;
}
int
qemudNetworkIfaceConnect(virConnectPtr conn,
......@@ -2515,6 +2563,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
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 = ',';
......@@ -3630,6 +3679,22 @@ int qemudBuildCommandLine(virConnectPtr conn,
(*tapfds)[(*ntapfds)++] = tapfd;
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;
}
......
......@@ -247,6 +247,11 @@ int qemudNetworkIfaceConnect (virConnectPtr conn,
unsigned long long qemuCmdFlags)
ATTRIBUTE_NONNULL(1);
int qemudPhysIfaceConnect(virConnectPtr conn,
virDomainNetDefPtr net,
char *linkdev,
int brmode);
int qemudProbeMachineTypes (const char *binary,
virCapsGuestMachinePtr **machines,
int *nmachines);
......
......@@ -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
......@@ -2903,6 +2904,8 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
int retries = 0;
qemuDomainObjPrivatePtr priv = vm->privateData;
virErrorPtr orig_err;
virDomainDefPtr def;
int i;
if (!virDomainObjIsActive(vm))
return;
......@@ -2914,8 +2917,7 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
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)
......@@ -2929,6 +2931,17 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
}
}
#if 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(net->mac, &dummy);
}
}
#endif
if (virKillProcess(vm->pid, 0) == 0 &&
virKillProcess(vm->pid, SIGTERM) < 0)
virReportSystemError(errno,
......@@ -5708,6 +5721,19 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
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) {
qemuReportError(VIR_ERR_NO_SUPPORT,
_("network 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)
......@@ -6326,6 +6352,13 @@ qemudDomainDetachNetDevice(struct qemud_driver *driver,
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
#if WITH_MACVTAP
if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
int dummy;
delMacvtapByMACAddress(detach->mac, &dummy);
}
#endif
if ((driver->macFilter) && (detach->ifname != NULL)) {
if ((errno = networkDisallowMacOnPort(driver,
detach->ifname,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册