[libvirt] [PATCH 0/4] Update interface xml to match netcf 0.1.5

The first two patches make minor additions to the parsing/formatting. The 3rd is a bit more intrusive, as it switches from using virInterfaceBareDef for subordinate interfaces to recursively using a full virInterfaceDef (but with guaranteed closure due to limiting the type of subordinate interface allowed based on parent interface). The final patch updates the RNG and test files accordingly.

--- src/conf/interface_conf.c | 11 +++++++---- src/conf/interface_conf.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 3c99027..ca82208 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -801,6 +801,7 @@ virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { } VIR_FREE(tmp); } + def->data.bridge.delay = virXMLPropString(bridge, "delay"); ctxt->node = bridge; virInterfaceDefParseBridge(conn, def, ctxt); break; @@ -1038,12 +1039,14 @@ virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf, int i; int ret = 0; + virBufferAddLit(buf, " <bridge"); if (def->data.bridge.stp == 1) - virBufferAddLit(buf, " <bridge stp='on'>\n"); + virBufferAddLit(buf, " stp='on'"); else if (def->data.bridge.stp == 0) - virBufferAddLit(buf, " <bridge stp='off'>\n"); - else - virBufferAddLit(buf, " <bridge>\n"); + virBufferAddLit(buf, " stp='off'"); + if (def->data.bridge.delay != NULL) + virBufferVSprintf(buf, " delay='%s'", def->data.bridge.delay); + virBufferAddLit(buf, ">\n"); for (i = 0;i < def->data.bridge.nbItf;i++) { if (virInterfaceBareDevDefFormat(conn, buf, def->data.bridge.itf[i]) diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 2683eee..4216087 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -97,6 +97,7 @@ typedef struct _virInterfaceBridgeDef virInterfaceBridgeDef; typedef virInterfaceBridgeDef *virInterfaceBridgeDefPtr; struct _virInterfaceBridgeDef { int stp; /* 0, 1 or -1 if undefined */ + char *delay; int nbItf; /* number of defined interfaces */ virInterfaceBareDefPtr *itf;/* interfaces */ }; -- 1.6.6.rc2.5.g49666

On 01/01/2010 08:40 PM, Laine Stump wrote:
--- src/conf/interface_conf.c | 11 +++++++---- src/conf/interface_conf.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 3c99027..ca82208 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -801,6 +801,7 @@ virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { } VIR_FREE(tmp); } + def->data.bridge.delay = virXMLPropString(bridge, "delay"); ctxt->node = bridge; virInterfaceDefParseBridge(conn, def, ctxt); break; @@ -1038,12 +1039,14 @@ virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf, int i; int ret = 0;
+ virBufferAddLit(buf, " <bridge"); if (def->data.bridge.stp == 1) - virBufferAddLit(buf, " <bridge stp='on'>\n"); + virBufferAddLit(buf, " stp='on'"); else if (def->data.bridge.stp == 0) - virBufferAddLit(buf, " <bridge stp='off'>\n"); - else - virBufferAddLit(buf, " <bridge>\n"); + virBufferAddLit(buf, " stp='off'"); + if (def->data.bridge.delay != NULL) + virBufferVSprintf(buf, " delay='%s'", def->data.bridge.delay); + virBufferAddLit(buf, ">\n");
for (i = 0;i < def->data.bridge.nbItf;i++) { if (virInterfaceBareDevDefFormat(conn, buf, def->data.bridge.itf[i]) diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 2683eee..4216087 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -97,6 +97,7 @@ typedef struct _virInterfaceBridgeDef virInterfaceBridgeDef; typedef virInterfaceBridgeDef *virInterfaceBridgeDefPtr; struct _virInterfaceBridgeDef { int stp; /* 0, 1 or -1 if undefined */ + char *delay; int nbItf; /* number of defined interfaces */ virInterfaceBareDefPtr *itf;/* interfaces */ };
ACK - Cole

On Fri, Jan 01, 2010 at 08:40:23PM -0500, Laine Stump wrote:
--- src/conf/interface_conf.c | 11 +++++++---- src/conf/interface_conf.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 3c99027..ca82208 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -801,6 +801,7 @@ virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { } VIR_FREE(tmp); } + def->data.bridge.delay = virXMLPropString(bridge, "delay"); ctxt->node = bridge; virInterfaceDefParseBridge(conn, def, ctxt); break; @@ -1038,12 +1039,14 @@ virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf, int i; int ret = 0;
+ virBufferAddLit(buf, " <bridge"); if (def->data.bridge.stp == 1) - virBufferAddLit(buf, " <bridge stp='on'>\n"); + virBufferAddLit(buf, " stp='on'"); else if (def->data.bridge.stp == 0) - virBufferAddLit(buf, " <bridge stp='off'>\n"); - else - virBufferAddLit(buf, " <bridge>\n"); + virBufferAddLit(buf, " stp='off'"); + if (def->data.bridge.delay != NULL) + virBufferVSprintf(buf, " delay='%s'", def->data.bridge.delay); + virBufferAddLit(buf, ">\n");
for (i = 0;i < def->data.bridge.nbItf;i++) { if (virInterfaceBareDevDefFormat(conn, buf, def->data.bridge.itf[i]) diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 2683eee..4216087 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -97,6 +97,7 @@ typedef struct _virInterfaceBridgeDef virInterfaceBridgeDef; typedef virInterfaceBridgeDef *virInterfaceBridgeDefPtr; struct _virInterfaceBridgeDef { int stp; /* 0, 1 or -1 if undefined */ + char *delay; int nbItf; /* number of defined interfaces */ virInterfaceBareDefPtr *itf;/* interfaces */ };
ACK Though, it'd be nice to convert this to an integer. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

--- src/conf/interface_conf.c | 32 +++++++++++++++++--------------- 1 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index ca82208..d7821e7 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -557,28 +557,30 @@ virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def, bridge = ctxt->node; nbItf = virXPathNodeSet(conn, "./interface", ctxt, &interfaces); - if (nbItf <= 0) { + if (nbItf < 0) { virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - "%s", _("bridge has no interfaces")); + "%s", _("bridge interfaces")); ret = -1; goto error; } - if (VIR_ALLOC_N(def->data.bridge.itf, nbItf) < 0) { - virReportOOMError(conn); - ret = -1; - goto error; - } - def->data.bridge.nbItf = nbItf; - - for (i = 0; i < nbItf;i++) { - ctxt->node = interfaces[i]; - itf = virInterfaceDefParseBareInterface(conn, ctxt, 0); - if (itf == NULL) { + if (nbItf > 0) { + if (VIR_ALLOC_N(def->data.bridge.itf, nbItf) < 0) { + virReportOOMError(conn); ret = -1; - def->data.bridge.nbItf = i; goto error; } - def->data.bridge.itf[i] = itf; + def->data.bridge.nbItf = nbItf; + + for (i = 0; i < nbItf;i++) { + ctxt->node = interfaces[i]; + itf = virInterfaceDefParseBareInterface(conn, ctxt, 0); + if (itf == NULL) { + ret = -1; + def->data.bridge.nbItf = i; + goto error; + } + def->data.bridge.itf[i] = itf; + } } error: -- 1.6.6.rc2.5.g49666

On Fri, Jan 01, 2010 at 08:40:24PM -0500, Laine Stump wrote:
--- src/conf/interface_conf.c | 32 +++++++++++++++++--------------- 1 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index ca82208..d7821e7 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -557,28 +557,30 @@ virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def,
bridge = ctxt->node; nbItf = virXPathNodeSet(conn, "./interface", ctxt, &interfaces); - if (nbItf <= 0) { + if (nbItf < 0) { virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - "%s", _("bridge has no interfaces")); + "%s", _("bridge interfaces")); ret = -1; goto error; } - if (VIR_ALLOC_N(def->data.bridge.itf, nbItf) < 0) { - virReportOOMError(conn); - ret = -1; - goto error; - } - def->data.bridge.nbItf = nbItf; - - for (i = 0; i < nbItf;i++) { - ctxt->node = interfaces[i]; - itf = virInterfaceDefParseBareInterface(conn, ctxt, 0); - if (itf == NULL) { + if (nbItf > 0) { + if (VIR_ALLOC_N(def->data.bridge.itf, nbItf) < 0) { + virReportOOMError(conn); ret = -1; - def->data.bridge.nbItf = i; goto error; } - def->data.bridge.itf[i] = itf; + def->data.bridge.nbItf = nbItf; + + for (i = 0; i < nbItf;i++) { + ctxt->node = interfaces[i]; + itf = virInterfaceDefParseBareInterface(conn, ctxt, 0); + if (itf == NULL) { + ret = -1; + def->data.bridge.nbItf = i; + goto error; + } + def->data.bridge.itf[i] = itf; + } }
error:
ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This was accomplished in xml parsing by doing away with the stripped-down virInterfaceBareDef object, and just always using virInterfaceDef, but with restrictions in certain places (eg, the type of subordinate interface allowed in parsing depends on the parent interface). xml formatting was similarly adjusted. In addition, the formatting functions keep track of the level of interface nesting, and insert extra leading spaces on each line accordingly (using %*s). The only change in formatted xml from previous (aside frmo supporting new combinations of interface types) is that the subordinate ethernet interfaces take up 2 lines rather than one, eg: <interface type='ethernet' name='eth0'> </interface> instead of: <interface type='ethernet' name='eth0'/> --- src/conf/interface_conf.c | 362 +++++++++++++++++++-------------------------- src/conf/interface_conf.h | 13 +-- 2 files changed, 156 insertions(+), 219 deletions(-) diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index d7821e7..6efc8aa 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -39,21 +39,18 @@ VIR_ENUM_IMPL(virInterface, VIR_INTERFACE_TYPE_LAST, "ethernet", "bridge", "bond", "vlan" ) +static virInterfaceDefPtr +virInterfaceDefParseXML(virConnectPtr conn, + xmlXPathContextPtr ctxt, int parentIfType); +static int +virInterfaceDefDevFormat(virConnectPtr conn, virBufferPtr buf, + const virInterfaceDefPtr def, int level); + #define virInterfaceReportError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_INTERFACE, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) static -void virInterfaceBareDefFree(virInterfaceBareDefPtr def) { - if (def == NULL) - return; - VIR_FREE(def->name); - VIR_FREE(def->mac_or_tag); - VIR_FREE(def->devname); - VIR_FREE(def); -} - -static void virInterfaceIpDefFree(virInterfaceIpDefPtr def) { if (def == NULL) return; @@ -90,7 +87,7 @@ void virInterfaceDefFree(virInterfaceDefPtr def) case VIR_INTERFACE_TYPE_BRIDGE: for (i = 0;i < def->data.bridge.nbItf;i++) { if (def->data.bridge.itf[i] != NULL) - virInterfaceBareDefFree(def->data.bridge.itf[i]); + virInterfaceDefFree(def->data.bridge.itf[i]); else break; /* to cope with half parsed data on errors */ } @@ -100,7 +97,7 @@ void virInterfaceDefFree(virInterfaceDefPtr def) VIR_FREE(def->data.bond.target); for (i = 0;i < def->data.bond.nbItf;i++) { if (def->data.bond.itf[i] != NULL) - virInterfaceBareDefFree(def->data.bond.itf[i]); + virInterfaceDefFree(def->data.bond.itf[i]); else break; /* to cope with half parsed data on errors */ } @@ -121,11 +118,9 @@ void virInterfaceDefFree(virInterfaceDefPtr def) } static int -virInterfaceDefParseBasicAttrs(virConnectPtr conn, virInterfaceDefPtr def, - xmlXPathContextPtr ctxt) { +virInterfaceDefParseName(virConnectPtr conn, virInterfaceDefPtr def, + xmlXPathContextPtr ctxt) { char *tmp; - unsigned long mtu; - int ret; tmp = virXPathString(conn, "string(./@name)", ctxt); if (tmp == NULL) { @@ -134,6 +129,14 @@ virInterfaceDefParseBasicAttrs(virConnectPtr conn, virInterfaceDefPtr def, return(-1); } def->name = tmp; + return(0); +} + +static int +virInterfaceDefParseMtu(virConnectPtr conn, virInterfaceDefPtr def, + xmlXPathContextPtr ctxt) { + unsigned long mtu; + int ret; ret = virXPathULong(conn, "string(./mtu/@size)", ctxt, &mtu); if ((ret == -2) || ((ret == 0) && (mtu > 100000))) { @@ -478,80 +481,12 @@ error: } -static virInterfaceBareDefPtr -virInterfaceDefParseBareInterface(virConnectPtr conn, xmlXPathContextPtr ctxt, - int ethernet_only) { - int t; - char *name = NULL; - char *type = NULL; - char *mac_or_tag = NULL; - char *devname = NULL; - virInterfaceBareDefPtr ret = NULL; - - type = virXPathString(conn, "string(./@type)", ctxt); - if (type == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - "%s", _("interface has no type")); - goto error; - } - if (STREQ(type, "ethernet")) { - t = VIR_INTERFACE_TYPE_ETHERNET; - name = virXPathString(conn, "string(./@name)", ctxt); - mac_or_tag = virXPathString(conn, "string(./mac/@address)", ctxt); - } else if ((STREQ(type, "vlan")) && (ethernet_only == 0)) { - t = VIR_INTERFACE_TYPE_VLAN; - name = virXPathString(conn, "string(./@name)", ctxt); - mac_or_tag = virXPathString(conn, "string(./vlan/@tag)", ctxt); - devname = virXPathString(conn, "string(./vlan/interface/@name)", ctxt); - } else { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("interface has unsupported type '%s'"), type); - VIR_FREE(type); - goto error; - } - VIR_FREE(type); - if (name == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - "%s", _("interface has no name")); - goto error; - } - if (t == VIR_INTERFACE_TYPE_VLAN) { - if (mac_or_tag == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("vlan %s has no tag"), name); - goto error; - } - if (devname == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("vlan %s has interface name"), name); - goto error; - } - } - if (VIR_ALLOC(ret) < 0) { - virReportOOMError(conn); - goto error; - } - ret->type = t; - ret->name = name; - ret->mac_or_tag = mac_or_tag; - ret->devname = devname; - return(ret); - -error: - VIR_FREE(name); - VIR_FREE(type); - VIR_FREE(name); - VIR_FREE(name); - VIR_FREE(ret); - return(NULL); -} - static int virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr *interfaces = NULL; xmlNodePtr bridge; - virInterfaceBareDefPtr itf; + virInterfaceDefPtr itf; int nbItf, i; int ret = 0; @@ -573,7 +508,7 @@ virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def, for (i = 0; i < nbItf;i++) { ctxt->node = interfaces[i]; - itf = virInterfaceDefParseBareInterface(conn, ctxt, 0); + itf = virInterfaceDefParseXML(conn, ctxt, VIR_INTERFACE_TYPE_BRIDGE); if (itf == NULL) { ret = -1; def->data.bridge.nbItf = i; @@ -594,7 +529,7 @@ virInterfaceDefParseBondItfs(virConnectPtr conn, virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr *interfaces = NULL; xmlNodePtr bond = ctxt->node; - virInterfaceBareDefPtr itf; + virInterfaceDefPtr itf; int nbItf, i; int ret = 0; @@ -614,7 +549,7 @@ virInterfaceDefParseBondItfs(virConnectPtr conn, virInterfaceDefPtr def, for (i = 0; i < nbItf;i++) { ctxt->node = interfaces[i]; - itf = virInterfaceDefParseBareInterface(conn, ctxt, 1); + itf = virInterfaceDefParseXML(conn, ctxt, VIR_INTERFACE_TYPE_BOND); if (itf == NULL) { ret = -1; def->data.bond.nbItf = i; @@ -732,7 +667,8 @@ virInterfaceDefParseVlan(virConnectPtr conn, virInterfaceDefPtr def, } static virInterfaceDefPtr -virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { +virInterfaceDefParseXML(virConnectPtr conn, + xmlXPathContextPtr ctxt, int parentIfType) { virInterfaceDefPtr def; int type; char *tmp; @@ -758,25 +694,46 @@ virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { virReportOOMError(conn); return NULL; } + + if (((parentIfType == VIR_INTERFACE_TYPE_BOND) + && (type != VIR_INTERFACE_TYPE_ETHERNET)) + || ((parentIfType == VIR_INTERFACE_TYPE_BRIDGE) + && (type != VIR_INTERFACE_TYPE_ETHERNET) + && (type != VIR_INTERFACE_TYPE_BOND) + && (type != VIR_INTERFACE_TYPE_VLAN)) + || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET) + || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) + { + virInterfaceReportError(conn, VIR_ERR_XML_ERROR, + _("interface has unsupported type '%s'"), type); + goto error; + } def->type = type; switch (type) { case VIR_INTERFACE_TYPE_ETHERNET: - if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0) + if (virInterfaceDefParseName(conn, def, ctxt) < 0) goto error; tmp = virXPathString(conn, "string(./mac/@address)", ctxt); if (tmp != NULL) def->mac = tmp; - if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) - goto error; - if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) - goto error; + if (parentIfType == VIR_INTERFACE_TYPE_LAST) { + /* only recognize these in toplevel bond interfaces */ + if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseMtu(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) + goto error; + } break; case VIR_INTERFACE_TYPE_BRIDGE: { xmlNodePtr bridge; + if (virInterfaceDefParseName(conn, def, ctxt) < 0) + goto error; if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) goto error; - if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0) + if (virInterfaceDefParseMtu(conn, def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) goto error; @@ -811,12 +768,18 @@ virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { case VIR_INTERFACE_TYPE_BOND: { xmlNodePtr bond; - if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0) - goto error; - if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) - goto error; - if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) + if (virInterfaceDefParseName(conn, def, ctxt) < 0) goto error; + if (parentIfType == VIR_INTERFACE_TYPE_LAST) { + /* only recognize these in toplevel bond interfaces */ + if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseMtu(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) + goto error; + } + bond = virXPathNode(conn, "./bond[1]", ctxt); if (bond == NULL) { virInterfaceReportError(conn, VIR_ERR_XML_ERROR, @@ -881,7 +844,7 @@ virInterfaceDefPtr virInterfaceDefParseNode(virConnectPtr conn, } ctxt->node = root; - def = virInterfaceDefParseXML(conn, ctxt); + def = virInterfaceDefParseXML(conn, ctxt, VIR_INTERFACE_TYPE_LAST); cleanup: xmlXPathFreeContext(ctxt); @@ -990,58 +953,12 @@ cleanup: } static int -virInterfaceBareDevDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED, - virBufferPtr buf, - const virInterfaceBareDefPtr def) { - if (def->type == VIR_INTERFACE_TYPE_ETHERNET) { - if (def->name == NULL) { - virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("bare ethernet has no name")); - return(-1); - } - virBufferVSprintf(buf, " <interface type='ethernet' name='%s'", - def->name); - if (def->mac_or_tag != NULL) { - virBufferVSprintf(buf, ">\n <mac address='%s'/>\n", - def->mac_or_tag); - virBufferAddLit(buf, " </interface>\n"); - } else { - virBufferAddLit(buf, "/>\n"); - } - } else if (def->type == VIR_INTERFACE_TYPE_VLAN) { - virBufferAddLit(buf, " <interface type='vlan'"); - if (def->name != NULL) - virBufferVSprintf(buf, " name='%s'", def->name); - if (def->mac_or_tag != NULL) { - virBufferAddLit(buf, ">\n"); - virBufferVSprintf(buf, " <vlan tag='%s'", def->mac_or_tag); - if (def->devname != NULL) { - virBufferAddLit(buf, ">\n"); - virBufferVSprintf(buf, " <interface name='%s'/>\n", - def->devname); - virBufferAddLit(buf, " </vlan>\n"); - } else - virBufferAddLit(buf, "/>\n"); - virBufferAddLit(buf, " </interface>\n"); - } else { - virBufferAddLit(buf, "/>\n"); - } - } else { - virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("bare interface type %d unknown"), - def->type); - return(-1); - } - return(0); -} - -static int virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf, - const virInterfaceDefPtr def) { + const virInterfaceDefPtr def, int level) { int i; int ret = 0; - virBufferAddLit(buf, " <bridge"); + virBufferVSprintf(buf, "%*s <bridge", level*2, ""); if (def->data.bridge.stp == 1) virBufferAddLit(buf, " stp='on'"); else if (def->data.bridge.stp == 0) @@ -1051,22 +968,22 @@ virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf, virBufferAddLit(buf, ">\n"); for (i = 0;i < def->data.bridge.nbItf;i++) { - if (virInterfaceBareDevDefFormat(conn, buf, def->data.bridge.itf[i]) - < 0) + if (virInterfaceDefDevFormat(conn, buf, + def->data.bridge.itf[i], level+2) < 0) ret = -1; } - virBufferAddLit(buf, " </bridge>\n"); + virBufferVSprintf(buf, "%*s </bridge>\n", level*2, ""); return(ret); } static int virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, - const virInterfaceDefPtr def) { + const virInterfaceDefPtr def, int level) { int i; int ret = 0; - virBufferAddLit(buf, " <bond"); + virBufferVSprintf(buf, "%*s <bond", level*2, ""); if (def->data.bond.mode == VIR_INTERFACE_BOND_BALRR) virBufferAddLit(buf, " mode='balance-rr'"); else if (def->data.bond.mode == VIR_INTERFACE_BOND_ABACKUP) @@ -1084,8 +1001,8 @@ virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, virBufferAddLit(buf, ">\n"); if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_MII) { - virBufferVSprintf(buf, " <miimon freq='%d'", - def->data.bond.frequency); + virBufferVSprintf(buf, "%*s <miimon freq='%d'", + level*2, "", def->data.bond.frequency); if (def->data.bond.downdelay > 0) virBufferVSprintf(buf, " downdelay='%d'", def->data.bond.downdelay); if (def->data.bond.updelay > 0) @@ -1101,7 +1018,8 @@ virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, "%s", _("bond arp monitoring has no target")); return(-1); } - virBufferVSprintf(buf, " <arpmon interval='%d' target='%s'", + virBufferVSprintf(buf, "%*s <arpmon interval='%d' target='%s'", + level*2, "", def->data.bond.interval, def->data.bond.target); if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ACTIVE) virBufferAddLit(buf, " validate='active'"); @@ -1112,29 +1030,30 @@ virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } for (i = 0;i < def->data.bond.nbItf;i++) { - if (virInterfaceBareDevDefFormat(conn, buf, def->data.bond.itf[i]) < 0) + if (virInterfaceDefDevFormat(conn, buf, def->data.bond.itf[i], level+2) < 0) ret = -1; } - virBufferAddLit(buf, " </bond>\n"); + virBufferVSprintf(buf, "%*s </bond>\n", level*2, ""); return(ret); } static int virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf, - const virInterfaceDefPtr def) { + const virInterfaceDefPtr def, int level) { if (def->data.vlan.tag == NULL) { virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("vlan misses the tag name")); return(-1); } - virBufferVSprintf(buf, " <vlan tag='%s'", def->data.vlan.tag); + virBufferVSprintf(buf, "%*s <vlan tag='%s'", + level*2, "", def->data.vlan.tag); if (def->data.vlan.devname != NULL) { virBufferAddLit(buf, ">\n"); - virBufferVSprintf(buf, " <interface name='%s'/>\n", - def->data.vlan.devname); - virBufferAddLit(buf, " </vlan>\n"); + virBufferVSprintf(buf, "%*s <interface name='%s'/>\n", + level*2, "", def->data.vlan.devname); + virBufferVSprintf(buf, "%*s </vlan>\n", level*2, ""); } else virBufferAddLit(buf, "/>\n"); return(0); @@ -1142,30 +1061,34 @@ virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf, static int virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED, - virBufferPtr buf, const virInterfaceDefPtr def) { + virBufferPtr buf, const virInterfaceDefPtr def, + int level) { int pp, ii; for (pp = 0; pp < def->nprotos; pp++) { - virBufferVSprintf(buf, " <protocol family='%s'>\n", def->protos[pp]->family); + virBufferVSprintf(buf, "%*s <protocol family='%s'>\n", + level*2, "", def->protos[pp]->family); if (def->protos[pp]->autoconf) { - virBufferAddLit(buf, " <autoconf/>\n"); + virBufferVSprintf(buf, "%*s <autoconf/>\n", level*2, ""); } if (def->protos[pp]->dhcp) { if (def->protos[pp]->peerdns == 0) - virBufferAddLit(buf, " <dhcp peerdns='no'/>\n"); + virBufferVSprintf(buf, "%*s <dhcp peerdns='no'/>\n", + level*2, ""); else if (def->protos[pp]->peerdns == 1) - virBufferAddLit(buf, " <dhcp peerdns='yes'/>\n"); + virBufferVSprintf(buf, "%*s <dhcp peerdns='yes'/>\n", + level*2, ""); else - virBufferAddLit(buf, " <dhcp/>\n"); + virBufferVSprintf(buf, "%*s <dhcp/>\n", level*2, ""); } for (ii = 0; ii < def->protos[pp]->nips; ii++) { if (def->protos[pp]->ips[ii]->address != NULL) { - virBufferVSprintf(buf, " <ip address='%s'", + virBufferVSprintf(buf, "%*s <ip address='%s'", level*2, "", def->protos[pp]->ips[ii]->address); if (def->protos[pp]->ips[ii]->prefix != 0) { virBufferVSprintf(buf, " prefix='%d'", @@ -1175,18 +1098,19 @@ virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED, } } if (def->protos[pp]->gateway != NULL) { - virBufferVSprintf(buf, " <route gateway='%s'/>\n", - def->protos[pp]->gateway); + virBufferVSprintf(buf, "%*s <route gateway='%s'/>\n", + level*2, "", def->protos[pp]->gateway); } - virBufferAddLit(buf, " </protocol>\n"); + virBufferVSprintf(buf, "%*s </protocol>\n", level*2, ""); } return(0); } static int virInterfaceStartmodeDefFormat(virConnectPtr conn, virBufferPtr buf, - enum virInterfaceStartMode startmode) { + enum virInterfaceStartMode startmode, + int level) { const char *mode; switch (startmode) { case VIR_INTERFACE_START_UNSPECIFIED: @@ -1205,20 +1129,24 @@ virInterfaceStartmodeDefFormat(virConnectPtr conn, virBufferPtr buf, "%s", _("virInterfaceDefFormat unknown startmode")); return -1; } - virBufferVSprintf(buf, " <start mode='%s'/>\n", mode); + virBufferVSprintf(buf, "%*s <start mode='%s'/>\n", level*2, "", mode); return(0); } -char *virInterfaceDefFormat(virConnectPtr conn, - const virInterfaceDefPtr def) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; +static int +virInterfaceDefDevFormat(virConnectPtr conn, virBufferPtr buf, + const virInterfaceDefPtr def, int level) { const char *type = NULL; - if ((def == NULL) || - ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN))) { + if (def == NULL) { virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("virInterfaceDefFormat argument problems")); + "%s", _("virInterfaceDefFormat NULL def")); + goto cleanup; + } + + if ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN)) { + virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("virInterfaceDefFormat missing interface name")); goto cleanup; } @@ -1228,56 +1156,72 @@ char *virInterfaceDefFormat(virConnectPtr conn, goto cleanup; } - virBufferVSprintf(&buf, "<interface type='%s' ", type); + virBufferVSprintf(buf, "%*s<interface type='%s' ", level*2, "", type); if (def->name != NULL) - virBufferEscapeString(&buf, "name='%s'", def->name); - virBufferAddLit(&buf, ">\n"); + virBufferEscapeString(buf, "name='%s'", def->name); + virBufferAddLit(buf, ">\n"); switch (def->type) { case VIR_INTERFACE_TYPE_ETHERNET: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mac != NULL) - virBufferVSprintf(&buf, " <mac address='%s'/>\n", def->mac); + virBufferVSprintf(buf, "%*s <mac address='%s'/>\n", + level*2, "", def->mac); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); break; case VIR_INTERFACE_TYPE_BRIDGE: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); - virInterfaceBridgeDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); + virInterfaceBridgeDefFormat(conn, buf, def, level); break; case VIR_INTERFACE_TYPE_BOND: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); - virInterfaceBondDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); + virInterfaceBondDefFormat(conn, buf, def, level); break; case VIR_INTERFACE_TYPE_VLAN: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mac != NULL) - virBufferVSprintf(&buf, " <mac address='%s'/>\n", def->mac); + virBufferVSprintf(buf, "%*s <mac address='%s'/>\n", + level*2, "", def->mac); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); - virInterfaceVlanDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); + virInterfaceVlanDefFormat(conn, buf, def, level); break; } - virBufferAddLit(&buf, "</interface>\n"); + virBufferVSprintf(buf, "%*s</interface>\n", level*2, ""); - if (virBufferError(&buf)) + if (virBufferError(buf)) goto no_memory; - return virBufferContentAndReset(&buf); - + return 0; no_memory: virReportOOMError(conn); cleanup: - virBufferFreeAndReset(&buf); - return NULL; + return -1; +} + +char *virInterfaceDefFormat(virConnectPtr conn, + const virInterfaceDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (virInterfaceDefDevFormat(conn, &buf, def, 0) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + return virBufferContentAndReset(&buf); } /* virInterfaceObj manipulation */ diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 4216087..889ad94 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -84,14 +84,7 @@ enum virInterfaceBondArpValid { VIR_INTERFACE_BOND_ARP_ALL, /* validate all */ }; -typedef struct _virInterfaceBareDef virInterfaceBareDef; -typedef virInterfaceBareDef *virInterfaceBareDefPtr; -struct _virInterfaceBareDef { - int type; /* should be only ethernet or vlan */ - char *name; /* the interface name */ - char *mac_or_tag; /* MAC address for ethernet, TAG for vlan */ - char *devname; /* device name for vlan */ -}; +struct _virInterfaceDef; /* forward declaration required for bridge/bond */ typedef struct _virInterfaceBridgeDef virInterfaceBridgeDef; typedef virInterfaceBridgeDef *virInterfaceBridgeDefPtr; @@ -99,7 +92,7 @@ struct _virInterfaceBridgeDef { int stp; /* 0, 1 or -1 if undefined */ char *delay; int nbItf; /* number of defined interfaces */ - virInterfaceBareDefPtr *itf;/* interfaces */ + struct _virInterfaceDef **itf;/* interfaces */ }; typedef struct _virInterfaceBondDef virInterfaceBondDef; @@ -115,7 +108,7 @@ struct _virInterfaceBondDef { char *target; /* arp monitoring target */ int validate; /* virInterfaceBondArpmValid */ int nbItf; /* number of defined interfaces */ - virInterfaceBareDefPtr *itf; /* interfaces ethernet only */ + struct _virInterfaceDef **itf; /* interfaces ethernet only */ }; typedef struct _virInterfaceVlanDef virInterfaceVlanDef; -- 1.6.6.rc2.5.g49666

On 01/01/2010 08:40 PM, Laine Stump wrote:
This was accomplished in xml parsing by doing away with the stripped-down virInterfaceBareDef object, and just always using virInterfaceDef, but with restrictions in certain places (eg, the type of subordinate interface allowed in parsing depends on the parent interface).
xml formatting was similarly adjusted. In addition, the formatting functions keep track of the level of interface nesting, and insert extra leading spaces on each line accordingly (using %*s).
Kind of unfortunate churn, and certainly makes the XML building uglier, but it works and is fairly simple.
The only change in formatted xml from previous (aside frmo supporting new combinations of interface types) is that the subordinate ethernet interfaces take up 2 lines rather than one, eg:
<interface type='ethernet' name='eth0'> </interface>
instead of:
<interface type='ethernet' name='eth0'/>
ACK - Cole

On 01/01/2010 08:40 PM, Laine Stump wrote:
+ + if (((parentIfType == VIR_INTERFACE_TYPE_BOND) + && (type != VIR_INTERFACE_TYPE_ETHERNET)) + || ((parentIfType == VIR_INTERFACE_TYPE_BRIDGE) + && (type != VIR_INTERFACE_TYPE_ETHERNET) + && (type != VIR_INTERFACE_TYPE_BOND) + && (type != VIR_INTERFACE_TYPE_VLAN)) + || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET) + || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) + { + virInterfaceReportError(conn, VIR_ERR_XML_ERROR, + _("interface has unsupported type '%s'"), type); + goto error; + }
Actually, I just built and the above line produces an error. 'type' is an int, so can't be formatted with '%s'. - Cole

On Fri, Jan 01, 2010 at 08:40:25PM -0500, Laine Stump wrote:
This was accomplished in xml parsing by doing away with the stripped-down virInterfaceBareDef object, and just always using virInterfaceDef, but with restrictions in certain places (eg, the type of subordinate interface allowed in parsing depends on the parent interface).
xml formatting was similarly adjusted. In addition, the formatting functions keep track of the level of interface nesting, and insert extra leading spaces on each line accordingly (using %*s).
Ohh, i didn't know about %*s
The only change in formatted xml from previous (aside frmo supporting new combinations of interface types) is that the subordinate ethernet interfaces take up 2 lines rather than one, eg:
<interface type='ethernet' name='eth0'> </interface>
instead of:
<interface type='ethernet' name='eth0'/> --- src/conf/interface_conf.c | 362 +++++++++++++++++++-------------------------- src/conf/interface_conf.h | 13 +-- 2 files changed, 156 insertions(+), 219 deletions(-)
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index d7821e7..6efc8aa 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -39,21 +39,18 @@ VIR_ENUM_IMPL(virInterface, VIR_INTERFACE_TYPE_LAST, "ethernet", "bridge", "bond", "vlan" )
+static virInterfaceDefPtr +virInterfaceDefParseXML(virConnectPtr conn, + xmlXPathContextPtr ctxt, int parentIfType); +static int +virInterfaceDefDevFormat(virConnectPtr conn, virBufferPtr buf, + const virInterfaceDefPtr def, int level); + #define virInterfaceReportError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_INTERFACE, code, __FILE__, \ __FUNCTION__, __LINE__, fmt)
static -void virInterfaceBareDefFree(virInterfaceBareDefPtr def) { - if (def == NULL) - return; - VIR_FREE(def->name); - VIR_FREE(def->mac_or_tag); - VIR_FREE(def->devname); - VIR_FREE(def); -} - -static void virInterfaceIpDefFree(virInterfaceIpDefPtr def) { if (def == NULL) return; @@ -90,7 +87,7 @@ void virInterfaceDefFree(virInterfaceDefPtr def) case VIR_INTERFACE_TYPE_BRIDGE: for (i = 0;i < def->data.bridge.nbItf;i++) { if (def->data.bridge.itf[i] != NULL) - virInterfaceBareDefFree(def->data.bridge.itf[i]); + virInterfaceDefFree(def->data.bridge.itf[i]); else break; /* to cope with half parsed data on errors */ } @@ -100,7 +97,7 @@ void virInterfaceDefFree(virInterfaceDefPtr def) VIR_FREE(def->data.bond.target); for (i = 0;i < def->data.bond.nbItf;i++) { if (def->data.bond.itf[i] != NULL) - virInterfaceBareDefFree(def->data.bond.itf[i]); + virInterfaceDefFree(def->data.bond.itf[i]); else break; /* to cope with half parsed data on errors */ } @@ -121,11 +118,9 @@ void virInterfaceDefFree(virInterfaceDefPtr def) }
static int -virInterfaceDefParseBasicAttrs(virConnectPtr conn, virInterfaceDefPtr def, - xmlXPathContextPtr ctxt) { +virInterfaceDefParseName(virConnectPtr conn, virInterfaceDefPtr def, + xmlXPathContextPtr ctxt) { char *tmp; - unsigned long mtu; - int ret;
tmp = virXPathString(conn, "string(./@name)", ctxt); if (tmp == NULL) { @@ -134,6 +129,14 @@ virInterfaceDefParseBasicAttrs(virConnectPtr conn, virInterfaceDefPtr def, return(-1); } def->name = tmp; + return(0); +} + +static int +virInterfaceDefParseMtu(virConnectPtr conn, virInterfaceDefPtr def, + xmlXPathContextPtr ctxt) { + unsigned long mtu; + int ret;
ret = virXPathULong(conn, "string(./mtu/@size)", ctxt, &mtu); if ((ret == -2) || ((ret == 0) && (mtu > 100000))) { @@ -478,80 +481,12 @@ error:
}
-static virInterfaceBareDefPtr -virInterfaceDefParseBareInterface(virConnectPtr conn, xmlXPathContextPtr ctxt, - int ethernet_only) { - int t; - char *name = NULL; - char *type = NULL; - char *mac_or_tag = NULL; - char *devname = NULL; - virInterfaceBareDefPtr ret = NULL; - - type = virXPathString(conn, "string(./@type)", ctxt); - if (type == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - "%s", _("interface has no type")); - goto error; - } - if (STREQ(type, "ethernet")) { - t = VIR_INTERFACE_TYPE_ETHERNET; - name = virXPathString(conn, "string(./@name)", ctxt); - mac_or_tag = virXPathString(conn, "string(./mac/@address)", ctxt); - } else if ((STREQ(type, "vlan")) && (ethernet_only == 0)) { - t = VIR_INTERFACE_TYPE_VLAN; - name = virXPathString(conn, "string(./@name)", ctxt); - mac_or_tag = virXPathString(conn, "string(./vlan/@tag)", ctxt); - devname = virXPathString(conn, "string(./vlan/interface/@name)", ctxt); - } else { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("interface has unsupported type '%s'"), type); - VIR_FREE(type); - goto error; - } - VIR_FREE(type); - if (name == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - "%s", _("interface has no name")); - goto error; - } - if (t == VIR_INTERFACE_TYPE_VLAN) { - if (mac_or_tag == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("vlan %s has no tag"), name); - goto error; - } - if (devname == NULL) { - virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("vlan %s has interface name"), name); - goto error; - } - } - if (VIR_ALLOC(ret) < 0) { - virReportOOMError(conn); - goto error; - } - ret->type = t; - ret->name = name; - ret->mac_or_tag = mac_or_tag; - ret->devname = devname; - return(ret); - -error: - VIR_FREE(name); - VIR_FREE(type); - VIR_FREE(name); - VIR_FREE(name); - VIR_FREE(ret); - return(NULL); -} - static int virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr *interfaces = NULL; xmlNodePtr bridge; - virInterfaceBareDefPtr itf; + virInterfaceDefPtr itf; int nbItf, i; int ret = 0;
@@ -573,7 +508,7 @@ virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def,
for (i = 0; i < nbItf;i++) { ctxt->node = interfaces[i]; - itf = virInterfaceDefParseBareInterface(conn, ctxt, 0); + itf = virInterfaceDefParseXML(conn, ctxt, VIR_INTERFACE_TYPE_BRIDGE); if (itf == NULL) { ret = -1; def->data.bridge.nbItf = i; @@ -594,7 +529,7 @@ virInterfaceDefParseBondItfs(virConnectPtr conn, virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr *interfaces = NULL; xmlNodePtr bond = ctxt->node; - virInterfaceBareDefPtr itf; + virInterfaceDefPtr itf; int nbItf, i; int ret = 0;
@@ -614,7 +549,7 @@ virInterfaceDefParseBondItfs(virConnectPtr conn, virInterfaceDefPtr def,
for (i = 0; i < nbItf;i++) { ctxt->node = interfaces[i]; - itf = virInterfaceDefParseBareInterface(conn, ctxt, 1); + itf = virInterfaceDefParseXML(conn, ctxt, VIR_INTERFACE_TYPE_BOND); if (itf == NULL) { ret = -1; def->data.bond.nbItf = i; @@ -732,7 +667,8 @@ virInterfaceDefParseVlan(virConnectPtr conn, virInterfaceDefPtr def, }
static virInterfaceDefPtr -virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { +virInterfaceDefParseXML(virConnectPtr conn, + xmlXPathContextPtr ctxt, int parentIfType) { virInterfaceDefPtr def; int type; char *tmp; @@ -758,25 +694,46 @@ virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { virReportOOMError(conn); return NULL; } + + if (((parentIfType == VIR_INTERFACE_TYPE_BOND) + && (type != VIR_INTERFACE_TYPE_ETHERNET)) + || ((parentIfType == VIR_INTERFACE_TYPE_BRIDGE) + && (type != VIR_INTERFACE_TYPE_ETHERNET) + && (type != VIR_INTERFACE_TYPE_BOND) + && (type != VIR_INTERFACE_TYPE_VLAN)) + || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET) + || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) + { + virInterfaceReportError(conn, VIR_ERR_XML_ERROR, + _("interface has unsupported type '%s'"), type); + goto error; + } def->type = type; switch (type) { case VIR_INTERFACE_TYPE_ETHERNET: - if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0) + if (virInterfaceDefParseName(conn, def, ctxt) < 0) goto error; tmp = virXPathString(conn, "string(./mac/@address)", ctxt); if (tmp != NULL) def->mac = tmp; - if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) - goto error; - if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) - goto error; + if (parentIfType == VIR_INTERFACE_TYPE_LAST) { + /* only recognize these in toplevel bond interfaces */ + if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseMtu(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) + goto error; + } break; case VIR_INTERFACE_TYPE_BRIDGE: { xmlNodePtr bridge;
+ if (virInterfaceDefParseName(conn, def, ctxt) < 0) + goto error; if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) goto error; - if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0) + if (virInterfaceDefParseMtu(conn, def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) goto error; @@ -811,12 +768,18 @@ virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) { case VIR_INTERFACE_TYPE_BOND: { xmlNodePtr bond;
- if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0) - goto error; - if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) - goto error; - if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) + if (virInterfaceDefParseName(conn, def, ctxt) < 0) goto error; + if (parentIfType == VIR_INTERFACE_TYPE_LAST) { + /* only recognize these in toplevel bond interfaces */ + if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseMtu(conn, def, ctxt) < 0) + goto error; + if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0) + goto error; + } + bond = virXPathNode(conn, "./bond[1]", ctxt); if (bond == NULL) { virInterfaceReportError(conn, VIR_ERR_XML_ERROR, @@ -881,7 +844,7 @@ virInterfaceDefPtr virInterfaceDefParseNode(virConnectPtr conn, }
ctxt->node = root; - def = virInterfaceDefParseXML(conn, ctxt); + def = virInterfaceDefParseXML(conn, ctxt, VIR_INTERFACE_TYPE_LAST);
cleanup: xmlXPathFreeContext(ctxt); @@ -990,58 +953,12 @@ cleanup: }
static int -virInterfaceBareDevDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED, - virBufferPtr buf, - const virInterfaceBareDefPtr def) { - if (def->type == VIR_INTERFACE_TYPE_ETHERNET) { - if (def->name == NULL) { - virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("bare ethernet has no name")); - return(-1); - } - virBufferVSprintf(buf, " <interface type='ethernet' name='%s'", - def->name); - if (def->mac_or_tag != NULL) { - virBufferVSprintf(buf, ">\n <mac address='%s'/>\n", - def->mac_or_tag); - virBufferAddLit(buf, " </interface>\n"); - } else { - virBufferAddLit(buf, "/>\n"); - } - } else if (def->type == VIR_INTERFACE_TYPE_VLAN) { - virBufferAddLit(buf, " <interface type='vlan'"); - if (def->name != NULL) - virBufferVSprintf(buf, " name='%s'", def->name); - if (def->mac_or_tag != NULL) { - virBufferAddLit(buf, ">\n"); - virBufferVSprintf(buf, " <vlan tag='%s'", def->mac_or_tag); - if (def->devname != NULL) { - virBufferAddLit(buf, ">\n"); - virBufferVSprintf(buf, " <interface name='%s'/>\n", - def->devname); - virBufferAddLit(buf, " </vlan>\n"); - } else - virBufferAddLit(buf, "/>\n"); - virBufferAddLit(buf, " </interface>\n"); - } else { - virBufferAddLit(buf, "/>\n"); - } - } else { - virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("bare interface type %d unknown"), - def->type); - return(-1); - } - return(0); -} - -static int virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf, - const virInterfaceDefPtr def) { + const virInterfaceDefPtr def, int level) { int i; int ret = 0;
- virBufferAddLit(buf, " <bridge"); + virBufferVSprintf(buf, "%*s <bridge", level*2, ""); if (def->data.bridge.stp == 1) virBufferAddLit(buf, " stp='on'"); else if (def->data.bridge.stp == 0) @@ -1051,22 +968,22 @@ virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf, virBufferAddLit(buf, ">\n");
for (i = 0;i < def->data.bridge.nbItf;i++) { - if (virInterfaceBareDevDefFormat(conn, buf, def->data.bridge.itf[i]) - < 0) + if (virInterfaceDefDevFormat(conn, buf, + def->data.bridge.itf[i], level+2) < 0) ret = -1; }
- virBufferAddLit(buf, " </bridge>\n"); + virBufferVSprintf(buf, "%*s </bridge>\n", level*2, ""); return(ret); }
static int virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, - const virInterfaceDefPtr def) { + const virInterfaceDefPtr def, int level) { int i; int ret = 0;
- virBufferAddLit(buf, " <bond"); + virBufferVSprintf(buf, "%*s <bond", level*2, ""); if (def->data.bond.mode == VIR_INTERFACE_BOND_BALRR) virBufferAddLit(buf, " mode='balance-rr'"); else if (def->data.bond.mode == VIR_INTERFACE_BOND_ABACKUP) @@ -1084,8 +1001,8 @@ virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, virBufferAddLit(buf, ">\n");
if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_MII) { - virBufferVSprintf(buf, " <miimon freq='%d'", - def->data.bond.frequency); + virBufferVSprintf(buf, "%*s <miimon freq='%d'", + level*2, "", def->data.bond.frequency); if (def->data.bond.downdelay > 0) virBufferVSprintf(buf, " downdelay='%d'", def->data.bond.downdelay); if (def->data.bond.updelay > 0) @@ -1101,7 +1018,8 @@ virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, "%s", _("bond arp monitoring has no target")); return(-1); } - virBufferVSprintf(buf, " <arpmon interval='%d' target='%s'", + virBufferVSprintf(buf, "%*s <arpmon interval='%d' target='%s'", + level*2, "", def->data.bond.interval, def->data.bond.target); if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ACTIVE) virBufferAddLit(buf, " validate='active'"); @@ -1112,29 +1030,30 @@ virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } for (i = 0;i < def->data.bond.nbItf;i++) { - if (virInterfaceBareDevDefFormat(conn, buf, def->data.bond.itf[i]) < 0) + if (virInterfaceDefDevFormat(conn, buf, def->data.bond.itf[i], level+2) < 0) ret = -1; }
- virBufferAddLit(buf, " </bond>\n"); + virBufferVSprintf(buf, "%*s </bond>\n", level*2, ""); return(ret); }
static int virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf, - const virInterfaceDefPtr def) { + const virInterfaceDefPtr def, int level) { if (def->data.vlan.tag == NULL) { virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("vlan misses the tag name")); return(-1); }
- virBufferVSprintf(buf, " <vlan tag='%s'", def->data.vlan.tag); + virBufferVSprintf(buf, "%*s <vlan tag='%s'", + level*2, "", def->data.vlan.tag); if (def->data.vlan.devname != NULL) { virBufferAddLit(buf, ">\n"); - virBufferVSprintf(buf, " <interface name='%s'/>\n", - def->data.vlan.devname); - virBufferAddLit(buf, " </vlan>\n"); + virBufferVSprintf(buf, "%*s <interface name='%s'/>\n", + level*2, "", def->data.vlan.devname); + virBufferVSprintf(buf, "%*s </vlan>\n", level*2, ""); } else virBufferAddLit(buf, "/>\n"); return(0); @@ -1142,30 +1061,34 @@ virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf,
static int virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED, - virBufferPtr buf, const virInterfaceDefPtr def) { + virBufferPtr buf, const virInterfaceDefPtr def, + int level) { int pp, ii;
for (pp = 0; pp < def->nprotos; pp++) {
- virBufferVSprintf(buf, " <protocol family='%s'>\n", def->protos[pp]->family); + virBufferVSprintf(buf, "%*s <protocol family='%s'>\n", + level*2, "", def->protos[pp]->family);
if (def->protos[pp]->autoconf) { - virBufferAddLit(buf, " <autoconf/>\n"); + virBufferVSprintf(buf, "%*s <autoconf/>\n", level*2, ""); }
if (def->protos[pp]->dhcp) { if (def->protos[pp]->peerdns == 0) - virBufferAddLit(buf, " <dhcp peerdns='no'/>\n"); + virBufferVSprintf(buf, "%*s <dhcp peerdns='no'/>\n", + level*2, ""); else if (def->protos[pp]->peerdns == 1) - virBufferAddLit(buf, " <dhcp peerdns='yes'/>\n"); + virBufferVSprintf(buf, "%*s <dhcp peerdns='yes'/>\n", + level*2, ""); else - virBufferAddLit(buf, " <dhcp/>\n"); + virBufferVSprintf(buf, "%*s <dhcp/>\n", level*2, ""); }
for (ii = 0; ii < def->protos[pp]->nips; ii++) { if (def->protos[pp]->ips[ii]->address != NULL) {
- virBufferVSprintf(buf, " <ip address='%s'", + virBufferVSprintf(buf, "%*s <ip address='%s'", level*2, "", def->protos[pp]->ips[ii]->address); if (def->protos[pp]->ips[ii]->prefix != 0) { virBufferVSprintf(buf, " prefix='%d'", @@ -1175,18 +1098,19 @@ virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED, } } if (def->protos[pp]->gateway != NULL) { - virBufferVSprintf(buf, " <route gateway='%s'/>\n", - def->protos[pp]->gateway); + virBufferVSprintf(buf, "%*s <route gateway='%s'/>\n", + level*2, "", def->protos[pp]->gateway); }
- virBufferAddLit(buf, " </protocol>\n"); + virBufferVSprintf(buf, "%*s </protocol>\n", level*2, ""); } return(0); }
static int virInterfaceStartmodeDefFormat(virConnectPtr conn, virBufferPtr buf, - enum virInterfaceStartMode startmode) { + enum virInterfaceStartMode startmode, + int level) { const char *mode; switch (startmode) { case VIR_INTERFACE_START_UNSPECIFIED: @@ -1205,20 +1129,24 @@ virInterfaceStartmodeDefFormat(virConnectPtr conn, virBufferPtr buf, "%s", _("virInterfaceDefFormat unknown startmode")); return -1; } - virBufferVSprintf(buf, " <start mode='%s'/>\n", mode); + virBufferVSprintf(buf, "%*s <start mode='%s'/>\n", level*2, "", mode); return(0); }
-char *virInterfaceDefFormat(virConnectPtr conn, - const virInterfaceDefPtr def) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; +static int +virInterfaceDefDevFormat(virConnectPtr conn, virBufferPtr buf, + const virInterfaceDefPtr def, int level) { const char *type = NULL;
- if ((def == NULL) || - ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN))) { + if (def == NULL) { virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("virInterfaceDefFormat argument problems")); + "%s", _("virInterfaceDefFormat NULL def")); + goto cleanup; + } + + if ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN)) { + virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("virInterfaceDefFormat missing interface name")); goto cleanup; }
@@ -1228,56 +1156,72 @@ char *virInterfaceDefFormat(virConnectPtr conn, goto cleanup; }
- virBufferVSprintf(&buf, "<interface type='%s' ", type); + virBufferVSprintf(buf, "%*s<interface type='%s' ", level*2, "", type); if (def->name != NULL) - virBufferEscapeString(&buf, "name='%s'", def->name); - virBufferAddLit(&buf, ">\n"); + virBufferEscapeString(buf, "name='%s'", def->name); + virBufferAddLit(buf, ">\n");
switch (def->type) { case VIR_INTERFACE_TYPE_ETHERNET: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mac != NULL) - virBufferVSprintf(&buf, " <mac address='%s'/>\n", def->mac); + virBufferVSprintf(buf, "%*s <mac address='%s'/>\n", + level*2, "", def->mac); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); break; case VIR_INTERFACE_TYPE_BRIDGE: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); - virInterfaceBridgeDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); + virInterfaceBridgeDefFormat(conn, buf, def, level); break; case VIR_INTERFACE_TYPE_BOND: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); - virInterfaceBondDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); + virInterfaceBondDefFormat(conn, buf, def, level); break; case VIR_INTERFACE_TYPE_VLAN: - virInterfaceStartmodeDefFormat(conn, &buf, def->startmode); + virInterfaceStartmodeDefFormat(conn, buf, def->startmode, level); if (def->mac != NULL) - virBufferVSprintf(&buf, " <mac address='%s'/>\n", def->mac); + virBufferVSprintf(buf, "%*s <mac address='%s'/>\n", + level*2, "", def->mac); if (def->mtu != 0) - virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu); - virInterfaceProtocolDefFormat(conn, &buf, def); - virInterfaceVlanDefFormat(conn, &buf, def); + virBufferVSprintf(buf, "%*s <mtu size='%d'/>\n", + level*2, "", def->mtu); + virInterfaceProtocolDefFormat(conn, buf, def, level); + virInterfaceVlanDefFormat(conn, buf, def, level); break; }
- virBufferAddLit(&buf, "</interface>\n"); + virBufferVSprintf(buf, "%*s</interface>\n", level*2, "");
- if (virBufferError(&buf)) + if (virBufferError(buf)) goto no_memory; - return virBufferContentAndReset(&buf); - + return 0; no_memory: virReportOOMError(conn); cleanup: - virBufferFreeAndReset(&buf); - return NULL; + return -1; +} + +char *virInterfaceDefFormat(virConnectPtr conn, + const virInterfaceDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (virInterfaceDefDevFormat(conn, &buf, def, 0) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + return virBufferContentAndReset(&buf); }
/* virInterfaceObj manipulation */ diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 4216087..889ad94 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -84,14 +84,7 @@ enum virInterfaceBondArpValid { VIR_INTERFACE_BOND_ARP_ALL, /* validate all */ };
-typedef struct _virInterfaceBareDef virInterfaceBareDef; -typedef virInterfaceBareDef *virInterfaceBareDefPtr; -struct _virInterfaceBareDef { - int type; /* should be only ethernet or vlan */ - char *name; /* the interface name */ - char *mac_or_tag; /* MAC address for ethernet, TAG for vlan */ - char *devname; /* device name for vlan */ -}; +struct _virInterfaceDef; /* forward declaration required for bridge/bond */
typedef struct _virInterfaceBridgeDef virInterfaceBridgeDef; typedef virInterfaceBridgeDef *virInterfaceBridgeDefPtr; @@ -99,7 +92,7 @@ struct _virInterfaceBridgeDef { int stp; /* 0, 1 or -1 if undefined */ char *delay; int nbItf; /* number of defined interfaces */ - virInterfaceBareDefPtr *itf;/* interfaces */ + struct _virInterfaceDef **itf;/* interfaces */ };
typedef struct _virInterfaceBondDef virInterfaceBondDef; @@ -115,7 +108,7 @@ struct _virInterfaceBondDef { char *target; /* arp monitoring target */ int validate; /* virInterfaceBondArpmValid */ int nbItf; /* number of defined interfaces */ - virInterfaceBareDefPtr *itf; /* interfaces ethernet only */ + struct _virInterfaceDef **itf; /* interfaces ethernet only */ };
typedef struct _virInterfaceVlanDef virInterfaceVlanDef;
ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

The RNG now supports IPv6 and bonds attached to bridges, along with some other minor tweaks. All test files from netcf have been copied to the test directory and added to the xml2xml and schema tests (and they all pass, of course ;-) --- docs/schemas/interface.rng | 316 ++++++++++++++-------- tests/interfaceschemadata/bond-arp.xml | 6 +- tests/interfaceschemadata/bond.xml | 6 +- tests/interfaceschemadata/bridge-bond.xml | 17 ++ tests/interfaceschemadata/bridge-empty.xml | 6 + tests/interfaceschemadata/bridge-no-address.xml | 3 +- tests/interfaceschemadata/bridge-vlan.xml | 2 +- tests/interfaceschemadata/bridge.xml | 5 +- tests/interfaceschemadata/bridge42.xml | 3 +- tests/interfaceschemadata/ipv6-autoconf-dhcp.xml | 7 + tests/interfaceschemadata/ipv6-autoconf.xml | 6 + tests/interfaceschemadata/ipv6-dhcp.xml | 6 + tests/interfaceschemadata/ipv6-local.xml | 5 + tests/interfaceschemadata/ipv6-static-multi.xml | 8 + tests/interfaceschemadata/ipv6-static.xml | 7 + tests/interfacexml2xmltest.c | 9 + 16 files changed, 288 insertions(+), 124 deletions(-) create mode 100644 tests/interfaceschemadata/bridge-bond.xml create mode 100644 tests/interfaceschemadata/bridge-empty.xml create mode 100644 tests/interfaceschemadata/ipv6-autoconf-dhcp.xml create mode 100644 tests/interfaceschemadata/ipv6-autoconf.xml create mode 100644 tests/interfaceschemadata/ipv6-dhcp.xml create mode 100644 tests/interfaceschemadata/ipv6-local.xml create mode 100644 tests/interfaceschemadata/ipv6-static-multi.xml create mode 100644 tests/interfaceschemadata/ipv6-static.xml diff --git a/docs/schemas/interface.rng b/docs/schemas/interface.rng index bed2f0a..a0df9ba 100644 --- a/docs/schemas/interface.rng +++ b/docs/schemas/interface.rng @@ -1,7 +1,13 @@ <!-- A Relax NG schema for network interfaces --> <grammar xmlns="http://relaxng.org/ns/structure/1.0" + xmlns:v="http://netcf.org/xml/version/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> - <start> + <!-- Versions for this schema are simple integers that are incremented + everytime a changed (but backwards compatible) version + is released. The current version is indicated with the v:serial + attribute on the start element. + --> + <start v:serial="4"> <choice> <ref name="ethernet-interface"/> <ref name="bridge-interface"/> @@ -109,12 +115,17 @@ <ref name="on-or-off"/> </attribute> </optional> - <oneOrMore> + <!-- Bridge forward delay (see 'brctl setfd') --> + <optional v:since="2"> + <attribute name="delay"><ref name="timeval"/></attribute> + </optional> + <zeroOrMore> <choice> <ref name="bare-ethernet-interface"/> <ref name="bare-vlan-interface"/> + <ref v:since="2" name="bare-bond-interface"/> </choice> - </oneOrMore> + </zeroOrMore> </element> </element> </define> @@ -125,90 +136,105 @@ <!-- Bonds --> - <define name="bond-interface"> - <element name="interface"> - <attribute name="type"> - <value>bond</value> - </attribute> - <ref name="name-attr"/> - <ref name="startmode"/> - <ref name="mtu"/> - <ref name="interface-addressing"/> - <element name="bond"> - <optional> - <attribute name="mode"> - <choice> - <value>balance-rr</value> - <!-- The primary interface is the first interface child - of the bond element --> - <value>active-backup</value> - <value>balance-xor</value> - <value>broadcast</value> - <value>802.3ad</value> - <value>balance-tlb</value> - <value>balance-alb</value> - </choice> - </attribute> - </optional> + <define name="bond-interface-common"> + <attribute name="type"> + <value>bond</value> + </attribute> + <ref name="name-attr"/> + </define> - <!-- FIXME: add more attributes + <define name="bond-element"> + <element name="bond"> + <optional> + <attribute name="mode"> + <choice> + <value>balance-rr</value> + <!-- The primary interface is the first interface child + of the bond element --> + <value>active-backup</value> + <value>balance-xor</value> + <value>broadcast</value> + <value>802.3ad</value> + <value>balance-tlb</value> + <value>balance-alb</value> + </choice> + </attribute> + </optional> - mode == 802.3ad - ad_select - lacp_rate - xmit_hash_policy + <!-- FIXME: add more attributes - mode == active-backup - fail_over_mac - num_grat_arp when mode == active-backup (since 3.3.0) - num_unsol_na when mode == active-backup (ipv6, since 3.4.0) + mode == 802.3ad + ad_select + lacp_rate + xmit_hash_policy - mode == balance-xor - xmit_hash_policy (since 2.6.3/3.2.2) - --> + mode == active-backup + fail_over_mac + num_grat_arp when mode == active-backup (since 3.3.0) + num_unsol_na when mode == active-backup (ipv6, since 3.4.0) - <choice> - <element name="miimon"> - <!-- miimon frequency in ms --> - <attribute name="freq"><ref name="uint"/></attribute> - <optional> - <attribute name="downdelay"><ref name="uint"/></attribute> - </optional> - <optional> - <attribute name="updelay"><ref name="uint"/></attribute> - </optional> - <optional> - <!-- use_carrier --> - <attribute name="carrier"> - <choice> - <!-- use MII/ETHTOOL ioctl --> - <value>ioctl</value> - <!-- use netif_carrier_ok() --> - <value>netif</value> - </choice> - </attribute> - </optional> - </element> - <element name="arpmon"> - <attribute name="interval"><ref name="uint"/></attribute> - <attribute name="target"><ref name="ipv4-addr"/></attribute> - <optional> - <attribute name="validate"> - <choice> - <value>none</value> - <value>active</value> - <value>backup</value> - <value>all</value> - </choice> - </attribute> - </optional> - </element> - </choice> - <oneOrMore> - <!-- The slave interfaces --> - <ref name="bare-ethernet-interface"/> - </oneOrMore> - </element> + mode == balance-xor + xmit_hash_policy (since 2.6.3/3.2.2) + --> + + <choice> + <element name="miimon"> + <!-- miimon frequency in ms --> + <attribute name="freq"><ref name="uint"/></attribute> + <optional> + <attribute name="downdelay"><ref name="uint"/></attribute> + </optional> + <optional> + <attribute name="updelay"><ref name="uint"/></attribute> + </optional> + <optional> + <!-- use_carrier --> + <attribute name="carrier"> + <choice> + <!-- use MII/ETHTOOL ioctl --> + <value>ioctl</value> + <!-- use netif_carrier_ok() --> + <value>netif</value> + </choice> + </attribute> + </optional> + </element> + <element name="arpmon"> + <attribute name="interval"><ref name="uint"/></attribute> + <attribute name="target"><ref name="ipv4-addr"/></attribute> + <optional> + <attribute name="validate"> + <choice> + <value>none</value> + <value>active</value> + <value>backup</value> + <value>all</value> + </choice> + </attribute> + </optional> + </element> + </choice> + <oneOrMore> + <!-- The slave interfaces --> + <ref name="bare-ethernet-interface"/> + </oneOrMore> + </element> + </define> + + <define name="bare-bond-interface"> + <element name="interface"> + <ref name="bond-interface-common"/> + <ref name="bond-element"/> + </element> + </define> + + <define name="bond-interface"> + <element name="interface"> + <ref name="bond-interface-common"/> + <ref name="startmode"/> + <ref name="mtu"/> + <ref name="interface-addressing"/> + <ref name="bond-element"/> </element> </define> @@ -245,47 +271,87 @@ different protocols --> <define name="interface-addressing"> - <optional> - <element name="protocol"> - <ref name="protocol-ipv4"/> - </element> - </optional> - </define> - - <define name="protocol-ipv4"> - <attribute name="family"> - <value>ipv4</value> - </attribute> <choice> - <element name="dhcp"> + <group> <optional> - <attribute name="peerdns"> - <ref name="yes-or-no"/> - </attribute> + <ref name="protocol-ipv4"/> </optional> - </element> - <!-- FIXME: This format should be good enough for IPv4 and IPv6, i.e. + <optional v:since="3"> + <ref name="protocol-ipv6"/> + </optional> + </group> + <group> + <optional v:since="3"> + <ref name="protocol-ipv6"/> + </optional> + <optional> + <ref name="protocol-ipv4"/> + </optional> + </group> + </choice> + </define> - ipaddr="192.168.0.5/24" - ipaddr="2001:DB8:ABCD::1/64" + <define name="protocol-ipv4"> + <element name="protocol"> + <attribute name="family"> + <value>ipv4</value> + </attribute> + <choice> + <ref name="dhcp-element"/> + <group> + <element name="ip"> + <attribute name="address"><ref name="ipv4-addr"/></attribute> + <optional> + <attribute name="prefix"><ref name="ipv4-prefix"/></attribute> + </optional> + </element> + <optional> + <element name="route"> + <attribute name="gateway"><ref name="ipv4-addr"/></attribute> + </element> + </optional> + </group> + </choice> + </element> + </define> - but will cause some backend pain - --> - <group> + <define name="protocol-ipv6"> + <element name="protocol"> + <attribute name="family"> + <value>ipv6</value> + </attribute> + <optional> + <element name="autoconf"><empty/></element> + </optional> + <optional> + <ref name="dhcp-element"/> + </optional> + <zeroOrMore> <element name="ip"> - <attribute name="address"><ref name="ipv4-addr"/></attribute> + <attribute name="address"><ref name="ipv6-addr"/></attribute> <optional> - <attribute name="prefix"><ref name="ipv4-prefix"/></attribute> + <attribute name="prefix"><ref name="ipv6-prefix"/></attribute> </optional> </element> - <optional> - <element name="route"> - <attribute name="gateway"><ref name="ipv4-addr"/></attribute> - </element> - </optional> - </group> - </choice> + </zeroOrMore> + <optional> + <element name="route"> + <attribute name="gateway"><ref name="ipv6-addr"/></attribute> + </element> + </optional> + </element> </define> + + <define name="dhcp-element"> + <element name="dhcp"> + <optional> + <attribute name="peerdns"> + <ref name="yes-or-no"/> + </attribute> + </optional> + </element> + </define> + <!-- Jim Fehlig (<jfehlig@novell.com>) suggest the following additions to DHCP: @@ -342,6 +408,12 @@ </data> </define> + <define name="timeval"> + <data type="double"> + <param name="minInclusive">0</param> + </data> + </define> + <define name='device-name'> <data type='string'> <param name="pattern">[a-zA-Z0-9_\.\-:/]+</param> @@ -367,13 +439,27 @@ <define name='ipv4-addr'> <data type='string'> - <param name="pattern">([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9]</param> + <param name="pattern">(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))\.){3}((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))</param> </data> </define> <define name='ipv4-prefix'> + <data type='unsignedInt'> + <param name="maxInclusive">32</param> + </data> + </define> + + <!-- Based on http://blog.mes-stats.fr/2008/10/09/regex-ipv4-et-ipv6 --> + <define name='ipv6-addr'> <data type='string'> - <param name="pattern">[1-9]|[12][0-9]|3[0-2]</param> + <!-- To understand this better, take apart the toplevel '|'s --> + <param name="pattern">(([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))))|(([0-9A-Fa-f]{1,4}:){0,5}:((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))))|(::([0-9A-Fa-f]{1,4}:){0,5}((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)</param> + </data> + </define> + + <define name='ipv6-prefix'> + <data type='unsignedInt'> + <param name="maxInclusive">128</param> </data> </define> diff --git a/tests/interfaceschemadata/bond-arp.xml b/tests/interfaceschemadata/bond-arp.xml index 7b4ed6f..69e1d98 100644 --- a/tests/interfaceschemadata/bond-arp.xml +++ b/tests/interfaceschemadata/bond-arp.xml @@ -6,7 +6,9 @@ </protocol> <bond mode='active-backup'> <arpmon interval='100' target='192.168.50.1' validate='active'/> - <interface type='ethernet' name='eth1'/> - <interface type='ethernet' name='eth0'/> + <interface type='ethernet' name='eth1'> + </interface> + <interface type='ethernet' name='eth0'> + </interface> </bond> </interface> diff --git a/tests/interfaceschemadata/bond.xml b/tests/interfaceschemadata/bond.xml index 81b92e3..c4e6d40 100644 --- a/tests/interfaceschemadata/bond.xml +++ b/tests/interfaceschemadata/bond.xml @@ -6,7 +6,9 @@ </protocol> <bond mode='active-backup'> <miimon freq='100' updelay='10' carrier='ioctl'/> - <interface type='ethernet' name='eth1'/> - <interface type='ethernet' name='eth0'/> + <interface type='ethernet' name='eth1'> + </interface> + <interface type='ethernet' name='eth0'> + </interface> </bond> </interface> diff --git a/tests/interfaceschemadata/bridge-bond.xml b/tests/interfaceschemadata/bridge-bond.xml new file mode 100644 index 0000000..a8c30b9 --- /dev/null +++ b/tests/interfaceschemadata/bridge-bond.xml @@ -0,0 +1,17 @@ +<interface type='bridge' name='br0'> + <start mode='onboot'/> + <mtu size='1500'/> + <bridge stp='off'> + <interface type='ethernet' name='eth2'> + </interface> + <interface type='bond' name='bond0'> + <bond mode='active-backup'> + <miimon freq='100' updelay='10' carrier='ioctl'/> + <interface type='ethernet' name='eth1'> + </interface> + <interface type='ethernet' name='eth0'> + </interface> + </bond> + </interface> + </bridge> +</interface> diff --git a/tests/interfaceschemadata/bridge-empty.xml b/tests/interfaceschemadata/bridge-empty.xml new file mode 100644 index 0000000..72861e6 --- /dev/null +++ b/tests/interfaceschemadata/bridge-empty.xml @@ -0,0 +1,6 @@ +<interface type='bridge' name='br0'> + <start mode='onboot'/> + <mtu size='1500'/> + <bridge stp='off'> + </bridge> +</interface> diff --git a/tests/interfaceschemadata/bridge-no-address.xml b/tests/interfaceschemadata/bridge-no-address.xml index cddafb1..7757534 100644 --- a/tests/interfaceschemadata/bridge-no-address.xml +++ b/tests/interfaceschemadata/bridge-no-address.xml @@ -5,6 +5,7 @@ <interface type='ethernet' name='eth0'> <mac address='ab:bb:cc:dd:ee:ff'/> </interface> - <interface type='ethernet' name='eth1'/> + <interface type='ethernet' name='eth1'> + </interface> </bridge> </interface> diff --git a/tests/interfaceschemadata/bridge-vlan.xml b/tests/interfaceschemadata/bridge-vlan.xml index 77f992d..559ebc4 100644 --- a/tests/interfaceschemadata/bridge-vlan.xml +++ b/tests/interfaceschemadata/bridge-vlan.xml @@ -6,7 +6,7 @@ <bridge stp='off'> <interface type='vlan' name='eth0.42'> <vlan tag='42'> - <interface name='eth0'/> + <interface name='eth0'/> </vlan> </interface> </bridge> diff --git a/tests/interfaceschemadata/bridge.xml b/tests/interfaceschemadata/bridge.xml index 1f17114..2535edf 100644 --- a/tests/interfaceschemadata/bridge.xml +++ b/tests/interfaceschemadata/bridge.xml @@ -4,10 +4,11 @@ <protocol family='ipv4'> <dhcp/> </protocol> - <bridge stp='off'> + <bridge stp='off' delay='0.01'> <interface type='ethernet' name='eth0'> <mac address='ab:bb:cc:dd:ee:ff'/> </interface> - <interface type='ethernet' name='eth1'/> + <interface type='ethernet' name='eth1'> + </interface> </bridge> </interface> diff --git a/tests/interfaceschemadata/bridge42.xml b/tests/interfaceschemadata/bridge42.xml index c6639ab..199b62c 100644 --- a/tests/interfaceschemadata/bridge42.xml +++ b/tests/interfaceschemadata/bridge42.xml @@ -2,6 +2,7 @@ <start mode='onboot'/> <mtu size='1500'/> <bridge stp='off'> - <interface type='ethernet' name='eth42'/> + <interface type='ethernet' name='eth42'> + </interface> </bridge> </interface> diff --git a/tests/interfaceschemadata/ipv6-autoconf-dhcp.xml b/tests/interfaceschemadata/ipv6-autoconf-dhcp.xml new file mode 100644 index 0000000..9ea716d --- /dev/null +++ b/tests/interfaceschemadata/ipv6-autoconf-dhcp.xml @@ -0,0 +1,7 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <autoconf/> + <dhcp/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-autoconf.xml b/tests/interfaceschemadata/ipv6-autoconf.xml new file mode 100644 index 0000000..eda0ea7 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-autoconf.xml @@ -0,0 +1,6 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <autoconf/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-dhcp.xml b/tests/interfaceschemadata/ipv6-dhcp.xml new file mode 100644 index 0000000..7439539 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-dhcp.xml @@ -0,0 +1,6 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <dhcp/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-local.xml b/tests/interfaceschemadata/ipv6-local.xml new file mode 100644 index 0000000..895d0f7 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-local.xml @@ -0,0 +1,5 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-static-multi.xml b/tests/interfaceschemadata/ipv6-static-multi.xml new file mode 100644 index 0000000..f0cb00b --- /dev/null +++ b/tests/interfaceschemadata/ipv6-static-multi.xml @@ -0,0 +1,8 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <ip address='3ffe:ffff:0:5::1' prefix='128'/> + <ip address='3ffe:ffff:0:5::3' prefix='128'/> + <ip address='3ffe:ffff:0:5::5' prefix='128'/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-static.xml b/tests/interfaceschemadata/ipv6-static.xml new file mode 100644 index 0000000..e43d2a2 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-static.xml @@ -0,0 +1,7 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <ip address='3ffe:ffff:0:5::1' prefix='128'/> + <route gateway='3ffe:ffff:1234:5678::1'/> + </protocol> +</interface> diff --git a/tests/interfacexml2xmltest.c b/tests/interfacexml2xmltest.c index ed3093c..d8f1b43 100644 --- a/tests/interfacexml2xmltest.c +++ b/tests/interfacexml2xmltest.c @@ -83,11 +83,20 @@ mymain(int argc, char **argv) DO_TEST("ethernet-static-no-prefix"); DO_TEST("bridge"); DO_TEST("bridge42"); + DO_TEST("bridge-bond"); + DO_TEST("bridge-empty"); + DO_TEST("bridge-no-address"); DO_TEST("bridge-vlan"); DO_TEST("bridge-no-address"); DO_TEST("vlan"); DO_TEST("bond"); DO_TEST("bond-arp"); + DO_TEST("ipv6-autoconf-dhcp"); + DO_TEST("ipv6-autoconf"); + DO_TEST("ipv6-dhcp"); + DO_TEST("ipv6-local"); + DO_TEST("ipv6-static-multi"); + DO_TEST("ipv6-static"); return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- 1.6.6.rc2.5.g49666

On 01/01/2010 08:40 PM, Laine Stump wrote:
The RNG now supports IPv6 and bonds attached to bridges, along with some other minor tweaks. All test files from netcf have been copied to the test directory and added to the xml2xml and schema tests (and they all pass, of course ;-) ---
ACK - Cole

On Fri, Jan 01, 2010 at 08:40:26PM -0500, Laine Stump wrote:
The RNG now supports IPv6 and bonds attached to bridges, along with some other minor tweaks. All test files from netcf have been copied to the test directory and added to the xml2xml and schema tests (and they all pass, of course ;-) --- docs/schemas/interface.rng | 316 ++++++++++++++-------- tests/interfaceschemadata/bond-arp.xml | 6 +- tests/interfaceschemadata/bond.xml | 6 +- tests/interfaceschemadata/bridge-bond.xml | 17 ++ tests/interfaceschemadata/bridge-empty.xml | 6 + tests/interfaceschemadata/bridge-no-address.xml | 3 +- tests/interfaceschemadata/bridge-vlan.xml | 2 +- tests/interfaceschemadata/bridge.xml | 5 +- tests/interfaceschemadata/bridge42.xml | 3 +- tests/interfaceschemadata/ipv6-autoconf-dhcp.xml | 7 + tests/interfaceschemadata/ipv6-autoconf.xml | 6 + tests/interfaceschemadata/ipv6-dhcp.xml | 6 + tests/interfaceschemadata/ipv6-local.xml | 5 + tests/interfaceschemadata/ipv6-static-multi.xml | 8 + tests/interfaceschemadata/ipv6-static.xml | 7 + tests/interfacexml2xmltest.c | 9 + 16 files changed, 288 insertions(+), 124 deletions(-) create mode 100644 tests/interfaceschemadata/bridge-bond.xml create mode 100644 tests/interfaceschemadata/bridge-empty.xml create mode 100644 tests/interfaceschemadata/ipv6-autoconf-dhcp.xml create mode 100644 tests/interfaceschemadata/ipv6-autoconf.xml create mode 100644 tests/interfaceschemadata/ipv6-dhcp.xml create mode 100644 tests/interfaceschemadata/ipv6-local.xml create mode 100644 tests/interfaceschemadata/ipv6-static-multi.xml create mode 100644 tests/interfaceschemadata/ipv6-static.xml
diff --git a/docs/schemas/interface.rng b/docs/schemas/interface.rng index bed2f0a..a0df9ba 100644 --- a/docs/schemas/interface.rng +++ b/docs/schemas/interface.rng @@ -1,7 +1,13 @@ <!-- A Relax NG schema for network interfaces --> <grammar xmlns="http://relaxng.org/ns/structure/1.0" + xmlns:v="http://netcf.org/xml/version/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> - <start> + <!-- Versions for this schema are simple integers that are incremented + everytime a changed (but backwards compatible) version + is released. The current version is indicated with the v:serial + attribute on the start element. + --> + <start v:serial="4"> <choice> <ref name="ethernet-interface"/> <ref name="bridge-interface"/> @@ -109,12 +115,17 @@ <ref name="on-or-off"/> </attribute> </optional> - <oneOrMore> + <!-- Bridge forward delay (see 'brctl setfd') --> + <optional v:since="2"> + <attribute name="delay"><ref name="timeval"/></attribute> + </optional> + <zeroOrMore> <choice> <ref name="bare-ethernet-interface"/> <ref name="bare-vlan-interface"/> + <ref v:since="2" name="bare-bond-interface"/> </choice> - </oneOrMore> + </zeroOrMore> </element> </element> </define> @@ -125,90 +136,105 @@ <!-- Bonds --> - <define name="bond-interface"> - <element name="interface"> - <attribute name="type"> - <value>bond</value> - </attribute> - <ref name="name-attr"/> - <ref name="startmode"/> - <ref name="mtu"/> - <ref name="interface-addressing"/> - <element name="bond"> - <optional> - <attribute name="mode"> - <choice> - <value>balance-rr</value> - <!-- The primary interface is the first interface child - of the bond element --> - <value>active-backup</value> - <value>balance-xor</value> - <value>broadcast</value> - <value>802.3ad</value> - <value>balance-tlb</value> - <value>balance-alb</value> - </choice> - </attribute> - </optional> + <define name="bond-interface-common"> + <attribute name="type"> + <value>bond</value> + </attribute> + <ref name="name-attr"/> + </define>
- <!-- FIXME: add more attributes + <define name="bond-element"> + <element name="bond"> + <optional> + <attribute name="mode"> + <choice> + <value>balance-rr</value> + <!-- The primary interface is the first interface child + of the bond element --> + <value>active-backup</value> + <value>balance-xor</value> + <value>broadcast</value> + <value>802.3ad</value> + <value>balance-tlb</value> + <value>balance-alb</value> + </choice> + </attribute> + </optional>
- mode == 802.3ad - ad_select - lacp_rate - xmit_hash_policy + <!-- FIXME: add more attributes
- mode == active-backup - fail_over_mac - num_grat_arp when mode == active-backup (since 3.3.0) - num_unsol_na when mode == active-backup (ipv6, since 3.4.0) + mode == 802.3ad + ad_select + lacp_rate + xmit_hash_policy
- mode == balance-xor - xmit_hash_policy (since 2.6.3/3.2.2) - --> + mode == active-backup + fail_over_mac + num_grat_arp when mode == active-backup (since 3.3.0) + num_unsol_na when mode == active-backup (ipv6, since 3.4.0)
- <choice> - <element name="miimon"> - <!-- miimon frequency in ms --> - <attribute name="freq"><ref name="uint"/></attribute> - <optional> - <attribute name="downdelay"><ref name="uint"/></attribute> - </optional> - <optional> - <attribute name="updelay"><ref name="uint"/></attribute> - </optional> - <optional> - <!-- use_carrier --> - <attribute name="carrier"> - <choice> - <!-- use MII/ETHTOOL ioctl --> - <value>ioctl</value> - <!-- use netif_carrier_ok() --> - <value>netif</value> - </choice> - </attribute> - </optional> - </element> - <element name="arpmon"> - <attribute name="interval"><ref name="uint"/></attribute> - <attribute name="target"><ref name="ipv4-addr"/></attribute> - <optional> - <attribute name="validate"> - <choice> - <value>none</value> - <value>active</value> - <value>backup</value> - <value>all</value> - </choice> - </attribute> - </optional> - </element> - </choice> - <oneOrMore> - <!-- The slave interfaces --> - <ref name="bare-ethernet-interface"/> - </oneOrMore> - </element> + mode == balance-xor + xmit_hash_policy (since 2.6.3/3.2.2) + --> + + <choice> + <element name="miimon"> + <!-- miimon frequency in ms --> + <attribute name="freq"><ref name="uint"/></attribute> + <optional> + <attribute name="downdelay"><ref name="uint"/></attribute> + </optional> + <optional> + <attribute name="updelay"><ref name="uint"/></attribute> + </optional> + <optional> + <!-- use_carrier --> + <attribute name="carrier"> + <choice> + <!-- use MII/ETHTOOL ioctl --> + <value>ioctl</value> + <!-- use netif_carrier_ok() --> + <value>netif</value> + </choice> + </attribute> + </optional> + </element> + <element name="arpmon"> + <attribute name="interval"><ref name="uint"/></attribute> + <attribute name="target"><ref name="ipv4-addr"/></attribute> + <optional> + <attribute name="validate"> + <choice> + <value>none</value> + <value>active</value> + <value>backup</value> + <value>all</value> + </choice> + </attribute> + </optional> + </element> + </choice> + <oneOrMore> + <!-- The slave interfaces --> + <ref name="bare-ethernet-interface"/> + </oneOrMore> + </element> + </define> + + <define name="bare-bond-interface"> + <element name="interface"> + <ref name="bond-interface-common"/> + <ref name="bond-element"/> + </element> + </define> + + <define name="bond-interface"> + <element name="interface"> + <ref name="bond-interface-common"/> + <ref name="startmode"/> + <ref name="mtu"/> + <ref name="interface-addressing"/> + <ref name="bond-element"/> </element> </define>
@@ -245,47 +271,87 @@ different protocols --> <define name="interface-addressing"> - <optional> - <element name="protocol"> - <ref name="protocol-ipv4"/> - </element> - </optional> - </define> - - <define name="protocol-ipv4"> - <attribute name="family"> - <value>ipv4</value> - </attribute> <choice> - <element name="dhcp"> + <group> <optional> - <attribute name="peerdns"> - <ref name="yes-or-no"/> - </attribute> + <ref name="protocol-ipv4"/> </optional> - </element> - <!-- FIXME: This format should be good enough for IPv4 and IPv6, i.e. + <optional v:since="3"> + <ref name="protocol-ipv6"/> + </optional> + </group> + <group> + <optional v:since="3"> + <ref name="protocol-ipv6"/> + </optional> + <optional> + <ref name="protocol-ipv4"/> + </optional> + </group> + </choice> + </define>
- ipaddr="192.168.0.5/24" - ipaddr="2001:DB8:ABCD::1/64" + <define name="protocol-ipv4"> + <element name="protocol"> + <attribute name="family"> + <value>ipv4</value> + </attribute> + <choice> + <ref name="dhcp-element"/> + <group> + <element name="ip"> + <attribute name="address"><ref name="ipv4-addr"/></attribute> + <optional> + <attribute name="prefix"><ref name="ipv4-prefix"/></attribute> + </optional> + </element> + <optional> + <element name="route"> + <attribute name="gateway"><ref name="ipv4-addr"/></attribute> + </element> + </optional> + </group> + </choice> + </element> + </define>
- but will cause some backend pain - --> - <group> + <define name="protocol-ipv6"> + <element name="protocol"> + <attribute name="family"> + <value>ipv6</value> + </attribute> + <optional> + <element name="autoconf"><empty/></element> + </optional> + <optional> + <ref name="dhcp-element"/> + </optional> + <zeroOrMore> <element name="ip"> - <attribute name="address"><ref name="ipv4-addr"/></attribute> + <attribute name="address"><ref name="ipv6-addr"/></attribute> <optional> - <attribute name="prefix"><ref name="ipv4-prefix"/></attribute> + <attribute name="prefix"><ref name="ipv6-prefix"/></attribute> </optional> </element> - <optional> - <element name="route"> - <attribute name="gateway"><ref name="ipv4-addr"/></attribute> - </element> - </optional> - </group> - </choice> + </zeroOrMore> + <optional> + <element name="route"> + <attribute name="gateway"><ref name="ipv6-addr"/></attribute> + </element> + </optional> + </element> </define> + + <define name="dhcp-element"> + <element name="dhcp"> + <optional> + <attribute name="peerdns"> + <ref name="yes-or-no"/> + </attribute> + </optional> + </element> + </define> + <!-- Jim Fehlig (<jfehlig@novell.com>) suggest the following additions to DHCP:
@@ -342,6 +408,12 @@ </data> </define>
+ <define name="timeval"> + <data type="double"> + <param name="minInclusive">0</param> + </data> + </define> + <define name='device-name'> <data type='string'> <param name="pattern">[a-zA-Z0-9_\.\-:/]+</param> @@ -367,13 +439,27 @@
<define name='ipv4-addr'> <data type='string'> - <param name="pattern">([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9]</param> + <param name="pattern">(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))\.){3}((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))</param> </data> </define>
<define name='ipv4-prefix'> + <data type='unsignedInt'> + <param name="maxInclusive">32</param> + </data> + </define> + + <!-- Based on http://blog.mes-stats.fr/2008/10/09/regex-ipv4-et-ipv6 --> + <define name='ipv6-addr'> <data type='string'> - <param name="pattern">[1-9]|[12][0-9]|3[0-2]</param> + <!-- To understand this better, take apart the toplevel '|'s --> + <param name="pattern">(([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))))|(([0-9A-Fa-f]{1,4}:){0,5}:((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))))|(::([0-9A-Fa-f]{1,4}:){0,5}((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2}))))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)</param> + </data> + </define> + + <define name='ipv6-prefix'> + <data type='unsignedInt'> + <param name="maxInclusive">128</param> </data> </define>
diff --git a/tests/interfaceschemadata/bond-arp.xml b/tests/interfaceschemadata/bond-arp.xml index 7b4ed6f..69e1d98 100644 --- a/tests/interfaceschemadata/bond-arp.xml +++ b/tests/interfaceschemadata/bond-arp.xml @@ -6,7 +6,9 @@ </protocol> <bond mode='active-backup'> <arpmon interval='100' target='192.168.50.1' validate='active'/> - <interface type='ethernet' name='eth1'/> - <interface type='ethernet' name='eth0'/> + <interface type='ethernet' name='eth1'> + </interface> + <interface type='ethernet' name='eth0'> + </interface> </bond> </interface> diff --git a/tests/interfaceschemadata/bond.xml b/tests/interfaceschemadata/bond.xml index 81b92e3..c4e6d40 100644 --- a/tests/interfaceschemadata/bond.xml +++ b/tests/interfaceschemadata/bond.xml @@ -6,7 +6,9 @@ </protocol> <bond mode='active-backup'> <miimon freq='100' updelay='10' carrier='ioctl'/> - <interface type='ethernet' name='eth1'/> - <interface type='ethernet' name='eth0'/> + <interface type='ethernet' name='eth1'> + </interface> + <interface type='ethernet' name='eth0'> + </interface> </bond> </interface> diff --git a/tests/interfaceschemadata/bridge-bond.xml b/tests/interfaceschemadata/bridge-bond.xml new file mode 100644 index 0000000..a8c30b9 --- /dev/null +++ b/tests/interfaceschemadata/bridge-bond.xml @@ -0,0 +1,17 @@ +<interface type='bridge' name='br0'> + <start mode='onboot'/> + <mtu size='1500'/> + <bridge stp='off'> + <interface type='ethernet' name='eth2'> + </interface> + <interface type='bond' name='bond0'> + <bond mode='active-backup'> + <miimon freq='100' updelay='10' carrier='ioctl'/> + <interface type='ethernet' name='eth1'> + </interface> + <interface type='ethernet' name='eth0'> + </interface> + </bond> + </interface> + </bridge> +</interface> diff --git a/tests/interfaceschemadata/bridge-empty.xml b/tests/interfaceschemadata/bridge-empty.xml new file mode 100644 index 0000000..72861e6 --- /dev/null +++ b/tests/interfaceschemadata/bridge-empty.xml @@ -0,0 +1,6 @@ +<interface type='bridge' name='br0'> + <start mode='onboot'/> + <mtu size='1500'/> + <bridge stp='off'> + </bridge> +</interface> diff --git a/tests/interfaceschemadata/bridge-no-address.xml b/tests/interfaceschemadata/bridge-no-address.xml index cddafb1..7757534 100644 --- a/tests/interfaceschemadata/bridge-no-address.xml +++ b/tests/interfaceschemadata/bridge-no-address.xml @@ -5,6 +5,7 @@ <interface type='ethernet' name='eth0'> <mac address='ab:bb:cc:dd:ee:ff'/> </interface> - <interface type='ethernet' name='eth1'/> + <interface type='ethernet' name='eth1'> + </interface> </bridge> </interface> diff --git a/tests/interfaceschemadata/bridge-vlan.xml b/tests/interfaceschemadata/bridge-vlan.xml index 77f992d..559ebc4 100644 --- a/tests/interfaceschemadata/bridge-vlan.xml +++ b/tests/interfaceschemadata/bridge-vlan.xml @@ -6,7 +6,7 @@ <bridge stp='off'> <interface type='vlan' name='eth0.42'> <vlan tag='42'> - <interface name='eth0'/> + <interface name='eth0'/> </vlan> </interface> </bridge> diff --git a/tests/interfaceschemadata/bridge.xml b/tests/interfaceschemadata/bridge.xml index 1f17114..2535edf 100644 --- a/tests/interfaceschemadata/bridge.xml +++ b/tests/interfaceschemadata/bridge.xml @@ -4,10 +4,11 @@ <protocol family='ipv4'> <dhcp/> </protocol> - <bridge stp='off'> + <bridge stp='off' delay='0.01'> <interface type='ethernet' name='eth0'> <mac address='ab:bb:cc:dd:ee:ff'/> </interface> - <interface type='ethernet' name='eth1'/> + <interface type='ethernet' name='eth1'> + </interface> </bridge> </interface> diff --git a/tests/interfaceschemadata/bridge42.xml b/tests/interfaceschemadata/bridge42.xml index c6639ab..199b62c 100644 --- a/tests/interfaceschemadata/bridge42.xml +++ b/tests/interfaceschemadata/bridge42.xml @@ -2,6 +2,7 @@ <start mode='onboot'/> <mtu size='1500'/> <bridge stp='off'> - <interface type='ethernet' name='eth42'/> + <interface type='ethernet' name='eth42'> + </interface> </bridge> </interface> diff --git a/tests/interfaceschemadata/ipv6-autoconf-dhcp.xml b/tests/interfaceschemadata/ipv6-autoconf-dhcp.xml new file mode 100644 index 0000000..9ea716d --- /dev/null +++ b/tests/interfaceschemadata/ipv6-autoconf-dhcp.xml @@ -0,0 +1,7 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <autoconf/> + <dhcp/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-autoconf.xml b/tests/interfaceschemadata/ipv6-autoconf.xml new file mode 100644 index 0000000..eda0ea7 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-autoconf.xml @@ -0,0 +1,6 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <autoconf/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-dhcp.xml b/tests/interfaceschemadata/ipv6-dhcp.xml new file mode 100644 index 0000000..7439539 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-dhcp.xml @@ -0,0 +1,6 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <dhcp/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-local.xml b/tests/interfaceschemadata/ipv6-local.xml new file mode 100644 index 0000000..895d0f7 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-local.xml @@ -0,0 +1,5 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-static-multi.xml b/tests/interfaceschemadata/ipv6-static-multi.xml new file mode 100644 index 0000000..f0cb00b --- /dev/null +++ b/tests/interfaceschemadata/ipv6-static-multi.xml @@ -0,0 +1,8 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <ip address='3ffe:ffff:0:5::1' prefix='128'/> + <ip address='3ffe:ffff:0:5::3' prefix='128'/> + <ip address='3ffe:ffff:0:5::5' prefix='128'/> + </protocol> +</interface> diff --git a/tests/interfaceschemadata/ipv6-static.xml b/tests/interfaceschemadata/ipv6-static.xml new file mode 100644 index 0000000..e43d2a2 --- /dev/null +++ b/tests/interfaceschemadata/ipv6-static.xml @@ -0,0 +1,7 @@ +<interface type='ethernet' name='eth0'> + <start mode='onboot'/> + <protocol family='ipv6'> + <ip address='3ffe:ffff:0:5::1' prefix='128'/> + <route gateway='3ffe:ffff:1234:5678::1'/> + </protocol> +</interface> diff --git a/tests/interfacexml2xmltest.c b/tests/interfacexml2xmltest.c index ed3093c..d8f1b43 100644 --- a/tests/interfacexml2xmltest.c +++ b/tests/interfacexml2xmltest.c @@ -83,11 +83,20 @@ mymain(int argc, char **argv) DO_TEST("ethernet-static-no-prefix"); DO_TEST("bridge"); DO_TEST("bridge42"); + DO_TEST("bridge-bond"); + DO_TEST("bridge-empty"); + DO_TEST("bridge-no-address"); DO_TEST("bridge-vlan"); DO_TEST("bridge-no-address"); DO_TEST("vlan"); DO_TEST("bond"); DO_TEST("bond-arp"); + DO_TEST("ipv6-autoconf-dhcp"); + DO_TEST("ipv6-autoconf"); + DO_TEST("ipv6-dhcp"); + DO_TEST("ipv6-local"); + DO_TEST("ipv6-static-multi"); + DO_TEST("ipv6-static");
return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); }
ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

