Dynamic Subscription to YANG Events and Datastores over NETCONF
RFC 9999
Eric Voit
Cisco Systems
evoit@cisco.com
Alexander Clemm
Huawei
ludwig@clemm.org
Alberto Gonzalez Prieto
Microsoft
alberto.gonzalez@microsoft.com
Einar Nilsen-Nygaard
Cisco Systems
einarnn@cisco.com
Ambika Prasad Tripathy
Cisco Systems
ambtripa@cisco.com
July 2019
This document provides a Network Configuration Protocol (NETCONF) binding to the dynamic subscription capability of both subscribed notifications and YANG-Push.
Introduction
This document specifies the binding of a stream of events which form part of a dynamic subscription to the NETCONF protocol [RFC6241]. Dynamic subscriptions are defined in [RFCYYYY]. In addition, as [RFCZZZZ] is itself built upon [RFCYYYY], this document enables a NETCONF client to request via a dynamic subscription and receive updates from a YANG datastore located on a NETCONF server.
This document assumes that the reader is familiar with the terminology and concepts defined in [RFCYYYY].
Terminology
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 following terms are defined in [RFCYYYY]: dynamic subscription, event stream, notification message, publisher, receiver, subscriber, subscription. No additional terms are defined.
Compatibility with RFC-5277's create-subscription
A publisher is allowed to concurrently support dynamic subscription RPCs of [RFCYYYY] at the same time as [RFC5277]'s "create-subscription" RPC. However a single NETCONF transport session MUST NOT support both this specification and a subscription established by [RFC5277]'s "create-subscription" RPC. To protect against any attempts to use a single NETCONF transport session in this way:
- A solution MUST reply with the [RFC6241] "rpc-error" element containing the "error-tag" value of "operation-not-supported" if a "create-subscription" RPC is received on a NETCONF session where an [RFCYYYY] established subscription exists.
- A solution MUST reply with the [RFC6241] "rpc-error" element containing the "error-tag" value of "operation-not-supported" if an "establish-subscription" request has been received on a NETCONF session where the "create-subscription" RPC has successfully [RFC5277] created a subscription.
If a publisher supports this specification but not subscriptions via [RFC5277], the publisher MUST NOT advertise "urn:ietf:params:netconf:capability:notification:1.0".
Mandatory XML, event stream and datastore support
The "encode-xml" feature of [RFCYYYY] MUST be supported. This indicates that XML is a valid encoding for RPCs, state change notifications, and subscribed content.
A NETCONF publisher supporting event stream subscription via [RFCYYYY] MUST support the "NETCONF" event stream identified in that document.
NETCONF connectivity and the Dynamic Subscriptions
Management of dynamic subscriptions occurs via RPCs as defined in [RFCZZZZ] and [RFCYYYY]. For a dynamic subscription, if the NETCONF session involved with the "establish-subscription" terminates, the subscription MUST be terminated.
For a dynamic subscription, any "modify-subscription", "delete-subscription", or "resync-subscription" RPCs MUST be sent using the same NETCONF session upon which the referenced subscription was established.
Notification Messages
Notification messages transported over the NETCONF protocol MUST be encoded in a <notification> message as defined within [RFC5277], Section 4. And per [RFC5277]'s "eventTime" object definition, the "eventTime" is populated with the event occurrence time.
For dynamic subscriptions, all notification messages MUST use the NETCONF transport session used by the "establish-subscription" RPC.
Dynamic Subscriptions and RPC Error Responses
When an RPC error occurs as defined in [RFCYYYY] Section 2.4.6 and [RFCZZZZ] Appendix A, the NETCONF RPC reply MUST include an "rpc-error" element per [RFC6241] with the error information populated as follows:
- An "error-type" node of "application".
- An "error-tag" node with the value being a string that corresponds to an identity associated with the error. For the mechanisms specified in this document, this "error-tag" will come from one of two places. Either it will correspond to the error identities within [RFCYYYY] section 2.4.6 for general subscription errors:

          error identity         uses error-tag
          ---------------------- --------------
          dscp-unavailable       invalid-value
          encoding-unsupported   invalid-value
          filter-unsupported     invalid-value
          insufficient-resources resource-denied
          no-such-subscription   invalid-value
          replay-unsupported     operation-not-supported

