mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 07:17:44 +00:00
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
This commit is contained in:
parent
315baab944
commit
a1b1ab1478
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user