mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
macvtap IFF_VNET_HDR configuration
This patch sets or unsets the IFF_VNET_HDR flag depending on what device is used in the VM. The manipulation of the flag is done in the open function and is only fatal if the IFF_VNET_HDR flag could not be cleared although it has to be (or if an ioctl generally fails). In that case the macvtap tap is closed again and the macvtap interface torn. * src/qemu/qemu_conf.c src/qemu/qemu_conf.h: pass qemuCmdFlags to qemudPhysIfaceConnect() * src/util/macvtap.c src/util/macvtap.h: add vnet_hdr boolean to openMacvtapTap(), and private function configMacvtapTap() * src/qemu/qemu_driver.c: add extra qemuCmdFlags when calling qemudPhysIfaceConnect()
This commit is contained in:
parent
61497d958e
commit
e52687e88f
@ -1434,14 +1434,20 @@ int
|
||||
qemudPhysIfaceConnect(virConnectPtr conn,
|
||||
virDomainNetDefPtr net,
|
||||
char *linkdev,
|
||||
int brmode)
|
||||
int brmode,
|
||||
unsigned long long qemuCmdFlags)
|
||||
{
|
||||
int rc;
|
||||
#if WITH_MACVTAP
|
||||
char *res_ifname = NULL;
|
||||
int vnet_hdr = 0;
|
||||
|
||||
if (qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HDR &&
|
||||
net->model && STREQ(net->model, "virtio"))
|
||||
vnet_hdr = 1;
|
||||
|
||||
rc = openMacvtapTap(conn, net->ifname, net->mac, linkdev, brmode,
|
||||
&res_ifname);
|
||||
&res_ifname, vnet_hdr);
|
||||
if (rc >= 0) {
|
||||
VIR_FREE(net->ifname);
|
||||
net->ifname = res_ifname;
|
||||
@ -1451,6 +1457,7 @@ qemudPhysIfaceConnect(virConnectPtr conn,
|
||||
(void)net;
|
||||
(void)linkdev;
|
||||
(void)brmode;
|
||||
(void)qemuCmdFlags;
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("No support for macvtap device"));
|
||||
rc = -1;
|
||||
@ -3752,7 +3759,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
||||
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
int tapfd = qemudPhysIfaceConnect(conn, net,
|
||||
net->data.direct.linkdev,
|
||||
net->data.direct.mode);
|
||||
net->data.direct.mode,
|
||||
qemuCmdFlags);
|
||||
if (tapfd < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -253,7 +253,8 @@ int qemudNetworkIfaceConnect (virConnectPtr conn,
|
||||
int qemudPhysIfaceConnect(virConnectPtr conn,
|
||||
virDomainNetDefPtr net,
|
||||
char *linkdev,
|
||||
int brmode);
|
||||
int brmode,
|
||||
unsigned long long qemuCmdFlags);
|
||||
|
||||
int qemudProbeMachineTypes (const char *binary,
|
||||
virCapsGuestMachinePtr **machines,
|
||||
|
@ -5725,7 +5725,8 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
|
||||
|
||||
if ((tapfd = qemudPhysIfaceConnect(conn, net,
|
||||
net->data.direct.linkdev,
|
||||
net->data.direct.mode)) < 0)
|
||||
net->data.direct.mode,
|
||||
qemuCmdFlags)) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -614,6 +614,64 @@ macvtapModeFromInt(enum virDomainNetdevMacvtapType mode)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* configMacvtapTap:
|
||||
* @tapfd: file descriptor of the macvtap tap
|
||||
* @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
|
||||
*
|
||||
* Returns 0 on success, -1 in case of fatal error, error code otherwise.
|
||||
*
|
||||
* Turn the IFF_VNET_HDR flag, if requested and available, make sure
|
||||
* it's off in the other cases.
|
||||
* A fatal error is defined as the VNET_HDR flag being set but it cannot
|
||||
* be turned off for some reason. This is reported with -1. Other fatal
|
||||
* error is not being able to read the interface flags. In that case the
|
||||
* macvtap device should not be used.
|
||||
*/
|
||||
static int
|
||||
configMacvtapTap(int tapfd, int vnet_hdr)
|
||||
{
|
||||
unsigned int features;
|
||||
struct ifreq ifreq;
|
||||
short new_flags = 0;
|
||||
int rc_on_fail = 0;
|
||||
const char *errmsg = NULL;
|
||||
|
||||
memset(&ifreq, 0, sizeof(ifreq));
|
||||
|
||||
if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("cannot get interface flags on macvtap tap"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_flags = ifreq.ifr_flags;
|
||||
|
||||
if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) {
|
||||
new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR;
|
||||
rc_on_fail = -1;
|
||||
errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap");
|
||||
} else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) {
|
||||
if (ioctl(tapfd, TUNGETFEATURES, &features) != 0)
|
||||
return errno;
|
||||
if ((features & IFF_VNET_HDR)) {
|
||||
new_flags = ifreq.ifr_flags | IFF_VNET_HDR;
|
||||
errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap");
|
||||
}
|
||||
}
|
||||
|
||||
if (new_flags != ifreq.ifr_flags) {
|
||||
ifreq.ifr_flags = new_flags;
|
||||
if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) {
|
||||
virReportSystemError(errno, "%s", errmsg);
|
||||
return rc_on_fail;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* openMacvtapTap:
|
||||
* Create an instance of a macvtap device and open its tap character
|
||||
@ -640,7 +698,8 @@ openMacvtapTap(virConnectPtr conn,
|
||||
const unsigned char *macaddress,
|
||||
const char *linkdev,
|
||||
int mode,
|
||||
char **res_ifname)
|
||||
char **res_ifname,
|
||||
int vnet_hdr)
|
||||
{
|
||||
const char *type = "macvtap";
|
||||
int c, rc;
|
||||
@ -699,9 +758,14 @@ create_name:
|
||||
|
||||
rc = openTap(cr_ifname, 10);
|
||||
|
||||
if (rc >= 0)
|
||||
if (rc >= 0) {
|
||||
if (configMacvtapTap(rc, vnet_hdr) < 0) {
|
||||
close(rc);
|
||||
rc = -1;
|
||||
goto link_del_exit;
|
||||
}
|
||||
*res_ifname = strdup(cr_ifname);
|
||||
else
|
||||
} else
|
||||
goto link_del_exit;
|
||||
|
||||
return rc;
|
||||
|
@ -33,9 +33,10 @@ int openMacvtapTap(virConnectPtr conn,
|
||||
const unsigned char *macaddress,
|
||||
const char *linkdev,
|
||||
int mode,
|
||||
char **res_ifname);
|
||||
char **res_ifname,
|
||||
int vnet_hdr);
|
||||
|
||||
void delMacvtap(const char *name);
|
||||
void delMacvtap(const char *ifname);
|
||||
|
||||
#endif /* WITH_MACVTAP */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user