- Or this "error-tag" will correspond to the error identities within [RFCZZZZ] Appendix A.1 for subscription errors specific to YANG datastores:

          error identity              uses error-tag
          ----------------------      --------------
          cant-exclude                operation-not-supported
          datastore-not-subscribable  invalid-value
          no-such-subscription-resync invalid-value
          on-change-unsupported       operation-not-supported
          on-change-sync-unsupported  operation-not-supported
          period-unsupported          invalid-value
          update-too-big              too-big
          sync-too-big                too-big
          unchanging-selection        operation-failed

- an "error-severity" of "error" (this MAY be included).
- an "error-app-tag" node with the value being a string that corresponds to an identity associated with the error, as defined in [RFCYYYY] section 2.4.6 for general subscriptions, and [RFCZZZZ] Appendix A.1, for datastore subscriptions. The specific identity to use depends on the RPC for which the error occurred. Each error identity will be inserted as the "error-app-tag" following the form <modulename>:<identityname>. An example of such as valid encoding would be "ietf-subscribed-notifications:no-such-subscription". Viable errors for different RPCs are as follows:

         RPC                     have base identity
         ----------------------  ----------------------------
         establish-subscription  establish-subscription-error
         modify-subscription     modify-subscription-error
         delete-subscription     delete-subscription-error
         kill-subscription       delete-subscription-error
         resync-subscription     resync-subscription-error

- In case of error responses to an "establish-subscription" or "modify-subscription" request there is the option of including an "error-info" node. This node may contain XML-encoded data with hints for parameter settings that might lead to successful RPC requests in the future. Following are the yang-data structures from [RFCYYYY] and [RFCZZZZ] which may be returned:

      establish-subscription returns hints in yang-data structure
      ---------------------- ------------------------------------
      target: event stream   establish-subscription-stream-error-info
      target: datastore      establish-subscription-datastore-error-info

      modify-subscription    returns hints in yang-data structure
      ---------------------- ------------------------------------
      target: event stream   modify-subscription-stream-error-info
      target: datastore      modify-subscription-datastore-error-info

The yang-data included within "error-info" SHOULD NOT include the optional leaf "reason", as such a leaf would be redundant with information that is already placed within the "error-app-tag".
In case of an rpc error resulting from a "delete-subscription", "kill-subscription", or "resync-subscription" request, no "error-info" needs to be included, as the "subscription-id" is the only RPC input parameter and no hints regarding this RPC input parameters need to be provided.
Security Considerations
This document does not introduce additional Security Considerations for dynamic subscriptions beyond those discussed in [RFCYYYY]. But there is one consideration worthy of more refinement based on the connection oriented nature of the NETCONF protocol. Specifically, if a buggy or compromised NETCONF subscriber sends a number of "establish-subscription" requests, then these subscriptions accumulate and may use up system resources. In such a situation, subscriptions MAY be terminated by terminating the underlying NETCONF session. The publisher MAY also suspend or terminate a subset of the active subscriptions on that NETCONF session in order to reclaim resources and preserve normal operation for the other subscriptions.
IANA Considerations
This document has no IANA actions.
References
Normative References
[RFC2119]

Key words for use in RFCs to Indicate Requirement Levels
DOI 10.17487/RFC2119
RFC 2119
BCP 14
S. Bradner
March 1997
[RFC5277]

NETCONF Event Notifications
DOI 10.17487/RFC5277
RFC 5277
S. Chisholm
H. Trevino
July 2008
[RFC6241]

