RFC 8342

Network Management Datastore Architecture (NMDA)

πŸ“… published March 2018, from ietf

Network Management Datastore Architecture (NMDA) πŸŽ€

Okay bestie, this is RFC 8342 🌸, and it's all about the Network Management Datastore Architecture (NMDA). It's an IETF Standards Track document, published in March 2018 πŸ’…, with ISSN 2070-1721.

The authors are a whole squad: M. Bjorklund from Tail-f Systems, J. Schoenwaelder from Jacobs University, P. Shafer and K. Watsen from Juniper Networks, and R. Wilton from Cisco Systems πŸ‘‘. The big header fact is that it updates RFC 7950 πŸ”₯, which is the YANG data modeling language spec. There's no Obsoletes line in the header, so it isn't replacing any earlier RFC. It's an update, not a replacement, periodt ✨.

Abstract

Okay so datastores are the glue 🧚 that binds YANG data models to network management protocols like NETCONF and RESTCONF. This doc sets up an architectural framework for datastores, built on what people learned from the first, simpler model. It fixes the requirements that the first model didn't handle well πŸ’–. And yes, it updates RFC 7950 πŸ¦‹.

Status of This Memo

This is an Internet Standards Track document 🌈.

It's a product of the Internet Engineering Task Force (IETF) and represents the consensus of the IETF community 🫢. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check out Section 2 of RFC 7841 πŸ“š.

For the current status, any errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc8342 πŸ”—.

Copyright (c) 2018 IETF Trust and the persons identified as the document authors. All rights reserved πŸ’œ.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stood on the publication date. Please read these carefully, because they spell out your rights and restrictions for this document πŸ™ˆ. Code Components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in that license πŸŽ€.

Table of Contents

   1. Introduction ....................................................3
   2. Objectives ......................................................4
   3. Terminology .....................................................5
   4. Background ......................................................8
      4.1. Original Model of Datastores ...............................9
   5. Architectural Model of Datastores ..............................11
      5.1. Conventional Configuration Datastores .....................12
           5.1.1. The Startup Configuration Datastore (<startup>) ....12
           5.1.2. The Candidate Configuration Datastore
                  (<candidate>) ......................................13
           5.1.3. The Running Configuration Datastore (<running>) ....13
           5.1.4. The Intended Configuration Datastore (<intended>) ..13
      5.2. Dynamic Configuration Datastores ..........................14
      5.3. The Operational State Datastore (<operational>) ...........14
           5.3.1. Remnant Configuration ..............................16
           5.3.2. Missing Resources ..................................16
           5.3.3. System-Controlled Resources ........................16
           5.3.4. Origin Metadata Annotation .........................17
   6. Implications on YANG ...........................................18
      6.1. XPath Context .............................................18
      6.2. Invocation of Actions and RPCs ............................19
   7. YANG Modules ...................................................20
   8. IANA Considerations ............................................26
      8.1. Updates to the IETF XML Registry ..........................26
      8.2. Updates to the YANG Module Names Registry .................27
   9. Security Considerations ........................................27
   10. References ....................................................28
      10.1. Normative References .....................................28
      10.2. Informative References ...................................29

   Appendix A. Guidelines for Defining Datastores ....................31
     A.1. Define Which YANG Modules Can Be Used in the Datastore .....31
     A.2. Define Which Subset of YANG-Modeled Data Applies ...........31
     A.3. Define How Data Is Actualized ..............................31
     A.4. Define Which Protocols Can Be Used .........................31
     A.5. Define YANG Identities for the Datastore ...................32
   Appendix B. Example of an Ephemeral Dynamic Configuration
               Datastore .............................................32
   Appendix C. Example Data ..........................................33
     C.1. System Example .............................................34
     C.2. BGP Example ................................................37
       C.2.1. Datastores .............................................38
       C.2.2. Adding a Peer ..........................................38
       C.2.3. Removing a Peer ........................................39
     C.3. Interface Example ..........................................40
       C.3.1. Pre-provisioned Interfaces .............................41
       C.3.2. System-Provided Interface ..............................42
   Acknowledgments ...................................................43
   Authors' Addresses ................................................44

1. Introduction ✨

Okay, so this doc gives us an architectural framework for datastores, the way network management protocols use them. That includes NETCONF [RFC6241], RESTCONF [RFC8040], and the YANG data modeling language [RFC7950] πŸ’…. Datastores are the thing that ties network management data models to the protocols, and once everyone agrees on one common model, data models can be written without caring which protocol is carrying them πŸ¦‹. The framework names a set of conceptual datastores, but it does not require every protocol to expose all of them πŸ™ˆ. It also doesn't care how the protocol encodes its data 🌸.

This document updates RFC 7950 in two spots: it refines the accessible tree for some XML Path Language (XPath) contexts (see Section 6.1), and it refines the invocation context of operations (see Section 6.2) πŸ”₯.

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 read as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in all capitals, exactly like that πŸ’œ.

2. Objectives πŸ¦‹

Okay bestie, network management data objects can take two different values. One is the value a user or app configured, and the other is the value the device is actually running with, its operational state 🌈. Those two can differ for lots of reasons. The system might be talking to hardware, or to other protocols and devices, or it might just take time for a config change to reach all the software and hardware 🫢. On top of that, config and operational state data can have different lifetimes ⏳.

The original datastore model made you model these objects twice in the YANG schema, once as "config true" objects and again as "config false" objects 😭. The interfaces data model [RFC8343] and the IP data model [RFC8344] handled this by splitting things into two separate branches off the root of the data tree: one for configuration and one for operational state πŸŽ€.

That duplication, plus the ad hoc split between config and state, caused a bunch of problems πŸ’€. Keeping config and state in separate branches is operationally messy, and it makes module definitions harder to read πŸ™ˆ. The relationship between the two branches also isn't machine readable, and filter expressions for config versus the related operational state work differently πŸ”₯.

The revised architecture in this document defines each data object only once in the YANG schema, but separate instances of that object can live in different datastores. For example, one instance holds the configured value and another holds the value actually in use ✨. It's a much more elegant, simpler fix πŸ‘‘.

The revised model also supports extra datastores for systems with fancier processing chains that turn configuration into operational state 🧚. For example, some systems keep configuration that isn't being used right now (so-called "inactive configuration"), and others use configuration templates to expand configuration data from a shared template πŸ“.

3. Terminology ✨

