Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Open Questions/Issues/Decisions

Questions/IssuesNotesDecisions
  • Are there any major advantages of using RFC 9144?
  • Does it have major differences when compared to RFC6902?
  • Can it be modified as per requirements of CPS? For example, using xpath format.

The documentation of RFC 9144 defines a POST operation to find the delta.

  • Does this mean this approach intends to persist the Delta generated to a database?
    • If so will it be an indefinite persistence of delta report or will the delta be removed from storage after a specific time period.
Code Block
titleSample POST request from RFC9144
collapsetrue
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"
   }
}

The current approach that is being used for development of Delta feature in CPS is a GET operation with no intention to persist the delta report.

It is meant to return the delta in following JSON format.

Code Block
titleSample delta report format
collapsetrue
[
  {
    "action": "ADD",
    "xpath": "/bookstore/categories/[@code=3]",
    "payload": {
      "code": 3,
      "name": "kidz"
    }
  },
  {
    "action": "DELETE",
    "xpath": "/bookstore/categories/[@code=1]",
    "payload": {
      "code": 1,
      "name": "Fiction"
    }
  },
  {
    "action": "UPDATE",
    "xpath": "/bookstore/categories/[@code=2]",
    "payload": {
      "name": "Comic"
    }
  
  • RFC 9144 defines a yang data model which will be helpful when persisting the Delta Report,
  • But if we go with the approach where the generated delta is not persisted then what will be the benefit of using the model?
  • Are we following any RFC specifications for PATCH operation? 

Intention of RFC 9144

Both RFC have their pros and cons. 

  • RFC 6902 thrives with its simple approach but lacks proper categorization of data.
  • RFC 9144 benefits because of proper categorization of data and detailed information provided as part of the report. But in doing so it complicates things by making it mandatory to persist the delta and adding and "edit-id" field to identify each delta report entity uniquely. And this approach does not report the paths of individual data nodes that changed, instead it reports only one path that was sent as part of request.

CPS delta report takes inspiration from both RFCs and cherry pics the best of both worlds to achieve its goals.

  • Keeping the simplicity in mind the Delta report will only contain 4 fields:
    • action, xpath, source-data and target-data.
  • The operation field present in both RFCs is replaced with "action" field because in CPS we want to report the action that was performed on the data.
  • The JSON path is replaced with xpath as CPS is based around xpaths. And the delta report will have the xpaths of every data node changed.
  • To properly categorize the data, we take the source-data and target-data fields from RFC 9144, this provides better data visualization over a combined field of "values" defined in RFC 6902.
  • Persisting of delta report is not needed in case of CPS. 

The documentation of RFC 9144 defines a POST operation to find the delta.

The reason for this is, according to the approach both source and target data are sent as JSON payload (as seen in source and target fields).



Code Block
titleSample POST request from RFC9144
collapsetrue
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:source",
   "target" : "ietf-datastores:target",
   "report-origin" : null,
   "xpath-filter" : "/ietf-interfaces:interfaces"
   }
}


  • The first Delta API does not require any payload to be sent as it uses 2 anchors and data stored under them to generate the delta. Hence it will be a GET API.
  • The second Delta API is going to generate delta between an anchor and JSON payload. Hence following the best practice, the second API will be a POST operation.


  • RFC 9144 defines a model which will be helpful when persisting the Delta Report,
  • But if we go with the approach where the generated delta is not persisted then what will be the benefit of using the model?


CPS does not require persisting of the delta generated.

So, only a few key points from this RFC are taken into consideration. Such as categorization of data as source and target data.

Intention of RFC 9144

RFC 9144 model defines Remote Procedure Calls (RPCs) intended to be used in conjunction with NETCONF or RESTCONFRFC 9144 YANG data model that defines RPCs intended to be used in conjunction with NETCONF [RFC6241] or RESTCONF [RFC8040]. These RPCs allow a client to request a server to compare two NMDA datastores and report any differences.

...

  • The core of the RFC 9144 solution is a new management operationoperator, <compare>, that compares the data tree contents of two datastores. The operation checks whether there are any differences in values or in data nodes that are contained in either datastore and returns any differences as output. The output is returned in the format specified in YANG Patch [RFC8072].
  • The RFC6902 approach to of Delta report generation follows the JSON patch format. A JSON Patch document represents an array of objects, where each object contains exactly one operation, path and associated values. The operation can have following values: add, remove, replace, move, copy and test. The path represents the JSON patch path and the values contain the difference in source and target values.
    Brief summary of JSON patch can be found in the following page: CPS Delta: Conventions to be used for Delta Report
