diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 6d9f06b930..1adb553ceb 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -7,6 +7,7 @@
+
@@ -77,12 +78,48 @@
nat
route
+ bridge
+ passthrough
+ private
+ vepa
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yes
+ no
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 9f7ce048ce..860eea3e42 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -50,7 +50,7 @@ VIR_ENUM_DECL(virNetworkForward)
VIR_ENUM_IMPL(virNetworkForward,
VIR_NETWORK_FORWARD_LAST,
- "none", "nat", "route" )
+ "none", "nat", "route", "bridge", "private", "vepa", "passthrough" )
#define virNetworkReportError(code, ...) \
virReportErrorHelper(VIR_FROM_NETWORK, code, __FILE__, \
@@ -87,6 +87,19 @@ virNetworkObjPtr virNetworkFindByName(const virNetworkObjListPtr nets,
}
+static void
+virPortGroupDefClear(virPortGroupDefPtr def)
+{
+ VIR_FREE(def->name);
+ VIR_FREE(def->virtPortProfile);
+}
+
+static void
+virNetworkForwardIfDefClear(virNetworkForwardIfDefPtr def)
+{
+ VIR_FREE(def->dev);
+}
+
static void virNetworkIpDefClear(virNetworkIpDefPtr def)
{
int ii;
@@ -135,14 +148,23 @@ void virNetworkDefFree(virNetworkDefPtr def)
VIR_FREE(def->name);
VIR_FREE(def->bridge);
- VIR_FREE(def->forwardDev);
VIR_FREE(def->domain);
+ for (ii = 0 ; ii < def->nForwardIfs && def->forwardIfs ; ii++) {
+ virNetworkForwardIfDefClear(&def->forwardIfs[ii]);
+ }
+ VIR_FREE(def->forwardIfs);
+
for (ii = 0 ; ii < def->nips && def->ips ; ii++) {
virNetworkIpDefClear(&def->ips[ii]);
}
VIR_FREE(def->ips);
+ for (ii = 0; ii < def->nPortGroups && def->portGroups; ii++) {
+ virPortGroupDefClear(&def->portGroups[ii]);
+ }
+ VIR_FREE(def->portGroups);
+
virNetworkDNSDefFree(def->dns);
VIR_FREE(def);
@@ -735,14 +757,63 @@ error:
return result;
}
+static int
+virNetworkPortGroupParseXML(virPortGroupDefPtr def,
+ xmlNodePtr node,
+ xmlXPathContextPtr ctxt)
+{
+ /*
+ * virPortGroupDef object is already allocated as part of an array.
+ * On failure clear it out, but don't free it.
+ */
+
+ xmlNodePtr save;
+ xmlNodePtr virtPortNode;
+ char *isDefault = NULL;
+
+ int result = -1;
+
+ save = ctxt->node;
+ ctxt->node = node;
+
+ /* grab raw data from XML */
+ def->name = virXPathString("string(./@name)", ctxt);
+ isDefault = virXPathString("string(./@default)", ctxt);
+ def->isDefault = isDefault && STRCASEEQ(isDefault, "yes");
+
+ virtPortNode = virXPathNode("./virtualport", ctxt);
+ if (virtPortNode &&
+ (virVirtualPortProfileParseXML(virtPortNode,
+ &def->virtPortProfile) < 0)) {
+ goto error;
+ }
+
+ result = 0;
+error:
+ if (result < 0) {
+ virPortGroupDefClear(def);
+ }
+ VIR_FREE(isDefault);
+
+ ctxt->node = save;
+ return result;
+}
+
static virNetworkDefPtr
virNetworkDefParseXML(xmlXPathContextPtr ctxt)
{
virNetworkDefPtr def;
char *tmp;
+ char *stp = NULL;
xmlNodePtr *ipNodes = NULL;
+ xmlNodePtr *portGroupNodes = NULL;
+ xmlNodePtr *forwardIfNodes = NULL;
xmlNodePtr dnsNode = NULL;
- int nIps;
+ xmlNodePtr virtPortNode = NULL;
+ xmlNodePtr forwardNode = NULL;
+ int nIps, nPortGroups, nForwardIfs;
+ char *forwardDev = NULL;
+ xmlNodePtr save = ctxt->node;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -779,9 +850,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
/* Parse bridge information */
def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt);
- tmp = virXPathString("string(./bridge[1]/@stp)", ctxt);
- def->stp = (tmp && STREQ(tmp, "off")) ? 0 : 1;
- VIR_FREE(tmp);
+ stp = virXPathString("string(./bridge[1]/@stp)", ctxt);
if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0)
def->delay = 0;
@@ -805,6 +874,36 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
goto error;
}
+ virtPortNode = virXPathNode("./virtualport", ctxt);
+ if (virtPortNode &&
+ (virVirtualPortProfileParseXML(virtPortNode,
+ &def->virtPortProfile) < 0)) {
+ goto error;
+ }
+
+ nPortGroups = virXPathNodeSet("./portgroup", ctxt, &portGroupNodes);
+ if (nPortGroups < 0)
+ goto error;
+
+ if (nPortGroups > 0) {
+ int ii;
+
+ /* allocate array to hold all the portgroups */
+ if (VIR_ALLOC_N(def->portGroups, nPortGroups) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ /* parse each portgroup */
+ for (ii = 0; ii < nPortGroups; ii++) {
+ int ret = virNetworkPortGroupParseXML(&def->portGroups[ii],
+ portGroupNodes[ii], ctxt);
+ if (ret < 0)
+ goto error;
+ def->nPortGroups++;
+ }
+ }
+ VIR_FREE(portGroupNodes);
+
nIps = virXPathNodeSet("./ip", ctxt, &ipNodes);
if (nIps < 0)
goto error;
@@ -828,17 +927,16 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
}
VIR_FREE(ipNodes);
- /* IPv4 forwarding setup */
- if (virXPathBoolean("count(./forward) > 0", ctxt)) {
- if (def->nips == 0) {
- virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Forwarding requested, but no IP address provided"));
- goto error;
- }
- tmp = virXPathString("string(./forward[1]/@mode)", ctxt);
+ forwardNode = virXPathNode("./forward", ctxt);
+ if (!forwardNode) {
+ def->forwardType = VIR_NETWORK_FORWARD_NONE;
+ def->stp = (stp && STREQ(stp, "off")) ? 0 : 1;
+ } else {
+ ctxt->node = forwardNode;
+ tmp = virXPathString("string(./@mode)", ctxt);
if (tmp) {
if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) {
- virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
+ virNetworkReportError(VIR_ERR_XML_ERROR,
_("unknown forwarding type '%s'"), tmp);
VIR_FREE(tmp);
goto error;
@@ -848,17 +946,116 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
def->forwardType = VIR_NETWORK_FORWARD_NAT;
}
+ forwardDev = virXPathString("string(./@dev)", ctxt);
- def->forwardDev = virXPathString("string(./forward[1]/@dev)", ctxt);
- } else {
- def->forwardType = VIR_NETWORK_FORWARD_NONE;
+ /* all of these modes can use a pool of physical interfaces */
+ nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
+ if (nForwardIfs < 0)
+ goto error;
+
+ if ((nForwardIfs > 0) || forwardDev) {
+ int ii;
+
+ /* allocate array to hold all the portgroups */
+ if (VIR_ALLOC_N(def->forwardIfs, MAX(nForwardIfs, 1)) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+
+ if (forwardDev) {
+ def->forwardIfs[0].usageCount = 0;
+ def->forwardIfs[0].dev = forwardDev;
+ forwardDev = NULL;
+ def->nForwardIfs++;
+ }
+
+ /* parse each forwardIf */
+ for (ii = 0; ii < nForwardIfs; ii++) {
+ forwardDev = virXMLPropString(forwardIfNodes[ii], "dev");
+ if (!forwardDev) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("Missing required dev attribute in network '%s' forward interface element"),
+ def->name);
+ goto error;
+ }
+
+ if ((ii == 0) && (def->nForwardIfs == 1)) {
+ /* both forwardDev and an interface element are present.
+ * If they don't match, it's an error. */
+ if (STRNEQ(forwardDev, def->forwardIfs[0].dev)) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("forward dev '%s' must match first interface element dev '%s' in network '%s'"),
+ def->forwardIfs[0].dev,
+ forwardDev, def->name);
+ goto error;
+ }
+ VIR_FREE(forwardDev);
+ continue;
+ }
+
+ def->forwardIfs[ii].dev = forwardDev;
+ forwardDev = NULL;
+ def->forwardIfs[ii].usageCount = 0;
+ def->nForwardIfs++;
+ }
+ }
+ VIR_FREE(forwardIfNodes);
+
+ switch (def->forwardType) {
+ case VIR_NETWORK_FORWARD_ROUTE:
+ case VIR_NETWORK_FORWARD_NAT:
+ /* It's pointless to specify L3 forwarding without specifying
+ * the network we're on.
+ */
+ if (def->nips == 0) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("%s forwarding requested, but no IP address provided for network '%s'"),
+ virNetworkForwardTypeToString(def->forwardType),
+ def->name);
+ goto error;
+ }
+ if (def->nForwardIfs > 1) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("multiple forwarding interfaces specified for network '%s', only one is supported"),
+ def->name);
+ goto error;
+ }
+ def->stp = (stp && STREQ(stp, "off")) ? 0 : 1;
+ break;
+ case VIR_NETWORK_FORWARD_PRIVATE:
+ case VIR_NETWORK_FORWARD_VEPA:
+ case VIR_NETWORK_FORWARD_PASSTHROUGH:
+ if (def->bridge) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("bridge name not allowed in %s mode (network '%s'"),
+ virNetworkForwardTypeToString(def->forwardType),
+ def->name);
+ goto error;
+ }
+ /* fall through to next case */
+ case VIR_NETWORK_FORWARD_BRIDGE:
+ if (def->delay || stp) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("bridge delay/stp options only allowed in route, nat, and isolated mode, not in %s (network '%s')"),
+ virNetworkForwardTypeToString(def->forwardType),
+ def->name);
+ goto error;
+ }
+ break;
+ }
}
-
+ VIR_FREE(stp);
+ ctxt->node = save;
return def;
error:
+ VIR_FREE(stp);
virNetworkDefFree(def);
VIR_FREE(ipNodes);
+ VIR_FREE(portGroupNodes);
+ VIR_FREE(forwardIfNodes);
+ VIR_FREE(forwardDev);
+ ctxt->node = save;
return NULL;
}
@@ -1043,6 +1240,19 @@ error:
return result;
}
+static void
+virPortGroupDefFormat(virBufferPtr buf,
+ const virPortGroupDefPtr def)
+{
+ virBufferAsprintf(buf, " name);
+ if (def->isDefault) {
+ virBufferAddLit(buf, " default='yes'");
+ }
+ virBufferAddLit(buf, ">\n");
+ virVirtualPortProfileFormat(buf, def->virtPortProfile, " ");
+ virBufferAddLit(buf, " \n");
+}
+
char *virNetworkDefFormat(const virNetworkDefPtr def)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -1058,24 +1268,48 @@ char *virNetworkDefFormat(const virNetworkDefPtr def)
virBufferAsprintf(&buf, " %s\n", uuidstr);
if (def->forwardType != VIR_NETWORK_FORWARD_NONE) {
+ const char *dev = virNetworkDefForwardIf(def, 0);
const char *mode = virNetworkForwardTypeToString(def->forwardType);
- if (mode) {
- if (def->forwardDev) {
- virBufferEscapeString(&buf, " forwardDev);
- } else {
- virBufferAddLit(&buf, " forwardType, def->name);
+ goto error;
+ }
+ virBufferAddLit(&buf, " \n", mode,
+ def->nForwardIfs ? "" : "/");
+
+ if (def->nForwardIfs) {
+ for (ii = 0; ii < def->nForwardIfs; ii++) {
+ if (def->forwardIfs[ii].dev) {
+ virBufferEscapeString(&buf, " \n",
+ def->forwardIfs[ii].dev);
+ }
}
- virBufferAsprintf(&buf, " mode='%s'/>\n", mode);
+ virBufferAddLit(&buf, " \n");
}
}
- virBufferAddLit(&buf, " bridge)
- virBufferEscapeString(&buf, " name='%s'", def->bridge);
- virBufferAsprintf(&buf, " stp='%s' delay='%ld' />\n",
- def->stp ? "on" : "off",
- def->delay);
+ if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
+ def->forwardType == VIR_NETWORK_FORWARD_NAT ||
+ def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
+
+ virBufferAddLit(&buf, " bridge)
+ virBufferEscapeString(&buf, " name='%s'", def->bridge);
+ virBufferAsprintf(&buf, " stp='%s' delay='%ld' />\n",
+ def->stp ? "on" : "off",
+ def->delay);
+ } else if (def->forwardType == VIR_NETWORK_FORWARD_BRIDGE &&
+ def->bridge) {
+ virBufferEscapeString(&buf, " \n", def->bridge);
+ }
+
+
if (def->mac_specified) {
char macaddr[VIR_MAC_STRING_BUFLEN];
virFormatMacAddr(def->mac, macaddr);
@@ -1093,6 +1327,11 @@ char *virNetworkDefFormat(const virNetworkDefPtr def)
goto error;
}
+ virVirtualPortProfileFormat(&buf, def->virtPortProfile, " ");
+
+ for (ii = 0; ii < def->nPortGroups; ii++)
+ virPortGroupDefFormat(&buf, &def->portGroups[ii]);
+
virBufferAddLit(&buf, "\n");
if (virBufferError(&buf))
@@ -1107,6 +1346,22 @@ char *virNetworkDefFormat(const virNetworkDefPtr def)
return NULL;
}
+virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net,
+ const char *portgroup)
+{
+ int ii;
+ for (ii = 0; ii < net->nPortGroups; ii++) {
+ if (portgroup) {
+ if (STREQ(portgroup, net->portGroups[ii].name))
+ return &net->portGroups[ii];
+ } else {
+ if (net->portGroups[ii].isDefault)
+ return &net->portGroups[ii];
+ }
+ }
+ return NULL;
+}
+
int virNetworkSaveXML(const char *configDir,
virNetworkDefPtr def,
const char *xml)
@@ -1209,11 +1464,16 @@ virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
goto error;
}
- /* Generate a bridge if none is specified, but don't check for collisions
- * if a bridge is hardcoded, so the network is at least defined
- */
- if (virNetworkSetBridgeName(nets, def, 0))
- goto error;
+ if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
+ def->forwardType == VIR_NETWORK_FORWARD_NAT ||
+ def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
+
+ /* Generate a bridge if none is specified, but don't check for collisions
+ * if a bridge is hardcoded, so the network is at least defined.
+ */
+ if (virNetworkSetBridgeName(nets, def, 0))
+ goto error;
+ }
if (!(net = virNetworkAssignDef(nets, def)))
goto error;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 5edcf27b17..92cc03eee0 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -33,11 +33,14 @@
# include "network.h"
# include "util.h"
-/* 2 possible types of forwarding */
enum virNetworkForwardType {
VIR_NETWORK_FORWARD_NONE = 0,
VIR_NETWORK_FORWARD_NAT,
VIR_NETWORK_FORWARD_ROUTE,
+ VIR_NETWORK_FORWARD_BRIDGE,
+ VIR_NETWORK_FORWARD_PRIVATE,
+ VIR_NETWORK_FORWARD_VEPA,
+ VIR_NETWORK_FORWARD_PASSTHROUGH,
VIR_NETWORK_FORWARD_LAST,
};
@@ -107,6 +110,21 @@ struct _virNetworkIpDef {
virSocketAddr bootserver;
};
+typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
+typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
+struct _virNetworkForwardIfDef {
+ char *dev; /* name of device */
+ int usageCount; /* how many guest interfaces are bound to this device? */
+};
+
+typedef struct _virPortGroupDef virPortGroupDef;
+typedef virPortGroupDef *virPortGroupDefPtr;
+struct _virPortGroupDef {
+ char *name;
+ bool isDefault;
+ virVirtualPortProfileParamsPtr virtPortProfile;
+};
+
typedef struct _virNetworkDef virNetworkDef;
typedef virNetworkDef *virNetworkDefPtr;
struct _virNetworkDef {
@@ -121,12 +139,21 @@ struct _virNetworkDef {
bool mac_specified;
int forwardType; /* One of virNetworkForwardType constants */
- char *forwardDev; /* Destination device for forwarding */
+
+ /* If there are multiple forward devices (i.e. a pool of
+ * interfaces), they will be listed here.
+ */
+ size_t nForwardIfs;
+ virNetworkForwardIfDefPtr forwardIfs;
size_t nips;
virNetworkIpDefPtr ips; /* ptr to array of IP addresses on this network */
virNetworkDNSDefPtr dns; /* ptr to dns related configuration */
+ virVirtualPortProfileParamsPtr virtPortProfile;
+
+ size_t nPortGroups;
+ virPortGroupDefPtr portGroups;
};
typedef struct _virNetworkObj virNetworkObj;
@@ -179,6 +206,16 @@ virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml,
char *virNetworkDefFormat(const virNetworkDefPtr def);
+static inline const char *
+virNetworkDefForwardIf(const virNetworkDefPtr def, size_t n)
+{
+ return ((def->forwardIfs && (def->nForwardIfs > n))
+ ? def->forwardIfs[n].dev : NULL);
+}
+
+virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net,
+ const char *portgroup);
+
virNetworkIpDefPtr
virNetworkDefGetIpByIndex(const virNetworkDefPtr def,
int family, size_t n);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f8b6abfa33..5e2ca68103 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -747,6 +747,7 @@ virNetworkRemoveInactive;
virNetworkSaveConfig;
virNetworkSetBridgeMacAddr;
virNetworkSetBridgeName;
+virPortGroupFindByName;
# node_device_conf.h
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 0a12bc08d4..a5809102ef 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -898,6 +898,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
virNetworkIpDefPtr ipdef)
{
int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
if (prefix < 0) {
networkReportError(VIR_ERR_INTERNAL_ERROR,
@@ -911,7 +912,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev) < 0) {
+ forwardIf) < 0) {
networkReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow forwarding from '%s'"),
network->def->bridge);
@@ -925,7 +926,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev) < 0) {
+ forwardIf) < 0) {
networkReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow forwarding to '%s'"),
network->def->bridge);
@@ -959,11 +960,13 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
if (iptablesAddForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
NULL) < 0) {
networkReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to enable masquerading to '%s'"),
- network->def->forwardDev ? network->def->forwardDev : NULL);
+ forwardIf ?
+ _("failed to add iptables rule to enable masquerading to %s") :
+ _("failed to add iptables rule to enable masquerading"),
+ forwardIf);
goto masqerr3;
}
@@ -971,11 +974,13 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
if (iptablesAddForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
"udp") < 0) {
networkReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to enable UDP masquerading to '%s'"),
- network->def->forwardDev ? network->def->forwardDev : NULL);
+ forwardIf ?
+ _("failed to add iptables rule to enable UDP masquerading to %s") :
+ _("failed to add iptables rule to enable UDP masquerading"),
+ forwardIf);
goto masqerr4;
}
@@ -983,11 +988,13 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
if (iptablesAddForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
"tcp") < 0) {
networkReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to enable TCP masquerading to '%s'"),
- network->def->forwardDev ? network->def->forwardDev : NULL);
+ forwardIf ?
+ _("failed to add iptables rule to enable TCP masquerading to %s") :
+ _("failed to add iptables rule to enable TCP masquerading"),
+ forwardIf);
goto masqerr5;
}
@@ -997,26 +1004,26 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
"udp");
masqerr4:
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
NULL);
masqerr3:
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev);
+ forwardIf);
masqerr2:
iptablesRemoveForwardAllowOut(driver->iptables,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev);
+ forwardIf);
masqerr1:
return -1;
}
@@ -1027,34 +1034,35 @@ networkRemoveMasqueradingIptablesRules(struct network_driver *driver,
virNetworkIpDefPtr ipdef)
{
int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
if (prefix >= 0) {
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
"tcp");
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
"udp");
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
- network->def->forwardDev,
+ forwardIf,
NULL);
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev);
+ forwardIf);
iptablesRemoveForwardAllowOut(driver->iptables,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev);
+ forwardIf);
}
}
@@ -1064,6 +1072,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
virNetworkIpDefPtr ipdef)
{
int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
if (prefix < 0) {
networkReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1077,7 +1086,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev) < 0) {
+ forwardIf) < 0) {
networkReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow routing from '%s'"),
network->def->bridge);
@@ -1089,7 +1098,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev) < 0) {
+ forwardIf) < 0) {
networkReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow routing to '%s'"),
network->def->bridge);
@@ -1103,7 +1112,7 @@ routeerr2:
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev);
+ forwardIf);
routeerr1:
return -1;
}
@@ -1114,19 +1123,20 @@ networkRemoveRoutingIptablesRules(struct network_driver *driver,
virNetworkIpDefPtr ipdef)
{
int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
if (prefix >= 0) {
iptablesRemoveForwardAllowIn(driver->iptables,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev);
+ forwardIf);
iptablesRemoveForwardAllowOut(driver->iptables,
&ipdef->address,
prefix,
network->def->bridge,
- network->def->forwardDev);
+ forwardIf);
}
}
@@ -2171,10 +2181,18 @@ static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) {
if (virNetworkObjIsDuplicate(&driver->networks, def, 1) < 0)
goto cleanup;
- if (virNetworkSetBridgeName(&driver->networks, def, 1))
- goto cleanup;
+ /* Only the three L3 network types that are configured by libvirt
+ * need to have a bridge device name / mac address provided
+ */
+ if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
+ def->forwardType == VIR_NETWORK_FORWARD_NAT ||
+ def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
- virNetworkSetBridgeMacAddr(def);
+ if (virNetworkSetBridgeName(&driver->networks, def, 1))
+ goto cleanup;
+
+ virNetworkSetBridgeMacAddr(def);
+ }
if (!(network = virNetworkAssignDef(&driver->networks,
def)))
@@ -2216,10 +2234,18 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
if (virNetworkObjIsDuplicate(&driver->networks, def, 0) < 0)
goto cleanup;
- if (virNetworkSetBridgeName(&driver->networks, def, 1))
- goto cleanup;
+ /* Only the three L3 network types that are configured by libvirt
+ * need to have a bridge device name / mac address provided
+ */
+ if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
+ def->forwardType == VIR_NETWORK_FORWARD_NAT ||
+ def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
- virNetworkSetBridgeMacAddr(def);
+ if (virNetworkSetBridgeName(&driver->networks, def, 1))
+ goto cleanup;
+
+ virNetworkSetBridgeMacAddr(def);
+ }
if (!(network = virNetworkAssignDef(&driver->networks,
def)))
diff --git a/tests/networkxml2xmlin/8021Qbh-net.xml b/tests/networkxml2xmlin/8021Qbh-net.xml
new file mode 100644
index 0000000000..2d779dcac0
--- /dev/null
+++ b/tests/networkxml2xmlin/8021Qbh-net.xml
@@ -0,0 +1,14 @@
+
+ 8021Qbh-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8c
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmlin/direct-net.xml b/tests/networkxml2xmlin/direct-net.xml
new file mode 100644
index 0000000000..d73c45489d
--- /dev/null
+++ b/tests/networkxml2xmlin/direct-net.xml
@@ -0,0 +1,7 @@
+
+ direct-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8f
+
+
+
+
diff --git a/tests/networkxml2xmlin/host-bridge-net.xml b/tests/networkxml2xmlin/host-bridge-net.xml
new file mode 100644
index 0000000000..960bc2da06
--- /dev/null
+++ b/tests/networkxml2xmlin/host-bridge-net.xml
@@ -0,0 +1,6 @@
+
+ host-bridge-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8e
+
+
+
diff --git a/tests/networkxml2xmlin/vepa-net.xml b/tests/networkxml2xmlin/vepa-net.xml
new file mode 100644
index 0000000000..b1a40c6e58
--- /dev/null
+++ b/tests/networkxml2xmlin/vepa-net.xml
@@ -0,0 +1,22 @@
+
+ vepa-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8b
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmlout/8021Qbh-net.xml b/tests/networkxml2xmlout/8021Qbh-net.xml
new file mode 100644
index 0000000000..d4d5b4b443
--- /dev/null
+++ b/tests/networkxml2xmlout/8021Qbh-net.xml
@@ -0,0 +1,14 @@
+
+ 8021Qbh-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8c
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmlout/direct-net.xml b/tests/networkxml2xmlout/direct-net.xml
new file mode 100644
index 0000000000..56cd7070a9
--- /dev/null
+++ b/tests/networkxml2xmlout/direct-net.xml
@@ -0,0 +1,7 @@
+
+ direct-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8f
+
+
+
+
diff --git a/tests/networkxml2xmlout/host-bridge-net.xml b/tests/networkxml2xmlout/host-bridge-net.xml
new file mode 100644
index 0000000000..84992a923e
--- /dev/null
+++ b/tests/networkxml2xmlout/host-bridge-net.xml
@@ -0,0 +1,6 @@
+
+ host-bridge-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8e
+
+
+
diff --git a/tests/networkxml2xmlout/nat-network-dns-hosts.xml b/tests/networkxml2xmlout/nat-network-dns-hosts.xml
index 9a83fed17f..b26fa03be1 100644
--- a/tests/networkxml2xmlout/nat-network-dns-hosts.xml
+++ b/tests/networkxml2xmlout/nat-network-dns-hosts.xml
@@ -1,7 +1,9 @@
default
81ff0d90-c91e-6742-64da-4a736edb9a9c
-
+
+
+
diff --git a/tests/networkxml2xmlout/nat-network-dns-txt-record.xml b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml
index bd1697608c..f767f486b4 100644
--- a/tests/networkxml2xmlout/nat-network-dns-txt-record.xml
+++ b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml
@@ -1,7 +1,9 @@
default
81ff0d90-c91e-6742-64da-4a736edb9a9b
-
+
+
+
diff --git a/tests/networkxml2xmlout/nat-network.xml b/tests/networkxml2xmlout/nat-network.xml
index eb71d9ea38..02d68495c2 100644
--- a/tests/networkxml2xmlout/nat-network.xml
+++ b/tests/networkxml2xmlout/nat-network.xml
@@ -1,7 +1,9 @@
default
81ff0d90-c91e-6742-64da-4a736edb9a9b
-
+
+
+
diff --git a/tests/networkxml2xmlout/routed-network.xml b/tests/networkxml2xmlout/routed-network.xml
index 3aa810929f..9235e15406 100644
--- a/tests/networkxml2xmlout/routed-network.xml
+++ b/tests/networkxml2xmlout/routed-network.xml
@@ -1,7 +1,9 @@
local
81ff0d90-c91e-6742-64da-4a736edb9a9b
-
+
+
+
diff --git a/tests/networkxml2xmlout/vepa-net.xml b/tests/networkxml2xmlout/vepa-net.xml
new file mode 100644
index 0000000000..af13d0fd45
--- /dev/null
+++ b/tests/networkxml2xmlout/vepa-net.xml
@@ -0,0 +1,22 @@
+
+ vepa-net
+ 81ff0d90-c91e-6742-64da-4a736edb9a8b
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index 065166d724..f354b0de31 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -88,6 +88,10 @@ mymain(void)
DO_TEST("netboot-proxy-network");
DO_TEST("nat-network-dns-txt-record");
DO_TEST("nat-network-dns-hosts");
+ DO_TEST("8021Qbh-net");
+ DO_TEST("direct-net");
+ DO_TEST("host-bridge-net");
+ DO_TEST("vepa-net");
return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
}