okay so this section is the glossary bestie, and it's lowkey the most important part πŸ’… the document says some of these terms are revised versions of definitions from [RFC6241] and [RFC7950] (see also Section 4). the revised ones are semantically equivalent to the originals, and the plan is for these to replace the old ones when those docs get revised 🫢

  • datastore: A conceptual place to store and access information. A datastore might be implemented, for example, using files, a database, flash memory locations, or combinations thereof. A datastore maps to an instantiated YANG data tree. πŸ—‚οΈ
  • schema node: A node in the schema tree. The formal definition is provided in RFC 7950. 🌳
  • datastore schema: The combined set of schema nodes for all modules supported by a particular datastore, taking into consideration any deviations and enabled features for that datastore. πŸ’œ
  • configuration: Data that is required to get a device from its initial default state into a desired operational state. This data is modeled in YANG using "config true" nodes. Configuration can originate from different sources. βš™οΈ
  • configuration datastore: A datastore holding configuration. πŸŽ€
  • running configuration datastore: A configuration datastore holding the current configuration of the device. It may include configuration that requires further transformations before it can be applied. This datastore is referred to as "<running>". πŸƒβ€β™€οΈβœ¨
  • candidate configuration datastore: A configuration datastore that can be manipulated without impacting the device's running configuration datastore and that can be committed to the running configuration datastore. This datastore is referred to as "<candidate>". πŸ™ˆ
  • startup configuration datastore: A configuration datastore holding the configuration loaded by the device into the running configuration datastore when it boots. This datastore is referred to as "<startup>". πŸš€
  • intended configuration: Configuration that is intended to be used by the device. It represents the configuration after all configuration transformations to <running> have been performed and is the configuration that the system attempts to apply. 🎯
  • intended configuration datastore: A configuration datastore holding the complete intended configuration of the device. This datastore is referred to as "<intended>". πŸ¦‹
  • configuration transformation: The addition, modification, or removal of configuration between the <running> and <intended> datastores. Examples of configuration transformations include the removal of inactive configuration and the configuration produced through the expansion of templates. πŸͺ„
  • conventional configuration datastore: One of the following set of configuration datastores: <running>, <startup>, <candidate>, and <intended>. These datastores share a common datastore schema, and protocol operations allow copying data between these datastores. The term "conventional" is chosen as a generic umbrella term for these datastores. πŸ‘‘
  • conventional configuration: Configuration that is stored in any of the conventional configuration datastores. 🌸
  • dynamic configuration datastore: A configuration datastore holding configuration obtained dynamically during the operation of a device through interaction with other systems, rather than through one of the conventional configuration datastores. 🌈
  • dynamic configuration: Configuration obtained via a dynamic configuration datastore. ⭐
  • learned configuration: Configuration that has been learned via protocol interactions with other systems and that is neither conventional nor dynamic configuration. 🧠
  • system configuration: Configuration that is supplied by the device itself. πŸ–₯️
  • default configuration: Configuration that is not explicitly provided but for which a value defined in the data model is used. πŸ“
  • applied configuration: Configuration that is actively in use by a device. Applied configuration originates from conventional, dynamic, learned, system, and default configuration. πŸ’–
  • system state: The additional data on a system that is not configuration, such as read-only status information and collected statistics. System state is transient and modified by interactions with internal components or other systems. System state is modeled in YANG using "config false" nodes. πŸ“Š
  • operational state: The combination of applied configuration and system state. πŸ”₯
  • operational state datastore: A datastore holding the complete operational state of the device. This datastore is referred to as "<operational>". 🧚
  • origin: A metadata annotation indicating the origin of a data item. 🏷️
  • remnant configuration: Configuration that remains part of the applied configuration for a period of time after it has been removed from the intended configuration or dynamic configuration. The time period may be minimal or may last until all resources used by the newly deleted configuration (e.g., network connections, memory allocations, file handles) have been deallocated. πŸ‘»

The following additional terms are not datastore specific, but they are commonly used and are thus defined here as well:

  • client: An entity that can access YANG-defined data on a server, over some network management protocol. πŸ§‘β€πŸ’»
  • server: An entity that provides access to YANG-defined data to a client, over some network management protocol. πŸ–₯οΈπŸ’…
  • notification: A server-initiated message indicating that a certain event has been recognized by the server. πŸ””
  • remote procedure call: An operation that can be invoked by a client on a server. πŸ“ž

4. Background πŸŽ€

okay so this part is the history lesson, and it's giving "how we got here" πŸ•°οΈ [RFC6241] (NETCONF) gives these definitions:

  • datastore: A conceptual place to store and access information. A datastore might be implemented, for example, using files, a database, flash memory locations, or combinations thereof.
  • configuration datastore: The datastore holding the complete set of configuration that is required to get a device from its initial default state into a desired operational state.

YANG 1.1 [RFC7950] adds the following refinements when NETCONF is used with YANG (which is the usual case, but note that NETCONF was defined before YANG existed) πŸ€“

  • datastore: When modeled with YANG, a datastore is realized as an instantiated data tree.
  • configuration datastore: When modeled with YANG, a configuration datastore is realized as an instantiated data tree with configuration.

[RFC6244] defined operational state data like this 🌊

  • Operational state data is a set of data that has been obtained by the system at runtime and influences the system's behavior similar to configuration data. In contrast to configuration data, operational state is transient and modified by interactions with internal components or other systems via specialized protocols.

Section 4.3.3 of [RFC6244] discusses operational state and mentions, among other things, the option to consider operational state as being stored in another datastore. Section 4.4 of [RFC6244] then concludes that, at the time of its writing, modeling state as distinct leafs and distinct branches is the recommended approach. πŸ“š

Implementation experience and requests from operators [OpState-Reqs] [OpState-Modeling] indicate that the datastore model initially designed for NETCONF and refined by YANG needs to be extended. In particular, the notion of intended configuration and applied configuration has developed. 🚧✨

4.1. Original Model of Datastores πŸ’…

the following drawing shows the original model of datastores as it is currently used by NETCONF [RFC6241] πŸ–ΌοΈ

       +-------------+                 +-----------+
       | <candidate> |                 | <startup> |
       |  (ct, rw)   |<---+       +--->| (ct, rw)  |
       +-------------+    |       |    +-----------+
              |           |       |           |
              |         +-----------+         |
              +-------->| <running> |<--------+
                        | (ct, rw)  |
                        +-----------+
                              |
                              v
                       operational state  <--- control plane
                           (cf, ro)

       ct = config true; cf = config false
       rw = read-write; ro = read-only
       boxes denote datastores

                              Figure 1

note that this diagram simplifies the model: "read-only" (ro) and "read-write" (rw) are to be understood from the client's perspective, at a conceptual level. In NETCONF, for example, support for <candidate> and <startup> is optional, and <running> does not have to be writable. Furthermore, <startup> can only be modified by copying <running> to <startup> in the standardized NETCONF datastore editing model. The RESTCONF protocol does not expose these differences and instead provides only a writable unified datastore, which hides whether edits are done through <candidate>, by directly modifying <running>, or via some other implementation-specific mechanism. RESTCONF also hides how configuration is made persistent. Note that implementations may also have additional datastores that can propagate changes to <running>. NETCONF explicitly mentions so-called "named datastores". 🌷