Network Configuration Protocol (NETCONF)
DOI 10.17487/RFC6241
RFC 6241
R. Enns, Ed.
M. Bjorklund, Ed.
J. Schoenwaelder, Ed.
A. Bierman, Ed.
June 2011
[RFC8174]

Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words
DOI 10.17487/RFC8174
RFC 8174
BCP 14
B. Leiba
May 2017
[RFCZZZZ]

A YANG Data Model for Subscriptions to YANG Datastores
A Clemm
E Voit
July 2019
RFC ZZZZ
DOI 10.17487/RFCZZZZ
[RFCYYYY]

A YANG Data Model for Subscriptions to Event Notifications
Eric Voit
Alexander Clemm
Alberto Gonzalez Prieto
Ambika Prasad Tripathy
Einar Nilsen-Nygaard
July 2019
RFC YYYY
DOI 10.17487/RFCYYYY
Informative References
[RFC8347]

A YANG Data Model for the Virtual Router Redundancy Protocol (VRRP)
DOI 10.17487/RFC8347
RFC 8347
X. Liu, Ed.
A. Kyparlis
R. Parikh
A. Lindem
M. Zhang
March 2018
[XPATH]

XML Path Language (XPath) Version 1.0
J Clark
S DeRose
November 1999
Examples
This section is non-normative. Additionally the subscription "id" values of 22, 23, and 39 used below are just examples. In production, the actual values of "id" may not be small integers.
Event Stream Discovery
As defined in [RFCYYYY] an event stream exposes a continuous set of events available for subscription. A NETCONF client can retrieve the list of available event streams from a NETCONF publisher using the "get" operation against the top-level container "/streams" defined in [RFCYYYY] Section 3.1.
The following example illustrates the retrieval of the list of available event streams:
Get Streams Request

<rpc message-id="101"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <get>
    <filter type="subtree">
      <streams
     xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications"/>
    </filter>
  </get>
</rpc>
After such a request, the NETCONF publisher returns a list of event streams available, as well as additional information which might exist in the container.
Dynamic Subscriptions
Establishing Dynamic Subscriptions
The following figure shows two successful "establish-subscription" RPC requests as per [RFCYYYY]. The first request is given a subscription "id" of 22, the second, an "id" of 23.
Multiple Subscriptions over a NETCONF Session

   +------------+                 +-----------+
   | Subscriber |                 | Publisher |
   +------------+                 +-----------+
         |                              |
         |    Capability Exchange       |
         |<---------------------------->|
         |                              |
         |                              |
         |    establish-subscription    |
         |----------------------------->|  (a)
         | RPC Reply: OK, id = 22       |
         |<-----------------------------|  (b)
         |                              |
         | notification message (for 22)|
         |<-----------------------------|
         |                              |
         |                              |
         |    establish-subscription    |
         |----------------------------->|
         | notification message (for 22)|
         |<-----------------------------|
         | RPC Reply: OK, id = 23       |
         |<-----------------------------|
         |                              |
         |                              |
         | notification message (for 22)|
         |<-----------------------------|
         | notification message (for 23)|
         |<-----------------------------|
         |                              |

To provide examples of the information being transported, example messages for interactions (a) and (b) in Figure 2 are detailed below:
"establish-subscription" Request (a)

<rpc message-id="102" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <establish-subscription
      xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    <stream-xpath-filter xmlns:ex="http://example.com/events">
      /ex:foo/
    </stream-xpath-filter>
    <stream>NETCONF</stream>
    <dscp>10</dscp>
  </establish-subscription>
</rpc>
As NETCONF publisher was able to fully satisfy the request (a), the publisher sends the subscription "id" of the accepted subscription within message (b):
"establish-subscription" Success (b)

<rpc-reply message-id="102"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <id
    xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    22
  </id>
</rpc-reply>

If the NETCONF publisher had not been able to fully satisfy the request, or subscriber has no authorization to establish the subscription, the publisher would have sent an RPC error response. For instance, if the "dscp" value of 10 asserted by the subscriber in Figure 3 proved unacceptable, the publisher may have returned:
An Unsuccessful Establish Subscription

