util: set vlan tag for macvtap passthrough mode on SRIOV VFs

SRIOV VFs used in macvtap passthrough mode can take advantage of the
SRIOV card's transparent vlan tagging. All the code was there to set
the vlan tag, and it has been used for SRIOV VFs used for hostdev
interfaces for several years, but for some reason, the vlan tag for
macvtap passthrough devices was stubbed out with a -1.

This patch moves a bit of common validation down to a lower level
(virNetDevReplaceNetConfig()) so it is shared by hostdev and macvtap
modes, and updates the macvtap caller to actually send the vlan config
instead of -1.
This commit is contained in:
Laine Stump 2016-05-04 13:18:16 -04:00
parent cd25acba26
commit 75db9997a0
10 changed files with 121 additions and 80 deletions

View File

@ -4032,7 +4032,7 @@
<p>
On Linux systems, the bridge device is normally a standard Linux
host bridge. On hosts that support Open vSwitch, it is also
possible to connect to an open vSwitch bridge device by adding
possible to connect to an Open vSwitch bridge device by adding
a <code>&lt;virtualport type='openvswitch'/&gt;</code> to the
interface definition. (<span class="since">Since
0.9.11</span>). The Open vSwitch type virtualport accepts two
@ -4816,34 +4816,46 @@ qemu-kvm -net nic,model=? /dev/null
<p>
If (and only if) the network connection used by the guest
supports vlan tagging transparent to the guest, an
supports VLAN tagging transparent to the guest, an
optional <code>&lt;vlan&gt;</code> element can specify one or
more vlan tags to apply to the guest's network
traffic <span class="since">Since 0.10.0</span>. (openvswitch
and type='hostdev' SR-IOV interfaces do support transparent vlan
tagging of guest traffic; everything else, including standard
more VLAN tags to apply to the guest's network
traffic <span class="since">Since 0.10.0</span>. Network
connections that support guest-transparent VLAN tagging include
1) type='bridge' interfaces connected to an Open vSwitch bridge
<span class="since">Since 0.10.0</span>, 2) SRIOV Virtual
Functions (VF) used via type='hostdev' (direct device
assignment) <span class="since">Since 0.10.0</span>, and 3)
SRIOV VFs used via type='direct' with mode='passthrough'
(macvtap "passthru" mode) <span class="since">Since
1.3.4</span>. All other connection types, including standard
linux bridges and libvirt's own virtual networks, <b>do not</b>
support it. 802.1Qbh (vn-link) and 802.1Qbg (VEPA) switches
provide their own way (outside of libvirt) to tag guest traffic
onto specific vlans.) To allow for specification of multiple
tags (in the case of vlan trunking), a
subelement, <code>&lt;tag&gt;</code>, specifies which vlan tag
to use (for example: <code>&lt;tag id='42'/&gt;</code>. If an
interface has more than one <code>&lt;vlan&gt;</code> element
defined, it is assumed that the user wants to do VLAN trunking
using all the specified tags. In the case that vlan trunking
with a single tag is desired, the optional
onto a specific VLAN. Each tag is given in a
separate <code>&lt;tag&gt;</code> subelement
of <code>&lt;vlan&gt;</code> (for example: <code>&lt;tag
id='42'/&gt;</code>). For VLAN trunking of multiple tags (which
is supported only on Open vSwitch connections),
multiple <code>&lt;tag&gt;</code> subelements can be specified,
which implies that the user wants to do VLAN trunking on the
interface for all the specified tags. In the case that VLAN
trunking of a single tag is desired, the optional
attribute <code>trunk='yes'</code> can be added to the toplevel
vlan element.
<code>&lt;vlan&gt;</code> element to differentiate trunking of a
single tag from normal tagging.
</p>
<p>
For network connections using openvswitch it is possible to
configure the 'native-tagged' and 'native-untagged' vlan modes
<span class="since">Since 1.1.0.</span> This uses the optional
<code>nativeMode</code> attribute on the <code>&lt;tag&gt;</code>
element: <code>nativeMode</code> may be set to 'tagged' or
'untagged'. The id attribute of the element sets the native vlan.
For network connections using Open vSwitch it is also possible
to configure 'native-tagged' and 'native-untagged' VLAN modes
<span class="since">Since 1.1.0.</span> This is done with the
optional <code>nativeMode</code> attribute on
the <code>&lt;tag&gt;</code> subelement: <code>nativeMode</code>
may be set to 'tagged' or 'untagged'. The <code>id</code>
attribute of the <code>&lt;tag&gt;</code> subelement
containing <code>nativeMode</code> sets which VLAN is considered
to be the "native" VLAN for this interface, and
the <code>nativeMode</code> attribute determines whether or not
traffic for that VLAN will be tagged.
</p>
<h5><a name="elementLink">Modifying virtual link state</a></h5>

View File

@ -608,31 +608,47 @@
</pre>
<p>
If (and only if) the network type supports vlan tagging
transparent to the guest, an optional <code>&lt;vlan&gt;</code>
element can specify one or more vlan tags to apply to the
traffic of all guests using this
network <span class="since">Since 0.10.0</span>. (openvswitch
and type='hostdev' SR-IOV networks do support transparent vlan
tagging of guest traffic; everything else, including standard
If (and only if) the network connection used by the guest
supports VLAN tagging transparent to the guest, an
optional <code>&lt;vlan&gt;</code> element can specify one or
more VLAN tags to apply to the guest's network
traffic <span class="since">Since 0.10.0</span>. Network
connections that support guest-transparent VLAN tagging include
1) type='bridge' interfaces connected to an Open vSwitch bridge
<span class="since">Since 0.10.0</span>, 2) SRIOV Virtual
Functions (VF) used via type='hostdev' (direct device
assignment) <span class="since">Since 0.10.0</span>, and 3)
SRIOV VFs used via type='direct' with mode='passthrough'
(macvtap "passthru" mode) <span class="since">Since
1.3.4</span>. All other connection types, including standard
linux bridges and libvirt's own virtual networks, <b>do not</b>
support it. 802.1Qbh (vn-link) and 802.1Qbg (VEPA) switches
provide their own way (outside of libvirt) to tag guest traffic
onto specific vlans.) As expected, the <code>tag</code>
attribute specifies which vlan tag to use. If a network has more
than one <code>&lt;vlan&gt;</code> element defined, it is
assumed that the user wants to do VLAN trunking using all the
specified tags. In the case that vlan trunking with a single tag
is desired, the optional attribute <code>trunk='yes'</code> can
be added to the vlan element.
onto a specific VLAN. Each tag is given in a
separate <code>&lt;tag&gt;</code> subelement
of <code>&lt;vlan&gt;</code> (for example: <code>&lt;tag
id='42'/&gt;</code>). For VLAN trunking of multiple tags (which
is supported only on Open vSwitch connections),
multiple <code>&lt;tag&gt;</code> subelements can be specified,
which implies that the user wants to do VLAN trunking on the
interface for all the specified tags. In the case that VLAN
trunking of a single tag is desired, the optional
attribute <code>trunk='yes'</code> can be added to the toplevel
<code>&lt;vlan&gt;</code> element to differentiate trunking of a
single tag from normal tagging.
</p>
<p>
For network connections using openvswitch it is possible to
configure the 'native-tagged' and 'native-untagged' vlan modes
<span class="since">Since 1.1.0</span>. This uses the optional
<code>nativeMode</code> attribute on the <code>&lt;tag&gt;</code>
element: <code>nativeMode</code> may be set to 'tagged' or
'untagged'. The id attribute of the element sets the native vlan.
For network connections using Open vSwitch it is also possible
to configure 'native-tagged' and 'native-untagged' VLAN modes
<span class="since">Since 1.1.0.</span> This is done with the
optional <code>nativeMode</code> attribute on
the <code>&lt;tag&gt;</code> subelement: <code>nativeMode</code>
may be set to 'tagged' or 'untagged'. The <code>id</code>
attribute of the <code>&lt;tag&gt;</code> subelement
containing <code>nativeMode</code> sets which VLAN is considered
to be the "native" VLAN for this interface, and
the <code>nativeMode</code> attribute determines whether or not
traffic for that VLAN will be tagged.
</p>
<p>
<code>&lt;vlan&gt;</code> elements can also be specified in

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2015 Red Hat, Inc.
* Copyright (C) 2010-2016 Red Hat, Inc.
* Copyright IBM Corp. 2008
*
* lxc_process.c: LXC process lifecycle management
@ -343,6 +343,7 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
net->ifname, &net->mac,
linkdev,
virDomainNetGetActualDirectMode(net),
virDomainNetGetActualVlan(net),
def->uuid,
prof,
&res_ifname,

