Signed-off-by: Shi Lei <shilei.massclouds@xxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list