提交 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 @@ ...@@ -52,6 +52,7 @@
#include "nodeinfo.h" #include "nodeinfo.h"
#include "logging.h" #include "logging.h"
#include "network.h" #include "network.h"
#include "macvtap.h"
#include "cpu/cpu.h" #include "cpu/cpu.h"
#define VIR_FROM_THIS VIR_FROM_QEMU #define VIR_FROM_THIS VIR_FROM_QEMU
...@@ -1420,6 +1421,53 @@ int qemudExtractVersion(struct qemud_driver *driver) { ...@@ -1420,6 +1421,53 @@ int qemudExtractVersion(struct qemud_driver *driver) {
return 0; 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 int
qemudNetworkIfaceConnect(virConnectPtr conn, qemudNetworkIfaceConnect(virConnectPtr conn,
...@@ -2515,6 +2563,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, ...@@ -2515,6 +2563,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
switch (net->type) { switch (net->type) {
case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_NETWORK:
case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_DIRECT:
virBufferAddLit(&buf, "tap"); virBufferAddLit(&buf, "tap");
virBufferVSprintf(&buf, "%cfd=%s", type_sep, tapfd); virBufferVSprintf(&buf, "%cfd=%s", type_sep, tapfd);
type_sep = ','; type_sep = ',';
...@@ -3630,6 +3679,22 @@ int qemudBuildCommandLine(virConnectPtr conn, ...@@ -3630,6 +3679,22 @@ int qemudBuildCommandLine(virConnectPtr conn,
(*tapfds)[(*ntapfds)++] = tapfd; (*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)) if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
goto no_memory; goto no_memory;
} }
......
...@@ -247,6 +247,11 @@ int qemudNetworkIfaceConnect (virConnectPtr conn, ...@@ -247,6 +247,11 @@ int qemudNetworkIfaceConnect (virConnectPtr conn,
unsigned long long qemuCmdFlags) unsigned long long qemuCmdFlags)
ATTRIBUTE_NONNULL(1); ATTRIBUTE_NONNULL(1);
int qemudPhysIfaceConnect(virConnectPtr conn,
virDomainNetDefPtr net,
char *linkdev,
int brmode);
int qemudProbeMachineTypes (const char *binary, int qemudProbeMachineTypes (const char *binary,
virCapsGuestMachinePtr **machines, virCapsGuestMachinePtr **machines,
int *nmachines); int *nmachines);
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
#include "libvirt_internal.h" #include "libvirt_internal.h"
#include "xml.h" #include "xml.h"
#include "cpu/cpu.h" #include "cpu/cpu.h"
#include "macvtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU #define VIR_FROM_THIS VIR_FROM_QEMU
...@@ -2903,6 +2904,8 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver, ...@@ -2903,6 +2904,8 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
int retries = 0; int retries = 0;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virErrorPtr orig_err; virErrorPtr orig_err;
virDomainDefPtr def;
int i;
if (!virDomainObjIsActive(vm)) if (!virDomainObjIsActive(vm))
return; return;
...@@ -2914,8 +2917,7 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver, ...@@ -2914,8 +2917,7 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
orig_err = virSaveLastError(); orig_err = virSaveLastError();
if (driver->macFilter) { if (driver->macFilter) {
int i; def = vm->def;
virDomainDefPtr def = vm->def;
for (i = 0 ; i < def->nnets ; i++) { for (i = 0 ; i < def->nnets ; i++) {
virDomainNetDefPtr net = def->nets[i]; virDomainNetDefPtr net = def->nets[i];
if (net->ifname == NULL) if (net->ifname == NULL)
...@@ -2929,6 +2931,17 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver, ...@@ -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 && if (virKillProcess(vm->pid, 0) == 0 &&
virKillProcess(vm->pid, SIGTERM) < 0) virKillProcess(vm->pid, SIGTERM) < 0)
virReportSystemError(errno, virReportSystemError(errno,
...@@ -5708,6 +5721,19 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, ...@@ -5708,6 +5721,19 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
if ((tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags)) < 0) if ((tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags)) < 0)
return -1; 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) if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0)
...@@ -6326,6 +6352,13 @@ qemudDomainDetachNetDevice(struct qemud_driver *driver, ...@@ -6326,6 +6352,13 @@ qemudDomainDetachNetDevice(struct qemud_driver *driver,
} }
qemuDomainObjExitMonitorWithDriver(driver, vm); 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 ((driver->macFilter) && (detach->ifname != NULL)) {
if ((errno = networkDisallowMacOnPort(driver, if ((errno = networkDisallowMacOnPort(driver,
detach->ifname, detach->ifname,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册