NETCONF | E. Voit |
Internet-Draft | Cisco Systems |
Intended status: Standards Track | A. Bierman |
Expires: April 2, 2018 | YumaWorks |
A. Clemm | |
Huawei | |
T. Jenkins | |
Cisco Systems | |
September 29, 2017 |
Notification Message Headers and Bundles
draft-ietf-netconf-notification-messages-01
This document defines a new notification message format, using yang-data. Included are:
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
This Internet-Draft will expire on April 2, 2018.
Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
Mechanisms to support subscription to event notifications and yang datastore push are being defined in [subscribe] and [yang-push]. Work on those documents has shown that notifications described in [RFC7950] section 7.16 could benefit from transport independent headers. Communicating the following information to receiving applications can be done without explicit linkage to an underlying transport protocol:
The document describes information elements needed for the functions above. It also provides YANG structures for sending messages containing one or more events and/or update records to a receiver.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
The definition of notification is in RFC 7950. Publisher, receiver, and subscription are defined in [subscribe].
There are a number of transport independent headers which should have common definition. These include:
A specific set of well-known objects are of potential use to networking layers prior being interpreted by some receiving application layer process. By exposing this object information as part of a header, and by using standardized object names, it becomes possible for this object information to be leveraged in transit.
The objects defined in the previous section are these well-known header objects. These objects are identified within a dedicated header subtree which leads off a particular transportable message. This allows header objects to be easily be decoupled, stripped, and processed separately.
There are two types of transportable messages: one format is used when there is one notification being encapsulated, and another format used when there are many notifications being bundled into one message.
A receiver which supporting this document MUST be able to handle receipt of either type of message from an publisher. It is possible that changes between message types can occur without any prior indication.
Below are contents of a message when there is only one notification in an encapsulated and encoded message:
yang-data message +-- message-header | +-- notification-time yang:date-and-time | +-- subscription-id* uint32 | +-- notification-id? uint32 | +-- observation-domain-id? string | +-- message-id? uint32 | +-- message-time? yang:date-and-time | +-- previous-message-id? uint32 | +-- message-generator-id? string | +-- signature? string +-- receiver-record-contents?
An actual instance of such a message when encoded in XML might look like:
<yang-data message xmlns="urn:ietf:params:xml:ns:yang:ietf-notification-messages:1.0"> <message-header> <notification-time> 2017-02-14T00:00:02Z </notification-time> <subscription-id> 823472 </subscription-id> <message-time> 2017-02-14T00:00:05Z </message-time> <message-id> 456 </message-id> <previous-message-id> 567 </previous-message-id> <signature> lKIo8s03fd23..... </signature> </message-header> <push-change-update xmlns= "urn:ietf:params:xml:ns:yang:ietf-yang-push:1.0"> <datastore-changes-xml> <alpha xmlns="http://example.com/sample-data/1.0" > <beta urn:ietf:params:xml:ns:netconf:base:1.0: operation="delete"/> </alpha> </datastore-changes-xml> </push-change-update> </yang-data>
In many implementations, it may be inefficient to transport every notification independently. Instead, scale and processing speed can be improved by placing multiple notifications into one transportable bundle.
When this is done, one additional header field becomes valuable. This is the "notification-count" which would tally the quantity of records which make up the contents of the bundle. It is true that the record count can be derived, but early access to this information could change receiver processing.
The format of a bundle would look as below. When compared to the unbundled notification, note that the headers have been split so that one set of headers associated with the notification occur once at the beginning of the message, and additional record specific headers which occur before individual records.
yang-data bundled-message +-- bundled-message-header | +-- message-time yang:date-and-time | +-- message-id? uint32 | +-- previous-message-id? uint32 | +-- message-generator-id? string | +-- signature? string | +-- notification-count? uint16 +-- notifications* +-- notification-header | +-- notification-time yang:date-and-time | +-- subscription-id* uint32 | +-- notification-id? uint32 | +-- observation-domain-id? string +-- receiver-record-contents?
An actual instance of a bundled notification might look like:
<yang-data bundled-message xmlns="urn:ietf:params:xml:ns:yang:ietf-notification-messages:1.0"> <bundled-message-header> <message-time> 2017-02-14T00:00:05Z </message-time> <message-id> 456 </message-id> <previous-message-id> 567 </previous-message-id> <signature> lKIo8s03fd23... </signature> <notification-count> 2 </notification-count> </bundled-message-header> <notifications> <notification> <notification-header> <notification-time> 2017-02-14T00:00:02Z </notification-time> <subscription-id> 823472 </subscription-id> </notification-header> <push-change-update xmlns= "urn:ietf:params:xml:ns:yang:ietf-yang-push:1.0"> <datastore-changes-xml> <alpha xmlns="http://example.com/sample-data/1.0"> <beta urn:ietf:params:xml:ns:netconf:base:1.0: operation="delete"/> </alpha> </datastore-changes-xml> </push-change-update> </notification> <notification> ...(record #2)... </notification> </notifications> </yang-data>
The type of notification transported within a record could be a header. However the notification name and namespace is the first element in the receiver record contents payload. As this can be determined by the YANG module containing the notification-stmt as represented within the first part of the encapsulated notification message, this information need not replicated within a header.
A publisher MUST select the set of headers to use for a particular message. The two mandatory headers which MUST always be applied to every message are 'message-time' and 'subscription-id'
Beyond these two mandatory headers, the following are additional sources which can add common headers to a message.
The set of headers used for any particular message is the superset of headers for the items listed above.
The YANG tree showing elements of configuration is depicted in the following figure.
module: ietf-notification-messages +--rw additional-default-headers {publisher}? +--rw additional-headers* common-header +--rw notification-specific-default* [module notification] +--rw module yang:yang-identifier +--rw notification string +--rw per-notification-headers* common-header
Configuration Model structure
Of note in this tree is the optional feature of 'publisher'. This feature indicates an ability to send notifications. A publisher supporting this specification MUST also be able to parse any messages received as defined in this document.
We need capability exchange from the receiver to the publisher at transport session initiation to indicate support for this specification.
For all types of transport connections, if the receiver indicates support for this specification, then it MAY be used. In addition, [RFC5277] one-way notifications MUST NOT be used if the receiver indicates support for this specification to a publisher which also supports it.
Where NETCONF transport is used, advertising this specification's namespace during an earlier client capabilities discovery phase MAY be used to indicate support for this specification:
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <capabilities> <capability> urn:ietf:params:xml:ns:yang:ietf-notification-messages:1.0 </capability> </capabilities> <session-id>4</session-id> </hello>
NOTE: It is understood that even though it is allowed in [RFC6241] section 8.1, robust NETCONF client driven capabilities exchange is not something which is common in implementation. Therefore reviewers are asked to submit alternative proposals to the mailing list.
For RESTCONF, a mechanism for capability discovery is TBD. Proposals are also welcome here.
The mechanism described above assumes that a capability discovery phase happens before a subscription is started. This is not always the case. As an example, consider HTTP2 configured subscriptions from section 3.1.3 of [http-push], there is no guarantee that a capability exchange has taken place before the updates are pushed. A solution for this could be that a receiver would reply "ok" and reply with the client capabilities as part of the POST. (Or just use a different HTTP status code like 202 instead of 200 'ok'). As such a requirement creates a new dependency for [http-push] upon this specification, more discussion is required to decide if this is a viable solution.
<CODE BEGINS> file "ietf-notification-messages.yang" module ietf-notification-messages { yang-version 1.1; namespace "urn:ietf:params:xml:ns:yang:ietf-notification-messages"; prefix nm; import ietf-yang-types { prefix yang; } import ietf-restconf { prefix rc; } organization "IETF"; contact "WG Web: <http://tools.ietf.org/wg/netconf/> WG List: <mailto:netconf@ietf.org> Editor: Eric Voit <mailto:evoit@cisco.com> Editor: Alexander Clemm <mailto:ludwig@clemm.org> Editor: Andy Bierman <mailto:andy@yumaworks.com> Editor: Tim Jenkins <mailto:timjenki@cisco.com>"; description "This module contains conceptual YANG specifications for yang-data messages carrying notifications with well known header objects."; revision 2017-09-28 { description "Initial version."; reference "draft-ietf-netconf-notification-messages-01"; } /* * FEATURES */ feature publisher { description "This feature indicates that support for both publisher and receiver of messages complying to the specification."; } /* * IDENTITIES */ /* Identities for common headers */ identity common-header { description "A well known header which can be included somewhere within a message."; } identity notification-time { base common-header; description "Header information consisting of the time an originating process created the notification or yang-data."; } identity notification-id { base common-header; description "Header information consisting of an identifier for the notification or yang-data record. "; } identity subscription-id { base common-header; description "Header information consisting of the identifier of the subscription associated with the notification or yang-data being encapsulated."; } identity observation-domain-id { base common-header; description "Header information identifying the software entity which created the notification or yang-data (e.g., process id)."; } identity message-id { base common-header; description "Header information that identifies a message to a specific receiver"; } identity message-time { base common-header; description "Header information consisting of time the message headers were placed generated prior to being sent to transport"; } identity previous-message-id { base common-header; description "Header information consisting of a message id previously sent by the publisher to a specific receiver (allows detection of loss/duplication)."; } identity message-generator-id { base common-header; description "Header information consisting of an identifier for a software entity which created the message (e.g., linecard 1)."; } identity signature { base common-header; description "Header information consisting of a signature on the contents of a message. This can be useful for originating applications to verify record contents even when shipping over unsecure transport."; } identity notification-count { base common-header; description "Header information consisting of the quantity of notifications in a bundled-message for a specific receiver."; } /* * TYPEDEFs */ typedef common-header { type identityref { base common-header; } description "Type of header object which may be included somewhere within a message."; } /* * GROUPINGS */ grouping message-header { description "Header information included with a message."; leaf message-id { type uint32; description "Unique id for a message going to a receiver."; } leaf message-time { type yang:date-and-time; description "time the message was generated prior to being sent to transport."; } leaf previous-message-id { type uint32; description "message id previously sent by publisher to a specific receiver (allows detection of loss/duplication)."; } leaf message-generator-id { type string; description "Software entity which created the message (e.g., linecard 1)."; } leaf signature { type string; description "Any originator signing of the contents of a message. This can be useful for originating applications to verify record contents even when shipping over unsecure transport."; } } grouping notification-header { description "Common informational objects which might help a receiver interpret the meaning, details, or importance of a notification."; leaf notification-time { type yang:date-and-time; mandatory true; description "Time the system recognized the occurrence of an event."; } leaf-list subscription-id { type uint32; description "Id of the subscription which led to the notification being generated."; } leaf notification-id { type uint32; description "Identifier for the notification record."; } leaf observation-domain-id { type string; description "Software entity which created the notification record (e.g., process id)."; } } /* * YANG-DATA messages for receivers */ /* Message to a receiver containing one notification.*/ rc:yang-data message { container message-header { description "delineates header info from content for easy parsing."; uses notification-header; uses message-header; } anydata notification-contents { description "Non-header info of what actually got sent to receiver. This includes after any content based security filtering. Need to determine if/how it is viable not to include tag encapsulation for this object."; } } /* Message to a receiver containing many bundled notifications.*/ rc:yang-data bundled-message { container bundled-message-header { description "Header info for messages."; uses message-header { refine message-time { mandatory true; } } leaf notification-count { type uint16; description "Quantity of notification records in a bundled-message specific receiver."; } } list notifications { description "Set of notifications to a receiver."; container notification-header { description "Header info for each bundled notification."; uses notification-header; } anydata notification-contents { description "Non-header info of what actually got sent to receiver. This includes after any content based security filtering. Need to determine if/how it is viable not to include tag encapsulation for this object."; } } } /* * DATA-NODES */ container additional-default-headers { if-feature "publisher"; description "This container maintains a list of which additional notifications should use which common headers if the receiver supports this specification. The name starts with additional because there are some mandatory common headers not listed in the container. These headers are (1) message-time and (2) subscription-id."; leaf-list additional-headers { type common-header; description "This list contains the additional default headers which are to be applied to each message from this publisher."; } list notification-specific-default { key "module notification"; description "For any included notification, this list provides additional common headers."; leaf module { type yang:yang-identifier; description "Name of the module containing a notification."; } leaf notification { type string { pattern 'notification $|yang-data $'; } description "The name of the notification or yang-data being sent."; } leaf-list per-notification-headers { type common-header; description "The set of additional default headers for a specific notification."; } } } } <CODE ENDS>
With this specification, there is no change to YANG's 'notification' statement
Legacy clients are unaffected, and existing users of [RFC5277], [RFC7950], and [RFC8040] are free to use current behaviors until all involved device support this specification.
Certain headers might be computationally complex for a publisher to deliver. Signatures or encryption are two examples of this. It MUST be possible to suspend or terminate a subscription due to lack of resources based on this reason.
Decisions on whether to bundle or not to a receiver are fully under the purview of the Publisher. A receiver could slow delivery to existing subscriptions by creating new ones. (Which would result in the publisher going into a bundling mode.)
For their valuable comments, discussions, and feedback, we wish to acknowledge Martin Bjorklund and Kent Watsen.
[RFC2119] | Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997. |
[RFC5277] | Chisholm, S. and H. Trevino, "NETCONF Event Notifications", RFC 5277, DOI 10.17487/RFC5277, July 2008. |
[RFC8174] | Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017. |
[subscribe] | Voit, E., Clemm, A., Gonzalez Prieto, A., Prasad Tripathy, A. and E. Nilsen-Nygaard, "Custom Subscription to Event Notifications", September 2017. |
[http-push] | Voit, Eric., Clemm, Alexander., Tripathy, A., Nilsen-Nygaard, E. and Alberto. Gonzalez Prieto, "Restconf and HTTP transport for event notifications", August 2016. |
[RFC6241] | Enns, R., Bjorklund, M., Schoenwaelder, J. and A. Bierman, "Network Configuration Protocol (NETCONF)", RFC 6241, DOI 10.17487/RFC6241, June 2011. |
[RFC7950] | Bjorklund, M., "The YANG 1.1 Data Modeling Language", RFC 7950, DOI 10.17487/RFC7950, August 2016. |
[RFC8040] | Bierman, A., Bjorklund, M. and K. Watsen, "RESTCONF Protocol", RFC 8040, DOI 10.17487/RFC8040, January 2017. |
[yang-push] | Clemm, A., Voit, E., Gonzalez Prieto, A., Prasad Tripathy, A. and E. Nilsen-Nygaard, "Subscribing to YANG datastore push updates", April 2017. |
(To be removed by RFC editor prior to publication)
v00 - v01
(To be removed by RFC editor prior to publication)
Is this capability just for notifications, or is it for any yang-data element too?
Improved discovery mechanisms for NETCONF
Do we want to have additional headers for a specific notification? Right now this is included, but it could be excluded.
Should we defer support for HTTP2 configured subscriptions until this draft is available? Without capabilities exchange, it might just be easier to wait.
Encoding of notification-contents so that individual notification framing isn't needed.
We need to link to Andy Bierman's anydata extensibility draft.
(To be removed by RFC editor prior to publication)
This section discusses a future functional addition which could leverage this draft. It is included for informational purposes only.
A dynamic subscriber might want to mandate that certain headers be used for push updates from a publisher. Some examples of this include a subscriber requesting to:
Providing this type of functionality would necessitate a new revision of the [subscribe]'s RPCs and state change notifications. Subscription specific header information would overwrite the default headers identified in this document.
(To be removed by RFC editor prior to publication)
YANG one-way exchanges currently use a non-extensible header and encoding defined in section 4 of RFC-5277. These RFCs MUST be updated to enable this draft. These RFCs SHOULD be updated to provide examples
Sections which expose netconf:capability:notification:1.0 are 4.2.10
Sections which provide examples using netconf:notification:1.0 are 7.10.4, 7.16.3, and 9.9.6
Section 6.4 demands use of RFC-5277's netconf:notification:1.0, and later in the section provides an example.