some observations πŸ‘€

  • Operational state has not been defined as a datastore, although there were proposals in the past to introduce an operational state datastore. πŸ™ƒ
  • The NETCONF <get> operation returns the contents of <running> together with the operational state. It is therefore necessary that "config false" data be in a different branch than the "config true" data if the operational state can have a different lifetime compared to configuration or if configuration is not immediately or successfully applied. 🌿
  • Several implementations have proprietary mechanisms that allow clients to store inactive data in <running>. Inactive data is conceptually removed before validation. 🫣
  • Some implementations have proprietary mechanisms that allow clients to define configuration templates in <running>. These templates are expanded automatically by the system, and the resulting configuration is applied internally. 🧩
  • Some operators have reported that it is essential for them to be able to retrieve the configuration that has actually been successfully applied, which may be a subset or a superset of the <running> configuration. πŸ₯ΊπŸ’•

5. Architectural Model of Datastores 🧩

okay so this is the new conceptual model of datastores, and it's basically the original model glowing up πŸ’… they extended it because the experience with the old one taught everyone a ton ✨

  +-------------+                 +-----------+
  | <candidate> |                 | <startup> |
  |  (ct, rw)   |<---+       +--->| (ct, rw)  |
  +-------------+    |       |    +-----------+
         |           |       |           |
         |         +-----------+         |
         +-------->| <running> |<--------+
                   | (ct, rw)  |
                   +-----------+
                         |
                         |        // configuration transformations,
                         |        // e.g., removal of nodes marked as
                         |        // "inactive", expansion of
                         |        // templates
                         v
                   +------------+
                   | <intended> | // subject to validation
                   | (ct, ro)   |
                   +------------+
                         |        // changes applied, subject to
                         |        // local factors, e.g., missing
                         |        // resources, delays
                         |
    dynamic              |   +-------- learned configuration
    configuration        |   +-------- system configuration
    datastores -----+    |   +-------- default configuration
                    |    |   |
                    v    v   v
                 +---------------+
                 | <operational> | <-- system state
                 | (ct + cf, ro) |
                 +---------------+

  ct = config true; cf = config false
  rw = read-write; ro = read-only
  boxes denote named datastores

                              Figure 2

5.1. Conventional Configuration Datastores πŸ“

okay so the conventional configuration datastores are a group of configuration datastores that all share exactly the same datastore schema, which means data can be copied between them 🫢 "conventional" is just the generic umbrella term for the whole squad. If a module doesn't contain any configuration data nodes and it isn't needed to satisfy any imports, then it MAY be omitted from the datastore schema for the conventional configuration datastores. The members are:

  • <running>
  • <candidate>
  • <startup>
  • <intended>

More conventional configuration datastores might show up in future documents, so keep your eyes open πŸ‘€

The flow of data between these datastores is shown in Section 5, so go check the diagram if you're confused.

Specific protocols may define their own explicit operations for copying between these datastores. For example, NETCONF defines the <copy-config> operation πŸŽ€

5.1.1. The Startup Configuration Datastore (<startup>) πŸš€

<startup> is a configuration datastore that holds the configuration the device loads when it boots. It only shows up on devices that keep the startup configuration separate from the running configuration datastore, so it's not everywhere πŸ™ˆ

Not every protocol or implementation supports the startup configuration datastore, just a heads up.

On devices with non-volatile storage, the contents of <startup> will typically persist across reboots thanks to that storage πŸ’Ύ At boot time, the device loads the saved startup configuration into <running>. When you want to save a new startup configuration, the data gets copied to <startup> through either implicit or explicit protocol operations. Main character energy for <startup>, honestly πŸ‘‘

5.1.2. The Candidate Configuration Datastore (<candidate>) 🧁

<candidate> is a configuration datastore you can manipulate without messing with the device's current configuration, and it can be committed to <running> when you're ready. It's giving "draft mode" and I'm obsessed 😭

Not every protocol or implementation supports the candidate configuration datastore either.

<candidate> doesn't typically persist across reboots, even if there's non-volatile storage around. If <candidate> is stored in non-volatile storage, it gets reset to the contents of <running> at boot time πŸ”„

5.1.3. The Running Configuration Datastore (<running>) 🌸

<running> is the configuration datastore that holds the device's current configuration. It MAY include configuration that still needs some transformation before it can be applied, like inactive configuration, or template-style configuration that needs expanding first. Still, <running> MUST always be a valid configuration data tree, as defined in Section 8.1 of [RFC7950]. No exceptions, bestie πŸ’…

If the device can be configured through conventional configuration datastores, then <running> MUST be supported. Non-negotiable ✨

If a device doesn't have a separate <startup> and it has non-volatile storage, the device will typically use that storage so <running> can persist across reboots πŸ¦‹

5.1.4. The Intended Configuration Datastore (<intended>) 🎯

<intended> is a read-only configuration datastore. It shows the configuration after all the transformations to <running> have been done (like template expansion or removing inactive configuration), and it's the configuration the system actually tries to apply πŸ”₯

<intended> and <running> are super tightly coupled, so they're basically besties 🫢 Whenever data is written to <running>, the server MUST also immediately update and validate <intended>. Zero delay, zero drama.

<intended> MAY also get updated independently of <running> if the effect of a configuration transformation changes. Even so, <intended> MUST always be a valid configuration data tree, as defined in Section 8.1 of [RFC7950]. Same energy as <running>, periodt πŸ’–

For simple implementations, <running> and <intended> are identical. Easy mode 🧚

The contents of <intended> are also related to the "config true" subset of <operational>. So a client can figure out how much of the intended configuration is actually in use by checking whether the contents of <intended> also show up in <operational> πŸ•΅οΈβ€β™€οΈ

<intended> doesn't persist across reboots, and its relationship with <running> means it doesn't need to πŸ™Œ

Right now there are no standard mechanisms that make <intended> end up with different content than <running>, but this architecture leaves room for them to be defined later 🌈

Here are two examples of what such a mechanism could look like. The first is support for marking nodes as inactive in <running>. Inactive nodes are not copied to <intended>. The second is support for templates, which can transform the configuration going from <running> into the configuration written to <intended> πŸ“

5.2. Dynamic Configuration Datastores πŸ¦‹

The model recognizes that dynamic configuration datastores are needed too. These are, by definition, not part of the device's persistent configuration. Some contexts call them "ephemeral datastores", since the information is ephemeral, meaning it's lost on reboot πŸ’¨ Dynamic configuration datastores talk to the rest of the system through <operational>.

The datastore schema for a dynamic configuration datastore MAY differ from the datastore schema used for conventional configuration datastores. If a module doesn't contain any configuration data nodes and it isn't needed to satisfy any imports, then it MAY be omitted from the datastore schema for the dynamic configuration datastore.

5.3. The Operational State Datastore (<operational>) πŸ‘€

<operational> is a read-only datastore made up of all the "config true" and "config false" nodes defined in the datastore's schema. In the original NETCONF model, operational state only had "config false" nodes. The reason they added "config true" nodes here is so you can expose all the operational settings without having to copy definitions across the data models πŸ™Œ