<rpc-reply message-id="102"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <rpc-error>
   <error-type>application</error-type>
   <error-tag>invalid-value</error-tag>
   <error-severity>error</error-severity>
   <error-app-tag>
     ietf-subscribed-notifications:dscp-unavailable
   </error-app-tag>
  </rpc-error>
</rpc-reply>
The subscriber can use this information in future attempts to establish a subscription.
Modifying Dynamic Subscriptions
An existing subscription may be modified. The following exchange shows a negotiation of such a modification via several exchanges between a subscriber and a publisher. This negotiation consists of a failed RPC modification request/response, followed by a successful one.
Interaction Model for Successful Subscription Modification

   +------------+                 +-----------+
   | Subscriber |                 | Publisher |
   +------------+                 +-----------+
         |                              |
         | notification message (for 23)|
         |<-----------------------------|
         |                              |
         | modify-subscription (id = 23)|
         |----------------------------->|  (c)
         | RPC error (with hint)        |
         |<-----------------------------|  (d)
         |                              |
         | modify-subscription (id = 23)|
         |----------------------------->|
         | RPC Reply: OK                |
         |<-----------------------------|
         |                              |
         | notification message (for 23)|
         |<-----------------------------|
         |                              |

If the subscription being modified in Figure 6 is a datastore subscription as per [RFCZZZZ], the modification request made in (c) may look like that shown in Figure 7. As can be seen, the modifications being attempted are the application of a new XPath filter as well as the setting of a new periodic time interval.
Subscription Modification Request (c)

<rpc message-id="303"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <modify-subscription
       xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications"
       xmlns:yp="urn:ietf:params:xml:ns:yang:ietf-yang-push">
    <id>23</id>
    <yp:datastore-xpath-filter xmlns:ex="http://example.com/datastore">
        /ex:foo/ex:bar
    </yp:datastore-xpath-filter>
    <yp:periodic>
      <yp:period>500</yp:period>
    </yp:periodic>
  </modify-subscription>
</rpc>
If the NETCONF publisher can satisfy both changes, the publisher sends a positive result for the RPC. If the NETCONF publisher cannot satisfy either of the proposed changes, the publisher sends an RPC error response (d). The following is an example RPC error response for (d) which includes a hint. This hint is an alternative time period value which might have resulted in a successful modification:
"modify-subscription" Failure with Hint (d)

<rpc-reply message-id="303"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <rpc-error>
    <error-type>application</error-type>
    <error-tag>invalid-value</error-tag>
    <error-severity>error</error-severity>
    <error-app-tag>
        ietf-yang-push:period-unsupported
    </error-app-tag>
    <error-info>
      <modify-subscription-datastore-error-info
          xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
        <period-hint>
            3000
        </period-hint>
      </modify-subscription-datastore-error-info>
    </error-info>
  </rpc-error>
</rpc-reply>
Deleting Dynamic Subscriptions
The following demonstrates deleting a subscription. This subscription may have been to either a stream or a datastore.
"delete-subscription"

<rpc message-id="103"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <delete-subscription
    xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    <id>22</id>
  </delete-subscription>
</rpc>
If the NETCONF publisher can satisfy the request, the publisher replies with success to the RPC request.
If the NETCONF publisher cannot satisfy the request, the publisher sends an error-rpc element indicating the modification didn't work. Figure 10 shows a valid response for existing valid subscription "id", but that subscription "id" was created on a different NETCONF transport session:
Unsuccessful "delete-subscription"

<rpc-reply message-id="103"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <rpc-error>
    <error-type>application</error-type>
    <error-tag>invalid-value</error-tag>
    <error-severity>error</error-severity>
    <error-app-tag>
        ietf-subscribed-notifications:no-such-subscription
    </error-app-tag>
  </rpc-error>
</rpc-reply>
Subscription State Notifications
A publisher will send subscription state notifications for dynamic subscriptions according to the definitions within [RFCYYYY].
subscription-modified
As per Section 2.7.2 of [RFCYYYY], a "subscription-modified" might be sent over NETCONF if the definition of a configured filter changes. A subscription state notification encoded in XML would look like:
"subscription-modified" Subscription State Notification

