Signed-off-by: Shi Lei <shilei.massclouds(a)gmx.com>
---
src/conf/network_conf.c | 12 ++++---
src/conf/network_conf.h | 1 +
src/network/bridge_driver.c | 80 +++++++++++++++++++++++++++++++++++++++++----
3 files changed, 82 insertions(+), 11 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 630a87f..6e1de6c 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -50,7 +50,7 @@ VIR_ENUM_IMPL(virNetworkForward,
VIR_NETWORK_FORWARD_LAST,
"none", "nat", "route", "open",
"bridge", "private", "vepa",
"passthrough",
- "hostdev")
+ "hostdev", "vlan")
VIR_ENUM_IMPL(virNetworkBridgeMACTableManager,
VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LAST,
@@ -1876,6 +1876,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
*/
switch (def->forward.type) {
case VIR_NETWORK_FORWARD_NONE:
+ case VIR_NETWORK_FORWARD_VLAN:
break;
case VIR_NETWORK_FORWARD_ROUTE:
@@ -1963,9 +1964,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
(def->forward.type != VIR_NETWORK_FORWARD_NONE &&
def->forward.type != VIR_NETWORK_FORWARD_NAT &&
def->forward.type != VIR_NETWORK_FORWARD_ROUTE &&
- def->forward.type != VIR_NETWORK_FORWARD_OPEN)) {
+ def->forward.type != VIR_NETWORK_FORWARD_OPEN &&
+ def->forward.type != VIR_NETWORK_FORWARD_VLAN)) {
virReportError(VIR_ERR_XML_ERROR,
- _("mtu size only allowed in open, route, nat, "
+ _("mtu size only allowed in open, route, nat, vlan "
"and isolated mode, not in %s (network
'%s')"),
virNetworkForwardTypeToString(def->forward.type),
def->name);
@@ -2474,6 +2476,7 @@ virNetworkDefFormatBuf(virBufferPtr buf,
def->forward.type == VIR_NETWORK_FORWARD_NAT ||
def->forward.type == VIR_NETWORK_FORWARD_ROUTE ||
def->forward.type == VIR_NETWORK_FORWARD_OPEN ||
+ def->forward.type == VIR_NETWORK_FORWARD_VLAN ||
def->bridge || def->macTableManager) {
virBufferAddLit(buf, "<bridge");
@@ -2481,7 +2484,8 @@ virNetworkDefFormatBuf(virBufferPtr buf,
if (def->forward.type == VIR_NETWORK_FORWARD_NONE ||
def->forward.type == VIR_NETWORK_FORWARD_NAT ||
def->forward.type == VIR_NETWORK_FORWARD_ROUTE ||
- def->forward.type == VIR_NETWORK_FORWARD_OPEN) {
+ def->forward.type == VIR_NETWORK_FORWARD_OPEN ||
+ def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
virBufferAsprintf(buf, " stp='%s' delay='%ld'",
def->stp ? "on" : "off",
def->delay);
}
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 54c8ed1..47bb83e 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -53,6 +53,7 @@ typedef enum {
VIR_NETWORK_FORWARD_VEPA,
VIR_NETWORK_FORWARD_PASSTHROUGH,
VIR_NETWORK_FORWARD_HOSTDEV,
+ VIR_NETWORK_FORWARD_VLAN,
VIR_NETWORK_FORWARD_LAST,
} virNetworkForwardType;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index da3c32e..314f78c 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -451,6 +451,7 @@ networkUpdateState(virNetworkObjPtr obj,
case VIR_NETWORK_FORWARD_NAT:
case VIR_NETWORK_FORWARD_ROUTE:
case VIR_NETWORK_FORWARD_OPEN:
+ case VIR_NETWORK_FORWARD_VLAN:
/* If bridge doesn't exist, then mark it inactive */
if (!(def->bridge && virNetDevExists(def->bridge) == 1))
virNetworkObjSetActive(obj, false);
@@ -2092,7 +2093,8 @@ networkRefreshDaemonsHelper(virNetworkObjPtr obj,
((def->forward.type == VIR_NETWORK_FORWARD_NONE) ||
(def->forward.type == VIR_NETWORK_FORWARD_NAT) ||
(def->forward.type == VIR_NETWORK_FORWARD_ROUTE) ||
- (def->forward.type == VIR_NETWORK_FORWARD_OPEN))) {
+ (def->forward.type == VIR_NETWORK_FORWARD_OPEN) ||
+ (def->forward.type == VIR_NETWORK_FORWARD_VLAN))) {
/* Only the three L3 network types that are configured by
* libvirt will have a dnsmasq or radvd daemon associated
* with them. Here we send a SIGHUP to an existing
@@ -2131,7 +2133,8 @@ networkReloadFirewallRulesHelper(virNetworkObjPtr obj,
if (virNetworkObjIsActive(obj) &&
((def->forward.type == VIR_NETWORK_FORWARD_NONE) ||
(def->forward.type == VIR_NETWORK_FORWARD_NAT) ||
- (def->forward.type == VIR_NETWORK_FORWARD_ROUTE))) {
+ (def->forward.type == VIR_NETWORK_FORWARD_ROUTE) ||
+ (def->forward.type == VIR_NETWORK_FORWARD_VLAN))) {
/* Only three of the L3 network types that are configured by
* libvirt need to have iptables rules reloaded. The 4th L3
* network type, forward='open', doesn't need this because it
@@ -2513,6 +2516,27 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver,
if (virNetDevBandwidthSet(def->bridge, def->bandwidth, true, true) < 0)
goto err5;
+ if (def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
+ char vlanDevName[IFNAMSIZ];
+ /* ifs[0].device.dev and vlan.tag[0] have been validated in networkValidate() */
+ if (virNetDevCreateVLanDev(def->forward.ifs[0].device.dev,
def->vlan.tag[0],
+ vlanDevName, sizeof(vlanDevName)) < 0)
+ goto err5;
+
+ if (virNetDevBridgeAddPort(def->bridge, vlanDevName) < 0) {
+ ignore_value(virNetDevDestroyVLanDev(def->forward.ifs[0].device.dev,
+ def->vlan.tag[0]));
+ goto err5;
+ }
+
+ if (virNetDevSetOnline(vlanDevName, true) < 0) {
+ ignore_value(virNetDevBridgeRemovePort(def->bridge, vlanDevName));
+ ignore_value(virNetDevDestroyVLanDev(def->forward.ifs[0].device.dev,
+ def->vlan.tag[0]));
+ goto err5;
+ }
+ }
+
VIR_FREE(macTapIfName);
VIR_FREE(macMapFile);
@@ -2576,6 +2600,18 @@ networkShutdownNetworkVirtual(virNetworkDriverStatePtr driver,
pid_t radvdPid;
pid_t dnsmasqPid;
+ if (def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
+ char vlanDevName[IFNAMSIZ];
+ ignore_value(virNetDevGetVLanDevName(def->forward.ifs[0].device.dev,
+ def->vlan.tag[0],
+ vlanDevName, sizeof(vlanDevName)));
+
+ ignore_value(virNetDevSetOnline(vlanDevName, false));
+ ignore_value(virNetDevBridgeRemovePort(def->bridge, vlanDevName));
+ ignore_value(virNetDevDestroyVLanDev(def->forward.ifs[0].device.dev,
+ def->vlan.tag[0]));
+ }
+
if (def->bandwidth)
virNetDevBandwidthClear(def->bridge);
@@ -2719,6 +2755,7 @@ networkCreateInterfacePool(virNetworkDefPtr netdef)
case VIR_NETWORK_FORWARD_NAT:
case VIR_NETWORK_FORWARD_ROUTE:
case VIR_NETWORK_FORWARD_OPEN:
+ case VIR_NETWORK_FORWARD_VLAN:
case VIR_NETWORK_FORWARD_LAST:
/* by definition these will never be encountered here */
break;
@@ -2817,6 +2854,7 @@ networkStartNetwork(virNetworkDriverStatePtr driver,
case VIR_NETWORK_FORWARD_NAT:
case VIR_NETWORK_FORWARD_ROUTE:
case VIR_NETWORK_FORWARD_OPEN:
+ case VIR_NETWORK_FORWARD_VLAN:
if (networkStartNetworkVirtual(driver, obj) < 0)
goto cleanup;
break;
@@ -2899,6 +2937,7 @@ networkShutdownNetwork(virNetworkDriverStatePtr driver,
case VIR_NETWORK_FORWARD_NAT:
case VIR_NETWORK_FORWARD_ROUTE:
case VIR_NETWORK_FORWARD_OPEN:
+ case VIR_NETWORK_FORWARD_VLAN:
ret = networkShutdownNetworkVirtual(driver, obj);
break;
@@ -3276,7 +3315,8 @@ networkValidate(virNetworkDriverStatePtr driver,
if (def->forward.type == VIR_NETWORK_FORWARD_NONE ||
def->forward.type == VIR_NETWORK_FORWARD_NAT ||
def->forward.type == VIR_NETWORK_FORWARD_ROUTE ||
- def->forward.type == VIR_NETWORK_FORWARD_OPEN) {
+ def->forward.type == VIR_NETWORK_FORWARD_OPEN ||
+ def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
/* if no bridge name was given in the config, find a name
* unused by any other libvirt networks and assign it.
@@ -3447,7 +3487,8 @@ networkValidate(virNetworkDriverStatePtr driver,
* a pool, and those using an Open vSwitch bridge.
*/
- vlanAllowed = (def->forward.type == VIR_NETWORK_FORWARD_HOSTDEV ||
+ vlanAllowed = (def->forward.type == VIR_NETWORK_FORWARD_VLAN ||
+ def->forward.type == VIR_NETWORK_FORWARD_HOSTDEV ||
def->forward.type == VIR_NETWORK_FORWARD_PASSTHROUGH ||
(def->forward.type == VIR_NETWORK_FORWARD_BRIDGE &&
def->virtPortProfile &&
@@ -3530,6 +3571,28 @@ networkValidate(virNetworkDriverStatePtr driver,
}
}
}
+
+ if (def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
+ if (virNetDevLoad8021Q() < 0)
+ return -1;
+
+ if (def->forward.nifs != 1 ||
+ strlen(def->forward.ifs[0].device.dev) == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("invalid dev in <forward mode='vlan'
dev='xxx'> "
+ "of network '%s' with forward
mode='%s'"),
+ def->name,
virNetworkForwardTypeToString(def->forward.type));
+ return -1;
+ }
+ if (def->vlan.nTags != 1 || def->vlan.tag[0] >= 4096) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported vlan config. check <vlan><tag
id='xxx'> "
+ "of network '%s' with forward
mode='%s'"),
+ def->name,
virNetworkForwardTypeToString(def->forward.type));
+ return -1;
+ }
+ }
+
return 0;
}
@@ -3757,7 +3820,8 @@ networkUpdate(virNetworkPtr net,
*/
if (def->forward.type == VIR_NETWORK_FORWARD_NONE ||
def->forward.type == VIR_NETWORK_FORWARD_NAT ||
- def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
+ def->forward.type == VIR_NETWORK_FORWARD_ROUTE ||
+ def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
switch (section) {
case VIR_NETWORK_SECTION_FORWARD:
case VIR_NETWORK_SECTION_FORWARD_INTERFACE:
@@ -4443,7 +4507,8 @@ networkAllocateActualDevice(virDomainDefPtr dom,
if ((netdef->forward.type == VIR_NETWORK_FORWARD_NONE) ||
(netdef->forward.type == VIR_NETWORK_FORWARD_NAT) ||
(netdef->forward.type == VIR_NETWORK_FORWARD_ROUTE) ||
- (netdef->forward.type == VIR_NETWORK_FORWARD_OPEN)) {
+ (netdef->forward.type == VIR_NETWORK_FORWARD_OPEN) ||
+ (netdef->forward.type == VIR_NETWORK_FORWARD_VLAN)) {
/* for these forward types, the actual net type really *is*
* NETWORK; we just keep the info from the portgroup in
* iface->data.network.actual
@@ -4701,7 +4766,8 @@ networkAllocateActualDevice(virDomainDefPtr dom,
* mode) and openvswitch bridges. Otherwise log an error and
* fail
*/
- if (!(actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
+ if (!(netdef->forward.type == VIR_NETWORK_FORWARD_VLAN ||
+ actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
(actualType == VIR_DOMAIN_NET_TYPE_DIRECT &&
virDomainNetGetActualDirectMode(iface)
== VIR_NETDEV_MACVLAN_MODE_PASSTHRU) ||
--
2.7.4