RFC 9144

Comparison of Network Management Datastore Architecture (NMDA) Datastores

๐Ÿ“… published December 2021, from ietf

RFC 9144 ๐Ÿ’– Comparison of Network Management Datastore Architecture (NMDA) Datastores โœจ

Okay bestie, this one is RFC 9144, a Standards Track doc (so it's an official Internet standard, no cap ๐Ÿ”ฅ). It's by Alex Clemm and Yingzhen Qu from Futurewei, Jeff Tantsura from Microsoft, and Andy Bierman from YumaWorks ๐Ÿงš. It came out in December 2021, and it's published under ISSN 2070-1721. The header doesn't list anything it obsoletes or updates, so it's a clean standalone drop ๐Ÿ’….

Abstract ๐Ÿฆ‹

This doc defines a Remote Procedure Call (RPC) operation that lets you compare management datastores that follow the Network Management Datastore Architecture (NMDA). So basically, it's a tool for checking two datastores against each other ๐Ÿ‘€.

Status of This Memo ๐ŸŒธ

This is an Internet Standards Track document, so it's officially a standard, not just a vibe ๐Ÿ˜ญ.

It's a product of the Internet Engineering Task Force (IETF) and represents the consensus of the IETF community. It went through public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841 ๐Ÿ’œ.

You can find the current status of this document, any errata, and how to send feedback at https://www.rfc-editor.org/info/rfc9144 ๐ŸŽ€.

Copyright (c) 2021 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 Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as described in the Revised BSD License โš–๏ธ.

Table of Contents ๐Ÿ“

1.  Introduction
2.  Key Words
3.  Data Model Overview
4.  YANG Data Model
5.  Example
6.  Performance Considerations
7.  IANA Considerations
  7.1.  Update to the IETF XML Registry
  7.2.  Update to the YANG Module Names Registry
8.  Security Considerations
9.  References
  9.1.  Normative References
  9.2.  Informative References
Appendix A.  Possible Future Extensions
Acknowledgments
Authors' Addresses

1. Introduction โœจ

Okay so the revised NMDA [RFC8342] adds a bunch of new datastores. Each one holds YANG-defined data [RFC7950] and gives you a different "viewpoint" on the data a server keeps. The new ones include <intended>, which holds validated configuration that a client app intends to take effect, and <operational>, which holds operational state data (like statistics) plus the configuration that is actually in effect ๐Ÿ’….

NMDA basically adds a lifecycle for management data ๐Ÿ”„. It separates data that's part of a configuration a user supplied, the configuration that has been successfully applied and is now part of operational state, and the full operational state, which includes applied configuration along with status and statistics ๐Ÿงš.

Because of that, the same management data model can show up in multiple datastores ๐ŸŒธ. Clients have to name the target datastore so they're clear about which viewpoint they want. For example, a client can tell whether it cares about the configuration that was supplied to a server and is supposed to be in effect, or the configuration that's been applied and is actually in effect on the server ๐Ÿ‘€.

Data can move from one datastore to another, so differences between datastores can happen ๐Ÿ˜ญ. Some of that is totally expected, since there can be a time lag between a configuration being given to the device and showing up in <intended>, and then taking effect and showing up in <operational>. But sometimes a configuration item that was meant to be applied never takes effect at all, or it takes an unusually long time. That can happen when certain conditions aren't met, when some parts of the configuration don't propagate because they're considered inactive, when resource dependencies don't get resolved, or even because of implementation errors in corner cases ๐Ÿ™ˆ.

When the configuration in effect is different from the configuration that was applied, things can go wrong fast ๐Ÿ’€. It gets harder to run the network properly because you have limited visibility into the actual operational status, which makes it harder to analyze and understand what's happening. Services can be negatively affected (like a degraded or broken customer service), and network resources can get misallocated ๐Ÿ˜ค.

An app can analyze differences between two datastores by pulling the contents of both and comparing them. But in lots of cases that's both costly and extremely wasteful ๐Ÿซ .

So this document introduces a YANG data model with RPCs meant to be used together with NETCONF [RFC6241] or RESTCONF [RFC8040]. These RPCs let a client ask a server to compare two NMDA datastores and report any differences ๐Ÿฆ‹.

2. Key Words ๐ŸŽ€

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐Ÿ“š. So if they're not in all caps, they're just regular words, no drama ๐Ÿ’….

3. Data Model Overview ๐Ÿ’œ

The core of this whole solution is a new management operation called <compare>. It compares the data tree contents of two datastores ๐Ÿ”. It checks for any differences in values or in data nodes contained in either datastore, and it returns those differences as output. The output is formatted as specified in YANG Patch [RFC8072] ๐ŸŽ.

The YANG data model defines the <compare> operation as a new RPC. It takes these input parameters ๐Ÿ‘‘:

  • source: The source identifies the datastore to serve as the reference for the comparison, for example <intended>.
  • target: The target identifies the datastore to compare against the source, for example <operational>.
  • filter-spec: This is a choice between different filter constructs used to identify the parts of the datastore to retrieve. It acts as a node selector that marks which data nodes are within the scope of the comparison and which are outside it. This lets you apply a comparison to just a specific part of the datastore you care about, like a particular subtree ๐ŸŒณ. Heads up: the filter does not allow expressions that match against data node values, because that may cause implementation difficulties and isn't required for normal use cases โš ๏ธ.
  • all: When set, this parameter says that all differences should be included, even differences about schema nodes that exist in only one of the datastores. When this parameter is not included, a prefiltering step is applied automatically to exclude data that doesn't pertain to both datastores. Specifically, if the same schema node isn't present in both datastores, then all instances of that schema node and all its descendants get excluded from the comparison โœ‚๏ธ. This lets client apps focus on the differences that are true mismatches of instance data, without needing more complex filter constructs ๐Ÿง.
  • report-origin: When set, this parameter says origin metadata should be included as part of the RPC output. When this parameter is omitted, origin metadata in comparisons that involve <operational> is omitted by default. Origin metadata only applies to <operational>, so it's also left out of comparisons that don't involve <operational>, no matter whether the parameter is set or not ๐Ÿ™ˆ.

The operation gives you one output parameter ๐ŸŽ‰:

  • differences: This parameter contains the list of differences, encoded per the YANG Patch data model defined in [RFC8072]. When a datastore node in the source of the comparison isn't present in the target, that can be indicated as either a "delete" or a "remove" in the patch, since there's no difference between those operations for the purposes of the comparison ๐Ÿงน. The YANG Patch data model is augmented to indicate the value of source datastore nodes, in addition to the patch itself that would need to be applied to the source to produce the target ๐Ÿช„. When the target datastore is <operational> and the input parameter "report-origin" is set, origin metadata is included as part of the patch. Including origin metadata can help explain the cause of a difference in some cases. For example, a data node might be part of <intended> while the origin of that same node in <operational> is reported as "system" ๐Ÿง .

The data model is defined in the ietf-nmda-compare YANG module. Its structure is shown in the figure below, and the notation follows [RFC8340] ๐Ÿ“.

module: ietf-nmda-compare
  rpcs:
    +---x compare
       +---w input
       |  +---w source            identityref
       |  +---w target            identityref
       |  +---w all?              empty
       |  +---w report-origin?    empty
       |  +---w (filter-spec)?
       |     +--:(subtree-filter)
       |     |  +---w subtree-filter?
       |     +--:(xpath-filter)
       |        +---w xpath-filter?     yang:xpath1.0 {nc:xpath}?
       +--ro output
          +--ro (compare-response)?
             +--:(no-matches)
             |  +--ro no-matches?    empty
             +--:(differences)
                +--ro differences
                   +--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?
                         +--ro source-value?

               Figure 1: Structure of ietf-nmda-compare

4. YANG Data Model ๐Ÿ’–

This YANG module is bestie-approved and includes references to [RFC6991], [RFC8342], [RFC8072], and [RFC6241]. ๐ŸŽ€ The module lives in the file "ietf-nmda-compare@2021-12-10.yang", and here it is in all its glory:

module ietf-nmda-compare {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:ietf-nmda-compare";
  prefix cmp;

  import ietf-yang-types {
    prefix yang;
    reference
      "RFC 6991: Common YANG Data Types";
  }
  import ietf-datastores {
    prefix ds;
    reference
      "RFC 8342: Network Management Datastore
       Architecture (NMDA)";
  }
  import ietf-yang-patch {
    prefix ypatch;
    reference
      "RFC 8072: YANG Patch Media Type";
  }
  import ietf-netconf {
    prefix nc;
    reference
      "RFC 6241: Network Configuration Protocol (NETCONF)";
  }

  organization
    "IETF NETMOD (Network Modeling) Working Group";
  contact
    "WG Web:   <https://datatracker.ietf.org/wg/netmod/>
     WG List:  <mailto:netmod@ietf.org>

     Author: Alexander Clemm
             <mailto:ludwig@clemm.org>

     Author: Yingzhen Qu
             <mailto:yqu@futurewei.com>

     Author: Jeff Tantsura
             <mailto:jefftant.ietf@gmail.com>

     Author: Andy Bierman
             <mailto:andy@yumaworks.com>";
  description
    "The YANG data model defines a new operation, <compare>, that
     can be used to compare NMDA datastores.

     Copyright (c) 2021 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 Revised 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 9144; see the
     RFC itself for full legal notices.";

  revision 2021-12-10 {
    description
      "Initial revision.";
    reference
      "RFC 9144: Comparison of Network Management Datastore
       Architecture (NMDA) Datastores";
  }

  /* RPC */

  rpc compare {
    description
      "NMDA datastore compare operation.";
    input {
      leaf source {
        type identityref {
          base ds:datastore;
        }
        mandatory true;
        description
          "The source datastore to be compared.";
      }
      leaf target {
        type identityref {
          base ds:datastore;
        }
        mandatory true;
        description
          "The target datastore to be compared.";
      }
      leaf all {
        type empty;
        description
          "When this leaf is provided, all data nodes are compared,
           whether their schema node pertains to both datastores or
           not.  When this leaf is omitted, a prefiltering step is
           automatically applied that excludes data nodes from the
           comparison that can occur in only one datastore but not
           the other.  Specifically, if one of the datastores
           (source or target) contains only configuration data and
           the other datastore is <operational>, data nodes for
           the config that is false are excluded from the
           comparison.";
      }
      leaf report-origin {
        type empty;
        description
          "When this leaf is provided, origin metadata is
           included as part of RPC output.  When this leaf is
           omitted, origin metadata in comparisons that involve
           <operational> is by default omitted.";
      }
      choice filter-spec {
        description
          "Identifies the portions of the datastores to be
               compared.";
        anydata subtree-filter {
          description
            "This parameter identifies the portions of the
             target datastore to retrieve.";
          reference
            "RFC 6241, Section 6.";
        }
        leaf xpath-filter {
          if-feature "nc:xpath";
          type yang:xpath1.0;
          description
            "This parameter contains an XPath expression
             identifying the portions of the target
             datastore to retrieve.";
          reference
            "RFC 6991: Common YANG Data Types";
        }
      }
    }
    output {
      choice compare-response {
        description
          "Comparison results.";
        leaf no-matches {
          type empty;
          description
            "This leaf indicates that the filter did not match
             anything and nothing was compared.";
        }
        container differences {
          description
            "The list of differences, encoded per RFC 8072 with an
             augmentation to include source values where applicable.
             When a datastore node in the source is not present in
             the target, this can be indicated either as a 'delete'
             or as a 'remove' as there is no difference between
             them for the purposes of the comparison.";
          uses ypatch:yang-patch {
            augment "yang-patch/edit" {
              description
                "Provides the value of the source of the patch,
                 respectively of the source of the comparison, in
                 addition to the target value, where applicable.";
              anydata source-value {
                when "../operation = 'delete'"
                   + "or ../operation = 'merge'"
                   + "or ../operation = 'move'"
                   + "or ../operation = 'replace'"
                   + "or ../operation = 'remove'";
                description
                  "The anydata 'value' is only used for 'delete',
                   'move', 'merge', 'replace', and 'remove'
                   operations.";
              }
              reference
                "RFC 8072: YANG Patch Media Type";
            }
          }
        }
      }
    }
  }
}

5. Example ๐ŸŽ€

okay so this example compares the difference between <operational> and <intended> for a subtree under "interfaces" ๐Ÿฆ‹ The subtree contains a subset of objects that are defined in a YANG data model for the management of interfaces defined in [RFC8343]. To get what's happening in the example, here's the excerpt of the data model that the comparison is based on:

container interfaces {
  description
    "Interface parameters.";
  list interface {
    key "name";
    leaf name {
      type string;
      description
        "The name of the interface.";
    }
    leaf description {
      type string;
      description
        "A textual description of the interface.";
    }
    leaf enabled {
      type boolean;
      default "true";
      description
        "This leaf contains the configured, desired state of the
         interface.";
    }
  }
}

Now for the actual data living in the <intended> and <operational> datastores, written in XML [W3C.REC-xml-20081126] ๐Ÿ’œ

<!--INTENDED-->
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
  <interface>
    <name>eth0</name>
    <enabled>false</enabled>
    <description>ip interface</description>
  </interface>
</interfaces>

<!--OPERATIONAL-->
<interfaces
    xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"
    xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin">
  <interface or:origin="or:learned">
    <name>eth0</name>
    <enabled>true</enabled>
  </interface>
</interfaces>

so <operational> doesn't have an instance for the leaf "description" that <intended> has ๐Ÿ‘€ The leaf "enabled" is giving disagreement too, being "true" in <operational> and "false" in <intended>. The leaf "name" is the same in both cases, slay. The origin of the leaf instances in <operational> is "learned", which may help explain the discrepancies โœจ

Here's the RPC request to compare <operational> (source of the comparison) with <intended> (target of the comparison) ๐Ÿ’…

<rpc message-id="101"
    xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <compare xmlns="urn:ietf:params:xml:ns:yang:ietf-nmda-compare"
      xmlns:ds="urn:ietf:params:xml:ns:yang:ietf-datastores">
    <source>ds:operational</source>
    <target>ds:intended</target>
    <report-origin/>
    <xpath-filter
        xmlns:if="urn:ietf:params:xml:ns:yang:ietf-interfaces">
      /if:interfaces
    </xpath-filter>
  </compare>
</rpc>

And when a difference is detected, the RPC reply looks like this ๐Ÿ˜ญ

<rpc-reply
     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
     message-id="101">
  <differences
     xmlns="urn:ietf:params:xml:ns:yang:ietf-nmda-compare"
     xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin">
    <yang-patch>
      <patch-id>interface status</patch-id>
      <comment>
        diff between operational (source) and intended (target)
      </comment>
      <edit>
        <edit-id>1</edit-id>
        <operation>replace</operation>
        <target>/ietf-interfaces:interface=eth0/enabled</target>
        <value>
          <if:enabled>false</if:enabled>
        </value>
        <source-value>
           <if:enabled or:origin="or:learned">true</if:enabled>
        </source-value>
      </edit>
      <edit>
        <edit-id>2</edit-id>
        <operation>create</operation>
        <target>/ietf-interfaces:interface=eth0/description</target>
        <value>
          <if:description>ip interface</if:description>
        </value>
      </edit>
    </yang-patch>
  </differences>
</rpc-reply>

The same request in RESTCONF, using JSON format [RFC7951] ๐ŸŒˆ

POST /restconf/operations/ietf-nmda-compare:compare HTTP/1.1
Host: example.com
Content-Type: application/yang-data+json
Accept: application/yang-data+json

{ "ietf-nmda-compare:input" : {
   "source" : "ietf-datastores:operational",
   "target" : "ietf-datastores:intended",
   "report-origin" : null,
   "xpath-filter" : "/ietf-interfaces:interfaces"
   }
}

And the same response in RESTCONF, using JSON format ๐Ÿงš

HTTP/1.1 200 OK
Date: Thu, 24 Jan 2019 20:56:30 GMT
Server: example-server
Content-Type: application/yang-data+json

{ "ietf-nmda-compare:output" : {
    "differences" : {
      "ietf-yang-patch:yang-patch" : {
        "patch-id" : "interface status",
        "comment" : "diff between intended (source) and operational",
        "edit" : [
          {
            "edit-id" : "1",
            "operation" : "replace",
            "target" : "/ietf-interfaces:interface=eth0/enabled",
            "value" : {
               "ietf-interfaces:interface/enabled" : "false"
            },
            "source-value" : {
               "ietf-interfaces:interface/enabled" : "true",
               "@ietf-interfaces:interface/enabled" : {
                 "ietf-origin:origin" : "ietf-origin:learned"
               }
             }
          },
          {
            "edit-id" : "2",
            "operation" : "create",
            "target" : "/ietf-interfaces:interface=eth0/description",
            "value" : {
              "ietf-interface:interface/description" : "ip interface"
            }
          }
        ]
      }
    }
  }
}

6. Performance Considerations ๐Ÿ’…

okay so <compare> can be computationally expensive, no cap ๐Ÿ˜ญ. Responsible client apps are expected to use it responsibly and sparingly, only when it's actually warranted. But implementations need to be aware that excessive invocation will burden system resources, so they need to make sure system performance does not get adversely impacted ๐Ÿซถ. One way an implementation can handle this is to limit the number of requests it serves to a client (or to any number of clients) in any one time interval. Requests coming in at a higher frequency than the implementation can reasonably sustain just get rejected ๐Ÿšซ.

Tools like YANG data models that let you monitor server resources, system performance, and statistics about RPCs and RPC rates are super useful, but they're outside the scope of this document ๐Ÿงš. When one gets defined, it should be general in nature and not limited to the RPC operation defined here. Main character energy is not needed for this one, it just needs to be broadly useful ๐ŸŒˆ.


7. IANA Considerations ๐ŸŽ€

7.1. Update to the IETF XML Registry

IANA has registered the following URI in the "IETF XML Registry" [RFC3688] ๐ŸŒธ:

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

7.2. Update to the YANG Module Names Registry

IANA has also registered the following YANG module in the "YANG Module Names" registry [RFC6020] ๐Ÿฆ‹:

name:  ietf-nmda-compare
namespace:  urn:ietf:params:xml:ns:yang:ietf-nmda-compare
prefix:  cmp
reference:  RFC 9144

8. Security Considerations ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ

Okay bestie, this part is SERIOUS ๐Ÿ˜ญ๐Ÿ™. The YANG module specified in this document defines a schema for data that's designed to be accessed through network management protocols like NETCONF [RFC6241] or RESTCONF [RFC8040]. The lowest NETCONF layer is the secure transport layer, and the mandatory-to-implement secure transport there is Secure Shell (SSH) [RFC6242]. The lowest RESTCONF layer is HTTPS, and the mandatory-to-implement secure transport there is TLS [RFC8446] ๐Ÿ”.

The Network Configuration Access Control Model (NACM) [RFC8341] gives you the tools to restrict access for particular NETCONF or RESTCONF users to a preconfigured subset of all the available NETCONF or RESTCONF protocol operations and content ๐Ÿ‘‘.

NACM specifies access for the server in its entirety, and the same access rules apply to all datastores. Any subtrees a requestor doesn't have read access to are silently skipped and not included in the comparison ๐Ÿ™ˆ.

The RPC operation defined in this YANG module, <compare>, may be considered sensitive or vulnerable in some network environments ๐Ÿ’€. That's why it's so important to control access to this operation. Here's the sensitivity/vulnerability of RPC operation <compare>:

Comparing datastores for differences takes a certain amount of processing resources at the server. An attacker could try to take a server down by sending a high volume of comparison requests ๐Ÿ˜ฑ. Server implementations can guard against this in several ways. For one, they can implement NACM so that proper authorization is required before requests can be made. Second, server implementations can limit the number of requests they serve to a client in any one time interval, rejecting requests made at a higher frequency than the implementation can reasonably sustain ๐Ÿ›ก๏ธ.


9. References ๐Ÿ“š

9.1. Normative References

9.2. Informative References


Appendix A. Possible Future Extensions ๐Ÿ”ฎ

It's conceivable to extend the <compare> operation with a bunch of extra features in the future โœจ.

Specifically, it's possible to define an extension with an optional feature for dampening. This would let clients specify a minimum time period a difference has to persist before it gets reported. That helps clients tell apart differences that are just fleeting from ones that aren't, and the non-fleeting ones may point to a real operational issue and inconsistency within the device ๐Ÿง.

For this, an additional input parameter can be added to specify the dampening period. Only differences that persist for at least the dampening time get reported. A value of 0, or leaving the parameter out, means no dampening. Reporting of differences MAY correspondingly be delayed by the dampening period from the time the request is received โณ.

To implement this, a server implementation might run a comparison when the RPC is first invoked and temporarily store the result. After that, it could wait until the dampening period is over and check whether the same differences are still observed. Whichever differences still persist are then returned ๐Ÿ’œ.


Acknowledgments ๐Ÿซถ

We thank Rob Wilton, Martin Bjorklund, Mahesh Jethanandani, Lou Berger, Kent Watsen, Phil Shafer, Ladislav Lhotka, Tim Carey, and Reshad Rahman for their valuable feedback and suggestions ๐ŸŒท.


Authors' Addresses ๐Ÿฆ‹

Alexander Clemm Futurewei 2330 Central Expressway Santa Clara, CA 95050 United States of America

Email: ludwig@clemm.org

Yingzhen Qu Futurewei 2330 Central Expressway Santa Clara, CA 95050 United States of America

Email: yqu@futurewei.com

Jeff Tantsura Microsoft

Email: jefftant.ietf@gmail.com

Andy Bierman YumaWorks

Email: andy@yumaworks.com

๐Ÿ“ฆ where this page comes from