<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
  <eventTime>2007-09-01T10:00:00Z</eventTime>
  <subscription-modified
      xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    <id>39</id>
    <stream-xpath-filter xmlns:ex="http://example.com/events">
      /ex:foo
    </stream-xpath-filter>
    <stream>NETCONF</stream>
  </subscription-modified>
</notification>
subscription-resumed, and replay-complete
A "subscription-resumed" would look like:
"subscription-resumed" Notification in XML

<notification
  xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
  <eventTime>2007-09-01T10:00:00Z</eventTime>
  <subscription-resumed
    xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    <id>39</id>
  </subscription-resumed>
</notification>
The "replay-complete" is virtually identical, with "subscription-resumed" simply being replaced by "replay-complete".
subscription-terminated and subscription-suspended
A "subscription-terminated" would look like:
"subscription-terminated" Subscription State Notification

<notification
  xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
  <eventTime>2007-09-01T10:00:00Z</eventTime>
  <subscription-terminated
    xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    <id>39</id>
    <reason>
       suspension-timeout
    </reason>
  </subscription-terminated>
</notification>
The "subscription-suspended" is virtually identical, with "subscription-terminated" simply being replaced by "subscription-suspended".
Filter Examples
This section provides examples which illustrate both XPath and subtree methods of filtering event record contents. The examples are based on the YANG notification "vrrp-protocol-error-event" as defined per the ietf-vrrp.yang model within [RFC8347]. Event records based on this specification which are generated by the publisher might appear as:
RFC 8347 (VRRP) - Example Notification

<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
  <eventTime>2018-09-14T08:22:33.44Z</eventTime>
  <vrrp-protocol-error-event
       xmlns="urn:ietf:params:xml:ns:yang:ietf-vrrp">
     <protocol-error-reason>checksum-error</protocol-error-reason>
  </vrrp-protocol-error-event>
</notification>
Suppose a subscriber wanted to establish a subscription which only passes instances of event records where there is a "checksum-error" as part of a VRRP protocol event. Also assume the publisher places such event records into the NETCONF stream. To get a continuous series of matching event records, the subscriber might request the application of an XPath filter against the NETCONF stream. An "establish-subscription" RPC to meet this objective might be:
Establishing a Subscription Error Reason via XPath

<rpc message-id="601" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <establish-subscription
    xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    <stream>NETCONF</stream>
    <stream-xpath-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-vrrp">
      /vrrp-protocol-error-event[
         vrrp:protocol-error-reason="vrrp:checksum-error"]
    </stream-xpath-filter>
  </establish-subscription>
</rpc>
For more examples of XPath filters, see [XPATH].
Suppose the "establish-subscription" in Figure 15 was accepted. And suppose later a subscriber decided they wanted to broaden this subscription cover to all VRRP protocol events (i.e., not just those with a "checksum error"). The subscriber might attempt to modify the subscription in a way which replaces the XPath filter with a subtree filter which sends all VRRP protocol events to a subscriber. Such a "modify-subscription" RPC might look like:
"Example "modify-subscription" RPC"

<rpc message-id="602" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <modify-subscription
     xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
    <id>99</id>
    <stream-subtree-filter>
     <vrrp-protocol-error-event
            xmlns="urn:ietf:params:xml:ns:yang:ietf-vrrp"/>
    </stream-subtree-filter>
  </modify-subscription>
</rpc>

For more examples of subtree filters, see [RFC6241], section 6.4.
Acknowledgments
We wish to acknowledge the helpful contributions, comments, and suggestions that were received from: Andy Bierman, Yan Gang, Sharon Chisholm, Hector Trevino, Peipei Guo, Susan Hares, Tim Jenkins, Balazs Lengyel, Martin Bjorklund, Mahesh Jethanandani, Kent Watsen, Qin Wu, and Guangying Zheng.