<operational> holds system state and all the configuration the system is actually using. That includes all applied configuration from <intended>, learned configuration, system-provided configuration, and default values defined by any supported data models. On top of that, <operational> also contains applied configuration from dynamic configuration datastores πŸ’œ

The datastore schema for <operational> MUST be a superset of the combined datastore schema used in all configuration datastores. The one exception: configuration data nodes supported in a configuration datastore MAY be left out of <operational> if a server can't accurately report them 🫣

Requests to retrieve nodes from <operational> always return the value in use if the node exists, no matter what default value the YANG module specifies. If no value comes back for a given node, that implies the node isn't used by the device.

What counts as "in use" depends on both the schema definition and the device implementation. Generally, functionality that's enabled and operational on the system would be considered "in use". Functionality that's neither enabled nor operational is considered not "in use", so it SHOULD be omitted from <operational> 🌿

<operational> SHOULD conform to any constraints specified in the data model. But since the main goal is returning "in use" values, constraints MAY be violated under some circumstances. Examples: an abnormal value is "in use", the structure of a list is being modified, or remnant configuration (see Section 5.3.1) still exists. Note that deviations SHOULD be used when it's known in advance that a device doesn't fully conform to the <operational> schema. Deviations are your friend here πŸŽ€

Only semantic constraints MAY be violated. These are the YANG "when", "must", "mandatory", "unique", "min-elements", and "max-elements" statements, plus the uniqueness of key values.

Syntactic constraints MUST NOT be violated. That covers hierarchical organization, identifiers, and type-based constraints. If a node in <operational> doesn't meet the syntactic constraints, then it MUST NOT be returned, and some other mechanism should be used to flag the error 🚩 Hard line, no crossing it.

<operational> does not persist across reboots 🧊

5.3.1. Remnant Configuration 🫧

Changes to configuration may take time to percolate through to <operational>. During that window, <operational> may contain nodes for both the previous and the current configuration, tracking the device's current operation as closely as possible. That remnant configuration from the previous configuration sticks around until the system has released the resources the newly deleted configuration used (like network connections, memory allocations, or file handles) 🧹

Remnant configuration is a classic example of where the semantic constraints in the data model can't be relied on for <operational>. The system might still have remnant configuration whose constraints were valid for the previous configuration but aren't valid for the current one πŸ˜΅β€πŸ’« Since constraints on "config false" nodes may refer to "config true" nodes, remnant configuration may force the violation of those constraints. So yeah, it's messy, but now you know why ✨

5.3.2. Missing Resources πŸ™ˆ

Okay so <intended> can point at resources that aren't actually around or physically present. When that happens, those parts of <intended> just don't get applied. The data still shows up in <intended>, but it doesn't show up in <operational> 🫠.

A classic example is an interface config that refers to an interface that isn't currently there. The interface config stays in <intended>, but it won't appear in <operational>.

Here's the thing: config validity can't depend on whether those resources are currently present, because then yanking a resource out could make your config invalid. That's a hard no πŸ’€, especially since rebooting the device would make it restart with an invalid config. So instead, we let config for missing resources live in <running> and <intended>, and it just won't show up in <operational> ✨.

5.3.3. System-Controlled Resources πŸŽ€

Sometimes the device controls the resources itself, and the system-controlled data pops into (and out of) <operational> dynamically πŸ¦‹. If a system-controlled resource shows up and there's matching config in <intended>, the system will try to apply that config. If applying it works, the config ends up in <operational> eventually 🌸.

5.3.4. Origin Metadata Annotation 🏷️

As config flows into <operational>, it's conceptually marked with a metadata annotation [RFC7952] that tells you where it came from. The origin applies to all configuration nodes except non-presence containers. The origin annotation is defined in Section 7, and its values are YANG identities. These identities are defined:

  • origin: the abstract base identity that the other origin identities are derived from.
  • intended: represents config provided by <intended>.
  • dynamic: represents config provided by a dynamic configuration datastore.
  • system: represents config provided by the system itself. Examples include applied config for an always-existing loopback interface, or interface config that's auto-created because of the hardware currently in the device.
  • learned: represents config that has been learned through protocol interactions with other systems, including link-layer negotiations, routing protocols, and DHCP.
  • default: represents config using a default value specified in the data model, using either values in the default statement or any values described in the description statement. The default origin is only used when the config hasn't been provided by any other source.
  • unknown: represents config where the system can't identify the origin.

These identities can be refined even further. For example, there could be separate identities for particular types or instances of dynamic configuration datastores derived from dynamic πŸ’œ.

For all configuration data nodes in <operational>, the device SHOULD report the origin that most accurately reflects the source of the configuration that's in use by the system πŸ”.

Sometimes it could be ambiguous which origin to use, i.e., when the same data node value has come from multiple sources. In that case, the description statement in the YANG module SHOULD be used as guidance for picking the right origin. For example:

If, for a particular config node, the YANG description statement says that a protocol-negotiated value overrides any configured value, then the origin is reported as learned, even when the learned value is the same as the configured value πŸ™Œ.

On the flip side, if, for a particular config node, the YANG description statement says that a protocol-negotiated value does not override an explicitly configured value, then the origin is reported as intended, even when the learned value is the same as the configured value πŸ’….

And if a device can't provide an accurate origin for a particular configuration data node, it SHOULD use the origin unknown 🫢.

6. Implications on YANG πŸ‘‘

6.1. XPath Context ✨

This section updates Section 6.4.1 of RFC 7950.

If a server implements the architecture defined in this document, the accessible trees for some XPath contexts get refined like this:

  • If the XPath expression is defined in a substatement to a data node that represents system state, the accessible tree is all operational state in the server. The root node has all top-level data nodes in all modules as children.
  • If the XPath expression is defined in a substatement to a notification statement, the accessible tree is the notification instance and all operational state in the server. If the notification is defined on the top level in a module, then the root node has the node representing the notification being defined and all top-level data nodes in all modules as children. Otherwise, the root node has all top-level data nodes in all modules as children.
  • If the XPath expression is defined in a substatement to an input statement in an rpc or action statement, the accessible tree is the RPC or action operation instance and all operational state in the server. The root node has top-level data nodes in all modules as children. Additionally, for an RPC, the root node also has the node representing the RPC operation being defined as a child. The node representing the operation being defined has the operation's input parameters as children.
  • If the XPath expression is defined in a substatement to an output statement in an rpc or action statement, the accessible tree is the RPC or action operation instance and all operational state in the server. The root node has top-level data nodes in all modules as children. Additionally, for an RPC, the root node also has the node representing the RPC operation being defined as a child. The node representing the operation being defined has the operation's output parameters as children.

6.2. Invocation of Actions and RPCs 🎬

This section updates Section 7.15 of RFC 7950.

Actions are always invoked in the context of the operational state datastore. The node for which the action is invoked MUST exist in the operational state datastore πŸ”₯.