It's been 12 days with no responses to these patches, so I figured I'd better give them some visibility so they're not forgotten. https://www.redhat.com/archives/libvir-list/2010-January/msg00003.html

On 01/13/2010 12:09 PM, Laine Stump wrote:
It's been 12 days with no responses to these patches, so I figured I'd better give them some visibility so they're not forgotten.
https://www.redhat.com/archives/libvir-list/2010-January/msg00003.html
Dan was kind enough to review and ACK these. Now if someone could just push them... ;-)

2010/1/19 Laine Stump <laine@laine.org>:
On 01/13/2010 12:09 PM, Laine Stump wrote:
It's been 12 days with no responses to these patches, so I figured I'd better give them some visibility so they're not forgotten.
https://www.redhat.com/archives/libvir-list/2010-January/msg00003.html
Dan was kind enough to review and ACK these. Now if someone could just push them... ;-)
Okay. pushed :) I had to apply this small patch to fix a compile error: diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 6efc8aa..8a17ed6 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -705,7 +705,8 @@ virInterfaceDefParseXML(virConnectPtr conn, || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) { virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("interface has unsupported type '%s'"), type); + _("interface has unsupported type '%s'"), + virInterfaceTypeToString(type)); goto error; } def->type = type; Matthias

On 01/19/2010 03:24 PM, Matthias Bolte wrote:
2010/1/19 Laine Stump<laine@laine.org>:
On 01/13/2010 12:09 PM, Laine Stump wrote:
It's been 12 days with no responses to these patches, so I figured I'd better give them some visibility so they're not forgotten.
https://www.redhat.com/archives/libvir-list/2010-January/msg00003.html
Dan was kind enough to review and ACK these. Now if someone could just push them... ;-)
Okay. pushed :)
Thanks!
I had to apply this small patch to fix a compile error:
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 6efc8aa..8a17ed6 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -705,7 +705,8 @@ virInterfaceDefParseXML(virConnectPtr conn, || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) { virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("interface has unsupported type '%s'"), type); + _("interface has unsupported type '%s'"), + virInterfaceTypeToString(type)); goto error; } def->type = type;
This is troublesome - I'm glad you caught it. The code was so obviously wrong, and yet when I build with it (just tried it again to be sure), I don't even get a warning (I tried turning on -Werror and the whole process aborts much earlier with warnings in some other file). What CFLAGS are you giving to configure? Here's what I have: CFLAGS="-g -Wformat -Wformat-security -Winit-self -Wall -Wpointer-arith -Wextra -Wshadow -Wcast-align -Wwrite-strings -Winline -Wno-sign-compare -Wp,-D_FORTIFY_SOURCE=2 -Dlint"