Example Delta generated as part of RFC9144Example JSON Patch document, transferred in an HTTP PATCH request:


Code Block
titleSample delta as per RFC9144
collapsetrue
{ "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"
            }
          }
        ]
      }
    }
  }
}



Code Block
titleSample JSON Patch document as per RFC6902
collapsetrue
PATCH /my/data HTTP/1.1
   Host: example.org
   Content-Length: 326
   Content-Type: application/json-patch+json
   If-Match: "abc123"

   [
     { "op": "test", "path": "/a/b/c", "value": "foo" },
     { "op": "remove", "path": "/a/b/c" },
     { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
     { "op": "replace", "path": "/a/b/c", "value": 42 },
     { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
     { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
   ]
Code Block
titleProposed delta report format based on JSON patch format above
collapsetrue
[
  {
    "action": "ADD",
    "xpath": "/bookstore/categories/[@code=3]",
    "payload": {
      "code": 3,
      "name": "kidz"
    }
  },
  {
    "action": "DELETE",
    "xpath": "/bookstore/categories/[@code=1]",
    "payload": {
      "code": 1,
      "name": "Fiction"
    }
  },
  {
    "action": "UPDATE",
    "xpath": "/bookstore/categories/[@code=2]",
    "payload": {
      "name": "Comic"
    }
  

RFC 9144 example using RESTCONF

The YANG data model defines the <compare> operation as a new RPC. The operation takes the following input parameters:

  • source: the source or reference datastore
  • target: the datastore to be compared against the source datastore
  • filter-spec: a xpath based filter to specify the data nodes to be compared in a given datastore.  This allows a comparison operation to be applied only to a specific part of the datastore that is of interest, such as a particular subtree.
  • all: When set, this parameter indicates that all differences should be included, including differences pertaining to schema nodes that exist in only one of the datastores. When this parameter is not included, a prefiltering step is automatically applied to exclude data from the comparison that does not pertain to both datastores.
  • report-origin: this parameter is used to indicate whether to include origin or source data in delta report or not.

The operation provides the following output parameters:

  • differences: This parameter contains the list of differences. Those differences are encoded per the YANG Patch data model defined in [RFC8072]



RFC 9144 example using RESTCONF

The model defines a <compare> operator used in an RPC. The operation takes the following input parameters:

  • source: the source datastore. This is comparable to source anchor or source data in CPS Delta feature.
  • target: the datastore to be compared against the source datastore. In CPS this will be the target anchor, or the JSON payload sent as part of delta request.
  • filter-spec: a path-based filter to specify the data nodes to be compared in a given datastore. This allows a comparison operation to be applied only to a specific part of the datastore that is of interest, such as a particular subtree. This is comparable to xpath in cps.
  • all: When set, this parameter indicates that all differences should be included, including differences pertaining to schema nodes that exist in only one of the datastores. When this parameter is not included, a prefiltering step is automatically applied to exclude data from the comparison that does not pertain to both datastores.
  • report-origin: this parameter is used to indicate whether to include origin or source data in delta report or not.

The operation provides the following output parameters:

  • differences: This parameter contains the list of differences. Those differences are encoded per the YANG Patch data model defined in [RFC8072]. And contain the following details:
    • edit-id: unique id given to a delta entity
    • operation: the type of operation, i.e add, remove or update
    • target-value: data in target datastore
    • source-value: data in source datastore
Code Block
titleStructure of ietf-nmda-compare. Source: RFC9144
collapsetrue
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?
Code Block
titleStructure of ietf-nmda-compare. Source: RFC9144
collapsetrue
module: ietf-nmda-compare
  rpcs:
    +---x compare
       +---w input
       |     +---w source:(xpath-filter)
       |      identityref
       |  +---w targetxpath-filter?     yang:xpath1.0 {nc:xpath}?
       +--ro identityrefoutput
        |  +---w all?ro (compare-response)?
              empty+--:(no-matches)
             |  +---wro reportno-originmatches?    empty
       |      +---w (filter-spec)?:(differences)
       |         +--:(subtree-filter)
ro differences
        |         |  +---wro subtreeyang-filter?patch
        |     +--:(xpath-filter)
       |        +---wro xpathpatch-filter?id     yang:xpath1.0 {nc:xpath}?
string
           +--ro output
          +--ro (compare-response)comment?
    string
         +--:(no-matches)
             |  ++--ro no-matches?    emptyedit* [edit-id]
             +--:(differences)
                +--ro differences
edit-id         string
          +--ro yang-patch
              +--ro operation       +--ro patch-id enumeration
   string
                      +--ro target comment?    string
                      +--ro edit* [edit-id]target-resource-offset
                         +--ro edit-idpoint?          stringtarget-resource-offset
                         +--ro where?   operation       enumeration
                         +--ro target value?
         target-resource-offset
                +--ro source-value?

RESTCONF Example

Sample Data

Code Block
titleSource Data
collapsetrue
{
  "interfaces": {
     +--ro point?"interface": {
           target-resource-offset"name": "eth0",
      "enabled": false,
      "description": "ip interface"
    }
  }
}


Code Block
titleTarget Data
collapsetrue
{
  "interfaces": {
 +--ro where?  "interface": {
       enumeration"name": "eth0",
      "enabled": true
                  +--ro value?
                         +--ro source-value?

RESTCONF Example

...

}
  }
}

Request in RESTCONF

Code Block
titleYANG ModelPOST Request
collapsetrue
container interfaces {
  description
    "Interface parameters.";
  list interfacePOST /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" key: "name";ietf-datastores:source",
   "target" leaf name {: "ietf-datastores:target",
   "report-origin"   type string;: null,
   "path-filter" : "/ietf-interfaces:interfaces"
   }
}

Response in RESTCONF

Code Block
titleResponse
collapsetrue
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" : {
   description
        "The name of the interface.";
    }
    leaf description {
      type string;
      description
        "A textual description of the interface.";
    }
    leaf enabled {
      type boolean;
 "patch-id" : "interface status",
       default "truecomment";
 : "diff between intended  description(source) and operational",
        "This leaf contains the configured, desired state of the
edit" : [
          {
      interface.";
    }
  }
}

Sample Data

Code Block
titleIntended/Reference Data
collapsetrue
{
  "interfaces": {
  "edit-id" : "1",
     "interface": {
      "nameoperation" : "eth0replace",
      "enabled": false,
      "descriptiontarget" : "ip interface"
/ietf-interfaces:interface=eth0/enabled",
     }
  }
}
Code Block
titleOperational/Comparand/Target Data
collapsetrue
{
       "interfacesvalue" : {
    "interface": {
           "name"ietf-interfaces:interface/enabled" : "eth0false",
       "enabled": true
    },
  }
}

Request in RESTCONF

Code Block
titlePOST Request
collapsetrue
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            "source-value" : {
               "ietf-interfaces:interface/enabled" : "true",
   "target" : "ietf-datastores:intended",
   "report-origin" : null,
   "xpath-filter" : "/ietf@ietf-interfaces:interfaces"
   }
}

Response in RESTCONF

Code Block
titleResponse
collapsetrue
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" : {
interface/enabled" : {
                 "ietf-origin:origin" : "ietf-origin:learned"
                "ietf-yang-patch:yang-patch" : {
}
           "patch-id" : "interface status", }
        "comment" : "diff between intended (source) and operational",
        "edit" : [ },
          {
            "edit-id" : "12",
            "operation" : "replacecreate",
            "target" : "/ietf-interfaces:interface=eth0/enableddescription",
            "value" : {
               "ietf-interfacesinterface:interface/enableddescription" : "falseip interface"
            },
          }
   "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"
            }
          }
        ]
      }
    }
  }
}}
  }
}

Decisions

The two RFCs used as reference for the delta feature have their own benefits and instead of following either of them as is, we decided to cherry pick the benefits of both the approaches to have the best suited Delta Report format for CPS.

The overall format of delta report closely resembles the format defined in RFC6902, this is because of the simplicity and minimal approach of this RFC while also providing all the necessary information in the delta report.

  • From RFC 6902 the following features have been chosen:
    • The fields in delta report will include action, xpath, source-data and target-data.
  • From RFC 9144 the following features have been chosen:
    • Instead of grouping the changes under one field named "values" as given in RFC 6902, we categorize then under source and target data.
    • The first API will be a GET operation as it does not require any payload as part of the request. But the second API will be a POST operation as it needs the user to send a JSON payload.