Note that this document doesn't constrain the result of invoking an RPC or action in any way. For example, an RPC might be defined to modify the contents of some datastore 🌈.

7. YANG Modules πŸ’–

okay bestie, the YANG modules are the heart of this whole doc 😭 there are two of them. ietf-datastores names the datastores, and ietf-origin adds the origin annotation. Here they are, exactly as written:

<CODE BEGINS> file "ietf-datastores@2018-02-14.yang"

module ietf-datastores {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:ietf-datastores";
  prefix ds;

  organization
    "IETF Network Modeling (NETMOD) Working Group";

  contact
    "WG Web:   <https://datatracker.ietf.org/wg/netmod/>

     WG List:  <mailto:netmod@ietf.org>

     Author:   Martin Bjorklund
               <mailto:mbj@tail-f.com>

     Author:   Juergen Schoenwaelder
               <mailto:j.schoenwaelder@jacobs-university.de>

     Author:   Phil Shafer
               <mailto:phil@juniper.net>

     Author:   Kent Watsen
               <mailto:kwatsen@juniper.net>

     Author:   Rob Wilton
               <rwilton@cisco.com>";

  description
    "This YANG module defines a set of identities for identifying
     datastores.

     Copyright (c) 2018 IETF Trust and the persons identified as
     authors of the code.  All rights reserved.