2010/1/20 Laine Stump <laine@laine.org>:
On 01/19/2010 03:24 PM, Matthias Bolte wrote:
2010/1/19 Laine Stump<laine@laine.org>:
On 01/13/2010 12:09 PM, Laine Stump wrote:
It's been 12 days with no responses to these patches, so I figured I'd better give them some visibility so they're not forgotten.
https://www.redhat.com/archives/libvir-list/2010-January/msg00003.html
Dan was kind enough to review and ACK these. Now if someone could just push them... ;-)
Okay. pushed :)
Thanks!
I had to apply this small patch to fix a compile error:
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 6efc8aa..8a17ed6 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -705,7 +705,8 @@ virInterfaceDefParseXML(virConnectPtr conn, || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) { virInterfaceReportError(conn, VIR_ERR_XML_ERROR, - _("interface has unsupported type '%s'"), type); + _("interface has unsupported type '%s'"), + virInterfaceTypeToString(type)); goto error; } def->type = type;
This is troublesome - I'm glad you caught it. The code was so obviously wrong, and yet when I build with it (just tried it again to be sure), I don't even get a warning (I tried turning on -Werror and the whole process aborts much earlier with warnings in some other file).
What CFLAGS are you giving to configure? Here's what I have:
CFLAGS="-g -Wformat -Wformat-security -Winit-self -Wall -Wpointer-arith -Wextra -Wshadow -Wcast-align -Wwrite-strings -Winline -Wno-sign-compare -Wp,-D_FORTIFY_SOURCE=2 -Dlint"
I use this line to configure: CFLAGS=-g\ -ggdb\ -O0 ./autogen.sh --prefix=/usr/local --enable-debug=yes --enable-compile-warnings=error This results in libtool running GCC 4.4.1 with this set of flags: -Wall -Wformat -Wformat-security -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wextra -Wshadow -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Winline -Wredundant-decls -Wno-sign-compare -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fasynchronous-unwind-tables -Werror -g -ggdb -O0 Matthias
participants (4)
-
Cole Robinson
-
Daniel P. Berrange
-
Laine Stump
-
Matthias Bolte