Defining Netconf Data Models using Document Schema Definition Languages (DSDL)
Plantronicsrohan@ekabal.comNortelschishol@nortel.comCESNETlhotka@cesnet.cz
Operations
NETCONF WGI-DInternet-DraftCANMOD
This document describes a concrete proposal for creating Netconf and other IETF data models using the RelaxNG schema language and the Schematron validation language, which are both part of ISO's Document Schema Definition Languages (DSDL) standard.
The NETCONF Working Group has completed a base protocol used for configuration management. This base specification defines protocol bindings and an XML container syntax for configuration and management operations, but does not include a modeling language or accompanying rules for how to model configuration and status information (in XML syntax) carried by Netconf. The IETF Operations area has a long tradition of defining data for SNMP Management Information Bases (MIBs) using the SMI to model its data. While this specific modeling approach has a number of well-understood problems, most of the data modeling features provided by SMI are still considered extremely important. Simply modeling the valid syntax rather than additional semantic relationships has caused significant interoperability problems in the past. The Netconf community concluded that a data modeling framework is needed to support ongoing development of IETF and vendor-defined management information modules.
A design team collected, clarified and categorized requirements
for a data modeling language from a broad group of IETF
participants. Many of these requirements have broad agreement within the design team. This document describes an approach that addresses all the broadly agreed requirements and the vast majority of the additional requirements.
The approach to data modeling described here uses the two most mature parts of the ISO Document Schema Definition Languages (DSDL) multi-part standard: Relax NG and Schematron (see also Part 1 of DSDL - the overview and an overview presentation on DSDL). The proposal then goes on to define additional processing and documentation annotation schema. Relax NG is a mature, traditional schema language for validating the structure of an XML document. Schematron is a rule-based schema validation language which uses XPath expressions to validate content and relational constraints. In addition, this document defines and reuses various annotation schema which can provide additional metadata about specific elements in the data model such as textual descriptions, default values, relational integrity key definitions, and whether data is configuration or status data.
This combination was created to specifically address a set of Netconf-specific modeling requirements, and in addition should be useful as a general purpose data modeling solution useful for other IETF working groups. The authors believe that reusing schema work being developed and used by other standards bodies provides substantial long-term benefits to the IETF management community, so this proposal attempts to reuse as much existing work as possible.
This document proposes a concrete data modeling environment which meets the Netconf data modeling design team requirements but is otherwise very general purpose in nature. The proposal is quite modular and draws from a number of existing standards and well-understood schemas. Relevant requirements will be mentioned in each major section, but a table of requirements is included in . In order to make it easier to compare various proposed solutions to provide a framework to define NETCONF content, each proposal produced a non-trivial data model description to generate an instance document compatible with the DHCP configuration example document in Appendix C of the requirements document. The full example data model document is shown in .
This document starts in by describing the use of RelaxNG to model XML syntax, element and attribute names, containment relationships, cardinality, data types, and simple range and pattern restrictions. RelaxNG can use its own basic type definitions or reuse the W3C XML Schema Datatypes definitions. It is also straightforward to reference one or more external libraries of data types, such as the IP and IEEE networking type libraries defined in .
While using an existing schema language is a good start toward the data modeling requirements, a data modeling solution also needs additional semantics conveyed. describes "processing annotations" which describe validation rules for instance documents based on the data model. These annotations are incorporated inline with the RelaxNG schema. Most of these validation rules can be validated either in source code generated by a human or in a machine readable way. The machine readable rules make extensive use of XPath expressions.
[TODO: illustration here]
An XSLT (Extensible Stylesheet Language: Transformations) document described in can convert the machine readable rules in a specific data model document into a Schematron validation document for that data model. This conversion is done only once each time the data model is modified.
describes how a Schematron document is used to validate an instance document, and describes a set of three different levels or phases of validation that this proposal supports. describes how Schematron can validate a very different set of rules on data model documents to make sure that they comply with specific conventions. This document defines a set of Schematron rules in , which are compatible with content restrictions imposed by Netconf.
describes how to attach document metadata (ex: title, author, dates), per element descriptions, semantic hints about elements, default values, units, and conformance status (active, deprecated, obsolete) to the data model as documentation annotations. Most of the document metadata is described using the Dublin Core metadata schemas. Default values are described using the DTD (Document Type Definition) compatibility annotations. The definition for units is copied from the units definitions used by the Geographic Markup Language GML. The rest of these annotations are defined in a RelaxNG annotation schema in .
describes the extensibility and versioning model envisioned by this proposal. It also describes the interaction between default values and extensibility in this proposal.
Finally, describes how to use the data model to support Netconf-specific requirements. In particular, this section describes how to model Netconf notifications of a nearly full DHCP scope and an IP address conflict, a Netconf-specific error response, and the definition of a new action to revoke a lease.
RelaxNG is an XML schema language developed by OASIS and then adopted by ISO as Part 2 of DSDL. It is now a full ISO standard. RelaxNG has a reputation that it is easy to read and easy to learn. RelaxNG has a solid theoretical basis, and is the canonical schema format for several major W3C standards (XHTML, SVG, XML signature, RDF). RelaxNG includes strong support for XML namespaces, treats attributes and elements similarly, and can define schemas which support (or do not support) unordered content. It can use integral types or an external data type library such as W3C XML Schema Datatypes.
Unlike W3C XML Schema (referred to later as XSD or WXS), RelaxNG only describes the structure and contents of XML documents. RelaxNG intentionally does not try to modify the information set of an XML document. For example, it does not address default values (supported in XML Data Type Definitions) or key and keyref types (supported in W3C XML Schema). Since RelaxNG supports arbitrary annotations, other languages can add semantics to a RelaxNG schema. Indeed, the RelaxNG DTD compatibility schema includes annotations for default values. The rest of DSDL also follows this modular philosophy. Part 6 of DSDL (work not started) is reserved for path-based integrity constraints (analogous to XSD keys and keyrefs).
RelaxNG has both an XML representation and a Compact representation. They can be converted automatically using open source tools such as Trang. Trang can also convert either form of RelaxNG to XSD format automatically with some minor restrictions (RelaxNG can represent some schema which XSD cannot). This document will use the Compact form for brevity and readability throughout.
In RelaxNG Compact syntax, the symbols '?' (one or zero), '+' (one or more), and '*' (zero or more) have their familiar meaning. The symbol ',' indicates the next pattern follows in order, the symbol '&' indicates that the next element can come before or after the current pattern, and the '|' symbol indicates a choice among patterns. Below is an example of a RelaxNG Compact schema snippet, simplified from the schema for the full example in this proposal.
start = element-dhcp
element-dhcp = element dhcp {
element subnet {
element network { ipv4-address-content },
element prefix-length {
xsd:short { minInclusive = "0" maxInclusive = "32" }
}
element-range?,
element leases {
element-lease*
}?,
}*
}
element-range = element range {
element low { ipv4-address-content },
element high { ipv4-address-content }
}
element-lease = element lease {
attribute ip-address { ipv4-address-content },
element starts { xsd:dateTime },
element ends { xsd:dateTime },
element mac-address { mac-address-content }
}
A full tutorial on RelaxNG is beyond the scope of this document. This proposal will try to introduce unfamiliar concepts as they appear, but in some cases, the reader may wish to consult an outside reference or tutorial. More information on RelaxNG is available in relaxng book and at the following web sites:
RelaxNG readily accepts annotations in other namespaces. For example, one of the RelaxNG DTD compatibility annotations is used to specify descriptive text about the element (shown as an initial annotation); another compatibilty annotation specifies default values (shown as a following annotation):
namespace compat = "http://relaxng.org/ns/compatibility/annotations/1.0"
element ice-cream {
[
compat:documentation ["Defines two flavors or ice cream"]
]
("vanilla" | "chocolate") >> compat:defaultValue ["chocolate"]
}
or in Relax NG XML format:
Defines two flavors of ice cream
vanillachocolatechocolate
]]>
There are a variety of reasons to add annotations, but this section of the proposal focuses on annotations which can be used to define further processing on an instance document, especially validation. Processing annotations could be implemented automatically by a machine or by a human reading descriptive text in the data model who implements source code. This document defines a new schema for both processing annotations and documentation annotations. This section begins by explaining the semantics of each of the processing annotations defined here. In our examples, this annotation schema will use the namespace prefix 'dml'.
The 'unique' annotation element specifies an expression (usually an element) that needs to be unique within a list. The annotation can follows any element definition which has a cardinality greater than one ('+' or '*'). The content of the unique element is an XPath expression which is evaluated relative to the element it follows (and its immediate parent). For example, in the following example, the 'port' element has to be unique within all other service elements under the servers element:
element-servers = element servers {
element service {
element name { xsd:string },
element port { xsd:unsignedShort }
>> dml:unique ["port"]
}+
}
# '//servers/service' must have only one 'port' with a specific value.
In terms of XPath expressions, this means that in the context '//servers/service/port', the XPath expression 'count( //servers/service[port=current()] ) = 1' needs to be true. (Does the number of service elements with a port element equal to the value of the current port element equal 1?). Expressing this rule as a series of XPath expressions makes the rule more precise, but it also enables a conversion of this constraint to a Schematron validation rule as discussed in . In the following snippet of instance document, the second http service is not allowed since its port number conflicts with another service.
ssh2222http80http2222
]]>This syntax is also capable of specifying that the combination of one or more fields is required to be unique.
In many cases, something is unique in a list because it is actually a key used in cross-element relationships. The 'key' annotation specifies that an expression can be used as a unique lookup key among the elements of a list (an element with cardinality greater than one). In addition, this key can be used in another element which is a key reference (keyref) to provide referential integrity between these related elements. As with the 'unique' element, the content of the 'key' element is an XPath expression which is evaluated relative to the element it follows (and its immediate parent).
As shown in the next example, the key can be a compound key (formed from more than one element or attribute), and it can reference descendants of arbitrary depth to form the key. The key to the subnet element in the instance document is "192.168.24.0/24".
Keys are critical for any data that will be configured or for any data that will be referenced via a keyref statement. Therefore key definitions are mandatory for all lists except as described below. For convenience, some lists have an implicit key:
list elements which have an 'id' (key) attribute with the type xsd:ID;list elements which have only an 'xml:lang' (key) attribute and only contain character data (no subelements); list elements which have no character data and a single mandatory (key) attribute; andlist elements which contain only character data (no subelements) and which have no attributes (the character data is the key).
element-dhcp = element dhcp {
element subnet {
element prefix {
element network { ipv4-address-content },
element prefix-length {
xsd:short { minInclusive = "0" maxInclusive = "32" }
}
},
element-range
>> dml:key ["concat(prefix/network, '/', prefix/prefix-length)"]
}+
}
192.168.24.024192.168.24.20192.168.24.250
]]>
The validation rule for keys are as follows: If an XML element with a maximum cardinality greater than one (for brevity a 'list element') has an 'id' attribute with type 'ID', the validation rules defined here will use the 'id' attribute as the list key. If a list element consists only of a single text value and no attributes, the validation rules defined here will use the text value as the key unless a different key definition is explicitly provided. Likewise, if a list element consists of an empty value and has only one attribute, the attribute will be used as the key unless a different key definition is explicitly provided.
The contents of the 'keyref' annotation contains an XPath expression which points to the element under which a 'key' annotation was defined. In the example in the previous section, the key element annotates the 'subnet' element. Therefore a keyref annotation referring to a specific subnet element will use the XPath expression '//dhcp:subnet'. Note that keyrefs could often refer to elements in a different namespace. For example, in the example that follows, the dhcp:interfaces-filter element consists of a list of tokens which refer to keys defined under the //int:interface schema definition.
element-subnet = element subnet {
element network { ipv4-address-content },
element prefix-length {
xsd:short { minInclusive = "0" maxInclusive = "32" }
},
element interface-filter {
element interface {
xsd:token
>> dml:keyref ["//int:interface"]
}+
}
}
element-interfaces = element int:interfaces {
element int:interface {
element int:ifIndex { xsd:token },
element int:ifType { xsd:token }
>> dml:key ["int:ifIndex"]
}+
}
10.1.1.024lo0en2lo0en1en2
]]>
Be aware that in some cases, a list may consist of elements which have both a key and keyref (a list of keyrefs).
An element in the data model tagged with the 'mustUse' annotation indicates that the tagged element needs to appear in the instance document whenever its parent appears. Items with a defaultValue annotation cannot also have a mustUse annotation.
In many schemas, there is a facility for using fragments or patches of XML documents. (Netconf uses these fragments extensively in edit-config operations for example). In order to accommodate these fragments, the cardinality of an otherwise "required" element may allow the element to be optional in an XML fragment. The mustUse annotation provides a way to express what is actually required in this situation.
See also the client-side conformance discussion in .
The 'infoType' annotation indicates the category of data that applies to the annotated element and all its children until another 'infoType' annotation. The content of the 'infoType' element is an enumeration. The 'config' type is the default value. It indicates that the covered data is configuration and that it is at least theoretically possible to include this data in read, write, create, and delete operations. Likewise 'status' and 'statistics' information can be read, but cannot be included in write, create, and delete operations.
The example below indicates that the 'leases' element and all its sub-elements are status information and not suitable for creating, writing, or deleting.
element-leases = element leases {
element lease {
attribute ip-address { ipv4-address-content },
element starts { xsd:dateTime },
element ends { xsd:dateTime },
element mac-address { mac-address-content }
}*
>> dml:infoType ["status"]
}
In addition, this annotation element has optional minAccess and maxAccess attributes which can override the default list of relevant operations. These attributes are discussed in more detail in .
Finally, the infoType is used to describe which elements are part of a
notification or other action, for example as used in and respectively.
In our DHCP example, the validation statement that "subnets can't overlap" is easy to say in English, but hard to write formally. In addition, some validation tests may be difficult or impossible to evaluate without local state information. The 'manual-validation-rule' annotation provides a natural language explanation of a validation constraint that can only be evaluated by a human. When validation rules (as in ) are automatically generated, a warning will be generated for each manual-validation-rule.
element-subnet = element subnet {
element network { ipv4-address-content },
element prefix-length {
xsd:short { minInclusive = "0" maxInclusive = "32" }
}
>> dml:manual-validation-rule [xml:lang="en"
"Subnets may not overlap"]
>> dml:manual-validation-rule [xml:lang="fr"
"Les sous-réseaux ne peuvent pas se superposer"]
}
In addition, the data model can also define additional rules formally by embedding specific Schematron rules. Schematron is a rule-based validation language for XML documents. Schematron patterns define a series of rules using XPath expressions which evaluate to a boolean value. These rules contain human language text which could be used to implement manual validation. The text node of the Schematron assert statement should provide text suitable for a human to write an equivalent validity check.
element-dhcp = element dhcp {
[
sch:pattern [
sch:rule [
context = "//dhcp:dhcp"
sch:assert [
test = "dhcp:default-lease-time <= dhcp:max-lease-time"
"Default lease time cannot be larger than maximum lease time"
]
]
]
]
element default-lease-time { xsd:unsignedInt }?,
element max-lease-time { xsd:unsignedInt }?,
...
}
The preceding example consists of a single rule. In the context of the 'dhcp' element, the value of the 'default-lease-time' element needs to be less than or equal to the value of the 'max-lease-time' element.
Both the 'dml:manual-validation-rule' and Schematron 'assert' elements can contain an attribute to convey Netconf-specific error messages. For more information, see .
Once these embedded Schematron rules are written, one vendor could enforce these rules in code, while another could validate against the embedded Schematron rules. A vendor can also use the provided XSLT transformation in to create a standalone Schematron file from the data model.
ISO Schematron is a rule-based validation language based on XPath expressions. It is Part 3 of the DSDL standard.
XPath is an expression language for defining parts of an XML document; it uses path expressions to navigate in XML documents and access XML nodes (elements, attributes, text, namespaces, processing-intructions, comments, and the root/document node. It also includes a library of functions. The XSLT and XLink specifications also rely on XPath expressions and built-in functions.
XPath uses path expressions to select nodes or node-sets in an XML document. These path expressions look very much like the expressions you see when you work with a traditional computer file system. While a complete tutorial on Schematron or tutorial on XPath is beyond the scope of this document, we will walk through a simple example to highlight the most important concepts. This example is functionally the same as the example of Schematron embedded in RelaxNG Compact in the last section. More Schematron resources are available here:
Below is a simple Schematron rule.
Default lease time cannot be larger than maximum lease time
]]>
The Schematron validator evaluates the context of each rule, then evaluates each assert or report clause within the rule. Lets look at a more complicated example that is used for insuring that a key is unique within a list context.
The value ifIndex must be unique among all interfaces.
]]>
For every ifIndex element, the 'assert' tests if the number of interfaces which have an ifIndex matching the current one (being evaluated) is one. This XPath expression is rather long. Since we will use this idiom repeatedly, we can define a Schematron abstract pattern to express this more succinctly:
The key "$key" needs to be unique within the list at: $context
]]>
Likewise, we can write Schematron abstract patterns for validating keyref relationships as well.
The contents of "$keyref-context" must be a
with the key "$key" in this context: $key-context.
]]>
Even the Schematron abstract patterns shown above contain paths that a computer could derive automatically. The XSLT stylesheet shown in reads the data model processing annotations to automatically generate Schematron patterns that use these abstract patterns. The XSLT stylesheet is just calculating the context XPaths by examining the document structure in the RelaxNG schema. Once generated, these rules can be used to test the validity of instance documents. These Schematron tests can provide different levels of validity checking.
Conceptually, an implementation can validate its instance data in different logical phases, adding more tests with each phase. We use three levels or phases for validating an instance document. There is a level of validation which is appropriate even for loose XML document fragments which still maintain their hierarchy (the fragment phase), there is a level of validation appropriate for a cohesive XML document but which may not be able to validate relational integrity checks against some operational state (the standard phase), and there is validation which includes all relational integrity checks (the full validation phase). For example, in Netconf an edit-config operation can cause the replacement a small fragment of XML. A candidate configuration may be waiting for application but can't check the readiness of a piece of hardware that the configuration refers to.
From the NETCONF perspective, these three phrases can considered to have the following scope and triggers:
the fragment phase: This can be run against individual NETCONF operations; should be automatically triggered the standard phase: This can be run against the candidate configuration, but won’t always pass; should be manually triggered the full validation phase: This can be run against a running configuration; should be automatically triggered
During the Fragment phase validation:
Verify that the content is appropriate to the operation (by passing a variable to Schematron with the type of operation)
During Standard phase validation (all rules except for keyref checking):
Verify that mustUse items are presentCheck the uniqueness for unique and key annotationsPrint a warning if any manual validation rules are present
During Full phase validation: add keyref checks.
All embedded Schematron will run in the standard phase unless the a 'dml:phase' attribute is included with the name of a different phase ('fragment' or 'full').
In addition to validating the instance data, it is necessary to validate the data model document whenever the data model itself is modified. In addition to syntax checks, the content of several of the annotations can be validated. Finally, certain bindings or usages will need to enforce constraints individual data model.
For example, Netconf needs the following restrictions:
Elements with cardinality greater than one (lists), which can have more than one child element need to have a key defined.Mixed content (non-whitespace text nodes interleaved with elements) is not allowed.All schema modules need to have a top-level version number attribute.
The Schematron file in will check these constraints.
This section describes annotations which do not have an effect on validation.
Metadata about the data model document (ex: title, author, dates) is expressed using a combination of Dublin Core metadata terms, and the DML schema defined in this document. This proposal recommends that all data models include a Dublin Core title, creator, description, and created (creation date) element. Data model authors can include any additional Dublin Core metadata which is relevant. In addition, the DML annotation schema adds an 'organization' annotation and a 'contact' annotation. Organization is a human readable string that indicates the organization responsible for the data model. It includes an optional language attribute. Contact is a URI that can be used to reach the author or maintainer of the data model. Using a mailto: URI is recommended. Finally, the version of the data model is expressed in a 'dataModelVersion' annotation.
>> dc:title [ "Example schema for DHCP server" ]
>> dml:dataModelVersion ["1.0"]
>> dc:type ["Dataset"]
>> dc:creator [ "Rohan Mahy" ]
>> dml:organization [ "as an individual" ]
>> dml:contact [ "mailto:rohan@example.org" ]
>> dc:created [ "2008-02-13" ]
Default values and semantic descriptions for individual schema items use the RelaxNG DTD compatibility annotations.
element default-lease-time {
xsd:unsignedInt
>> compat:defaultValue ["3600"] >> dml:units ["s"]
>> compat:documentation [ xml:lang="en"
"The default duration of a DHCP lease in seconds" ]
}?
Typically default values only apply to a specific version of a data model. Default values which persist for all versions of a module are identified with a special attribute as described in .
The 'units' annotation expresses the unit of measure for an element with a numeric value. The syntax for this annotation is copied from the GML (Geographic Markup Language) specification.
NOTE: It is recommended that the symbol be an identifier for a unit of measure as specified in the Unified Code of Units of Measure (UCUM) (http://aurora.regenstrief.org/UCUM). This provides a set of symbols and a grammar for constructing identifiers for units of measure that are unique, and may be easily entered with a keyboard supporting the limited character set known as 7-bit ASCII. ISO 2955 formerly provided a specification with this scope, but was withdrawn in 2001. UCUM largely follows ISO 2955 with modifications to remove ambiguities and other problems.
URL for GML specs is: http://www.opengeospatial.org/standards/gml
The compat:documentation annotation can also be used to provide general descriptions of elements, similar to the DESCRIPTION tag in SNMP MIBs.
Some schemas include container elements which have a semantic meaning (for example, to enable a specific service) when they are present even if they are empty. The 'existence' annotation provides a semantic hint to a processor that such an element cannot be omitted just because it is empty. (This document does not condone or condemn this practice.)
> dml:existence []
>> compat:documentation
["The presence of a range element turns on dynamic addressing " ~
"for the subnet. If low and high elements are missing, the " ~
"DHCP server serves dynamic addresses for the whole range " ~
"except for any router addresses on that subnet."]
}
10.254.240.022
]]>
The 'list-order' annotation conveys whether the order of a list is semantically meaningful as another semantic hint. The value 'any-order' means that order is not meaningful, while the value 'user-order' means that the order of the elements in the list are semantically meaningful. The default semantic in the absence of this annotation is that order is not semantically meaningful.
element-router-list-option = element router-list {
element router { ipv4-address-content }+
>> dml:order ["user-order"]
}
The 'status' annotation is used to convey conformance status (active, deprecated, obsolete) of a particular element. See for more detailed semantics of this annotation.
The data model can also include a 'mustUnderstand' annotation. This annotation contains a space-separated list of namespace prefixes that the consumer of the document must be able to understand to continue processing the document. This attribute can also be included in instance documents as described in .
This proposal expects large amounts of configuration will be split into modules. A module represents a cohesive set of data about a particular aspect of a device which is generally separable from other aspects of the device. For example, configuration of a DHCP server vs. a web server, or configuration of router interfaces vs. access lists.
Each module needs to have its own namespace and a module version number. Each module has a Relax NG start pattern indicating the top-level element for that module. If this module is used as a standalone document, the start pattern indicates the root element of the XML document.
If (quite likely) a device supports several modules, a configuration file can be constructed by including all the relevant modules as external references. The entire grammar from the external reference is included starting from the external start pattern. The patterns in the external grammar are locally scoped so that a pattern in one module does not conflict with another pattern of the same name in another module. In the example below, the DHCP module and the interfaces module both have an "element-interface" pattern, but this does not cause a conflict since these patterns are in different scopes.
# config-root.rnc
default namespace = "http://example.org/ns/root"
start = element-config
element-config = element config {
external "interfaces.rnc" ? &
external "dhcp.rnc" ?
}
The example above allows (and correctly validates) instance documents with the following hierarchy:
]]>
The authors envision that data model modules for Netconf and other IETF protocols will have a small set of standardized modules and potentially a much larger collection of vendor-defined modules. Often standardized modules are partially open to allow vendors to extend a data model without modifying the original core module definition. Assume that the example DHCP module is a standardized module and that a vendor wants to add two new extensions to this module.
Rather than reference the standardized module directly in 'config-root.rnc', the vendor creates a new module shim which includes the core module and then either adds new definitions or includes additional definitions. The shim can mix inline definitions with included definitions.
# dhcp+extensions.rnc
include "dhcp.rnc" # base module
include "dhcp-tz.rnc" # timezone option extension
include "dhcp-wins.rnc" # WINS server option extension
The included files redefine an existing pattern in the base module by combining the new content with the base content. Relax NG supports combination through interleave (with the "&=" operator) and combination through choice (with the "|=" operator). The example here uses combination with interleave since the base module also used interleave within the contents of 'element-dhcp-option'.
# dhcp-tz.rnc
namespace tz = "http://example.org/ns/dhcp/timezone"
element-dhcp-option &= element tz:timezone { token }?
# dhcp-wins.rnc
namespace wins = "http://example.org/ns/dhcp/wins-option"
element-dhcp-option &= element wins:wins-server { token }*
All data models defined using this proposal are expected to have at least one namespace URI per module and a top level dml:dataModelVersion attribute which provides the current version number for that module. The extensibility model suggested here has future extensibility implications motivated strongly by the importance of backwards compatibility.
Elements and attributes are never removed from the schema for a particular namespace. However, content can be deprecated in any version change. Content which was deprecated in a previous version of the same schema can be made obsolete when updating the schema to the next "major version number". Module maintainers can indicate the status of module elements using the dml:status annotation.
In some cases the "no deletion" policy will cause content to migrate to a new element name if the structure of the old element name was poorly implemented. If the model developer truly wants to reuse an element or attribute name which was made obsolete, the schema can migrate to a new namespace.
It is not acceptable to add new mandatory content (content with either a dml:mustUse annotation or content with a cardinality of at least one) without breaking backwards compatibility. While this can be a bit limiting when trying to add critical new features, adding default values (see next section) to new optional content can get around many of the limitations.
These limitation are not a result of using Relax NG, but rather based on operational experience with SNMP, CLI and other management interfaces. The goal is to provide stability to NETCONF clients (operator scripts and management applications) and other usages of this proposal using content defined using these rules.
There are a set of default values which are very stable over time and across implementations. Typically these are related to a default or constant in a protocol. For example, the example below shows a timer default defined in the SIP protocol. This example adds an attribute to the defaultValue annotation which indicates that this particular default is a module-level default and will never change for this element in this namespace:
element-sip-timers = element sip-timers {
element t1-timer {
xsd:positiveInteger
>> compat:defaultValue [ dml:moduleDefault="true"
"500" ] >> dml:units ["ms"]
}
...
}
These module defaults will be the same for all implementations of the schema across different products and different versions. Implementations themselves tend to have a set of default values which differ from this module-level default. This second type, an implementation default, differs between implementations and between versions as appropriate. In fact, different implementations may have different sets of elements for which they have defined default values.
Implementation defaults are an important feature to be able to maintain backwards compatibility. It allows for new elements to be added to a schema in a way that clients not familiar with the new elements can continue to send older configuration commands and still successfully change the configuration in a deterministic and predictable fashion. Given the static nature of module-level defaults, they will rarely be used, so implementation defaults fill this gap.
The proposal provides the ability for model developers to specify default values when applicable. Whether these values are retrieved as a result of various operations (ex: a 'get' or 'get-config' operation in Netconf) is a protocol-specific behaviour and is not prescribed by the solution. This provides the flexibility for the protocol to support both an operation which returns elements who currently have the default value and an operation which does not. It also leaves it to the protocol to decide whether or not to present elements who have been explicitly set to the same value as the default.
When a compat:defaultValue annotation appears without the dml:moduleDefault attribute, the defaultValue is an implementation (per-version) default.
While many of the features described above are motivated by Netconf, they all could be applicable or relevant to other data modeling applications. The mechanisms described below are specific to Netconf.
The get operation retrieves all data of any infoType. The get-config operation only retreives data with an infoType of 'config'.
The edit-config operation can be performed on content whose
minAccess/maxAccess allows creation, modification or deletion and
which a particular implementation has provided supported for these
operations.
Creatable content are elements whose maxAccess clause allows creation
and that exist in an implementation that supports creation of that
element. Writable content are elements whose maxAccess clause allows
writing and that exist in an implementation that supports editing of
that element. Deletable content are elements whose maxAccess clause
allows deleting and that exist in an implementation that supports
deleting of that element. Readable content are elements whose
maxAccess clause allows reading and that exist in an implementation
that supports reading of that element.
During an edit-config operation using merge, if an element or
attribute is creatable and this object does not exist, it is created.
If it is not creatable, the an error is reported. During a replace,
If the element or attribute is writeable and exists, then all child
nodes not present in the XML that are deletable are deleted, and
child nodes present in the XML but not present in the datastore which
are creatable are created. During a create, the element or attribute
is created if it does not exist, if it is creatable. During a
delete, if the element or attribute is deletable the element is
deleted if it exists. An attempt to create, modify or delete
elements or child elements when these operations are not supported
will result in an error.
The copy-config operations replaces one configuration with another.
The access writes of the individual managed resources and data
elements involved in the configuration are not taken into account in this case.
The delete-config operation deletes an entire configuration
datastore. Likewise, the access writes of the individual managed
resources and data elements involved in the configuration are not
taken into account.
Read-only data should not itself be included in an edit-config
operation, but may be included when an operation is performed on a containing element with sufficient privileges. These elements get created when their containing element is created and deleted when their containing element is deleted.
Below is the definition of two Netconf notifications. The first definition consists of completely new content. The second definition contains new content and reuses a pattern from DHCP configuration portion of the data model.
namespace rng = "http://relaxng.org/ns/structure/1.0"
namespace xsd = "http://www/w3/org/2001/XMLSchema-datatypes"
namespace xml = "http://www.w3.org/XML/1998/namespace"
namespace sch = "http://www.ascc.net/xml/schematron"
namespace dc = "http://purl.org/dc/terms"
namespace dml = "http://example.org/ns/dml"
namespace compat ="http://relaxng.org/ns/compatibility/annotations/1.0"
namespace notif = "urn:ietf:params:xml:ns:netconf:notification:rng:1.0"
namespace ns1 = "notif"
default namespace = "http://www.example.com/dhcp"
compat:documentation [
"This schema demonstrates defining two Netconf notifications." ~
"The contents of the first notification is defined using" ~
"entirely new content. The second notification reuses content" ~
"defined for use in Netconf get operations."
]
include "notifications.rnc" inherit = ns1
notificationContent |=
[
compat:documentation [
"This notification is sent out when an IP address" ~
"conflict is detected. The DHCP client discovers" ~
"its assigned address is already in use."
]
]
element dhcpAddressConflictNotification {
element ip-address { ipv4-address-content },
element rogue-mac-address {
mac-address-content
>> compat:documentation ["The conflicting MAC address"]
},
element leased-mac-address {
mac-address-content
>> compat:documentation ["The MAC address of the DHCP client"]
}
>> dml:infoType ["notify"]
}
notificationContent |=
[
compat:documentation [
"This notification is sent out when the dynamic" ~
"IP address range for a subnet is nearly full."
]
]
element dhcpScopeNearlyFullNotification {
(
element addresses-used { xsd:integer },
element addresses-avail { xsd:integer },
element-subnet
)+
>> dml:infoType ["notify"]
}
start |= notificationType
Below is an example specification of a new Netconf action.
namespace rng = "http://relaxng.org/ns/structure/1.0"
namespace xsd = "http://www/w3/org/2001/XMLSchema-datatypes"
namespace xml = "http://www.w3.org/XML/1998/namespace"
namespace sch = "http://www.ascc.net/xml/schematron"
namespace dc = "http://purl.org/dc/terms"
namespace dml = "http://example.org/ns/dml"
namespace compat ="http://relaxng.org/ns/compatibility/annotations/1.0"
namespace netconf = "urn:ietf:params:xml:ns:netconf:base:1.0"
namespace ns1 = "netconf"
default namespace = "http://www.example.com/dhcp"
compat:documentation [
"This schema defines the dhcp revoke lease rpc action"
]
include "netconf.rnc" inherit = ns1
revokeLeaseType = element revoke-lease {
element address { ipv4-address-content }+
>> dml:infoType ["action"]
}
rpcType |= revokeLeaseType
start |= rpcType
Custom Netconf error messages are available as error annotation attributes for Schematron. Schematron allows attributes from other namespaces in all its elements. The 'dml:netconf-error-app-tag' attribute can be used to provide a error-app-tag value specific to the data model. In addition, the error text can be localized in Schematron using the 'diagnostics' element.
The contents of "$keyref-context" must be a
with the key "$key" in this context: $key-context.
The contents of "$keyref-context" must be a 'keyref'
with the key "$key" in this context: $key-context.
Les contenus de "$keyref-context" droite être un 'keyref'
avec le clé "$key" dans cette contexte: $key-context
]]>
This would generate the following RPC error during an edit-config with full validation enabled:
applicationinvalid-valueerrorkeyref-failure//dhcp:subnet[@key="192.168.16.0/24]
/dhcp:interface-filter[interface='en4']
The contents of "//dhcp:interface-filter" must be a 'keyref'
with the key "//int:ifIndex" in this context: int:interface.
Les contenus de "//dhcp:interface-filter" droite être un 'keyref'
avec le clé "//int:ifIndex" dans cette contexte: int:interface
]]>
All types of XML schemas validate based on the contents of a "document". In the context of Netconf, what is considered a single XML document for validation purposes is an important issue which is directly related to the use of XML validation tools that can parse Netconf data models. Three possibilities are worth considering:
Each Netconf message is a document. Any XML inside the Netconf message (both the "envelope" and the configuration or other operational data) needs to be valid according to some combination of schema.An entire device configuration is an XML document. In this case, the schema included in a Netconf operation (especially in an edit-config or get-config operation) is logically validated separately from the Netconf "envelope". There can be mulitple documents accessible to Netconf. For example, a device can support multiple candidate configurations and a running configuration, each of which is handled as a separate XML document. This option allows individual configuration files on a disk to be validated.Each module is an XML document. This option is similar to the second option, except that a naming convention for specific instance files is needed for referential integrity validation to succeed. Breaking a configuration file into smaller logical chunks allows automatic validation to proceed more quickly and consume less memory. It also insures that validation checks are only run for configuration modules which have changed since the last validation, or which refer to modules which have changed. Another benefit of this approach is that it becomes much easier to insure that non-random id attributes are unique within the scope of a document.
One of the implications of this choice is that the starting element of an XML document needs to be specified, either in the schema language (as supported in Relax NG) or externally in text and to validators. This is an aspect of Netconf's usage of XML which is underspecified and somewhat sloppy. The full DHCP configuration example in assumes option 2 and so it defines a root config element (which would be required for option 2). However, each module include a top level element which could become the root element of its own document.
To implement option 3, the non-abstract Schematron rule described in for keyref validation would need to be modified slightly to include the correct document name. Specifically, the key-context would become something like: "document('interfaces.xml')//int:interfaces/int:interface"
This proposal also used option 1 in order to demonstrate notifications and actions which extend the Netconf protocol itself. These example could be reworked to also include the relevant configuration as an external reference to avoid naming conflicts.
Finally, part 4 of DSDL is the Namespace-based Validation Dispatching Language (NVDL) could be useful for managing modules defined using different schema languages. An NVDL script controls the dispatching of elements or attributes in a given XML document to different validators,
depending on the namespaces of the elements or attributes. An NVDL script also specifies which schemas are used by these validators. These schemas can be written in any schema language.
When defining NETCONF content, it is also necessary to define
machine-readable conformance for that content. The conformance method
described provides a means of providing information about individual
elements which is then used to calculate the schema conformance. There
is no separate definition of schema conformance. Previous solutions with
separate conformance sections were found to have issues, particularly in
keeping them up to date as the schema evolved. They also were not always
used outside of standards activities where people did not either fully
understand them or see the value in them.
Conformance specifies not only whether to object must be supported, but
also the level of access, read versus write for example that is
minimally required.
When defining attributes and elements in the XML syntax, the 'optional',
'oneOrMore' or 'zeroOrMore' tags are used to specify the cardinality of
the element. In the compact syntax, "?" means optional, "+" means one or
more, "*" means zero or more. When no cardinality indicator is present,
this is interpreted to mean exactly once.
Operations that can be performed on managed objects fall into one of the
following equivalence classes: "create", "delete", "read", "write", and
"execute". A value of "create" means it is possible to create new instances of this element. A value of "delete" means it is possible to destroy instances of this element. A value of "read" means that it is possible to view values of this element. A value of "write" means it is possible to modify an instance of this element. A value of "execute" means that there is a side effect execution such as rebooting that is permissible as a result of the command.
The kind of access which is allowed for a particular element depends on its infoType. The minimum access needed for an implementation for a specific kind of infoType is that element's 'minAccess'. The maximum access allowed is that element's 'maxAccess'. Normally these values do not need to be modified. There is a default access class for each infoType.
Data CategoryminAccessmaxAccessconfigreadread,write,create,deletestatusreadreadstatisticsreadread,deleteactionexecuteexecutenotifyreadread
However, if a specific piece of data needs a different class it can be modified using the infoType annotation's minAccess and maxAccess attributes. For example, perhaps a 'controller' element can only be created automatically as a side-effect of some other action. The example below documents this by explicitly setting the maxAccess attribute:
element-controller = element controller {
# a bunch of sub-elements of controller
# ...
>> dml:infoType [ maxAccess="read write delete" "config"]
>> compat:documentation ["Can't create a controller"]
}
To describe how this applies specifically to Netconf:
a value of "create" means it is possible to create new instances of this
element using commands like the NETCONF 'edit-config' or copy- config'
commands. A value of "delete" means it is possible to destroy instances
of this element using commands like the NETCONF 'edit-config',
'copy-config' or 'delete-config' operations. A value of "read" means
that it is possible to view values of this element using commands like
the 'get-config', 'get' or 'notification' operations. A value of
"write" means it is possible to modify an instance of this element using
commands like the NETCONF 'edit-config' or 'copy- config' commands. A
value of "execute" means that there is a side effect execution such as
rebooting that is permissible as a result of the command. For example,
commands like the NETCONF 'edit-config' or a 'copy-config' command or
the ability to execute a commands like the 'lock', 'unlock' or
'kill-session' command.
As a schema evolves, certain elements and attributes may no longer be
relevant. Simply deleting these from the schema may be acceptable for
elements that did not see implementation, but others will require a
strategy to allow implementers to migrate away from the old elements. An
optional processing annotation called "status" SHOULD be used to provide
the status of the element. When not present, it will assume a value of
"current". The other value of this object are "deprecated" and
"obsolete". A value of "deprecated" indicates that implementations
should consider migrating away from this object and that its
implementation is no longer required to be considered conformant. A
value of "obsolete" means the object should not be implemented.
Deprecated and obsolete content is never removed from the document and
its element name can never be re-used.
In XML syntax
<dml:status>current</dml:status>
In compact syntax
>> dml:status [ "current" ]
Additional information about conformance should be specified using a
documentation tag.
Examples of additional conformance information that may be useful to
provide includes how implementations can specify specific exceptions to
required conformance, dependencies between elements (in order to do A,
you need to first do B) and conditional conformance (if BGP, then ...).
In order to claim compliance to a schema, all elements and attributes
need to conform to their given cardinality definitions and all elements and
attributes with a status of "current" and with a cardinality greater
than or equal to one need to be supported. In addition, all of the
operations listed by the minAccess attribute need to be supported.
Client-side conformance is a method of indicating whether presence of an
object is required in order to be a valid configuration. A new
processing annotation is added called mustUse to support this. When
present, this object is required in a valid configuration and when not
present, it is optional in a valid configuration. Note that optional
objects may have default values to enable them to have values in the
configuration without being explicitly set by the client.
In XML syntax
<dml:mustUse/>
In compact syntax
>> dml:mustUse []
The following outlines how the RCDML requirements (version -03) are met by this solution or when
applicably, why it was felt requirements should not be met.
The following requirements are all met by this proposal.
3.1.1 Notification Definition3.1.2 Notification Get
This proposal can be used to define notifications reusing or separately defining content in any proportion. Two example notiications are shown in .
3.1.3 Locking
This solution does not preclude the fine-grain locking mechanism proposed in the partial locking draft.
That approach primarily is built using XPath and it is well-
understood how to use XPath with Relax NG-based solutions.
3.1.4 All Base Operations
Operations using get, get-config, and edit-config are described in and .
3.1.5 Define new NETCONF Operations3.1.6 Separation of Operations and Payload
The proposal allows definition of new Netconf actions. An example is in . The dml:infoType annotation provides a clear distinction between actions and incorporated data.
3.1.7 Error Annotation
Netconf-specific error messages can be defined using 'dml:netconf-error-app-tag' error annotation attributes added to embedded Schematron rules as described in .
3.1.8 No Mixed Content
The Schematron rules run against each data model (described in ) prevent introducing mixed content.
3.2.1 Human Readable3.2.2 Machine Readable3.2.3 Textual Representation (72 column ASCII)3.2.7 Diff Friendly
These are inherent features of Relax NG Compact.
3.2.4 Document Information
The proposal uses DublinCore elements and the dml:organization and dml:email elements, as described in .
3.2.5 Change control3.2.6 Dependency risk reduction
Relax NG and Schematron (and the rest of DSDL) are ISO standards. DublinCore is a publication of the [openmetadata alliance?] We can reference specific versions of these references. The DML annotations described in this proposal would have IETF change control.
3.2.8.1. Descriptions using Local Languages3.2.8.2. UTF-8 Encoding3.2.8.3. Localization Support3.2.8.4. Error String Localization
The proposal uses UTF-8 encoding and allows arbitrary text annotations in any language. Localization of a data model is a user-interface issue. An additional annotation (not defined here) could be added to provide localized names for elements for automatically generated web forms for example. Error string localization is shown in .
3.2.8.5. Tag Names and Strings in Local Languages
While XML elements can be named with non-ASCII characters in Relax NG, this practice is discouraged by the IETF. If desirable, a warning or error could be incorporated into the data model Schematron rules described in if non-ASCII characters are present in element and attribute names. Alternatively, DSDL Part 8 - The Document Schema Renaming Language (DSRL) could be used to transalte between localized and canonical tag names.
3.3.1 Modularity3.3.2 Reusable Definitions3.3.3 Modular extension
Relax NG allows schema to be defined in separate files, and to both reuse and extend parts of schema (patterns) defined in separate files.
The full example in shows how the DHCP module is extended with the timezone option in dhcp-tz.rnc and the WINS server option in dhcp-wins.rnc without modifying the original dhcp.rnc schema or its annotations. A dhcp+extensions.rnc file needed a single line added to include the new extension. Multiple extensions to the same portion of the schema are allowed. To add a new module, a single line is added to the top-level "config-root.rnc" file. Pattern names do not need to be unique among multiple modules. More extensibility issues are discussed in .
3.4.1 Default values on the wire
Default values are mentioned in . Default values are specific to a specific version of the data model. Data with a default value can be excluded from an instance document if the carrying protocol provides some way to discriminate between configuration with and without default values. When used with Netconf, the edit config will exclude default values unless defaults are explicitly requested in a get or get-config request.
3.4.2.1 Ordered Lists3.4.2.2 Order within containers3.4.2.3 Interleaving
Relax NG supports both ordered and unordered collections of non-like elements through the "," (sequence) and "&" (interleave) operators. While interleaved collections proxide more flexibility, sequenced content is supported for backwards compatibility, etc. The dml:list-order annotation can be used as a semantic hint so that Netconf agents know if the order of a list is semantically meaningful.
3.4.3.1 Validate instance data3.4.3.2 Tools to validate instance data
Instance data is valid if it validates against both Relax NG (with emebbeded Schematron and the machine-generated Schematron schemas for uniqueness and referential integrity. Validators for these schema exist.
3.4.4 Instance Canonicalization
To canonicalize an instance of a data model created using this proposal, follow the rules defined in and then for element or attribute values which are of type token or list, replace any sequence of whitespce characters with a single space (0x20) character and remove any leading or trailing whitespace.
3.4.5 Character set encoding3.4.6 Model instance localization
Relax NG handles UTF-8 data correctly. While element and attribute names are allowed to consist of non-ASCII data, this usage is strongly discouraged. Wherever character content occurs, the data model can include multiple versions of this content with xml:lang attributes to allow for localization.
3.5.1 Human readable semantics3.5.2 Basic types3.5.3 Handling opaque data
The Relax NG Compact syntax has a human readable syntax. The manual and schematron validation rules are also human readable. Relax NG includes a set of basic data types and allows the use of external datatype libraries, including the XML Schema data type library. An appendix also includes a reusable library of content types commonly used in network management.
3.5.4.1 Define Keys3.5.4.2 Deep Keys
The proposal describes a mechanism for defining keys in . These can be compound and/or arbitrarily deep keys.
3.5.5.1 Simple Relationships
The key and keyref annotations (described in and ) define a formal 1:1 or 1:n relationship between objects in different hierarchies. These relationships can be formally validated.
3.5.5.3 Retrieve Relationships instance
The value of the element that the keyref processing annotation was attached
to will provide the relationship instance information in the NETCONF content.
For example, the keyref definition for the interface element
element interface-filter {
element interface {
xsd:token
>> dml:keyref ["//int:interface"]
}+
}
Has an instance of lo0en2
]]>
which is the instance of the particular interface involved in this reference.
3.5.6. Hierarchical Data
The proposal supports hierarchical data of arbitrary depth.
3.5.7.1. Referential Integrity
The proposal supports validation of complex relationships. Furthermore, as discussed in , the proposal supports three "phases" of validation according to context.
3.5.8 Characterize Data
Data is characterized as configuration, status, statistics, notification, and action using the dml:infoType annotation discussed in .
3.5.9.1. Default Values
Static default values are defined using the Relax NG DTD compatibility 'defaultValue' annotation.
3.5.10.1. Formal Description of Constraints3.5.10.2. Multi-element Constraints3.5.10.3. Non-Key Uniqueness
This proposal supports contraints using human-readable and/or inline Schematron as described in . Range and pattern constraints are part of the XML Schema Datatypes library and reused by Relax NG. A shortcut for constraining uniqueness is described in .
3.5.11 Units
A unit annotation is defined and described in .
3.5.12 Define actions
This is a duplicate of requirement 3.1.5.
3.6.1.1. Language Versioning3.6.1.2. User Extensions3.6.1.3. Mandatory Extensions
The data modeling annotations (DML for convenience) defined in this proposal are extensible. The version of these annotations is documented in a dmlVersion attribute of the dml element. Users can add additional DML element and attribute annotations as needed. These are ignored if not understood unless they contain a namespace name which is in the dml:mustUnderstand list of namespace prefixes.
3.6.2.1. Model Version Identification
Each data model module needs to have a dml:version annotation on its top-level (root) element.
3.6.2.2. Interaction with defaults
In this proposal, defaults are only valid for a specfic version of a data model. If the client does not have the current version of the data model it cannot make any assumptions about default values in use.
3.6.2.3. Conformance Interference
[TODO].
3.6.2.4. Obsolete Portions of a Model
The dml:status annotation is used to mark portions of a schema deprecated or obsolete.
3.6.3.1. Schema Version of Instance
Each data model module is encouraged to include a dmlVersion attribute on its root element with the version of the data model generated. The schematron validator for data models described in can generate a warning or error if a data model does not include such an attribute.
3.6.3.2. Interaction with default Values
Use of defaults is discussed extensively in .
3.6.3.3. Backwards Compatibility3.6.3.4. Forwards Compatibility
These issues are discussed in detail in .
3.6.3.5. Must-Understand Model Extensions
Clients which do not support a namespace indentified in the namespace prefix list in a dml:mustUnderstand element or attribute need to generate an error. This element or attribute can be added either under the top-level element of a module, the top-level configuration element, or as an attribute to the appropriate Netconf RPC element.
3.7.1. Conformance to the Modeling Language
An implementation conforms to this proposal if:
it automatically validates instance documents using a conformant Relax NG validator;it automatically validates instance documents using any inline Schematron validation rules for the appropriate phase using a conformant Schematron validator; andit verifies 'unique', 'key', 'keyref'. 'mustUse' and 'infoType' constraints on instance documents as described in .
Any other implementation which validates equivalently is also conformant.
3.7.2.2. Server Conformance to Schema3.7.2.3. Client Conformance To Schema3.7.2.4. Versioned Conformance
These issues are discussed in detail in .
3.8.1. Standard Technology
This proposal maximizes reuse of standard technology in the form of ISO DSDL Part 2 (Relax NG), ISO DSDL Part 3 (Schematron), the Relax NG DTD compatibility annotations, and the DublinCore metadata annotations.
3.8.2. Translate Models to Other Forms
The syntax portion of the model definition proposed by this document already uses Relax NG. This format can be converted to XSD (W3C XML Schema) automatically using existing tools (e.g. Trang) with a few simple limitations related to inherent limitations in XSD. For example, XSD does not support the interleave pattern, so interleaved element would not be allowed or would need to be converted to choice blocks which are compatible with XSD substitution groups.
The conversion is very slightly lossy. The start pattern in Relax NG defines the root XML element. This information is lost in translation as there is no applicable concept in XSD. Other than that, no information is lost.
3.8.3. Minimize SMI Translation Pain
SNMP was primarily used for operational data while NETCONF will be used for both
configuration and operational data. We therefore believe it is more important to
define a useful set of datatypes which are a good fit for NETCONF rather then
translating straight from SMI. The emphasis is on being able to exploit data type
definitions from the XML world, such as W3C XML Schema Datatypes definitions and
the relax NG native datatype library. That having been said, it is possible to define
a data type library with a comparable set of definitions to provide parity to the
ones used in SMI. A hopefully suitable data type library is defined in .
3.8.4. Generate Models from Other Forms
The standard XML representation for UML is the XML Metadata Interchange (XMI) format. It is possible to generate Relax NG and the annotations described here using an XSLT transformation stylesheet from XMI when the UML uses a compatible subset of concepts (e.g. no many-to-many relationships). Converting between UML and Relax NG is discussed in the van der Vlist Relax NG book in Chapter 14, Section 3.
3.8.5. Isolate Models from Protocol
This proposal has a clear separation of generic data modeling features and a very rich Netconf binding.
3.8.6. Library Support
Relax NG is supported in dozens of commercial and open source XML editors, validators, and XML libraries. Schematron is implemented in a handful of commercial and open source products. Use of schematron for validation is not strictly necessary, since validation rules are also presented in human-readable text. Any implementation which validates correctly is acceptable. Since DSDL is an ISO standard and the W3C is incorporating parts of DSDL in its newer specification, it is likely that implementation of these specification will increase.
3.8.7. RFC 3139 Considerations
The scope of the NETCONF data model work is 'Device-Local Configuration'.
Many of the requirements identified in this RFC are met by the NETCONF protocol, independent
of the features of the data modeling language choice. The solution does specifically meet the
requirement for data-specific errors identified in requirement 10 as well as provide for the extensibility of configuration data that requirement 14 is looking for.
3.8.8. RFC 3216 Considerations
Some of the requirements developed and captured during the
development of SMIng are relevant to this discussion. Others are
applicable to very specific protocol nuances of either SNMP or
COPS-PR or specific use cases for these technologies that are likely
not relevant to NETCONF. The requirements which are the most
relevant to this discussion are reflected in the list above.
3.5.5.2. Many-to-Many Relationships
The authors did not see a compelling need for many-to-many relationships
as a native feature of the data modeling solution.
In most cases, this could be emulated as follows. Consider a
many-to-many relationship between ports and interfaces. Each port
can contain a list of keyrefs to interfaces. Likewise, each interface
can contain a list of keyrefs to ports.
3.5.7.2. Extended Referential Integrity
In order to evaluate if this solution support referential integrity checks against pre-configured resources, we need to make some assumptions on how pre-configuration is modelled. If pre-configured resources are part of the configuration with special status information to indicate that the underlying hardware or software is currently not installed, then the same validation rules used for present resources applies. For example, the validity of referenced resources in keyref definitions can be verified. Additional referential checks could be added that are aware of whether equipment is pre-configured or present and respond appropriately.
Validating against unreachable resources and validating against operational data runs into issues that have more to do with network element limitations then with the choice of specification language. The current operational state on the network element is related to the current configuration, which is likely different then the operational state that will result once the configuration is applied. While some network elements are able to support determining the new operational state prior to the configuration being committed, this feature may be beyond the ability of most NETCONF-managed network elements to provide. While Schematron can in theory support checks of this nature, we feel this is an advanced feature and not one we should be focusing on at present.
3.5.9.2 Dynamic Defaults
Dynamic default values are very complex. They introduce brittleness in the system. The additional bandwidth of sending configuration information which has a dynamic default is minor and presents an opportunity for significant simplification. Therefore this proposal does not address dynamic defaults. If desirable, they could be added as a separate extension (possibly introduced with the mustUnderstand annotation). Any such extension would probably use XPath expressions to formally describe the dynamic relationships.
3.7.2.1. Conditional Conformance
This proposal does not support conditional conformance. Conditional conformance in the past introduced a considerable amount of complexity with very little gain and occasionally major interoperability problems. As such, this proposal does not support conditional conformance. Conformance is implemented at the granularty of an XML namespace.
The example below
In order to fit within 72 characters in width, the pattern restriction on 'ip-address-content' had to be split across two lines. This is indicated by the '~' operator in the example. This operator in Relax NG Compact is equivalent to concatening the two lines into a single quoted string literal.
# config-root.rnc
namespace rng = "http://relaxng.org/ns/structure/1.0"
namespace dc = "http://purl.org/dc/terms"
namespace dml = "http://example.org/ns/dml"
namespace compat ="http://relaxng.org/ns/compatibility/annotations/1.0"
namespace cfg = "http://example.org/ns/cfg"
start = element-config
element-config = element cfg:config { config-contents }
config-contents = empty
config-contents &= external "interfaces.rnc" ?
config-contents &= external "dhcp.rnc" ?
# interfaces.rnc
namespace rng = "http://relaxng.org/ns/structure/1.0"
namespace xsd = "http://www/w3/org/2001/XMLSchema-datatypes"
namespace xml = "http://www.w3.org/XML/1998/namespace"
namespace sch = "http://www.ascc.net/xml/schematron"
namespace dc = "http://purl.org/dc/terms"
namespace dml = "http://example.org/ns/dml"
namespace compat ="http://relaxng.org/ns/compatibility/annotations/1.0"
namespace int = "http://example.org/ns/int"
default namespace = "http://example.org/ns/int"
start = element-interfaces
element-interfaces = element interfaces {
element-interface+
>> dc:title [ "Example Interfaces schema fragment" ]
}
element-interface = element interface {
element ifIndex { xsd:token },
element ifType { xsd:token }
>> dml:key [ "ifIndex"]
>> dml:version ["1.0"]
}
# dhcp+extensions.rnc
namespace rng = "http://relaxng.org/ns/structure/1.0"
datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
include "dhcp.rnc" # base module
include "dhcp-tz.rnc" # timezone option extension
include "dhcp-wins.rnc" # WINS server option extension
# dhcp.rnc
namespace rng = "http://relaxng.org/ns/structure/1.0"
namespace xsd = "http://www/w3/org/2001/XMLSchema-datatypes"
namespace xml = "http://www.w3.org/XML/1998/namespace"
namespace sch = "http://www.ascc.net/xml/schematron"
namespace dc = "http://purl.org/dc/terms"
namespace dml = "http://example.org/ns/dml"
namespace dhcp = "http://example.org/ns/dhcp"
namespace int = "http://example.org/ns/int"
namespace nt = "http://example.org/ns/net-types"
namespace compat ="http://relaxng.org/ns/compatibility/annotations/1.0"
default namespace = "http://example.org/ns/dhcp"
include "network-types.rnc"
start = element-dhcp
element-dhcp = element dhcp {
global-timer-elements,
element-subnet*,
element-shared-network*
>> dc:title [ "Example schema for DHCP server" ]
>> dml:version ["1.0"]
>> dc:type ["Dataset"]
>> dc:creator [ "Rohan Mahy" ]
>> dml:organization [ "as an individual" ]
>> dml:contact [ "mailto:rohan@ekabal.com" ]
>> dc:created [ "2008-02-13" ]
}
global-timer-elements = (
[
sch:pattern [
sch:rule [
context = "//dhcp:dhcp"
sch:assert [
test = "dhcp:default-lease-time <= dhcp:max-lease-time"
"Default lease time cannot be larger than maximum lease time"
]
]
]
]
element default-lease-time {
xsd:unsignedInt
>> compat:defaultValue ["3600"] >> dml:units ["s"]
}?,
element max-lease-time { xsd:unsignedInt
>> dml:units ["s"] }?
)
element-shared-network = element shared-network {
attribute name { token },
element-subnet*
}
element-subnet = element subnet {
element-network,
element-prefix-length,
element-range?,
element-dhcp-options?,
element max-lease-time {
xsd:unsignedInt
>> dml:units ["s"]
>> dml:status ["deprecated"]
}?,
element leases {
element-lease*
>> dml:infoType ["status"]
}?,
element-interface-filter?
>> dml:key ["concat(network, '/', prefix-length)"]
>> dml:manual-validation-rule [
"Verify that none of the subnets overlap with other subnets." ]
}
element-network = element network {
ipv4-address-content
}
element-prefix-length = element prefix-length {
xsd:short { minInclusive = "0" maxInclusive = "32" }
}
element-range = element range {
element low { ipv4-address-content }?,
element high { ipv4-address-content }?
>> dml:existence []
>> dml:manual-validation-rule [
"Verify the range is within the subnet." ]
}
element-dhcp-options = element dhcp-options {
element-router-list-option? &
element-domain-list-option? &
element-custom-option*
}
element-lease = element lease {
attribute ip-address { ipv4-address-content },
element starts { xsd:dateTime },
element ends { xsd:dateTime },
element mac-address { mac-address-content }
>> dml:key ["@ip-address"]
}
element-router-list-option = element router-list {
element router { ipv4-address-content }+
>> dml:order ["user-order"]
}
element-domain-list-option = element domain-list {
element domain { token }+
}
element-custom-option = element custom {
attribute option { xsd:unsignedByte },
(
element ip-address { ipv4-address-content }
| element string { string }
)
>> dml:key ["@option"]
}
element-interface-filter = element interface-filter {
element-interface+
}
element-interface = element interface {
token >> dml:keyref ["//int:interface"]
}
# dhcp-tz.rnc
namespace rng = "http://relaxng.org/ns/structure/1.0"
datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
namespace tz = "http://example.org/ns/dhcp/timezone"
element-dhcp-option &= element tz:timezone { token }?
# dhcp-wins.rnc
namespace rng = "http://relaxng.org/ns/structure/1.0"
datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
namespace wins = "http://example.org/ns/dhcp/wins-option"
element-dhcp-option &= element wins:wins-server { token }*
#network-types.rnc
namespace rng = "http://relaxng.org/ns/structure/1.0"
namespace xsd = "http://www/w3/org/2001/XMLSchema-datatypes"
namespace xml = "http://www.w3.org/XML/1998/namespace"
namespace sch = "http://www.ascc.net/xml/schematron"
namespace dc = "http://purl.org/dc/terms"
namespace dml = "http://example.org/ns/dml"
namespace compat ="http://relaxng.org/ns/compatibility/annotations/1.0"
ipv4-address-content = xsd:token { pattern =
"((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}" ~
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])"
}
mac-address-content = xsd:token { pattern =
"(([0-9a-fA-F]{2}):?){5}[0-9a-fA-F]{2}" }
Below is the complete Relax NG Compact formal syntax for the annotations schema.
> compat:defaultValue ["config"]
}
access-strings = ( "read" | "write" | "create" | "delete" | "execute" )
mustUse-flag = element mustUse { xsd:boolean
>> compat:defaultValue ["false"]
}
manual-validation = element manual-validation-rule { string-with-lang }
# Semantic hints
list-order = element order {
("any-order" | "user-order")
>> compat:defaultValue ["any-order"]
}
container-existence = element existence { empty }
units = element units {
xsd:string { pattern="[^: \n\r\t]+" }
# allow familiar units, but no whitespace or absolute URIs here
|
xsd:anyURI { pattern="([a-zA-Z][a-zA-Z0-9\-\+\.]*:|\.\./|\./|#).*" }
# allow absolute URIs, plus relative URIs with ./ or ../
# prohibit relative URIs that could look like a unit, ex: m/s
}
# Definition copied from definition of gml:Uomidentifier from
# Section 8.2.3.6 of Geography Markup Language (GML) v3.2.1
string-with-lang = (
attribute xml:lang { xsd:language },
xsd:string
)
conformStatus = element status {
"active" | "deprecated" | "obsolete"
>> compat:defaultValue ["active"]
}
# the mustUnderstand element contains space separated list of namespace
# tokens that need to be supported to correctly process the data model
mustUnderstand = element mustUnderstand { list { xsd:NCName } }
dml-netconf-error-app-tag =
attribute netconf-error-app-tag { xsd:string }
dml-phase-attribute = attribute phase { "fragment" | "std" | "full" }
dml-moduleDefault = attribute moduleDefault {
xsd:boolean >> compat:defaultValue ["false"]
}
]]>
TBD
This document merely evaluates a possible technical approach. It requires no action by IANA. A specification that uses this approach would need to register a namespace with IANA.
Randy Presuhn contributed to the development of this proposal and provided useful advice on the extensibility model. Thanks to Alan Hawrylyshen for an early read.
Write up notes on how the XSLT works.
Generating rules for uniqueness and key verification. Walk upward until an element element (add to front of path) or ref element (recurse) is encountered. Include namespace prefixes. Continue once more for the parent element.
Generating rules for key verification.
Generating rules for keyref validation.
Deleting elements or attributes which are marked obsolete.
TODO
Part 5 of the DSDL Framework defines a very flexible and powerful
syntax for creating named sets of user-defined datatypes. While
this might be the ultimate way for defining new datatypes, this
syntax, known as Datatype Library Language (DTLL) , is still work in progress and the number of
implementations is quite small.As an interim solution, the datatypes necessary for NETCONF
data modelling purposes can be provided in two different
forms:
Generic simple datatypes - various types of numbers, strings,
booleans, dates etc. - are available in all RELAX NG
implementations via the W3C XML Schema Datatypes library .Domain-specific datatypes such as IP addresses, DNS domain
names and MAC addresses can be prepared as libraries of patterns
expressed in RELAX NG.RELAX NG has built-in support for the W3C XML Schema Datatypes
library . In the compact syntax, the
namespace of this library
("http://www.w3.org/2001/XMLSchema-datatypes") is declared
implicitly with prefix "xsd". In the XML syntax, the URI of this
(or any other) datatype library must be explicitly declared
using the "datatypeLibrary" attribute.Usage of datatypes from the XML Schema Library in RELAX NG is
straightforward. For example, an element containing autonomous
system number can be defined as follows:
element asn { xsd:unsignedShort }
Likewise, it is easy to impose additional restrictions by
means of so called facets, for example ranges of permissible
values:
element hello-multiplier {
xsd:unsignedByte { minInclusive = "3" maxInclusive = "20" }
}
The most important datatypes provided by the XML Schema Library
are summarized in .TypeMeaningbyte8-bit integer valueshort16-bit integer valueint32-bit integer valuelong64-bit integer valueunsignedByte8-bit unsigned integer valueunsignedShort16-bit unsigned integer valueunsignedInt32-bit unsigned integer valueunsignedLong64-bit unsigned integer valuefloat32-bit IEEE floating-point valuedouble64-bit IEEE floating-point valuestringcharacter string without whitespace normalizationtokencharacter string with whitespace
normalizationbooleanboolean type with values "true" or "false"base64Binarybinary data in base64 encodinganyURIuniform resource identifierdateTimedate and time value according to ISO 8601This section contains two library modules with
reusable RELAX NG patterns:
inet-types - common Internet-related datatypes such as IP
addresses and prefixes, port numbers and DNS domain namesieee-types - common datatypes defined in IEEE 802
standards: MAC address, bridge identifier and VLAN
identifier.The patterns defined in these modules can be used, unmodified
or with modifications, in RELAX NG schemas. This is accomplished
by including one or more modules in the schema, for example
include "inet-types.rnc"
In the compact syntax, the way the included pattern
definitions are used is almost identical to the previous case of
simple datatype libraries; the only difference is the absence
of a namespace prefix. In the following example, the
"ip-address" pattern is defined in the "inet-types" module:
element source-address { ip-address }
The patterns in the "inet-types" and "ieee-types" modules are
designed for maximum flexibility. They can be extended or
modified using standard RELAX NG mechanisms. As an example,
consider the definition of "port-number" pattern that does not allow a zero value. If a
data modeller had an application where the zero value is
meaningful, she could reuse the definition in the following way:
port-number |= "0"
This construct is called "combination by choice" in RELAX NG
and is equivalent to the following definition:
port-number = xsd:unsignedShort { minInclusive = "1" } | "0"
Extension of patterns defined in an external module is
possible through "combination by interleave". For example, if we
wanted to add scope identifier to IP prefixes, we could redefine
the "ip-prefix" pattern as follows:
ip-prefix &= element scope { xsd:token }
This is equivalent to the following definition:
ip-prefix = ((attribute version { "ipv4" }?, ipv4-prefix)
| (attribute version { "ipv6" }?, ipv6-prefix))
& element scope { xsd:token }
Finally, the third possibility for modifying predefined
patterns is to replace selected pattern definitions entirely
with our own versions.This pattern defines possible values for IP protocol
version. See RFC 791
and RFC 2460.This pattern represents Differentiated Services Code Point. See RFC 3289,
RFC 2474
and RFC 2780.
This pattern represents the flow label – 20-bit value
that is used for discriminating traffic flows. See RFC 2460.This pattern represents the port number that is used by
transport layer protocols such as TCP or UDP. See RFC 4001.This pattern represents IP address (either IPv4 or IPv6). The
version may be indicated in the "version" attribute, otherwise it
is determined from the textual format.This pattern represents IPv4 address in the usual dotted quad
notation.The pattern is referenced by:
ip-addressipv4-prefixhostThis pattern represents IPv6 address in one of the three
textual formats defined in RFC 4291,
section 2.2 (full, shortened and mixed).The pattern is referenced by:
ip-addressipv6-prefixhostThis pattern represents IP prefix (either IPv4 or IPv6). The
version may be indicated in the "version" attribute, otherwise it
is determined from the textual format.This pattern represents IPv4 prefix. Prefix length is
specified by the "length" subelement.The pattern is referenced by:
ip-prefixThis pattern represents IPv6 prefix. Prefix length is
specified by the "length" subelement.The pattern is referenced by:
ip-prefixThis pattern represents DNS domain name, see RFC 1034
and RFC 1123.The pattern is referenced by:
hostThis pattern represents either an IP address (IPv4 or IPv6)
or a host name. The type of the contents may be indicated by the
"content-type" attribute, otherwise it is determined from
textual format.This pattern represents an IEEE 802 MAC address in the
canonical format.This pattern represents an identifier of a MAC bridge. See
IEEE 802.1D-2004,
Section 9.2.5.
This pattern represents a 12-bit VLAN identifier that is used
as a VLAN tag in IEEE 802.1Q frames. See IEEE 802.1Q-2005.For those who prefer the XML syntax of Relax NG, the "dhcp.rnc" file
was converted to "dhcp.rng" using Trang. Some additional whitespace was added to
improve readability and to make the document fit in 72 characters.
Example schema for DHCP server1.0DatasetRohan Mahyas an individualmailto:rohan@ekabal.com2008-02-13
Default lease time cannot be larger than maximum lease time
3600sssdeprecatedstatusconcat(network, '/', prefix-length)
Verify that none of the subnets overlap with other subnets.
0
32
Verify the range is within the subnet.
@ip-addressuser-order@option//int:interface
]]>
Document Schema Definition Languages (DSDL) — Part 3: Rule-based validation — Schematron
ISODocument Schema Definition Languages (DSDL): Part 2: Regular Grammer-based Validation - Relax NGISOXML Path Language (XPath) 2.0World Wide Web ConsortiumWorld Wide Web ConsortiumXSL Transformations (XSLT)World Wide Web ConsortiumThe Unified Code for Units of Measure The Regenstrief Institute For Health Care The Regenstrief Institute For Health Care Relax NGO'Reilly Document Schema Definition Languages (DSDL) - Part 1:
OverviewISO/IECDocument Schema Definition Languages (DSDL) - Part 5:
Datatypes - Datatype Library Language (DTLL)ISO/IECOpenGIS Geography Markup Language (GML Implementation SpecificationOpenGIS OpenGIS OpenGIS OpenGIS OpenGIS