     Redistribution and use in source and binary forms, with or
     without modification, is permitted pursuant to, and subject to
     the license terms contained in, the Simplified BSD License set
     forth in Section 4.c of the IETF Trust's Legal Provisions
     Relating to IETF Documents
     (https://trustee.ietf.org/license-info).

     This version of this YANG module is part of RFC 8342
     (https://www.rfc-editor.org/info/rfc8342); see the RFC itself
     for full legal notices.";

  revision 2018-02-14 {
    description
      "Initial revision.";
    reference
      "RFC 8342: Network Management Datastore Architecture (NMDA)";
  }

  /*
   * Identities
   */

  identity datastore {
    description
      "Abstract base identity for datastore identities.";
  }

  identity conventional {
    base datastore;
    description
      "Abstract base identity for conventional configuration
       datastores.";
  }

  identity running {
    base conventional;
    description
      "The running configuration datastore.";
  }

  identity candidate {
    base conventional;
    description
      "The candidate configuration datastore.";
  }

  identity startup {
    base conventional;
    description
      "The startup configuration datastore.";
  }
  identity intended {
    base conventional;
    description
      "The intended configuration datastore.";
  }

  identity dynamic {
    base datastore;
    description
      "Abstract base identity for dynamic configuration datastores.";
  }

  identity operational {
    base datastore;
    description
      "The operational state datastore.";
  }

  /*
   * Type definitions
   */

  typedef datastore-ref {
    type identityref {
      base datastore;
    }
    description
      "A datastore identity reference.";
  }
}

<CODE ENDS>
<CODE BEGINS> file "ietf-origin@2018-02-14.yang"

module ietf-origin {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:ietf-origin";
  prefix or;

  import ietf-yang-metadata {
    prefix md;
  }

  organization
    "IETF Network Modeling (NETMOD) Working Group";

  contact
    "WG Web:   <https://datatracker.ietf.org/wg/netmod/>

     WG List:  <mailto:netmod@ietf.org>

     Author:   Martin Bjorklund
               <mailto:mbj@tail-f.com>

     Author:   Juergen Schoenwaelder
               <mailto:j.schoenwaelder@jacobs-university.de>

     Author:   Phil Shafer
               <mailto:phil@juniper.net>

     Author:   Kent Watsen
               <mailto:kwatsen@juniper.net>

     Author:   Rob Wilton
               <rwilton@cisco.com>";

  description
    "This YANG module defines an 'origin' metadata annotation and a
     set of identities for the origin value.

     Copyright (c) 2018 IETF Trust and the persons identified as
     authors of the code.  All rights reserved.

     Redistribution and use in source and binary forms, with or
     without modification, is permitted pursuant to, and subject to
     the license terms contained in, the Simplified BSD License set
     forth in Section 4.c of the IETF Trust's Legal Provisions
     Relating to IETF Documents
     (https://trustee.ietf.org/license-info).

     This version of this YANG module is part of RFC 8342
     (https://www.rfc-editor.org/info/rfc8342); see the RFC itself
     for full legal notices.";

  revision 2018-02-14 {
    description
      "Initial revision.";
    reference
      "RFC 8342: Network Management Datastore Architecture (NMDA)";
  }

  /*
   * Identities
   */

  identity origin {
    description
      "Abstract base identity for the origin annotation.";
  }

  identity intended {
    base origin;
    description
      "Denotes configuration from the intended configuration
       datastore.";
  }

  identity dynamic {
    base origin;
    description
      "Denotes configuration from a dynamic configuration
       datastore.";
  }

  identity system {
    base origin;
    description
      "Denotes configuration originated by the system itself.

       Examples of system configuration include applied configuration
       for an always-existing loopback interface, or interface
       configuration that is auto-created due to the hardware
       currently present in the device.";
  }
  identity learned {
    base origin;
    description
      "Denotes configuration learned from protocol interactions with
       other devices, instead of via either the intended
       configuration datastore or any dynamic configuration
       datastore.

       Examples of protocols that provide learned configuration
       include link-layer negotiations, routing protocols, and
       DHCP.";
  }

  identity default {
    base origin;
    description
      "Denotes configuration that does not have a configured or
       learned value but has a default value in use.  Covers both
       values defined in a 'default' statement and values defined
       via an explanation in a 'description' statement.";
  }

  identity unknown {
    base origin;
    description
      "Denotes configuration for which the system cannot identify the
       origin.";
  }

  /*
   * Type definitions
   */

  typedef origin-ref {
    type identityref {
      base origin;
    }
    description
      "An origin identity reference.";
  }
  /*
   * Metadata annotations
   */

  md:annotation origin {
    type origin-ref;
    description
      "The 'origin' annotation can be present on any configuration
       data node in the operational state datastore.  It specifies
       from where the node originated.  If not specified for a given
       configuration data node, then the origin is the same as the
       origin of its parent node in the data tree.  The origin for
       any top-level configuration data nodes must be specified.";
  }
}

<CODE ENDS>

8. IANA Considerations 🌸

8.1. Updates to the IETF XML Registry

okay so this doc registers two URIs in the "IETF XML Registry" [RFC3688] 🧚 and it follows the format from [RFC3688] to do it. The registrations go like this:

URI: urn:ietf:params:xml:ns:yang:ietf-datastores
Registrant Contact: The IESG.
XML: N/A; the requested URI is an XML namespace.

URI: urn:ietf:params:xml:ns:yang:ietf-origin
Registrant Contact: The IESG.
XML: N/A; the requested URI is an XML namespace.

8.2. Updates to the YANG Module Names Registry

this doc also registers two YANG modules in the "YANG Module Names" registry [RFC6020] πŸ¦‹ following the format in [RFC6020]. Here are the registrations:

name:         ietf-datastores
namespace:    urn:ietf:params:xml:ns:yang:ietf-datastores
prefix:       ds
reference:    RFC 8342

name:         ietf-origin
namespace:    urn:ietf:params:xml:ns:yang:ietf-origin
prefix:       or
reference:    RFC 8342

9. Security Considerations πŸ”’

okay, this section is giving serious main character energy, so pay attention bestie πŸ’€

This doc talks about an architectural model of datastores for network management using NETCONF/RESTCONF and YANG. It has no security impact on the Internet.

Although this doc specifies several YANG modules, those modules only define identities and a metadata annotation. So the "YANG module security guidelines" [YANG-SEC] do not apply.

The origin metadata annotation exposes where the values in the applied configuration came from. Origin info may provide hints that certain control-plane protocols are active on a device πŸ‘€. Since origin info is tied to applied configuration values, only clients that have permission to read those applied values can see it. Security administrators should consider how sensitive origin information is when they write access control rules 🫢


10. References πŸ“š

10.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC6241]  Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed.,
           and A. Bierman, Ed., "Network Configuration Protocol
           (NETCONF)", RFC 6241, DOI 10.17487/RFC6241, June 2011,
           <https://www.rfc-editor.org/info/rfc6241>.

[RFC7950]  Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language",
           RFC 7950, DOI 10.17487/RFC7950, August 2016,
           <https://www.rfc-editor.org/info/rfc7950>.

[RFC7952]  Lhotka, L., "Defining and Using Metadata with YANG",
           RFC 7952, DOI 10.17487/RFC7952, August 2016,
           <https://www.rfc-editor.org/info/rfc7952>.

[RFC8040]  Bierman, A., Bjorklund, M., and K. Watsen, "RESTCONF
           Protocol", RFC 8040, DOI 10.17487/RFC8040, January 2017,
           <https://www.rfc-editor.org/info/rfc8040>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in
           RFC 2119 Key Words", BCP 14, RFC 8174,
           DOI 10.17487/RFC8174, May 2017,
           <https://www.rfc-editor.org/info/rfc8174>.

[W3C.REC-xml-20081126]
           Bray, T., Paoli, J., Sperberg-McQueen, M., Maler, E., and
           F. Yergeau, "Extensible Markup Language (XML) 1.0
           (Fifth Edition)", World Wide Web Consortium Recommendation
           REC-xml-20081126, November 2008,
           <https://www.w3.org/TR/2008/REC-xml-20081126>.

10.2. Informative References πŸ“š

Okay bestie, these are the "if you want the full backstory" links 🧚 Each one has a tag in square brackets so you can find it again.

[NETMOD-Operational] Bjorklund, M. and L. Lhotka, "Operational Data in NETCONF and YANG", Work in Progress, draft-bjorklund-netmod-operational-00, October 2012.

[OpState-Enhance] Watsen, K., Bierman, A., Bjorklund, M., and J. Schoenwaelder, "Operational State Enhancements for YANG, NETCONF, and RESTCONF", Work in Progress, draft-kwatsen-netmod-opstate-02, February 2016.

[OpState-Modeling] Shakir, R., Shaikh, A., and M. Hines, "Consistent Modeling of Operational State Data in YANG", Work in Progress, draft-openconfig-netmod-opstate-01, July 2015.

[OpState-Reqs] Watsen, K. and T. Nadeau, "Terminology and Requirements for Enhanced Handling of Operational State", Work in Progress, draft-ietf-netmod-opstate-reqs-04, January 2016.

[RFC3688] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, DOI 10.17487/RFC3688, January 2004, <https://www.rfc-editor.org/info/rfc3688>.

[RFC6020] Bjorklund, M., Ed., "YANG - A Data Modeling Language for the Network Configuration Protocol (NETCONF)", RFC 6020, DOI 10.17487/RFC6020, October 2010, <https://www.rfc-editor.org/info/rfc6020>.

[RFC6244] Shafer, P., "An Architecture for Network Management Using NETCONF and YANG", RFC 6244, DOI 10.17487/RFC6244, June 2011, <https://www.rfc-editor.org/info/rfc6244>.

[RFC8343] Bjorklund, M., "A YANG Data Model for Interface Management", RFC 8343, DOI 10.17487/RFC8343, March 2018, <https://www.rfc-editor.org/info/rfc8343>.

[RFC8344] Bjorklund, M., "A YANG Data Model for IP Management", RFC 8344, DOI 10.17487/RFC8344, March 2018, <https://www.rfc-editor.org/info/rfc8344>.

[With-config-state] Wilton, R., ""With-config-state" Capability for NETCONF/RESTCONF", Work in Progress, draft-wilton-netmod-opstate-yang-02, December 2015.

[YANG-SEC] IETF, "YANG Security Guidelines", <https://trac.ietf.org/trac/ops/wiki/yang-security-guidelines>.


Appendix A. Guidelines for Defining Datastores ✨

Okay so, if you're defining a brand new datastore in this architecture, it should be written up in a document (an RFC works great πŸ’…) whose whole job is defining that datastore. When it makes sense, you can define more than one datastore in the same document, like when they're logically connected πŸ”— Each datastore's definition should cover the points in the subsections below.

A.1. Define Which YANG Modules Can Be Used in the Datastore

Not every YANG module is allowed in every datastore πŸ™ˆ Some datastores may limit which data models can be used in them. If you want only a subset of all modules to be targeted at the datastore, then the documentation defining the datastore must say so.

A.2. Define Which Subset of YANG-Modeled Data Applies

By default, the data in a datastore is modeled by all YANG statements in the available YANG modules. But you can also set criteria that YANG statements have to meet before they show up in a datastore. For instance, maybe only "config true" nodes, or "config false" nodes that also carry a specific YANG extension, are present in the datastore ✨

A.3. Define How Data Is Actualized

The new datastore must spell out how it interacts with other datastores πŸ¦‹

For example, the diagram in Section 5 shows dynamic configuration datastores feeding into <operational>. How this interaction happens has to be defined by the particular dynamic configuration datastores. Sometimes it can happen implicitly, as soon as the data lands in the dynamic configuration datastore. Other times an explicit action (e.g., an RPC) may be required to trigger the application of the datastore's data πŸ’–

A.4. Define Which Protocols Can Be Used

By default, it's assumed that both the NETCONF and RESTCONF protocols can be used to interact with a datastore. However, it may be that only one specific protocol can be used (e.g., Forwarding and Control Element Separation (ForCES)), or that only a subset of all protocol operations or capabilities are available (e.g., no locking or no XPath-based filtering) πŸŽ€

A.5. Define YANG Identities for the Datastore

The datastore must be defined with a YANG identity that uses the "ds:datastore" identity, or one of its derived identities, as its base. This identity is necessary so that the datastore can be referenced in protocol operations (e.g., <get-data>) πŸ‘‘

The datastore may also be defined with an identity that uses the "or:origin" identity, or one of its derived identities, as its base. This identity is needed if the datastore interacts with <operational>, so that data originating from the datastore can be identified as such via the "origin" metadata attribute defined in Section 7 🫢

An example of these guidelines in use is provided in Appendix B.


Appendix B. Example of an Ephemeral Dynamic Configuration Datastore 🧚

This section defines documentation for an example dynamic configuration datastore using the guidelines from Appendix A. For brevity, only a terse example is provided. It's expected that a standalone RFC would be written once this type of scenario is fully considered πŸ“

This example defines a dynamic configuration datastore called "ephemeral", which is loosely modeled after the work done in the I2RS Working Group 🌈

+--------------------+----------------------------------------------+
| Name               | Value                                        |
+--------------------+----------------------------------------------+
| Name               | ephemeral                                    |
|                    |                                              |
| YANG modules       | all (default)                                |
|                    |                                              |
| YANG nodes         | all "config true" data nodes                 |
|                    |                                              |
| How applied        | changes automatically propagated to          |
|                    | <operational>                                |
|                    |                                              |
| Protocols          | NETCONF/RESTCONF (default)                   |
|                    |                                              |
| Defining YANG      | "example-ds-ephemeral"                       |
| module             |                                              |
+--------------------+----------------------------------------------+

Properties of the Example "ephemeral" Datastore πŸ’œ

module example-ds-ephemeral {
  yang-version 1.1;
  namespace "urn:example:ds-ephemeral";
  prefix eph;

  import ietf-datastores {
    prefix ds;
  }
  import ietf-origin {
    prefix or;
  }

  // datastore identity
  identity ds-ephemeral {
    base ds:dynamic;
    description
      "The ephemeral dynamic configuration datastore.";
  }

  // origin identity
  identity or-ephemeral {
    base or:dynamic;
    description
      "Denotes data from the ephemeral dynamic configuration
       datastore.";
  }
}

Appendix C. Example Data 🌸

The use of datastores is complex, and a lot of the subtle effects are way easier to see with examples πŸ‘€ This section presents a series of example data models with some sample contents of the various datastores.

The XML [W3C.REC-xml-20081126] snippets that follow are provided as examples only πŸ’…

C.1. System Example

In this example, the following fictional module is used:

module example-system {
  yang-version 1.1;
  namespace urn:example:system;
  prefix sys;

  import ietf-inet-types {
    prefix inet;
  }

  container system {
    leaf hostname {
      type string;
    }

    list interface {
      key name;

      leaf name {
        type string;
      }

      container auto-negotiation {
        leaf enabled {
          type boolean;
          default true;
        }
        leaf speed {
          type uint32;
          units mbps;
          description
            "The advertised speed, in Mbps.";
        }
      }

      leaf speed {
        type uint32;
        units mbps;
        config false;
        description
          "The speed of the interface, in Mbps.";
      }
      list address {
        key ip;

        leaf ip {
          type inet:ip-address;
        }
        leaf prefix-length {
          type uint8;
        }
      }
    }
  }
}

The operator has configured the hostname and two interfaces, so the contents of <intended> are:

<system xmlns="urn:example:system">

  <hostname>foo.example.com</hostname>

  <interface>
    <name>eth0</name>
    <auto-negotiation>
      <speed>1000</speed>
    </auto-negotiation>
    <address>
      <ip>2001:db8::10</ip>
      <prefix-length>64</prefix-length>
    </address>
  </interface>

  <interface>
    <name>eth1</name>
    <address>
      <ip>2001:db8::20</ip>
      <prefix-length>64</prefix-length>
    </address>
  </interface>

</system>

The system has detected that the hardware for one of the configured interfaces ("eth1") is not yet present, so the configuration for that interface is not applied πŸ™ƒ Further, the system has received a hostname and an additional IP address for "eth0" over DHCP. On top of filling in the default value for the auto-negotiation enabled leaf, a loopback interface entry is also automatically instantiated by the system. All of this is reflected in <operational>. Note how the "origin" metadata attribute for several "config true" data nodes is inherited from their parent data nodes πŸ¦‹

<system
    xmlns="urn:example:system"
    xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin">

  <hostname or:origin="or:learned">bar.example.com</hostname>

  <interface or:origin="or:intended">
    <name>eth0</name>
    <auto-negotiation>
      <enabled or:origin="or:default">true</enabled>
      <speed>1000</speed>
    </auto-negotiation>
    <speed>100</speed>
    <address>
      <ip>2001:db8::10</ip>
      <prefix-length>64</prefix-length>
    </address>
    <address or:origin="or:learned">
      <ip>2001:db8::1:100</ip>
      <prefix-length>64</prefix-length>
    </address>
  </interface>

  <interface or:origin="or:system">
    <name>lo0</name>
    <address>
      <ip>::1</ip>
      <prefix-length>128</prefix-length>
    </address>
  </interface>

</system>

C.2. BGP Example

okay so let's look at a totally fictional BGP module (not real, just vibes) πŸ¦‹

container bgp {
  leaf local-as {
    type uint32;
  }
  leaf peer-as {
    type uint32;
  }
  list peer {
    key name;
    leaf name {
      type inet:ip-address;
    }
    leaf local-as {
      type uint32;
      description
        "... Defaults to ../local-as.";
    }
    leaf peer-as {
      type uint32;
      description
        "... Defaults to ../peer-as.";
    }
    leaf local-port {
      type inet:port;
    }
    leaf remote-port {
      type inet:port;
      default 179;
    }
    leaf state {
      config false;
      type enumeration {
        enum init;
        enum established;
        enum closing;
      }
    }
  }
}

ngl this model is giving genius πŸ’… Both bgp/peer/local-as and bgp/peer/peer-as have complex hierarchical values, so the user can set default values for all peers in one single spot πŸŽ€

It also fully integrates state ("config false") nodes with configuration ("config true") nodes πŸ”₯ There's no separate "bgp-state" hierarchy with all the repeated containment and naming nodes. That makes the model simpler and way more readable, bestie 🫢

C.2.1. Datastores

each datastore is a different view of these nodes πŸ‘‘ <running> holds the configuration the operator provided, like a single BGP peer. <intended> conceptually holds the data as validated, after the removal of data not intended for validation and after any local template mechanisms are performed. <operational> shows the data from <intended> plus any "config false" nodes ✨

C.2.2. Adding a Peer

if the user configures a single BGP peer, that peer will be visible in both <running> and <intended> 🧚 It may also appear in <candidate> if the server supports the candidate configuration datastore. Retrieving the peer will return only the user-specified values.

no time delay should exist between the appearance of the peer in <running> and <intended> ⏱️

in this scenario, we added the following to <running>:

<bgp>
  <local-as>64501</local-as>
  <peer-as>64502</peer-as>
  <peer>
    <name>2001:db8::2:3</name>
  </peer>
</bgp>

C.2.2.1. <operational>

the operational datastore will contain the fully expanded peer data, including "config false" nodes. In our example, that means the "state" node shows up 🌸

on top of that, <operational> will contain the "currently in use" values for all nodes. So local-as and peer-as get populated even if they aren't given values in <intended>. The value of bgp/local-as will be used if bgp/peer/local-as isn't provided, and bgp/peer-as and bgp/peer/peer-as have the same relationship. In the operational view, every peer ends up with values for its local-as and peer-as, even if those weren't explicitly configured and are coming from bgp/local-as and bgp/peer-as instead πŸ¦‹

each BGP peer has a TCP connection associated with it, using the values of local-port and remote-port from <intended>. If those values aren't supplied, the system will select values. When the connection is established, <operational> will contain the current values for the local-port and remote-port nodes regardless of their origin. If the system chose the values, the "origin" attribute will be set to "system". Before the connection is established, one or both of the nodes may not appear, since the system may not have their values yet πŸ’€

<bgp xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin"
     or:origin="or:intended">
  <local-as>64501</local-as>
  <peer-as>64502</peer-as>
  <peer>
    <name>2001:db8::2:3</name>
    <local-as or:origin="or:default">64501</local-as>
    <peer-as or:origin="or:default">64502</peer-as>
    <local-port or:origin="or:system">60794</local-port>
    <remote-port or:origin="or:default">179</remote-port>
    <state>established</state>
  </peer>
</bgp>

C.2.3. Removing a Peer

okay so changes to configuration can take time to percolate through all the software components involved 🫠 During that period it is imperative to keep giving an accurate view of how the device is working. <operational> will contain nodes for both the previous and current configuration, tracking the current operation of the device as closely as possible 🎯

let's say a client removes a BGP peer. When a peer is removed, the operational state keeps reflecting that the peer exists until its resources are released, including closing the peer's connection. During that time the current data values stay visible in <operational>, with the "origin" attribute set to indicate where the original data came from πŸ‘€

<bgp xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin"
     or:origin="or:intended">
  <local-as>64501</local-as>
  <peer-as>64502</peer-as>
  <peer>
    <name>2001:db8::2:3</name>
    <local-as or:origin="or:default">64501</local-as>
    <peer-as or:origin="or:default">64502</peer-as>
    <local-port or:origin="or:system">60794</local-port>
    <remote-port or:origin="or:default">179</remote-port>
    <state>closing</state>
  </peer>
</bgp>

once resources are released and the connection is closed, the peer's data is removed from <operational> 🧹


C.3. Interface Example

in this section we're using this simple interface data model πŸ“

container interfaces {
  list interface {
    key name;
    leaf name {
      type string;
    }
    leaf description {
      type string;
    }
    leaf mtu {
      type uint16;
    }
    leaf-list ip-address {
      type inet:ip-address;
    }
  }
}

C.3.1. Pre-provisioned Interfaces

one common issue in networking devices is supporting Field Replaceable Units (FRUs) that can be inserted and removed from the device without a reboot or interfering with normal operation πŸ”§ These FRUs are typically interface cards, and the devices support pre-provisioning of these interfaces.

if a client creates an interface "et-0/0/0" but the interface doesn't physically exist yet, then <intended> might contain the following:

<interfaces>
  <interface>
    <name>et-0/0/0</name>
    <description>Test interface</description>
  </interface>
</interfaces>

since the interface doesn't exist, this data does not appear in <operational> πŸ™ˆ

when a FRU containing this interface is inserted, the system detects it and processes the associated configuration. <operational> will contain the data from <intended>, plus nodes added by the system, like the current value of the interface's MTU ✨

<interfaces xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin"
            or:origin="or:intended">
  <interface>
    <name>et-0/0/0</name>
    <description>Test interface</description>
    <mtu or:origin="or:system">1500</mtu>
  </interface>
</interfaces>

if the FRU is removed, the interface data is removed from <operational> πŸ‘‹

C.3.2. System-Provided Interface

imagine the system provides a loopback interface (named "lo0") with a default IPv4 address of "127.0.0.1" and a default IPv6 address of "::1" 🌈 The system will only provide configuration for this interface if there is no data for it in <intended>.

when no configuration for "lo0" appears in <intended>, <operational> will show the system-provided data:

<interfaces xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin"
            or:origin="or:intended">
  <interface or:origin="or:system">
    <name>lo0</name>
    <ip-address>127.0.0.1</ip-address>
    <ip-address>::1</ip-address>
  </interface>
</interfaces>

when configuration for "lo0" does appear in <intended>, <operational> will show that data with the origin set to "intended". If the "ip-address" isn't provided, then the system-provided value appears as follows:

<interfaces xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin"
            or:origin="or:intended">
  <interface>
    <name>lo0</name>
    <description>loopback</description>
    <ip-address or:origin="or:system">127.0.0.1</ip-address>
    <ip-address>::1</ip-address>
  </interface>
</interfaces>

Acknowledgments ✨

this document grew out of many discussions that took place since 2010 🌸 Several documents ([NETMOD-Operational] [With-config-state] [OpState-Reqs] [OpState-Enhance] [OpState-Modeling], as well as [RFC6244]) touched on some of the problems of the original datastore model. The following people were authors of these works in progress or were otherwise actively involved in the discussions that led to this document 🫢

  • Lou Berger, LabN Consulting, L.L.C., <lberger@labn.net>
  • Andy Bierman, YumaWorks, <andy@yumaworks.com>
  • Marcus Hines, Google, <hines@google.com>
  • Christian Hopps, Deutsche Telekom, <chopps@chopps.org>
  • Balazs Lengyel, Ericsson, <balazs.lengyel@ericsson.com>
  • Ladislav Lhotka, CZ.NIC, <lhotka@nic.cz>
  • Acee Lindem, Cisco Systems, <acee@cisco.com>
  • Thomas Nadeau, Brocade Networks, <tnadeau@lucidvision.com>
  • Tom Petch, Engineering Networks Ltd, <ietfc@btconnect.com>
  • Anees Shaikh, Google, <aashaikh@google.com>
  • Rob Shakir, Google, <robjs@google.com>
  • Jason Sterne, Nokia, <jason.sterne@nokia.com>

Juergen Schoenwaelder was partly funded by Flamingo, a Network of Excellence project (ICT-318488) supported by the European Commission under its Seventh Framework Programme. bestie, that's the whole squad πŸŒˆπŸ’–


Authors' Addresses πŸ’œ

Martin Bjorklund

Tail-f Systems

Email: mbj@tail-f.com

Juergen Schoenwaelder

Jacobs University

Email: j.schoenwaelder@jacobs-university.de

Phil Shafer

Juniper Networks

Email: phil@juniper.net

Kent Watsen

Juniper Networks

Email: kwatsen@juniper.net

Robert Wilton

Cisco Systems

Email: rwilton@cisco.com

πŸ“¦ where this page comes from