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); }