YANG Push
The YANG Push feature allows data to be sent to a client automatically, using NETCONF notifications.
A separate mechanism for managing dynamic subscriptions is used by YANG Push, which is intended to replace the existing <create-subscription> RPC operation defined in RFC 5277. This new set of RPC operations (defined in RFC 8639) is used for current event stream subscriptions. It is also used for new datastore subscriptions (defined in RFC 8641).
The YANG Push support will be provided in multiple phases, and is almost complete in the 25.10 release train.
Dynamic subscriptions over NETCONF in XML (23.10)
Periodic subscriptions
Conventional datastore On-Change subscriptions
Simulated On-Change subscriptions for the Operational Datastore
On-Change subscriptions for the Operational Datastore from subsystem events (TBD)
Proprietary support for JSON and CBOR encoding with NETCONF (25.10)
Dynamic subscriptions over RESTCONF in XML or JSON (25.10)
Configured subscriptions for Binary Push support (25.10)
gRPC for native protobuf files (TBD)
gNMI ONCHANGE subscriptions (24.10)
RFC 9254 CBOR+SID encoding over UDP or TCP (25.10)
UDP-Notif Protocol support (25.10)
CLI Parameters for YANG Push
Parameter |
Default |
Description |
|---|---|---|
--bundle=yang-push |
not loaded |
The bundle parameter is used to enable or disable the entire YANG Push feature |
1400 |
Control size of message chunks sent to the receiver |
|
4 |
Specifies the maximum number of on-change push subscriptions that can be in use at once for the <operational> datastore |
|
16 |
Specifies the maximum number of periodic push subscriptions that can be in use at once |
|
100 |
Specifies the minimum value for the 'dampening-period' parameter that will be accepted for an on-change push subscription. (centiseconds) |
|
100 |
Specifies the minimum value for the 'period' parameter that will be accepted for a periodic push subscription. (centiseconds) |
|
true |
Specifies if the simulated on-change push subscriptions should be enabled for the <operational> datastore. |
|
true |
Specifies the notification message that should be used for a simulated on-change push subscription. |
|
500 |
Specifies the value for the 'period' parameter that will be used for simulated operational on-change push subscription. |
|
true |
Must be 'true' to use YANG Push |
|
false |
Enable or disable the Binary Push modules and features. |
|
true |
Enable or disable the YANG Push 2 modules and features. |
|
sid-file |
Select the YANG/CBOR SID assignment mode |
YANG Push 2
Warning
Many specifications implemented in this feature are based on Internet Drafts that are not stable and subject to change at any time.
Backward compatibility with Internet Drafts is not supported
Use with caution until the RFCs are published
A large set of new standards are being developed for YANG Push. The 25.10 release train implements many of these Internet Drafts. It is included in the Advanced feature set in the 'yumapro-sdk' and 'yumapro-pthreads' packages. The WITH_YANG_PUSH and WITH_YANG_PUSH2 compiler flags are required to build this feature from source code.
The following yangcli-pro 'show session' summary shows the related YANG modules:
notifications@2013-03-15
yumaworks-yangpush-dev@2019-11-22
ietf-distributed-notif@2026-04-13
ietf-notification-capabilities@2022-02-17
ietf-sid-file@2024-07-31
ietf-subscribed-notif-receivers@2024-02-01
ietf-subscribed-notifications@2019-09-09
Features:
configured
dscp
encode-json
encode-xml
replay
subtree
xpath
ietf-system-capabilities@2022-02-17
ietf-udp-client@2025-06-04 (I)
ietf-udp-notif-transport@2025-06-04
Features:
encode-cbor
segmentation
ietf-yang-library@2019-01-04
ietf-yang-patch@2017-02-22
ietf-yang-push@2019-09-09
Features:
on-change
Deviations:
yumaworks-yangpush-dev
ietf-yang-push-revision@2025-12-07
Features:
yang-push-revision-supported
ietf-yang-revisions@2024-06-04 (I)
ietf-yang-semver@2025-01-21 (I)
yumaworks-yang-cbor@2022-05-21
UDP-Notif Protocol
Document: UDP-based Transport for Configured Subscriptions
YANG Module: ietf-udp-notif-transport.yang
This is the only protocol supported for configured subscriptions at this time.
Warning
This protocol is not secure. Data is sent unencrypted using the UDP protocol.
The following features are supported:
encode-cbor : RFC 9254 YANG to CBOR encoding is fully supported
segmentation : The Segmentation feature is fully supported and should be used to avoid dropped events.
The --max-chunk-size CLI parameter or 'max-segment-size' leaf controls the payload size used when sending messages to a UDP-Notif Collector.
If the 'enable-segmentation' leaf is 'true' or not present then the max-segment-size is used for each segment (except perhaps the last segment).
If the 'enable-segmentation' leaf is 'false' the max-segment-size is used for the one segment allowed per message.
If the message would be too big then the 'excluded-events' counter is incremented for the subscription and receiver.
All standard media types are supported (XML, JSON, CBOR)
Distributed Notifications
Document: Subscription to Distributed Notifications
YANG Module: ietf-distributed-notif.yang
This module adds a Publisher ID to subscriptions to identity the source of the event generation. This allows multiple publishers to use the same source IP address.
There is no requirement that all publishers have a unique identifier.
Note
The publisher ID for the main server is set to '1'
A future release will support additional publisher IDs when subsystems can generate Push updates
Versioning Support in Subscriptions
Document: Support of Versioning in YANG Notifications Subscription
YANG Module: ietf-yang-push-revision.yang
This module adds the ability to check the modules and module revisions that are being used by the server. The client can list module names, revision dates, and/or revision labels that must be supported by the server. If the module or specified revision is not supported then the subscription is rejected.
Usage
The 'module-version-subs' list parameter can be used for event stream and datastore subscriptions
If a list entry contains only a 'name' key leaf then any revision of that module is required for the subscription to be valid
<module-version-subs xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push-revision"> <name>ietf-netconf-acm</name> </module-version-subs>
If a list entry contains a key leaf and a 'revision' leaf, then that revision date must match the revision date of the specified module for the subscription to be valid
<module-version-subs xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push-revision"> <name>ietf-netconf-acm</name> <revision>2018-02-14</revision> </module-version-subs>
If a list entry contains a key leaf and a 'revision-version' option leaf, then that revision or a version of the YANG module must be less than or equal to the revision or version label of the specified module for the subscription to be valid. The module must have an IETF Semver extension (ysv:version) defined for a reivsion label to be found.
<module-version-subs xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push-revision"> <name>ietf-netconf-acm</name> <version>1.0.3</version> </module-version-subs>
Error Examples
If an unknown module name such as 'bad'module' is specified then an error is returned.
Example Request:
<rpc message-id="4"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<establish-subscription xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<encoding
xmlns:unt="urn:ietf:params:xml:ns:yang:ietf-udp-notif-transport">unt:encode-cbor</encoding>
<datastore
xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:operational</datastore>
<datastore-xpath-filter
xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">/nacm</datastore-xpath-filter>
<module-version-subs xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push-revision">
<name>ietf-netconf-acm</name>
</module-version-subs>
<module-version-subs xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push-revision">
<name>bad-module</name>
</module-version-subs>
<periodic xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<period>2000</period>
</periodic>
</establish-subscription>
</rpc>
Example Error Reply:
The 'operation-failed' error-tag is returned
The 'module-not-found' error message is returned
The 'error-path' references the bad 'module-version-subs' entry
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="4" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:sn="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications"
xmlns:ypr="urn:ietf:params:xml:ns:yang:ietf-yang-push-revision"
xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<rpc-error>
<error-type>protocol</error-type>
<error-tag>operation-failed</error-tag>
<error-severity>error</error-severity>
<error-app-tag>data-incomplete</error-app-tag>
<error-path>/nc:rpc/sn:establish-subscription/ypr:module-version-subs[ypr:name='bad-module']</error-path>
<error-message xml:lang="en">module not found</error-message>
<error-info>
<error-number>236</error-number>
</error-info>
</rpc-error>
</rpc-reply>
RFCs and Features Supported
There are multiple ways to do the same thing in YANG Push, so not all of it is implemented at once.
The "dynamic subscriptions" functionality is implemented in phase 1.
The "configured subscriptions" functionality is now supported, starting in the 25.10 release train. The UDP-Notif Protocol is the only protocol that uses configured subscriptions and receivers.
RFC 8639: Subscription to YANG Notifications
YANG Module: ietf-subscribed-notifications@2019-09-09.yang
Supported Features
encode-xml
encode-json (25.10)
replay
subtree
xpath
YANG Push 2 Supported Features
configured
dscp
Unsupported Features
interface-designation
qos
supports-vrf
RFC 8640: Dynamic Subscription to YANG Events and Datastores over NETCONF
RFC 8641: Subscription to YANG Notifications for Datastore Updates
YANG Module: ietf-yang-push@2019-09-09.yang
Supported Features
on-change
anchor-time parameter is now supported starting in 25.10-1
Supported Features in YANG Push 2
/subscriptionssubtree can be configured with event stream and datastore subscriptions/subscriptions/receiver-instancessubtree can be configured with UDP-Notif Collectors
Unsupported Features
/subscriptionsdata node is not available for NMDA access to <operational> values of dynamic subscriptions
RFC 8650: Dynamic Subscription to YANG Events and Datastores over RESTCONF
YANG Push Tree Diagram
The current set of YANG Push related definitions is shown below.
module: ietf-subscribed-notifications
+--ro streams
| +--ro stream* [name]
| +--ro name string
| +--ro description? string
| +--ro replay-support? empty {replay}?
| +--ro replay-log-creation-time yang:date-and-time {replay}?
| +--ro replay-log-aged-time? yang:date-and-time {replay}?
+--rw filters
| +--rw stream-filter* [name]
| | +--rw name string
| | +--rw (filter-spec)?
| | +--:(stream-subtree-filter)
| | | +--rw stream-subtree-filter? <anydata> {subtree}?
| | +--:(stream-xpath-filter)
| | +--rw stream-xpath-filter? yang:xpath1.0 {xpath}?
| +--rw yp:selection-filter* [filter-id]
| +--rw yp:filter-id string
| +--rw (yp:filter-spec)?
| +--:(yp:datastore-subtree-filter)
| | +--rw yp:datastore-subtree-filter? <anydata> {sn:subtree}?
| +--:(yp:datastore-xpath-filter)
| +--rw yp:datastore-xpath-filter? yang:xpath1.0 {sn:xpath}?
+--rw subscriptions
+--rw subscription* [id]
| +--rw id subscription-id
| +--rw (target)
| | +--:(stream)
| | | +--rw (stream-filter)?
| | | | +--:(by-reference)
| | | | | +--rw stream-filter-name stream-filter-ref
| | | | +--:(within-subscription)
| | | | +--rw (filter-spec)?
| | | | +--:(stream-subtree-filter)
| | | | | +--rw stream-subtree-filter? <anydata> {subtree}?
| | | | +--:(stream-xpath-filter)
| | | | +--rw stream-xpath-filter? yang:xpath1.0 {xpath}?
| | | +--rw stream stream-ref
| | | +--ro replay-start-time? yang:date-and-time {replay}?
| | | +--rw configured-replay? empty {configured,replay}?
| | +--:(yp:datastore)
| | +--rw yp:datastore identityref
| | +--rw (yp:selection-filter)?
| | +--:(yp:by-reference)
| | | +--rw yp:selection-filter-ref selection-filter-ref
| | +--:(yp:within-subscription)
| | +--rw (yp:filter-spec)?
| | +--:(yp:datastore-subtree-filter)
| | | +--rw yp:datastore-subtree-filter? <anydata> {sn:subtree}?
| | +--:(yp:datastore-xpath-filter)
| | +--rw yp:datastore-xpath-filter? yang:xpath1.0 {sn:xpath}?
| +--rw stop-time? yang:date-and-time
| +--rw dscp? inet:dscp {dscp}?
| +--rw weighting? uint8 {qos}?
| +--rw dependency? subscription-id {qos}?
| +--rw transport? transport {configured}?
| +--rw encoding? encoding
| +--rw purpose? string {configured}?
| +--rw (notification-message-origin)? {configured}?
| | +--:(interface-originated)
| | | +--rw source-interface? if:interface-ref {interface-designation}?
| | +--:(address-originated)
| | +--rw source-vrf? -> /ni:network-instances/network-instance/name {supports-vrf}?
| | +--rw source-address? inet:ip-address-no-zone
| +--ro configured-subscription-state? enumeration {configured}?
| +--rw receivers
| | +--rw receiver* [name]
| | +--rw name string
| | +--ro sent-event-records? yang:zero-based-counter64
| | +--ro excluded-event-records? yang:zero-based-counter64
| | +--ro state enumeration
| | +---x reset {configured}?
| | | +--ro output
| | | +--ro time yang:date-and-time
| | +--rw snr:receiver-instance-ref? -> /sn:subscriptions/snr:receiver-instances/receiver-instance/name
| +--rw (yp:update-trigger)?
| | +--:(yp:periodic)
| | | +--rw yp:periodic!
| | | +--rw yp:period centiseconds
| | | +--rw yp:anchor-time? yang:date-and-time
| | +--:(yp:on-change) {on-change}?
| | +--rw yp:on-change!
| | +--rw yp:dampening-period? centiseconds
| | +--rw yp:sync-on-start? boolean
| | +--rw yp:excluded-change* change-type
| +--ro dn:message-publisher-id* uint32
| +--rw ypr:module-version-config* [module-name] {yang-push-revision-supported}?
| +--rw ypr:module-name yang:yang-identifier
| +--rw ypr:revision? rev:revision-date
| +--rw ypr:version? ysver:version
+--rw snr:receiver-instances
+--rw snr:receiver-instance* [name]
+--rw snr:name string
+--rw (snr:transport-type)
+--:(unt:udp-notif)
+--rw unt:udp-notif-receiver
+--rw unt:remote-address inet:host
+--rw unt:remote-port inet:port-number
+--rw unt:local-address? inet:ip-address {local-binding}?
+--rw unt:local-port? inet:port-number {local-binding}?
+--rw unt:dtls! {dtls}?
+--rw unt:enable-segmentation? boolean
+--rw unt:max-segment-size? uint16
rpcs:
+---x establish-subscription
| +---w input
| | +---w (target)
| | | +--:(stream)
| | | | +---w (stream-filter)?
| | | | | +--:(by-reference)
| | | | | | +---w stream-filter-name stream-filter-ref
| | | | | +--:(within-subscription)
| | | | | +---w (filter-spec)?
| | | | | +--:(stream-subtree-filter)
| | | | | | +---w stream-subtree-filter? <anydata> {subtree}?
| | | | | +--:(stream-xpath-filter)
| | | | | +---w stream-xpath-filter? yang:xpath1.0 {xpath}?
| | | | +---w stream stream-ref
| | | | +---w replay-start-time? yang:date-and-time {replay}?
| | | +--:(yp:datastore)
| | | +---w yp:datastore identityref
| | | +---w (yp:selection-filter)?
| | | +--:(yp:by-reference)
| | | | +---w yp:selection-filter-ref selection-filter-ref
| | | +--:(yp:within-subscription)
| | | +---w (yp:filter-spec)?
| | | +--:(yp:datastore-subtree-filter)
| | | | +---w yp:datastore-subtree-filter? <anydata> {sn:subtree}?
| | | +--:(yp:datastore-xpath-filter)
| | | +---w yp:datastore-xpath-filter? yang:xpath1.0 {sn:xpath}?
| | +---w stop-time? yang:date-and-time
| | +---w dscp? inet:dscp {dscp}?
| | +---w weighting? uint8 {qos}?
| | +---w dependency? subscription-id {qos}?
| | +---w encoding? encoding
| | +---w (yp:update-trigger)?
| | | +--:(yp:periodic)
| | | | +---w yp:periodic!
| | | | +---w yp:period centiseconds
| | | +--:(yp:on-change) {on-change}?
| | | +---w yp:on-change!
| | | +---w yp:dampening-period? centiseconds
| | | +---w yp:sync-on-start? boolean
| | | +---w yp:excluded-change* change-type
| | +---w ypr:module-version-config* [module-name] {yang-push-revision-supported}?
| | +---w ypr:module-name yang:yang-identifier
| | +---w ypr:revision? rev:revision-date
| | +---w ypr:version? ysver:version
| +--ro output
| +--ro id subscription-id
| +--ro replay-start-time-revision? yang:date-and-time {replay}?
+---x modify-subscription
| +---w input
| +---w id subscription-id
| +---w (target)
| | +--:(stream)
| | | +---w (stream-filter)?
| | | +--:(by-reference)
| | | | +---w stream-filter-name stream-filter-ref
| | | +--:(within-subscription)
| | | +---w (filter-spec)?
| | | +--:(stream-subtree-filter)
| | | | +---w stream-subtree-filter? <anydata> {subtree}?
| | | +--:(stream-xpath-filter)
| | | +---w stream-xpath-filter? yang:xpath1.0 {xpath}?
| | +--:(yp:datastore)
| | +---w yp:datastore? identityref
| | +---w (yp:selection-filter)?
| | +--:(yp:by-reference)
| | | +---w yp:selection-filter-ref selection-filter-ref
| | +--:(yp:within-subscription)
| | +---w (yp:filter-spec)?
| | +--:(yp:datastore-subtree-filter)
| | | +---w yp:datastore-subtree-filter? <anydata> {sn:subtree}?
| | +--:(yp:datastore-xpath-filter)
| | +---w yp:datastore-xpath-filter? yang:xpath1.0 {sn:xpath}?
| +---w (yp:update-trigger)?
| | +--:(yp:periodic)
| | | +---w yp:periodic!
| | | +---w yp:period centiseconds
| | +--:(yp:on-change) {on-change}?
| | +---w yp:on-change!
| | +---w yp:dampening-period? centiseconds
| +---w ypr:module-version-config* [module-name] {yang-push-revision-supported}?
| +---w ypr:module-name yang:yang-identifier
| +---w ypr:revision? rev:revision-date
| +---w ypr:version? ysver:version
+---x delete-subscription
| +---w input
| +---w id subscription-id
+---x kill-subscription
+---w input
+---w id subscription-id
notifications:
+---n replay-completed {replay}?
| +--ro id subscription-id
+---n subscription-completed {configured}?
| +--ro id subscription-id
+---n subscription-modified
| +--ro id subscription-id
| +--ro (target)
| | +--:(stream)
| | | +--ro (stream-filter)?
| | | | +--:(by-reference)
| | | | | +--ro stream-filter-name stream-filter-ref
| | | | +--:(within-subscription)
| | | | +--ro (filter-spec)?
| | | | +--:(stream-subtree-filter)
| | | | | +--ro stream-subtree-filter? <anydata> {subtree}?
| | | | +--:(stream-xpath-filter)
| | | | +--ro stream-xpath-filter? yang:xpath1.0 {xpath}?
| | | +--ro stream stream-ref
| | | +--ro replay-start-time? yang:date-and-time {replay}?
| | +--:(yp:datastore)
| | +--ro yp:datastore identityref
| | +--ro (yp:selection-filter)?
| | +--:(yp:by-reference)
| | | +--ro yp:selection-filter-ref selection-filter-ref
| | +--:(yp:within-subscription)
| | +--ro (yp:filter-spec)?
| | +--:(yp:datastore-subtree-filter)
| | | +--ro yp:datastore-subtree-filter? <anydata> {sn:subtree}?
| | +--:(yp:datastore-xpath-filter)
| | +--ro yp:datastore-xpath-filter? yang:xpath1.0 {sn:xpath}?
| +--ro stop-time? yang:date-and-time
| +--ro dscp? inet:dscp {dscp}?
| +--ro weighting? uint8 {qos}?
| +--ro dependency? subscription-id {qos}?
| +--ro transport? transport {configured}?
| +--ro encoding? encoding
| +--ro purpose? string {configured}?
| +--ro (yp:update-trigger)?
| | +--:(yp:periodic)
| | | +--ro yp:periodic!
| | | +--ro yp:period centiseconds
| | | +--ro yp:anchor-time? yang:date-and-time
| | +--:(yp:on-change) {on-change}?
| | +--ro yp:on-change!
| | +--ro yp:dampening-period? centiseconds
| | +--ro yp:sync-on-start? boolean
| | +--ro yp:excluded-change* change-type
| +--ro dn:message-publisher-id* uint32
| +--ro ypr:module-version* [module-name] {yang-push-revision-supported}?
| | +--ro ypr:module-name yang:yang-identifier
| | +--ro ypr:revision rev:revision-date
| | +--ro ypr:version? ysver:version
| +--ro ypr:yang-library-content-id? -> /yanglib:yang-library/content-id {yang-push-revision-supported}?
+---n subscription-resumed
| +--ro id subscription-id
+---n subscription-started {configured}?
| +--ro id subscription-id
| +--ro (target)
| | +--:(stream)
| | | +--ro (stream-filter)?
| | | | +--:(by-reference)
| | | | | +--ro stream-filter-name stream-filter-ref
| | | | +--:(within-subscription)
| | | | +--ro (filter-spec)?
| | | | +--:(stream-subtree-filter)
| | | | | +--ro stream-subtree-filter? <anydata> {subtree}?
| | | | +--:(stream-xpath-filter)
| | | | +--ro stream-xpath-filter? yang:xpath1.0 {xpath}?
| | | +--ro stream stream-ref
| | | +--ro replay-start-time? yang:date-and-time {replay}?
| | | +--ro replay-previous-event-time? yang:date-and-time {replay}?
| | +--:(yp:datastore)
| | +--ro yp:datastore identityref
| | +--ro (yp:selection-filter)?
| | +--:(yp:by-reference)
| | | +--ro yp:selection-filter-ref selection-filter-ref
| | +--:(yp:within-subscription)
| | +--ro (yp:filter-spec)?
| | +--:(yp:datastore-subtree-filter)
| | | +--ro yp:datastore-subtree-filter? <anydata> {sn:subtree}?
| | +--:(yp:datastore-xpath-filter)
| | +--ro yp:datastore-xpath-filter? yang:xpath1.0 {sn:xpath}?
| +--ro stop-time? yang:date-and-time
| +--ro dscp? inet:dscp {dscp}?
| +--ro weighting? uint8 {qos}?
| +--ro dependency? subscription-id {qos}?
| +--ro transport? transport {configured}?
| +--ro encoding? encoding
| +--ro purpose? string {configured}?
| +--ro (yp:update-trigger)?
| | +--:(yp:periodic)
| | | +--ro yp:periodic!
| | | +--ro yp:period centiseconds
| | | +--ro yp:anchor-time? yang:date-and-time
| | +--:(yp:on-change) {on-change}?
| | +--ro yp:on-change!
| | +--ro yp:dampening-period? centiseconds
| | +--ro yp:sync-on-start? boolean
| | +--ro yp:excluded-change* change-type
| +--ro dn:message-publisher-id* uint32
| +--ro ypr:module-version* [module-name] {yang-push-revision-supported}?
| | +--ro ypr:module-name yang:yang-identifier
| | +--ro ypr:revision rev:revision-date
| | +--ro ypr:version? ysver:version
| +--ro ypr:yang-library-content-id? -> /yanglib:yang-library/content-id {yang-push-revision-supported}?
+---n subscription-suspended
| +--ro id subscription-id
| +--ro reason identityref
+---n subscription-terminated
+--ro id subscription-id
+--ro reason identityref
module: ietf-system-capabilities
+--ro system-capabilities
+--ro datastore-capabilities* [datastore]
| +--ro datastore -> /yanglib:yang-library/datastore/name
| +--ro per-node-capabilities* []
| +--ro (node-selection)?
| | +--:(node-selector)
| | +--ro node-selector? nacm:node-instance-identifier
| +--ro notc:subscription-capabilities
| +--ro notc:max-nodes-per-update? uint32
| +--ro notc:periodic-notifications-supported? notification-support
| +--ro (notc:update-period)?
| | +--:(notc:minimum-update-period)
| | | +--ro notc:minimum-update-period? uint32
| | +--:(notc:supported-update-period)
| | +--ro notc:supported-update-period* uint32
| +--ro notc:on-change-supported? notification-support {yp:on-change}?
| +--ro notc:minimum-dampening-period? uint32 {yp:on-change}?
| +--ro notc:supported-excluded-change-type* union {yp:on-change}?
+--ro notc:subscription-capabilities
+--ro notc:max-nodes-per-update? uint32
+--ro notc:periodic-notifications-supported? notification-support
+--ro (notc:update-period)?
| +--:(notc:minimum-update-period)
| | +--ro notc:minimum-update-period? uint32
| +--:(notc:supported-update-period)
| +--ro notc:supported-update-period* uint32
+--ro notc:on-change-supported? notification-support {yp:on-change}?
+--ro notc:minimum-dampening-period? uint32 {yp:on-change}?
+--ro notc:supported-excluded-change-type* union {yp:on-change}?
+--ro ypr:yang-push-module-revision-supported? boolean
module: ietf-yang-push
rpcs:
+---x resync-subscription {on-change}?
+---w input
+---w id sn:subscription-id
notifications:
+---n push-update
| +--ro id? sn:subscription-id
| +--ro datastore-contents? <anydata>
| +--ro incomplete-update? empty
| +--ro dn:message-publisher-id? uint32
+---n push-change-update {on-change}?
+--ro id? sn:subscription-id
+--ro datastore-changes
| +--ro yang-patch
| +--ro patch-id string
| +--ro comment? string
| +--ro edit* [edit-id]
| +--ro edit-id string
| +--ro operation enumeration
| +--ro target target-resource-offset
| +--ro point? target-resource-offset
| +--ro where? enumeration
| +--ro value? <anydata>
+--ro incomplete-update? empty
+--ro dn:message-publisher-id? uint32
module: yumaworks-yang-cbor
+--ro yang-sid-info!
+--ro sid-set-id? sid-set-id
+--ro yang-sid-mode? ywt:yang-sid-mode
+--ro lsid-size? ywt:lsid-size
+--ro current-sid-max? sid:sid
+--ro current-sid-count? uint64
rpcs:
+---x get-yang-sid-data
+---w input
| +---w lower-bound? sid:sid
| +---w upper-bound? sid:sid
+--ro output
+--ro current-set-id? sid-set-id
+--ro data
+--ro sid-item* [sid]
+--ro sid sid:sid
+--ro namespace? enumeration
+--ro module-name? string
+--ro identifier? union
Configuring YANG Push
There is no CLI parameter to turn YANG Push on or off. Instead, then --bundle parameter is used.
A bundle named "yang-push" is used:
yang-pushis a reserved library name in the server.The SIL library (libyang-push.so) contains the RPC operation callbacks for YANG Push. The "agt" directory contains the server implementation code.
The server does not need to support or enable NMDA to use YANG Push. If the --with-nmda parameter is set to ‘false’ then the <operational> datastore will consist of config=false data nodes and their ancestor lists, list keys, and containers.
The source code must be built using WITH_YANG_PUSH=1 or EVERYTHING=1 make flag in order for the YANG Push code to be included in the target binaries.
Command line example:
netconfd-pro --bundle=yang-push
Config file example;
netconfd-pro {
bundle yang-push
}
Configuring Named Filters
The /filters container and /filters/stream-filter list are defined in RFC 8639.
+--rw filters
| +--rw stream-filter* [name]
| | +--rw name string
| | +--rw (filter-spec)?
| | +--:(stream-subtree-filter)
| | | +--rw stream-subtree-filter? <anydata> {subtree}?
| | +--:(stream-xpath-filter)
| | +--rw stream-xpath-filter? yang:xpath1.0 {xpath}?
| +--rw yp:selection-filter* [filter-id]
| +--rw yp:filter-id string
| +--rw (yp:filter-spec)?
| +--:(yp:datastore-subtree-filter)
| | +--rw yp:datastore-subtree-filter? <anydata> {sn:subtree}?
| +--:(yp:datastore-xpath-filter)
| +--rw yp:datastore-xpath-filter? yang:xpath1.0 {sn:xpath}?
Named filters are fully supported, using the /filters subtree:
An event stream subscription can use the "stream-filter" list
A datastore subscriptions can use the selection-filter list.
Even though the contents of each list are similar, the content of the filters is not.
A "stream-filter" is a notification filter, and the content is exactly like the <filter> element used in the "create-subscription" operation.
A "selection-filter" is a retrieval filter, and the content is exactly like the <filter> element used in the "get" operation.
Filter Configuration Restrictions
A filter can be created at any time.
A filter can be modified at any time. If any subscriptions are using the filter then they will updated to use the new filter as soon as possible. This is usually as soon as any current message on that session is completed.
If the new filter is not acceptable for a subscription using the filter then that subscription will be terminated. Use caution when modifying a filter that is in use.
A filter can only be deleted if no subscription is using it.
An empty filter is allowed, which means only a key leaf was provided and not a filter leaf. This allows placeholders to be used. It is not recommended to use this feature. An empty filter is the same as no filter, and if that is not allowed for a subscription, then it will be rejected (or deleted if already active).
Sending anydata for a subtree filter, or an xpath1.0 leaf for an XPath filter can be complex or even unsupported in the client. XPath filters will be accepted without prefixed identifiers. If prefixes are used, then they must be properly mapped to a module namespace URI using an "xmlns" attribute. If multiple nodes match the same local name then prefixes are required to pick only one of them.
Filter Examples
A subtree filter for an event stream that selects the "netconf-session-end" event:
<filters xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<stream-filter>
<name>filter1</name>
<stream-subtree-filter>
<netconf-session-end xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-notifications" />
</stream-subtree-filter>
</stream-filter>
</filters>
An XPath filter for an event stream that selects the "netconf-session-start" event:
<filters xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<stream-filter>
<name>filter2</name>
<stream-xpath-filter xmlns:n="urn:ietf:params:xml:ns:yang:ietf-netconf-notifications"
>/n:netconf-session-start</stream-xpath-filter>
</stream-filter>
</filters>
A subtree filter for a datastore that selects the /nacm/groups subtree.
<filters xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<selection-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<filter-id>filter2</filter-id>
<datastore-subtree-filter>
<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
<groups />
</nacm>
</datastore-subtree-filter>
</selection-filter>
</filters>
An XPath filter for a datastore that selects the /nacm/groups subtree:
<filters xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<selection-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<filter-id>filter3</filter-id>
<datastore-xpath-filter
xmlns:n="urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
>/n:nacm/n:groups</datastore-xpath-filter>
</selection-filter>
</filters>
YANG Push RPC Operations
The following RPC Operations are supported
establish-subscription
modify-subscription
delete-subscription
kill-subscription
resync-subscription
YANG Push Notification Events
The following Notifications are supported:
push-update
push-change-update
replay-completed
subscription-modified
subscription-resumed
subscription-suspended
subscription-terminated
Periodic Subscriptions
A periodic push subscription request that is granted will cause the specified data to be pushed at a specified interval.
The data is sent whether it changed or not. Every interval, a push-update notification with the specified data will be sent to the subscription.
The --push-max-periodic CLI parameter controls the number of these push subscriptions that can be enabled at once. This is the server total, so one subscription could use up all the subscriptions. The server does not prevent a session from establishing multiple subscriptions.
Use the <establish-subscription> operation to start a periodic subscription. The "datastore", and "period" parameters must be provided.
There are no filter restrictions for a periodic subscription. Any filter that is allowed for a <get> operation may be used for a periodic subscription. If a named filter is used then it can be modified while a periodic subscription is active. The subscription output will be updated as soon as possible after a filter reference in use is modified.
The datastore parameter can be set to "candidate", "operational", or "running". It must be set to "operational" to monitor config=false data nodes.
Example: Retrieve the /interfaces-state/interface entry for interface "lo" every 30 seconds.
The client might send this request:
<?xml version="1.0" encoding="UTF-8"?>
<rpc message-id="2" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<establish-subscription xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<datastore xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:operational</datastore>
<datastore-subtree-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>lo</name>
</interface>
</interfaces-state>
</datastore-subtree-filter>
<periodic xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<period>3000</period>
</periodic>
</establish-subscription>
</rpc>
The server sends the subscription-id in the reply if the subscription was accepted.
This is important since multiple subscriptions per session are allowed. The <push-update> and <push-change-update> notifications each contain an <id> leaf that matches the value returned in the <rpc-reply> for the <establish-subscription> request.
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="2" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<id xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">1</id>
</rpc-reply>
The server will send an initial "push-update" notification right away, and then periodically every 30 seconds
<?xml version="1.0" encoding="UTF-8"?>
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2020-10-11T19:02:59Z</eventTime>
<push-update xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<id>1</id>
<datastore-contents>
<interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>lo</name>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type"
>ianaift:softwareLoopback</type>
<admin-status>up</admin-status>
<oper-status>up</oper-status>
<if-index>1</if-index>
<phys-address>00:00:00:00:00:00</phys-address>
<speed>0</speed>
<statistics>
<in-octets>163797125</in-octets>
<in-unicast-pkts>866265</in-unicast-pkts>
<in-multicast-pkts>0</in-multicast-pkts>
<in-discards>0</in-discards>
<in-errors>0</in-errors>
<out-octets>163797125</out-octets>
<out-unicast-pkts>866265</out-unicast-pkts>
<out-discards>0</out-discards>
<out-errors>0</out-errors>
</statistics>
</interface>
</interfaces-state>
</datastore-contents>
</push-update>
</notification>
Conventional On-Change Subscriptions
A conventional on-change subscription request that is granted will cause the specified data to be pushed when the data has changed. The "candidate" and "running" datastores can be monitored.
There is no internal overhead such as polling to support this subscription type. The server will check these subscriptions when a successful commit to the target datastore has been completed. Error operations are not reported to the subscription.
If the sync-on-start option is selected then a <push-update> will be sent when the subscription starts. After that, only <push-change-update> events will usually be sent. The resync-subscription operation will cause a new <push-update> notification to be generated as soon as possible.
The "on-change" presence container must be provided, and a "dampening-period" parameter must be provided. This must be greater or equal to the --push-min-dampening CLI parameter value.
The filter parameter is restricted. Two modes of operation are provided:
object monitoring mode: The filter must represent one configuration data node. All instances of that one object will be monitored.
datastore replication mode: No filter at all is used
Example: Object Monitoring Mode
Retrieve the /nacm/groups/group entry from <running> if any group is
edited
Assume the client has created a named filter called "nacm-group"
<config>
<filters xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<selection-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<filter-id>nacm-group</filter-id>
<datastore-xpath-filter
xmlns:n="urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
>/n:nacm/n:groups/n:group</datastore-xpath-filter>
</selection-filter>
</filters>
</config>
The client might send this request using a "selection-filter-ref" instead of an inline filter:
The dampening period is set to 10 seconds in this example.
<rpc message-id="5" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<establish-subscription xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<datastore xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:running</datastore>
<selection-filter-ref
xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">nacm-group</selection-filter-ref>
<on-change xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<dampening-period>1000</dampening-period>
<excluded-change>move</excluded-change>
<sync-on-start>true</sync-on-start>
</on-change>
</establish-subscription>
</rpc>
Assume the server sent an <id> response with a value of "1" like the example above.
If the "sync-on-start" parameter is set to "true" (the default) then the server will send a <push-update> notification as soon as the subscription starts:
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2020-10-11T19:39:21Z</eventTime>
<push-update xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<id>1</id>
<datastore-contents>
<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
<groups>
<group>
<name>test1</name>
</group>
</groups>
</nacm>
</datastore-contents>
</push-update>
</notifications>
The server will send a <push-change-update> notification when the targeted entry is changed
<?xml version="1.0" encoding="UTF-8"?>
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2020-10-11T19:42:01Z</eventTime>
<push-change-update xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<id>1</id>
<datastore-changes>
<yang-patch xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<patch-id>0</patch-id>
<edit>
<edit-id>E1</edit-id>
<operation>create</operation>
<target>/ietf-netconf-acm:nacm/groups/group=monitor</target>
<value>
<group xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
<name>monitor</name>
<user-name>admin1</user-name>
<user-name>admin2</user-name>
</group>
</value>
</edit>
</yang-patch>
</datastore-changes>
</push-change-update>
</notification>
Example: Datastore Replication Mode
Retrieve the patch for <running> if any config is edited
The dampening period is set to 10 seconds in this example.
The client might send this request without any filter parameter:
<?xml version="1.0" encoding="UTF-8"?>
<rpc message-id="2" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<establish-subscription xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<datastore xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:running</datastore>
<on-change xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<dampening-period>1000</dampening-period>
</on-change>
</establish-subscription>
</rpc>
The server sends an <rpc-reply> with a new subscription ID, since another is in progress:
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="2" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<id xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">2</id>
</rpc-reply>
The server will send the initial <push-update> notification right away
<?xml version="1.0" encoding="UTF-8"?>
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2020-10-11T19:50:29Z</eventTime>
<push-update xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<id>2</id>
<datastore-contents>
<filters xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<selection-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<filter-id>nacm-group</filter-id>
<datastore-xpath-filter xmlns:n="urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
>/n:nacm/n:groups/n:group</datastore-xpath-filter>
</selection-filter>
</filters>
<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
<groups>
<group>
<name>test1</name>
</group>
<group>
<name>monitor</name>
<user-name>admin1</user-name>
<user-name>admin2</user-name>
</group>
</groups>
</nacm>
</datastore-contents>
</push-update>
</notification>
If the <running> datastore changes at all the server will send a <push-change-update> notification:
In this example, the /nacm/rule-list entry is edited:
<?xml version="1.0" encoding="UTF-8"?>
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2020-10-11T20:03:37Z</eventTime>
<push-change-update xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<id>2</id>
<datastore-changes>
<yang-patch xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<patch-id>1</patch-id>
<edit>
<edit-id>E1</edit-id>
<operation>create</operation>
<target>/ietf-netconf-acm:nacm/rule-list=allow-nacm-read</target>
<value>
<rule-list xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
<name>allow-nacm-read</name>
<group>monitor</group>
<rule>
<name>r1</name>
<module-name>ietf-netconf-acm</module-name>
<access-operations>read</access-operations>
<action>permit</action>
<comment>allow monitor group to read nacm</comment>
</rule>
</rule-list>
</value>
</edit>
</yang-patch>
</datastore-changes>
</push-change-update>
</notification>
Simulated Operational On-Change Subscriptions
A simulated operational on-change subscription request that is granted will cause the specified data to be pushed when the data has changed. The "operational" datastore can be monitored. These subscriptions are only allowed if the --push-simop-enabled parameter is set to ‘true’.
There is an internal polling and processing overhead required to support this subscription type. The server will check these subscriptions when the --push-simop-period interval expires. If the "dampening-period" parameter is provided then the maximum of these two parameters is used for the internal polling interval, when dampening is required.
If the sync-on-start option is selected then a <push-update> will be sent when the subscription starts. After that, only <push-change-update> Event notifications will usually be sent. The <resync-subscription> operation will cause a new <push-update> Event notification to be generated as soon as possible.
The "on-change" presence container must be provided, and a "dampening-period" parameter must be provided. This must be greater or equal to the --push-min-dampening CLI parameter value.
There are no filter restrictions for a simulated operational subscription. Any filter that is allowed for a <get> operation may be used for a simulated operational subscription. If a named filter is used then it can be modified while a subscription is active. The subscription output will be updated as soon as possible after a filter reference in use is modified.
Example: Retrieve the /netconf-state/backup-files subtree if it changes
In this example, the <datastore-xpath-filter> does not use any prefixes. The server will accept this filter and find the correct data nodes even if the prefixes are missing.
In this example, the dampening period is 1 second.
<?xml version="1.0" encoding="UTF-8"?>
<rpc message-id="9" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<establish-subscription xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<datastore xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:operational</datastore>
<datastore-xpath-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
>/netconf-state/backup-files</datastore-xpath-filter>
<on-change xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<dampening-period>100</dampening-period>
</on-change>
</establish-subscription>
</rpc>
The server will send a <push-update> notification right away for this filter:
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2020-10-11T20:20:21Z</eventTime>
<push-update xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<id>4</id>
<datastore-contents>
<netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">
<backup-files xmlns="http://yumaworks.com/ns/yumaworks-system">
<backup-file>
<name>push1.xml</name>
<backup-time>2020-08-29T20:10:23Z</backup-time>
</backup-file>
<backup-file>
<name>push2.xml</name>
<backup-time>2020-08-29T20:50:35Z</backup-time>
</backup-file>
</backup-files>
</netconf-state>
</datastore-contents>
</push-update>
</notification>
If any backup file changes then the entire <backup-files> container is returned in the <push-change-update> notification:
Note that the operation will always be "replace" for a simulated operational on-change subscription.
<?xml version="1.0" encoding="UTF-8"?>
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2020-10-11T20:25:35Z</eventTime>
<push-change-update xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<id>4</id>
<datastore-changes>
<yang-patch xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<patch-id>0</patch-id>
<comment>simop</comment>
<edit>
<edit-id>E1</edit-id>
<operation>replace</operation>
<target>/</target>
<value>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">
<backup-files xmlns="http://yumaworks.com/ns/yumaworks-system">
<backup-file>
<name>push1.xml</name>
<backup-time>2020-08-29T20:10:23Z</backup-time>
</backup-file>
<backup-file>
<name>push2.xml</name>
<backup-time>2020-08-29T20:50:35Z</backup-time>
</backup-file>
<backup-file>
<name>test-snap.xml</name>
<backup-time>2020-10-11T20:25:34Z</backup-time>
</backup-file>
</backup-files>
</netconf-state>
</data>
</value>
</edit>
</yang-patch>
</datastore-changes>
</push-change-update>
</notification>
Operational On-Change Subscriptions
An operational on-change subscription request that is granted will cause the specified data to be pushed when the subsystem responsible for pushing object updates sends a push-update to the main server. This mode is not yet implemented.
Data Synchronization With anchor-time
A periodic datastore subscription can specific an 'anchor-time' parameter to cause the first periodic update to occur at an interval based on the anchor-time. YANG Push subscriptions across multiple devices can be setup to start at the same time, so time series databases can be populated with related data samples.
anchor-time Usage
The anchor-time parameter is not well defined in RFC 8641. The implementation supported by the server is restricted.
The anchor-time can be set in the <establish-subscription> or <modify-subscription> operation.
If YANG Push 2 is enabled, then it can also be supported with Configured Subscriptions
The date-and-time format is used as follows for anchor-time:
YYYY-MM-DDTHH:MM:SSZ
There are multiple parts:
The date field 'YYYY-MM-DD' must be present and can be any valid date. This field is ignored.
The letter
Tmust follow the date fieldThe time field 'HH:MM:SS' must be present
The letter
Zmust follow the time field. This field is ignored.
The time field is the only field used, as follows:
Only one part in the 'time' field can be used (hours, minutes, or seconds)
If multiple fields are set, then the first non-zero field is used for the anchor interval.
'HH': hours value from '00' to '23'
'MM': minutes value from '00' to '59'
'SS': seconds value from '00' to '59'
If the seconds field has a fractional part (e.g.,
30.1234) then the fractional part is ignored.If the timezone field is present (e.g.,
+03:00) then it is ignored.
Example:
Start the collection at the next minute.
Wait between 0 and 59 seconds for the next start of the interval.
2025-01-01T00:01:00Z
Example:
Start the collection at the next 5 minute interval.
Wait between 0 and 299 seconds for the next start of the interval.
2025-01-01T00:05:00Z
Example:
Start the collection at the next 30 second interval.
Wait between 0 and 29 seconds for the next start of the interval.
2025-01-01T00:00:30Z
Example:
Start the collection at the next one hour interval.
Wait between 0 and 3599 seconds for the next start of the interval.
2025-01-01T01:00:00Z
Example: Full client request
Monitor the
/interfaces-state/interfacelistStart on a 1 minute interval
Send an update every 30 seconds
The client might send the following request:
<?xml version="1.0" encoding="UTF-8"?>
<rpc message-id="2"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<establish-subscription
xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<datastore xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:operational</datastore>
<datastore-xpath-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">/interfaces-state/interface</datastore-xpath-filter>
<periodic xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<period>3000</period>
<anchor-time>2025-01-01T00:01:00Z</anchor-time>
</periodic>
</establish-subscription>
</rpc>
The server log should show the anchor-time handling,
if the --log-level setting is debug2 or higher.
agt_not: Convert anchor-time '2025-01-01T00:01:00Z' to hr: 0 min: 1 sec: 0
Time now: 2025-09-18T18:50:10Z
Got wait time 50 seconds for interval 60
agt_not: Activated Push subscription 1 for session '3'
agt_rpc: sending data <rpc-reply> for ses 3 msg '2'
Note that the server will send an 'rpc-reply' message right away, even though the subscription is waiting for the anchor-time interval.
YANG Push UDP-Notif Deployment with NetGauze and Kafka
This section describes how to deploy YANG Push using configured subscriptions on netconfd-pro with either yangcli-pro or NetGauze as the UDP-Notif collector. It also describes the optional Kafka integration path.
The deployment covered by this section uses configured subscriptions.
Configured subscriptions are created by editing the /subscriptions subtree.
This is different from NETCONF dynamic subscriptions, which are created with
the <establish-subscription> RPC and deliver events over the same NETCONF
session.
End-to-End Test Procedure
This onboarding section describes the complete end-to-end validation workflow for YANG Push over UDP Notif using netconfd-pro, NetGauze, and an optional Kafka-compatible message broker.
The goal of the test is to confirm that netconfd-pro can operate as a YANG Push Publisher, send configured subscription notifications over UDP Notif, and that NetGauze can receive, decode, validate, and optionally publish the resulting JSON telemetry records to Kafka.
The procedure validates the full data path:
netconfd-pro -> UDP Notif -> NetGauze -> Kafka topic -> consumer
The following sections describe each step in detail:
Start Kafka or Redpanda. Kafka Setup for NetGauze
Create the udp-notif-json topic. Kafka Setup for NetGauze
Start NetGauze with the provided YAML configuration. Using NetGauze as the YANG Push Collector
Start netconfd-pro with the yang-push bundle enabled.
Configure the UDP Notif receiver instance on netconfd-pro. Configure the UDP-Notif Receiver Instance
Configure a periodic or on-change configured subscription on netconfd-pro. Configure a Periodic YANG Push Subscription
Confirm that NetGauze logs show UDP Notif and YANG Push activity.
Confirm that the Publisher sends <subscription-started>, followed by <push-update> or <push-change-update> notifications.
Confirm that Kafka receives records on the udp-notif-json topic.
Retrieve the
/subscriptionssubtree from netconfd-pro and confirm receiver state, subscription state, and event counters.
At the end of this procedure, the deployment is considered functional when NetGauze receives UDP Notif messages, the Publisher counters increase, and Kafka receives JSON telemetry records when the Kafka publisher is enabled.
Architecture
In this deployment model, netconfd-pro acts as the YANG Push Publisher. A configured subscription is created in the server configuration datastore. The subscription references a receiver instance that defines the UDP-Notif collector address and port.
After the configured subscription becomes active, the Publisher sends a <subscription-started> notification to the configured receiver. After that, periodic subscriptions send <push-update> notifications, and on-change subscriptions send <push-change-update> notifications when the selected data changes.
Note
A <subscription-started> notification is expected for configured subscriptions. It is not expected for a dynamic <establish-subscription> subscription over NETCONF.
The collector can be one of the following:
yangcli-pro UDP-Notif Collector
NetGauze UDP-Notif / YANG Push Collector
When NetGauze is used, the collector can optionally publish normalized output to Kafka. Downstream consumers can then retrieve the messages from Kafka and, if configured, validate them against schemas retrieved through a YANG Schema Registry.
NetGauze is not only a raw UDP receiver. In the YANG Push workflow, it also uses NETCONF access to the Publisher to retrieve schema context, YANG Library data, and subscription metadata. This information is used to validate and normalize received messages.
netconfd-pro Build and Startup
The yang-push bundle must be available and loaded by netconfd-pro. The WITH_YANG_PUSH and WITH_YANG_PUSH2 compiler flags are required when building this feature from source code.
When CBOR/SID-encoded telemetry is used, build and enable the YANG-CBOR feature by using the WITH_YANG_CBOR compiler flag.
Example startup command:
netconfd-pro \
--bundle=yang-push \
--with-notifications=true \
--with-yang-push2=true
Equivalent configuration file fragment:
netconfd-pro {
bundle yang-push
with-notifications true
with-yang-push2 true
}
Refer to CLI Parameters for YANG Push for additional configuration options.
Recommended verification from yangcli-pro:
> connect server=127.0.0.1 user=<user> password=<password>
> show session
Notification Capabilities:
Old Subscriptions (RFC 5277): yes
Interleave: yes
Replay: yes
New Subscriptions (RFC 8639): yes
Dynamic: yes
Configured: yes
Filters: yes
YANG Push (RFC 8641): yes
On-Change: yes
Encodings: XML JSON
The session summary should show the YANG Push and UDP-Notif modules and the related features, including configured, encode-json, encode-xml, on-change, and the UDP-Notif segmentation feature when available.
Using yangcli-pro as a YANG Push Collector
yangcli-pro can be used as a local validation Collector before introducing NetGauze or Kafka.
Start yangcli-pro with the Collector enabled, refer to UDP-Notif Collector for more details and configuration options:
yangcli-pro \
--collector-enabled=true \
--collector-address=127.0.0.1 \
--collector-port=9999
Alternatively, start the Collector from inside yangcli-pro:
> connect server=127.0.0.1 user=tony password=<password>
> collector start collector-address=127.0.0.1 collector-port=9999
> collector status
Collector Enabled: true
Collector Active: true
Collector Publishers: 1
Collector Messages: 0
The NETCONF session is important because the Collector needs access to the Publisher's YANG modules and YANG Library context in order to decode received UDP-Notif messages.
Note
Do not rely on the default collector port in examples. Set collector-port explicitly and use the same port in the configured udp-notif-receiver.
Kafka Setup for NetGauze
The Kafka publisher is optional. NetGauze can receive and validate UDP Notif messages without Kafka. Kafka is only required when the NetGauze publishers section is enabled and JSON telemetry output must be written to a Kafka-compatible message broker.
For local end-to-end testing, Redpanda is the recommended broker because it is Kafka API compatible, runs as a single container, and includes the rpk command-line tool inside the container. This avoids installing the full Apache Kafka toolchain only to create and inspect one test topic.
The example below starts a single-node Redpanda broker and exposes the
Kafka API on 127.0.0.1:19092. This port matches the NetGauze
configuration value:
bootstrap.servers: 127.0.0.1:19092
Start the local Redpanda broker:
docker run -d --name redpanda-udpnotif \
-p 19092:19092 \
-p 9644:9644 \
docker.redpanda.com/redpandadata/redpanda:latest \
redpanda start \
--overprovisioned \
--smp 1 \
--memory 1G \
--reserve-memory 0M \
--node-id 0 \
--check=false \
--kafka-addr PLAINTEXT://0.0.0.0:19092 \
--advertise-kafka-addr PLAINTEXT://127.0.0.1:19092
Verify that the broker container is running:
docker ps --filter name=redpanda-udpnotif
Create the Kafka topic used by the NetGauze JSON publisher:
docker exec -it redpanda-udpnotif \
rpk topic create udp-notif-json \
--brokers 127.0.0.1:19092
Verify that the topic exists:
docker exec -it redpanda-udpnotif \
rpk topic list \
--brokers 127.0.0.1:19092
Start a consumer to inspect messages published by NetGauze:
docker exec -it redpanda-udpnotif \
rpk topic consume udp-notif-json \
--brokers 127.0.0.1:19092
After the broker and topic are available, start NetGauze with the Kafka publisher enabled. When UDP Notif messages are received and processed, NetGauze should publish JSON telemetry records to the udp-notif-json topic.
Note
If NetGauze reports BrokerTransportFailure or Connection refused, the Kafka-compatible broker is not reachable at the configured bootstrap.servers address. Verify that the Redpanda container is running, that port 19092 is published to the host, and that the NetGauze YAML file uses the same broker address.
Note
This single-node Redpanda setup is intended for local development and interoperability testing. Production deployments should use the operational Kafka or Redpanda deployment model required by the target environment.
Using NetGauze as the YANG Push Collector
Refer to the official NetGauze documentation for more details and installation steps.
Before starting NetGauze, create the cache directory used for the YANG Library and schema context cache:
sudo mkdir -p /tmp/netgauze-udpnotif-cache
sudo chown -R user:user /tmp/netgauze-udpnotif-cache
chmod 700 /tmp/netgauze-udpnotif-cache
For persistent deployments, use a cache directory outside /tmp, such as
/var/cache/netgauze/udpnotif.
The following command starts NetGauze with the local YAML configuration file:
cd ~/swdev/yangpush2/NetGauze
cargo run -p netgauze-collector --release -- /etc/yumapro/config.yaml
Example configuration:
runtime:
threads: 4
logging:
level: netgauze_collector=trace,netgauze_udp_notif_service=trace,netgauze_yang_push=trace,info
ansi: true
telemetry:
url: http://localhost:4317/v1/metrics
id: netgauze-udpnotif-telemetry
exporter_timeout: 3000
reader_interval: 60000
reader_timeout: 3000
udp_notif:
subscriber_timeout: 100
listeners:
- address: 0.0.0.0:10000
workers: 1
cache_location: /tmp/netgauze-udpnotif-cache
# NetGauze uses NETCONF-side information to retrieve schema context,
# YANG Library data, and subscription metadata required for validation.
netconf:
username: user
private_key_path: /home/user/.ssh/id_ed25519
port: 830
# max_retries: 3
# max_backoff_secs: 5
publishers:
debug-kafka:
buffer_size: 1000
endpoints:
udp-json: !TelemetryKafkaJson
topic: udp-notif-json
producer_config:
bootstrap.servers: 127.0.0.1:19092
message.timeout.ms: "60000"
queue.buffering.max.messages: "1000"
writer_id: netgauze-udpnotif-json
Configuration notes:
listeners must match the remote-address and remote-port configured on the Publisher. For a local test, the Publisher can send to
127.0.0.1:10000and NetGauze can listen on0.0.0.0:10000.cache_location stores NetGauze's YANG-Push/YANG Library cache. Clear this directory when testing incompatible schema or draft changes.
The netconf section must allow NetGauze to reach the Publisher on port
830and authenticate with the configured SSH key.The publishers section is optional. If it is enabled, the Kafka broker configured in bootstrap.servers must be reachable before NetGauze starts.
The example Kafka endpoint publishes JSON messages to the udp-notif-json topic on
127.0.0.1:19092.
Note
For collector-only validation, omit or comment out the publishers section. If the Kafka publisher is enabled while no broker is listening on the configured address, NetGauze can start the UDP listener successfully but then report a Kafka BrokerTransportFailure or Connection refused error.
Configure the UDP-Notif Receiver Instance
The receiver instance defines where the Publisher sends UDP-Notif messages.
The following example configures a NetGauze or yangcli-pro collector
listening on UDP port 10000.
Replace 127.0.0.1 with the Collector host address when the Collector is not
running on the same host as netconfd-pro.
The edit-config request for this scenario is shown below:
<edit-config>
<target>
<running/>
</target>
<config>
<subscriptions xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<receiver-instances xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notif-receivers">
<receiver-instance>
<name>netgauze</name>
<udp-notif-receiver xmlns="urn:ietf:params:xml:ns:yang:ietf-udp-notif-transport">
<remote-address>127.0.0.1</remote-address>
<remote-port>10000</remote-port>
<enable-segmentation>false</enable-segmentation>
</udp-notif-receiver>
</receiver-instance>
</receiver-instances>
</subscriptions>
</config>
</edit-config>
Note
Segmentation is disabled in this example to keep the initial interoperability test simple. For larger notifications, enable segmentation and configure max-segment-size when both the Publisher and Collector support segmented UDP Notif messages.
Subscription ID Range -- Important, Frequently Missed Constraint
Note
The id key of /subscriptions/subscription is shared between dynamic
and configured subscriptions on netconfd-pro. Dynamic subscriptions
(establish-subscription) have existed for years and clients generally
expect low integer IDs starting at 1. Consequently, current YumaPro releases
reserve IDs 1-1000 for dynamic subscriptions and require configured
subscriptions to use IDs in the range 1001-2000; a configured subscription
outside that range is rejected. IDs 100 and 101, as sometimes shown in
generic tutorials, will fail on such a release. The examples below use 1501
and 1502 accordingly.
Configure a Periodic YANG Push Subscription
The following example configures a periodic subscription for the running datastore. The selected data is sent to the netgauze receiver instance by using UDP-Notif transport and JSON encoding.
The period value is in centiseconds. In this example, 1000 means
10 seconds.
The <edit-config> request for this scenario is shown below:
<edit-config>
<target>
<running/>
</target>
<config>
<subscriptions xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<subscription>
<id>1502</id>
<datastore xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push" xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:running</datastore>
<datastore-xpath-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
/top-config-list/config-cont
</datastore-xpath-filter>
<module-version-subs xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push-revision">
<name>get2-test</name>
<revision>2022-03-02</revision>
</module-version-subs>
<transport xmlns:unt="urn:ietf:params:xml:ns:yang:ietf-udp-notif-transport">unt:udp-notif</transport>
<encoding>encode-json</encoding>
<receivers>
<receiver>
<name>netgauze</name>
<receiver-instance-ref xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notif-receivers">netgauze</receiver-instance-ref>
</receiver>
</receivers>
<periodic xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<period>1000</period>
</periodic>
</subscription>
</subscriptions>
</config>
</edit-config>
Note
The datastore-xpath-filter examples above /top-config-list/config-cont
target the get2-test module, which is a YumaWorks internal regression
module bundled with netconfd-pro test suites. It is used here because it
produces a deterministic, reproducible dataset for the captured log output.
The XPath filter, the referenced module name and revision in
module-version-subs, and the namespace declarations should be replaced
with the equivalent production YANG module (for example,
ietf-interfaces) before this configuration is applied outside of a
lab environment.
Expected Publisher behavior after the commit:
The configured subscription is validated.
The receiver state is initialized.
The Publisher sends <subscription-started> to the receiver.
The Publisher sends the first <push-update>.
The Publisher continues to send <push-update> notifications at the configured period.
The server log for the <subscription-started> notification may look like this:
agt_udp_notif: write msg OK ses=5 siz=724
ses: Invoking Send Hook Fn for finish msg ses:5
End UDP-Notif Msg 1 for rcvr netgauze
agt_not: Sent <subscription-started> on datastore subscription '1502' for session '5'
Notification contents:
ncEvent:notification {
eventTime 2026-07-10T21:05:29.464048Z
sn:subscription-started {
id 1502
yp:datastore ds:running
yp:datastore-subtree-filter {
get2test:top-config-list {
config-cont (not set)
}
}
encoding sn:encode-json
yp:periodic {
period 1000
anchor-time 2026-07-10T21:05:29Z
}
dn:message-publisher-id 1
ypr:module-version get2-test {
name get2-test
revision 2022-03-02
}
ypr:yang-library-content-id 8519
}
}
agt_push: Process periodic push_cb: P=1000 tdiff=1000 subid=1502 sid=0
agt_push: Start send Periodic push for subid 1502
ses: Invoking Send Hook Fn for start msg ses:5
Start UDP-Notif Msg 2 for rcvr netgauze
agt_tree_process_val: enter filval: datastore-subtree-filter curval: config curobj: config oper_curval: none
agt_tree: process_val empty return
Send UDP-Notif for rcvr netgauze
udpnotif: HDR: enc=json hdrlen=12 msglen=236 pubid=1 msgid=2
Write UDP-Notif Buff 2 for rcvr netgauze datalen=224
{
"ietf-notification:notification": {
"eventTime":"2026-07-10T21:05:39.138199Z",
"ietf-yang-push:push-update": {
"id":1502,
"ietf-distributed-notif:message-publisher-id":1,
"datastore-contents": {
}
}
}
}
agt_udp_notif: write msg OK ses=5 siz=236
ses: Invoking Send Hook Fn for finish msg ses:5
End UDP-Notif Msg 2 for rcvr netgauze
Note
The datastore-contents object is empty in this <push-update> notification because the target data node has not been created yet.
Note
The field ietf-distributed-notif:message-publisher-id, present in every <push-update> and <push-change-update> payload shown above, originates from draft-ietf-netconf-distributed-notif (Distributed Notification Delivery). It identifies which Publisher instance generated a given notification, which matters when a single logical device exports telemetry from more than one internal publishing process, or when messages from several Publishers are aggregated in a shared Kafka topic and must be attributed back to their source.
Assume the target node is created with the following <edit-config> request:
<edit-config>
<target>
<running/>
</target>
<config>
<top-config-list xmlns="http://yumaworks.com/ns/get2-test">
<id>11</id>
<config-cont>
<config-leaf
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
nc:operation="merge">test3</config-leaf>
</config-cont>
</top-config-list>
</config>
</edit-config>
After the data exists, the <push-update> notification in the netconfd-pro server log may look like this:
Send UDP-Notif for rcvr netgauze
udpnotif: HDR: enc=json hdrlen=12 msglen=373 pubid=1 msgid=2
Write UDP-Notif Buff 2 for rcvr netgauze datalen=361
{
"ietf-notification:notification": {
"eventTime":"2026-07-10T21:07:13.140983Z",
"ietf-yang-push:push-update": {
"id":1502,
"ietf-distributed-notif:message-publisher-id":1,
"datastore-contents": {
"get2-test:top-config-list": [
{
"id":11,
"config-cont": {
"config-leaf":"test3"
}
}
]
}
}
}
}
The NetGauze logging after the subscription is configured may look as follows:
TRACE netgauze_udp_notif_service::actor: [Actor 0-0.0.0.0:10000] decoded udp-notif packet peer=127.0.0.1:38198 message_id=2 publisher_id=1
TRACE netgauze_udp_notif_service::actor: [Actor 0-0.0.0.0:10000] sending udp-notif packet received to all subscribers peer=127.0.0.1:38198 message_id=2 publisher_id=1 subscriber_count=1
TRACE netgauze_udp_notif_service::actor: [Actor 0-0.0.0.0:10000] sent udp-notif message to actor subscriber peer=127.0.0.1:38198 message_id=2 publisher_id=1 actor_subscriber_id=1
TRACE netgauze_yang_push::validation: Decoded UDP-Notif payload, starting the validation step peer=127.0.0.1:38198 message_id=2 publisher_id=1 notification_type="YangPushChangeUpdate"
TRACE netgauze_yang_push::validation: Successfully send UDP-Notif message for the next actor to process peer=127.0.0.1:38198 message_id=2 publisher_id=1 subscription_id=1502 router_content_id="EMPTY" target={ datastore: EMPTY, datastore-xpath-filter: EMPTY } cached_content_id="" notification_type="YangPushChangeUpdate"
TRACE netgauze_collector::yang_push::enrichment: Received Yang Push Change Update Message peer=127.0.0.1:38198 message_id=2 publisher_id=1 subscription_id=1502 router_content_id="EMPTY" target={ datastore: EMPTY, datastore-xpath-filter: EMPTY } notification_type="YangPushChangeUpdate" cached_content_id=""
TRACE netgauze_collector::publishers: Message delivered successfully to kafka
Configure an On-Change YANG Push Subscription
The following example configures an on-change subscription for the running datastore. sync-on-start requests an initial <push-update> when the subscription starts. After that, the Publisher sends <push-change-update> notifications when the selected data changes.
The <edit-config> request for this scenario is shown below:
<edit-config>
<target>
<running/>
</target>
<config>
<subscriptions xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<subscription>
<id>1501</id>
<datastore
xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push"
xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">ds:running</datastore>
<datastore-xpath-filter xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
/top-config-list/config-cont
</datastore-xpath-filter>
<transport xmlns:unt="urn:ietf:params:xml:ns:yang:ietf-udp-notif-transport">unt:udp-notif</transport>
<encoding>encode-json</encoding>
<receivers>
<receiver>
<name>netgauze</name>
<receiver-instance-ref
xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notif-receivers">netgauze</receiver-instance-ref>
</receiver>
</receivers>
<on-change xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
<dampening-period>500</dampening-period>
<sync-on-start>true</sync-on-start>
</on-change>
</subscription>
</subscriptions>
</config>
</edit-config>
Note
Operational on-change behavior depends on the server implementation and the enabled YANG Push mode. For simulated operational on-change testing, keep the --push-simop-enabled parameter set to true and use a dampening value that is not smaller than the server's configured minimum.
Whenever the target node is updated, the server sends a <push-change-update> notification to the collector. The server log may look like this:
agt_push: Process on-change push_cb: DP=500 tdiff=800 subid=1501 sid=0
ses: Invoking Send Hook Fn for start msg ses:5
Start UDP-Notif Msg 2 for rcvr netgauze
Send UDP-Notif for rcvr netgauze
udpnotif: HDR: enc=json hdrlen=12 msglen=632 pubid=1 msgid=2
Write UDP-Notif Buff 2 for rcvr netgauze datalen=620
{
"ietf-notification:notification": {
"eventTime":"2026-07-10T21:13:41.529318Z",
"ietf-yang-push:push-change-update": {
"id":1501,
"ietf-distributed-notif:message-publisher-id":1,
"datastore-changes": {
"ietf-yang-push:yang-patch": {
"patch-id":"0",
"edit": [
{
"edit-id":"E1",
"operation":"create",
"target":"/get2-test:top-config-list=11",
"value": {
"get2-test:top-config-list": [
{
"id":11,
"config-cont": {
"config-leaf":"test3"
}
}
]
}
}
]
}
}
}
}
}
agt_udp_notif: write msg OK ses=5 siz=632
ses: Invoking Send Hook Fn for finish msg ses:5
End UDP-Notif Msg 2 for rcvr netgauze
Retrieve Configured Subscriptions and Receiver Counters
Use a NETCONF <get> request to inspect the current subscription state, configured receiver instances, and UDP Notif delivery counters.
This request is useful after a configured subscription is committed because it shows both the configured subscription data and the operational state that the Publisher maintains for active receivers. The returned data can be used to confirm that the subscription exists, the receiver reference is resolved, and the Publisher is attempting to send notifications to the expected collector.
Use <get> instead of <get-config> for this check because counters and receiver state are operational data.
<get xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<filter type="subtree">
<subscriptions xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications"/>
</filter>
</get>
The response may look as follows:
{
"ietf-subscribed-notifications:subscriptions": {
"subscription": [
{
"id": 1502,
"ietf-yang-push:datastore": "ietf-datastores:running",
"ietf-yang-push:datastore-xpath-filter": "/top-config-list/config-cont",
"transport": "ietf-udp-notif-transport:udp-notif",
"encoding": "encode-json",
"configured-subscription-state": "valid",
"receivers": {
"receiver": [
{
"name": "netgauze",
"sent-event-records": "0",
"excluded-event-records": "0",
"state": "active",
"ietf-subscribed-notif-receivers:receiver-instance-ref": "netgauze"
}
]
},
"ietf-yang-push:on-change": {
"dampening-period": 500,
"sync-on-start": true
},
"ietf-distributed-notif:message-publisher-id": [
1
],
"ietf-yang-push-revision:module-version-subs": [
{
"name": "get2-test",
"revision": "2022-03-02"
}
]
}
],
"ietf-subscribed-notif-receivers:receiver-instances": {
"receiver-instance": [
{
"name": "netgauze",
"ietf-udp-notif-transport:udp-notif-receiver": {
"remote-address": "127.0.0.1",
"remote-port": 9999,
"enable-segmentation": false
}
}
]
}
}
}
Delete a Configured Subscription
A configured subscription is removed by deleting the corresponding
/subscription list entry from the running datastore. The subscription
identifier in the delete request must match the configured subscription that
should be stopped.
Deleting the subscription stops the Publisher from sending UDP-Notif messages for that subscription. The receiver instance is not deleted by this operation. This allows the same receiver instance to be reused by other configured subscriptions.
The following example deletes configured subscription 1502:
<edit-config>
<target>
<running/>
</target>
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<subscriptions xmlns="urn:ietf:params:xml:ns:yang:ietf-subscribed-notifications">
<subscription nc:operation="delete"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
<id>1502</id>
</subscription>
</subscriptions>
</config>
</edit-config>
After the deletion, the netconfd-pro server log may look like this:
***** start commit phase on running for session 7, transaction 906423 *****
Start full commit of transaction 906423: 1 edit on running config
Start invoking commit SIL callback for delete on ietf-subscribed-notifications:subscription
Start key walk for subscription
End key walk for subscription: retkey:
id 1502
Enter subscription_edit callback for commit phase
Enter u_sn_subscription_edit callback for commit phase
id=1502
update=none
agt_not: Removed live subscription for configured
agt_not: Start delete-subscription callback for subscription 1502
agt_push: Mark subscription 1502 for deletion
UDP-Notif Troubleshooting
No UDP Packets Are Received
This issue usually means that the Publisher is not sending UDP Notif messages, the receiver address or port is incorrect, or packets are blocked before they reach the collector.
Check the following items first:
Confirm that the configured remote-address points to the collector host.
Confirm that the configured remote-port matches the collector listener.
Confirm that the collector is actually listening on the expected UDP port.
Confirm that the configured subscription was committed successfully.
Confirm that the subscription is present under
/subscriptions/subscription.Use tcpdump to confirm whether packets leave the Publisher host or arrive on the collector host.
Example packet capture command:
sudo tcpdump -i any -nn -s 0 -vv udp port 10000
If packets are visible on the Publisher host but not on the collector host, the issue is likely network routing, firewall, container networking, or an incorrect destination address.
If no packets are visible on the Publisher host, the issue is likely the configured subscription, receiver configuration, or subscription activation state.
<subscription-started> Is Not Observed
The <subscription-started> notification is expected when a configured subscription becomes active. It confirms that the Publisher accepted the configured subscription and initialized delivery to the configured receiver.
Check the following items:
Confirm that the subscription was created under
/subscriptionsby using <edit-config>.Confirm that the subscription is a configured subscription, not a dynamic <establish-subscription> request.
Confirm that the receiver instance exists and that the subscription references the correct receiver-instance-ref value.
Confirm that the configured receiver is not suspended or stuck in a failed delivery state.
Check the netconfd-pro server log for subscription validation errors.
If the collector was started after the subscription was created, delete and recreate the configured subscription so that startup delivery can be tested from a clean state.
Verify the correct subscription ID, must be 1001+ value. Refer to this section: Subscription ID Range -- Important, Frequently Missed Constraint
Dynamic NETCONF subscriptions created with <establish-subscription> are not
validated in the same way as configured UDP Notif subscriptions. For this test,
the expected path is the configured /subscriptions datastore path.
NetGauze Receives UDP Packets but Cannot Decode or Validate Them
Confirm that NetGauze can open a NETCONF session to the Publisher.
Confirm the SSH key path and username in the NetGauze config.
Confirm that the Publisher exposes YANG Library data and required modules.
Remove the NetGauze cache directory after changing YANG modules, draft revisions, SID files, or message encoding.
Example:
rm -rf /tmp/netgauze-udpnotif-cache
This issue usually means that UDP delivery is working, but NetGauze cannot build the correct YANG schema context for the received messages.
NetGauze is not only a UDP listener. In this workflow, it also uses NETCONF access to the Publisher to retrieve YANG Library data, YANG modules, subscription metadata, and schema context. If that NETCONF-side lookup fails, NetGauze may receive packets but fail to decode or validate the message content.
Example cache reset command:
rm -rf /tmp/netgauze-udpnotif-cache
mkdir -p /tmp/netgauze-udpnotif-cache
chmod 700 /tmp/netgauze-udpnotif-cache
For persistent deployments, use a cache directory outside /tmp, such as
/var/cache/netgauze/udpnotif.