View File

@ -3057,11 +3057,12 @@ networkValidate(virNetworkDriverStatePtr driver,
* a pool, and those using an Open vSwitch bridge.
*/
vlanAllowed = ((def->forward.type == VIR_NETWORK_FORWARD_BRIDGE &&
vlanAllowed = (def->forward.type == VIR_NETWORK_FORWARD_HOSTDEV ||
def->forward.type == VIR_NETWORK_FORWARD_PASSTHROUGH ||
(def->forward.type == VIR_NETWORK_FORWARD_BRIDGE &&
def->virtPortProfile &&
def->virtPortProfile->virtPortType
== VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) ||
def->forward.type == VIR_NETWORK_FORWARD_HOSTDEV);
== VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH));
vlanUsed = def->vlan.nTags > 0;
for (i = 0; i < def->nPortGroups; i++) {
@ -4276,11 +4277,15 @@ networkAllocateActualDevice(virDomainDefPtr dom,
*/
if (virDomainNetGetActualVlan(iface)) {
/* vlan configuration via libvirt is only supported for
* PCI Passthrough SR-IOV devices and openvswitch bridges.
* otherwise log an error and fail
/* vlan configuration via libvirt is only supported for PCI
* Passthrough SR-IOV devices (hostdev or macvtap passthru
* mode) and openvswitch bridges. Otherwise log an error and
* fail
*/
if (!(actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
(actualType == VIR_DOMAIN_NET_TYPE_DIRECT &&
virDomainNetGetActualDirectMode(iface)
== VIR_NETDEV_MACVLAN_MODE_PASSTHRU) ||
(actualType == VIR_DOMAIN_NET_TYPE_BRIDGE &&
virtport && virtport->virtPortType
== VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH))) {

View File

@ -266,6 +266,7 @@ qemuInterfaceDirectConnect(virDomainDefPtr def,
&net->mac,
virDomainNetGetActualDirectDev(net),
virDomainNetGetActualDirectMode(net),
virDomainNetGetActualVlan(net),
def->uuid,
virDomainNetGetActualVirtPortProfile(net),
&res_ifname,

View File

@ -1,6 +1,6 @@
/* virhostdev.c: hostdev management
*
* Copyright (C) 2006-2007, 2009-2015 Red Hat, Inc.
* Copyright (C) 2006-2007, 2009-2016 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
* Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
*
@ -387,7 +387,6 @@ virHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
virNetDevVPortProfilePtr virtPort;
int ret = -1;
int vf = -1;
int vlanid = -1;
bool port_profile_associate = true;
if (virHostdevIsVirtualFunction(hostdev) != 1) {
@ -416,27 +415,9 @@ virHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
port_profile_associate);
} else {
/* Set only mac and vlan */
if (vlan) {
if (vlan->nTags != 1 || vlan->trunk) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("vlan trunking is not supported "
"by SR-IOV network devices"));
goto cleanup;
}
if (vf == -1) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("vlan can only be set for SR-IOV VFs, but "
"%s is not a VF"), linkdev);
goto cleanup;
}
vlanid = vlan->tag[0];
} else if (vf >= 0) {
vlanid = 0; /* assure any current vlan tag is reset */
}
ret = virNetDevReplaceNetConfig(linkdev, vf,
&hostdev->parent.data.net->mac,
vlanid, stateDir);
vlan, stateDir);
}
cleanup:
VIR_FREE(linkdev);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2015 Red Hat, Inc.
* Copyright (C) 2007-2016 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -2547,7 +2547,8 @@ virNetDevRestoreVfConfig(const char *pflinkdev,
*/
int
virNetDevReplaceNetConfig(const char *linkdev, int vf,
const virMacAddr *macaddress, int vlanid,
const virMacAddr *macaddress,
virNetDevVlanPtr vlan,
const char *stateDir)
{
int ret = -1;
@ -2566,11 +2567,29 @@ virNetDevReplaceNetConfig(const char *linkdev, int vf,
linkdev = pfdevname;
}
if (vf == -1)
if (vf == -1) {
if (vlan) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("vlan can only be set for SR-IOV VFs, but "
"%s is not a VF"), linkdev);
goto cleanup;
}
ret = virNetDevReplaceMacAddress(linkdev, macaddress, stateDir);
else
} else {
int vlanid = 0; /* assure any current vlan tag is reset */
if (vlan) {
if (vlan->nTags != 1 || vlan->trunk) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("vlan trunking is not supported "
"by SR-IOV network devices"));
goto cleanup;
}
vlanid = vlan->tag[0];
}
ret = virNetDevReplaceVfConfig(linkdev, vf, macaddress, vlanid,
stateDir);
}
cleanup:
VIR_FREE(pfdevname);
@ -2636,7 +2655,7 @@ int
virNetDevReplaceNetConfig(const char *linkdev ATTRIBUTE_UNUSED,
int vf ATTRIBUTE_UNUSED,
const virMacAddr *macaddress ATTRIBUTE_UNUSED,
int vlanid ATTRIBUTE_UNUSED,
virNetDevVlanPtr vlan ATTRIBUTE_UNUSED,
const char *stateDir ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2015 Red Hat, Inc.
* Copyright (C) 2007-2016 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -30,6 +30,7 @@
# include "virnetlink.h"
# include "virmacaddr.h"
# include "virpci.h"
# include "virnetdevvlan.h"
# include "device_conf.h"
# ifdef HAVE_STRUCT_IFREQ
@ -175,7 +176,8 @@ int virNetDevLinkDump(const char *ifname, int ifindex,
ATTRIBUTE_RETURN_CHECK;
int virNetDevReplaceNetConfig(const char *linkdev, int vf,
const virMacAddr *macaddress, int vlanid,
const virMacAddr *macaddress,
virNetDevVlanPtr vlan,
const char *stateDir)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(5);

View File

@ -975,6 +975,7 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
const virMacAddr *macaddress,
const char *linkdev,
virNetDevMacVLanMode mode,
virNetDevVlanPtr vlan,
const unsigned char *vmuuid,
virNetDevVPortProfilePtr virtPortProfile,
char **ifnameResult,
@ -1021,7 +1022,7 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
if (virNetDevReplaceMacAddress(linkdev, macaddress, stateDir) < 0)
return -1;
} else {
if (virNetDevReplaceNetConfig(linkdev, -1, macaddress, -1, stateDir) < 0)
if (virNetDevReplaceNetConfig(linkdev, -1, macaddress, vlan, stateDir) < 0)
return -1;
}
}
@ -1281,6 +1282,7 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED,
const virMacAddr *macaddress ATTRIBUTE_UNUSED,
const char *linkdev ATTRIBUTE_UNUSED,
virNetDevMacVLanMode mode ATTRIBUTE_UNUSED,
virNetDevVlanPtr vlan ATTRIBUTE_UNUSED,
const unsigned char *vmuuid ATTRIBUTE_UNUSED,
virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
char **res_ifname ATTRIBUTE_UNUSED,

View File

@ -28,6 +28,7 @@
# include "virsocketaddr.h"
# include "virnetdevbandwidth.h"
# include "virnetdevvportprofile.h"
# include "virnetdevvlan.h"
/* the mode type for macvtap devices */
typedef enum {
@ -69,6 +70,7 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *ifname,
const virMacAddr *macaddress,
const char *linkdev,
virNetDevMacVLanMode mode,
virNetDevVlanPtr vlan,
const unsigned char *vmuuid,
virNetDevVPortProfilePtr virtPortProfile,
char **res_ifname,
@ -77,8 +79,8 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *ifname,
int *tapfd,
size_t tapfdSize,
unsigned int flags)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(5)
ATTRIBUTE_NONNULL(7) ATTRIBUTE_NONNULL(9) ATTRIBUTE_RETURN_CHECK;
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6)
ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(10) ATTRIBUTE_RETURN_CHECK;
int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname,
const virMacAddr *macaddress,